У меня есть файл устройства (SYMLINK
) /dev/CDMAModem
генерируется udev
править. Я хочу найти номер шины и номер фактического устройства. На самом деле я хочу выполнить USBDEVFS_RESET
ioctl на устройстве /dev/bus/usb/BUS_NO/DEVICE_NO
в моей C ++ программе.
—-Правило Удев —-
SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="zte_ev", ATTRS{bNumEndpoints}=="03", SYMLINK+="CDMAModem"SUBSYSTEMS=="usb", ACTION=="remove", DRIVERS=="zte_ev", ATTRS{bNumEndpoints}=="03", SYMLINK-="CDMAModem"
Я думаю, что 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
Вы можете выполнить ioctl
в файле, представленном символической ссылкой /dev/CDMAModem
как и в файле под /dev/bus/
состав.
#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'
я думаю stat()
библиотечный вызов был бы хорошим местом для начала … Наряду с libusb.
Если все, что вы хотите сделать, это разрешить ссылку, вы можете использовать readlink и проанализировать информацию позже с помощью строковых функций.
Функция: ssize_t readlink (const char * имя файла, char * буфер, размер size_t)
Функция readlink получает значение имени файла символьной ссылки. Имя файла, на которое указывает ссылка, копируется в буфер. Эта строка имени файла не заканчивается нулем; 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
и фильтр для busnum
а также devnum
атрибуты из вывода. Я надеюсь, что некоторые разработчики, которые участвуют в libudev
развитие должно помочь и может быть udev
рассылка поможет.