浅析libusb控制接口和mountd守护进程处理uevent切换usb设备的实现
1. UMS mode (USB Mass-Storage mode) [ums]
2. 从usb_gadget_register_driver的实现来看,insmod xxx.ko,然后重新插拔一下usb cable,那么pc再次枚举到的设备就是insmod xxx.ko对应的设备了[luther.gliethttp]
3. init进程没有对change event事件进行处理,mountd守护进程的detect_thread线程会等待该uevent事件到来,然后卸载前一个ko,加载欲成为设备的相应ko驱动[luther.gliethttp].
4. 其实uevent已经在udc_uevent中将ret数值打入了uevent strings中了MODE=;NET_ENUM=;TESTMODE=;直接解析就可以了,所以就不需要read_usb_switch了[luther.gliethttp].
5. libusb库链接程序时,可以使用 -static -lusb选项,将libusb静态编译到程序中,这样其他pc就不用单独安装libusb了[luther.gliethttp].
====================================================================
usb_init=>我的是strncpy(usb_path, "/dev/bus/usb", sizeof(usb_path) - 1);"/dev/bus/usb"或者"/proc/bus/usb"
usb_find_busses=>然后将usb目录下的所有文件目录路径名bus->dirname添加到struct usb_bus *usb_busses = NULL;
链表上,比如:/dev/bus/usb下的001和002目录等.
usb_find_devices=>根据文件目录路径名遍历usb_busses文件夹下的所有文件对应的char节点,如果合法将dev添加bus->devices设备链表上.
同时将char节点的文件路径名作为访问文件节点的路径名存储起来.
//比如打开host控制器的2号hub下插入的第1个设备
//usb_path="/dev/bus/usb"
//dev->bus->dirname="002"
//dev->filename="001"
/* Get the device number */
ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo);
ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH);
usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor);
可以看到我的pc主机usb-host2控制器挂接了4个usb设备,usb-host1控制器挂接了1个设备
luther@gliethttp:~$ tree /dev/bus/usb/
/dev/bus/usb/
|-- 001
| `-- 001
|-- 002
| |-- 001
| |-- 002
| |-- 003
| `-- 004
`-- devices -> .usbfs/devices
luther@gliethttp:~$ ll /dev/bus/usb/002/
total 0
crw-rw-r-- 1 root root 189, 128 2008-10-16 17:30 001
crw-rw-r-- 1 root root 189, 129 2008-10-16 17:30 002
crw-rw-r-- 1 root root 189, 130 2008-10-16 17:30 003
可以看到major都是189,因为是bus2,所以从128开始,一个bus现在最多支持128个usb设备.
//根据pid和vid查找设备是否已经存在
struct usb_device *find_device(int vendor, int product) {
struct usb_bus *bus;
struct usb_device *right_dev;
right_dev = NULL;
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
right_dev = dev;
DevicesN++;
}
}
}
return right_dev;
}
然后调用usb_open打开find_device()返回的usb_device设备,
usb_dev_handle *usb_open(struct usb_device *dev)
{
usb_dev_handle *udev;
udev = malloc(sizeof(*udev));
if (!udev)
return NULL;
udev->fd = -1;
udev->device = dev;
udev->bus = dev->bus;
udev->config = udev->interface = udev->altsetting = -1;
if (usb_os_open(udev) < 0) {
free(udev);
return NULL;
}
return udev;
}
int usb_os_open(usb_dev_handle *dev)
{
dev->fd = device_open(dev->device);
return 0;
}
static int device_open(struct usb_device *dev)
{
char filename[PATH_MAX + 1];
int fd;
snprintf(filename, sizeof(filename) - 1, "%s/%s/%s",
usb_path, dev->bus->dirname, dev->filename);
//比如打开host控制器的2号hub下插入的第1个设备//usb_path="/dev/bus/usb"//dev->bus->dirname="002"//dev->filename="001" fd = open(filename, O_RDWR);
if (fd < 0) {
fd = open(filename, O_RDONLY);
if (fd < 0)
USB_ERROR_STR(-errno, "failed to open %s: %s",
filename, strerror(errno));
}
return fd;
}
====================================================================
链接程序时,可以使用 -static -lusb选项,将libusb静态编译到程序中,这样其他pc就不用单独安装libusb了[luther.gliethttp].
以下代码摘自libusb-0.1.12
#define USB_MAXDRIVERNAME 255
struct usb_getdriver {
unsigned int interface;
char driver[USB_MAXDRIVERNAME + 1];
};
#define IOCTL_USB_CONTROL _IOWR('U', 0, struct usb_ctrltransfer)
#define IOCTL_USB_BULK _IOWR('U', 2, struct usb_bulktransfer)
#define IOCTL_USB_RESETEP _IOR('U', 3, unsigned int)
#define IOCTL_USB_SETINTF _IOR('U', 4, struct usb_setinterface)
#define IOCTL_USB_SETCONFIG _IOR('U', 5, unsigned int)
#define IOCTL_USB_GETDRIVER _IOW('U', 8, struct usb_getdriver)
#define IOCTL_USB_SUBMITURB _IOR('U', 10, struct usb_urb)
#define IOCTL_USB_DISCARDURB _IO('U', 11)
#define IOCTL_USB_REAPURB _IOW('U', 12, void *)
#define IOCTL_USB_REAPURBNDELAY _IOW('U', 13, void *)
#define IOCTL_USB_CLAIMINTF _IOR('U', 15, unsigned int)
#define IOCTL_USB_RELEASEINTF _IOR('U', 16, unsigned int)
#define IOCTL_USB_CONNECTINFO _IOW('U', 17, struct usb_connectinfo)
#define IOCTL_USB_IOCTL _IOWR('U', 18, struct usb_ioctl)
#define IOCTL_USB_HUB_PORTINFO _IOR('U', 19, struct usb_hub_portinfo)
#define IOCTL_USB_RESET _IO('U', 20)
#define IOCTL_USB_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_US