2012-05-18 44 views
3

我需要知道如何找出/ proc/bus/usb/devices/dev/sdX設備映射到哪個項目。基本上,我需要知道給定U盤(可能沒有序列號)的供應商ID和產品ID。如何將/ proc/bus/usb/devices條目映射到/ dev/sdX設備?

在我的情況,我有這樣的條目在/ proc /總線/ USB /設備我的閃存驅動器:

T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 6 Spd=480 MxCh= 0 
D: Ver= 2.00 Cls=00(>ifc) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 
P: Vendor=0781 ProdID=5530 Rev= 2.00 
S: Manufacturer=SanDisk 
S: Product=Cruzer 
S: SerialNumber=0765400A1BD05BEE 
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=200mA 
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage 
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms 

我碰巧知道,在我的情況下,它是/ dev/sda上,但我我不知道如何在代碼中弄清楚這一點。我的第一個方法是通過所有的/ dev/sdXX設備迴路並出具SCSI_IOCTL_GET_BUS_NUMBER和/或SCSI_IOCTL_GET_IDLUN請求,但返回的信息不幫我搭配起來:

/tmp # ./getscsiinfo /dev/sda 
SCSI bus number: 8 
ID: 00 
LUN: 00 
Channel: 00 
Host#: 08 
four_in_one: 08000000 
host_unique_id: 0 

我不知道我是怎麼可以使用SCSI總線編號或ID,LUN,Channel,Host將其映射到/ proc/bus/usb/devices中的條目。或者,我怎麼可能從/ proc /巴士/ USB/001/006設備,這是一個USBFS設備並沒有出現喜歡同樣的IOCTL的獲得SCSI總線號:

/tmp # ./getscsiinfo /proc/bus/usb/001/006 
Could not get bus number: Inappropriate ioctl for device 

這裏的測試代碼爲我的小getscsiinfo測試工具:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <scsi/scsi.h> 
#include <scsi/sg.h> 
#include <sys/ioctl.h> 

struct scsi_idlun 
{ 
    int four_in_one; 
    int host_unique_id; 
}; 

int main(int argc, char** argv) { 
    if (argc != 2) 
     return 1; 

    int fd = open(argv[1], O_RDONLY | O_NONBLOCK); 
    if (fd < 0) 
    { 
     printf("Error opening device: %m\n"); 
     return 1; 
    } 

    int busNumber = -1; 
    if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &busNumber) < 0) 
    { 
     printf("Could not get bus number: %m\n"); 
     close(fd); 
     return 1; 
    } 

    printf("SCSI bus number: %d\n", busNumber); 

    struct scsi_idlun argid; 
    if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &argid) < 0) 
    { 
     printf("Could not get id: %m\n"); 
     close(fd); 
     return 1; 
    } 

    printf("ID: %02x\n", argid.four_in_one & 0xFF); 
    printf("LUN: %02x\n", (argid.four_in_one >> 8) & 0xFF); 
    printf("Channel: %02x\n", (argid.four_in_one >> 16) & 0xFF); 
    printf("Host#: %02x\n", (argid.four_in_one >> 24) & 0xFF); 
    printf("four_in_one: %08x\n", (unsigned int)argid.four_in_one); 
    printf("host_unique_id: %d\n", argid.host_unique_id); 

    close(fd); 
    return 0; 
} 

有沒有人有任何想法?

回答

2

我相信你可以使用libudev庫來收集這些信息。

這裏有一些細節吧:http://www.signal11.us/oss/udev/

我發現像這樣的上述網站:

..使用libudev,我們就可以檢查設備,包括他們的供應商ID (VID),產品ID(PID),序列號和設備字符串,而無需打開設備。此外,libudev會準確告訴我們設備節點位於/ dev內部的位置,從而爲應用程序提供了一種健壯且與分佈無關的訪問設備的方式。 ...

+0

不幸的是,我似乎無法從udev獲取/ dev/sdX節點。 dev節點路徑libudev返回給我的usb棒爲空。但是我確實得到了它的父路徑(主控制器),但不幸的是指向了/ proc/bus/usb/001/006設備。我需要能夠安裝這個設備,我只能做到這一點與適當的/ dev/sdX的設備...我不知道哪一個/ dev/sdX設備涉及到的/ proc /巴士/ USB/001/006。 libudev也不會給我這些信息。 – Tom

+0

大多數Linux系統都有'udev'配置爲在插入USB密鑰時執行操作。也許你可以根據你的需要調整配置規則 –

2

udevadm是能夠實現你正在努力實現的目標。

udevadm info -a -p $(udevadm info -q path -n /dev/sda) 

udevadm的人士會告訴你它是如何做。

0

/SCSI/SCSI。在那裏您可以找到具有特定渠道ID和LUN編號的供應商和序列號。

0

這不是那麼容易,也沒有很好的文檔記錄(至少從一個高層次的角度來看)。以下內容應該可以在3.1以上版本的內核中使用(至少)。

我發現最簡單(可能不是唯一的方法)是從塊設備條目導航並測試每個塊設備,直到找到與USB條目匹配的設備。

