通过设备文件符号链接查找总线编号和设备编号

我有一个由udev规则生成的设备文件( SYMLINK/dev/CDMAModem 。 我想查找实际设备的总线编号和设备编号。 其实我想在我的C ++程序中执行设备/dev/bus/usb/BUS_NO/DEVICE_NO上的USBDEVFS_RESET ioctl。

—- udev规则—-

 SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="zte_ev", ATTRS{bNumEndpoints}=="03", SYMLINK+="CDMAModem" SUBSYSTEMS=="usb", ACTION=="remove", DRIVERS=="zte_ev", ATTRS{bNumEndpoints}=="03", SYMLINK-="CDMAModem" 

Solutions Collecting From Web of "通过设备文件符号链接查找总线编号和设备编号"

您可以像在/dev/bus/结构下的文件上一样对symlink /dev/CDMAModem表示的文件执行ioctl

 #include <fcntl.h> #include <sys/ioctl.h> #include <linux/usbdevice_fs.h> int f = open("/dev/CDMAModem", O_RDWR); ioctl(f, USBDEVFS_RESET); 

如果你真的想找到这个链接指向的地方, file命令会告诉你。

 > file /dev/CDMAModem /dev/CDMAModem: symbolic link to `bus/usb/BUS/DEV' 

我认为libudev会给你:

 #include <libudev.h> #include <stdio.h> #include <stdlib.h> #include <locale.h> #include <unistd.h> int main(int argc, char **argv) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; udev = udev_new(); enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "CDMAModem"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { const char *path; path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); fprintf(stderr, "devnum: %s\n", udev_device_get_sysattr_value(dev, "devnum")); fprintf(stderr, "busnum: %s\n", udev_device_get_sysattr_value(dev, 'busnum:)); udev_device_unref(dev); } udev_enumerate_unref(enumerate); udev_unref(udev); return 0; } 

你可以使用这个信息与ioctl(),我认为,在:

 [charles@localhost 2-1]$ cd /sys/class/mem/random [charles@localhost 2-1]$echo $PWD /sys/devices/pci0000:00/0000:00:11.0/0000:02:00.0/usb2/2-1 

我认为stat()库调用将是一个很好的开始…随着libusb。

如果您只想解决链接问题,则可以使用readlink并稍后使用字符串函数解析信息。

函数:ssize_t readlink(const char * filename,char * buffer,size_t size)

readlink函数获取符号链接文件名的值。 链接指向的文件名被复制到缓冲区。 这个文件名字符串不是以null结尾的; readlink通常返回复制的字符数。 size参数指定要复制的最大字符数,通常是缓冲区的分配大小。

 ~$ sudo udevadm info -a -p $(sudo udevadm info -q path -n /dev/CDMAModem) [sudo] password for gowtham: Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/ttyUSB0/tty/ttyUSB0': KERNEL=="ttyUSB0" SUBSYSTEM=="tty" DRIVER=="" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/ttyUSB0': KERNELS=="ttyUSB0" SUBSYSTEMS=="usb-serial" DRIVERS=="zte_ev" ATTRS{port_number}=="0" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0': KERNELS=="2-1.2:1.0" SUBSYSTEMS=="usb" DRIVERS=="zte_ev" ATTRS{bInterfaceClass}=="ff" ATTRS{bInterfaceSubClass}=="ff" ATTRS{bInterfaceProtocol}=="ff" ATTRS{bNumEndpoints}=="03" ATTRS{supports_autosuspend}=="1" ATTRS{bAlternateSetting}==" 0" ATTRS{bInterfaceNumber}=="00" ATTRS{interface}=="Data Interface" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2': KERNELS=="2-1.2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{devpath}=="1.2" ATTRS{idVendor}=="19d2" ATTRS{speed}=="12" ATTRS{bNumInterfaces}==" 6" ATTRS{bConfigurationValue}=="1" ATTRS{bMaxPacketSize0}=="64" ATTRS{busnum}=="2" ATTRS{devnum}=="8" 
  ATTRS{busnum}=="2" ATTRS{devnum}=="8" 

虽然这是丑陋的,但工程。 从C ++程序调用udevadm并从输出中筛选busnumdevnum属性。 我希望一些参与libudev开发的开发者能够帮助,并且可能是udev邮件列表。