我需要知道如何确定/ proc / bus / usb / devices / / dev / sdX设备映射到哪个条目。基本上,我需要知道给定USB记忆棒的供应商ID和产品ID(可能没有序列号)。
在我的情况下,我在/ proc / bus / usb / devices中有我的闪存驱动器的这个条目:
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 / bus / usb / 001/006设备获取SCSI总线编号,这是一个usbfs设备,似乎不喜欢相同的ioctl:
/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;
}
有没有人有任何想法?
答案 0 :(得分:2)
我相信您可以使用libudev库收集此类信息。
以下是有关它的一些细节:http://www.signal11.us/oss/udev/
我在上面的网站上发现了类似的内容:
..使用libudev,我们将能够检查设备,包括它们的供应商ID(VID),产品ID(PID),序列号和设备字符串,而无需打开设备。此外,libudev将告诉我们设备节点内部/ dev的确切位置,为应用程序提供了一种健壮且独立于分发的访问设备的方式。 ...
答案 1 :(得分:2)
udevadm
能够满足您的目标。
udevadm info -a -p $(udevadm info -q path -n /dev/sda)
udevadm
的来源会告诉你它是如何完成的。
答案 2 :(得分:0)
对于使用没有udev的系统的任何人,此链接都有您正在寻找的确切答案:
答案 3 :(得分:0)
您可以使用/ proc / scsi / scsi代替使用usbfs的proc / bus / usb。在那里,您可以找到具有特定通道ID和LUN编号的供应商和序列号。
答案 4 :(得分: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
请注意,您不必对链接中显示的数字做出任何假设。根据总线子系统,映射可能完全不同。例如,在Raspberry Pi上,它看起来像这样:
# 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设备描述符。
我对这个更权威的答案感到好奇。上面的方法是通过反复试验得出的,但是已经在几个不同的设备和内核上工作没有问题。