例如,假設在/sys/block塊設備,如sdb,你可以找到硬件設備描述符條目是這樣的:

# cd /sys/block 
# cd `readlink sdb`; cd ../../../../../.. 
# ls -l 
total 0 
drwxr-xr-x 6 root root  0 Aug 14 10:47 1-1:1.0 
-rw-r--r-- 1 root root 4096 Aug 14 10:52 authorized 
-rw-r--r-- 1 root root 4096 Aug 14 10:52 avoid_reset_quirk 
-r--r--r-- 1 root root 4096 Aug 14 10:47 bcdDevice 
-rw-r--r-- 1 root root 4096 Aug 14 10:49 bConfigurationValue 
-r--r--r-- 1 root root 4096 Aug 14 10:47 bDeviceClass 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bDeviceProtocol 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bDeviceSubClass 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bmAttributes 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bMaxPacketSize0 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bMaxPower 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bNumConfigurations 
-r--r--r-- 1 root root 4096 Aug 14 10:49 bNumInterfaces 
-r--r--r-- 1 root root 4096 Aug 14 10:49 busnum 
-r--r--r-- 1 root root 4096 Aug 14 10:52 configuration 
-r--r--r-- 1 root root 65553 Aug 14 10:47 descriptors 
-r--r--r-- 1 root root 4096 Aug 14 10:52 dev 
-r--r--r-- 1 root root 4096 Aug 14 10:49 devnum 
-r--r--r-- 1 root root 4096 Aug 14 10:52 devpath 
lrwxrwxrwx 1 root root  0 Aug 14 10:47 driver -> ../../../../../../bus/usb/drivers/usb 
drwxr-xr-x 3 root root  0 Aug 14 10:52 ep_00 
-r--r--r-- 1 root root 4096 Aug 14 10:47 idProduct 
-r--r--r-- 1 root root 4096 Aug 14 10:47 idVendor 
-r--r--r-- 1 root root 4096 Aug 14 10:52 ltm_capable 
-r--r--r-- 1 root root 4096 Aug 14 10:47 manufacturer 
-r--r--r-- 1 root root 4096 Aug 14 10:49 maxchild 
lrwxrwxrwx 1 root root  0 Aug 14 10:52 port -> ../1-0:1.0/port1 
drwxr-xr-x 2 root root  0 Aug 14 10:52 power 
-r--r--r-- 1 root root 4096 Aug 14 10:47 product 
-r--r--r-- 1 root root 4096 Aug 14 10:52 quirks 
-r--r--r-- 1 root root 4096 Aug 14 10:47 removable 
--w------- 1 root root 4096 Aug 14 10:52 remove 
-r--r--r-- 1 root root 4096 Aug 14 10:47 serial 
-r--r--r-- 1 root root 4096 Aug 14 10:49 speed 
lrwxrwxrwx 1 root root  0 Aug 14 10:47 subsystem -> ../../../../../../bus/usb 
-rw-r--r-- 1 root root 4096 Aug 14 10:47 uevent 
-r--r--r-- 1 root root 4096 Aug 14 10:52 urbnum 
-r--r--r-- 1 root root 4096 Aug 14 10:49 version 

(你可以找到的USB描述符here on the BeyondLogic site.的內容,優秀的文檔)

鑑於上述情況,您應該能夠將一個或多個USB設備字段映射到/proc/bus/usb/devices的內容。我發現,序列號是最容易匹配,因此,如果你是以上cat serial,你會得到相同的序列號爲上市:

T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 
D: Ver= 2.00 Cls=00(>ifc) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 
P: Vendor=0781 ProdID=5575 Rev=01.26 
S: Manufacturer=SanDisk 
S: Product=Cruzer Glide 
S: SerialNumber=4C530100801115115112 
C: #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=200mA 
I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage 

如果你去/sys/block,你可以列出完整每個設備的存儲驅動程序sysfs條目中主機設備條目的路徑。通常情況下,我這樣做是使用一些編程方法,而不是在shell提示符下,但在這裏你可以看到鏈接本身:

# ls -l sd* 
lrwxrwxrwx 1 root root 0 Aug 14 10:45 sda -> ../devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda 
lrwxrwxrwx 1 root root 0 Aug 14 10:47 sdb -> ../devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host33/target33:0:0/33:0:0:0/block/sdb 

請注意,你不能讓你的鏈接顯示的數字做任何假設。根據總線子系統的不同,映射可能會非常不同。例如,在樹莓派,它看起來像這樣:

# ls -l sd* 
lrwxrwxrwx 1 root root 0 Aug 13 23:54 sda -> ../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/host3/target3:0:0/3:0:0:0/block/sda 
lrwxrwxrwx 1 root root 0 Aug 13 23:54 sdb -> ../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/host4/target4:0:0/4:0:0:0/block/sdb 

所以,最好的辦法是採取在上面列出的方法和導航相對於存儲驅動程序,找到USB設備描述符。

我很好奇這個更權威的答案。上述方法是通過反覆試驗得出的,但一直在努力研究幾種不同的設備和內核。

相關問題