在linux,更新了usb设备的firmware后,你需要重新插拔一下usb设备来让系统读取到新的usb设备信息。
我们可以通过软件的方式让usb设备reset,实现hot-replug目的,让系统重新读取usb设备信息。
有两种方法让内核replug USB设备:
一:使用usbfs系统reset USB设备
先看看源码:
在drivers/usb/core/devio.c里的usbdev_ioctl函数里有
case USBDEVFS_RESET: snoop(&dev->dev, "%s: RESET\n", __func__); ret = proc_resetdevice(ps); break;
proc_resetdevice调用了drivers/usb/core/hub.c的usb_reset_device重置usb设备,使内核replug该usb
只需打开usbfs里面对应的usb文件进行ioctl(fd, USBDEVFS_RESET, NULL)即可。
二:修改设备驱动,在ioctl里添加USBDEVFS_RESET选项
我在ftdi_sio驱动里,添加
static int ftdi_device_reset(struct usb_serial_port *port) { struct usb_device *dev = port->serial->dev; int ret; ret = usb_lock_device_for_reset(dev,NULL); if (ret == 0) { ret = usb_reset_device(dev); usb_unlock_device(dev); } return ret; } static int ftdi_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s cmd 0x%04x", __func__, cmd); /* Based on code from acm.c and others */ switch (cmd) { /* To support usb_control_msg to ttyUSB */ case USBDEVFS_CONTROL: //dev_printk(KERN_DEBUG, &port->serial->dev->dev, "%s: CONTROL\n", __FUNCTION__); return tty_usb_control(port, (void __user *)arg); break; /* reset after downloading new firmware */ case USBDEVFS_RESET: return ftdi_device_reset(port); break;
使用该内核,则可以通过设备驱动进行replug该usb设备,很方便。
使用驱动reset设备:
static int usb_device_reset(int fd) { int ret; #define FTDI_USBDEV_RESET _IO('U', 20) ret = ioctl(fd, FTDI_USBDEV_RESET, NULL); if (ret < 0) printf("USB device reset: %s\n", strerror(errno)); return ret; }
上面的#define FTDI_USBDEV_RESET _IO('U', 20),其实就是USBDEVFS_RESET
我使用修改了的驱动实现,实际效果如下:
root@DLRC:/opt/sniffer/bin#setmoteid_4x -d /dev/ttyUSB0 -w 92 product :HKUST ATC Telos Rev B(9), len:24 old product :HKUST ATC Telos Rev B(9), len:24 new product : HKUST ATC Telos Rev B(92) serial save:DS000338, len:8 ftdi_sio 1-1.4.3:1.0: forced unbind ep93xx-ohci ep93xx-ohci: shutdown urb c563dde0 ep1in-bulk ftdi_sio 1-1.4.3:1.0: device disconnected hub 1-1.4:1.0: state 7 ports 4 chg 0000 evt 0008 hub 1-1.4:1.0: state 7 ports 4 chg 0000 evt 0008 usb 1-1.4.3: reset full speed USB device using ep93xx-ohci and address 4 hub 1-1.4:1.0: state 7 ports 4 chg 0000 evt 0008 hub 1-1.4:1.0: state 7 ports 4 chg 0000 evt 0008 usb 1-1.4.3: ep0 maxpacket = 8 usbserial_generic 1-1.4.3:1.0: usb_probe_interface usbserial_generic 1-1.4.3:1.0: usb_probe_interface - got id ftdi_sio 1-1.4.3:1.0: usb_probe_interface ftdi_sio 1-1.4.3:1.0: usb_probe_interface - got id ftdi_sio 1-1.4.3:1.0: FTDI USB Serial Device converter detected usb 1-1.4.3: Detected FT232BM usb 1-1.4.3: FTDI USB Serial Device converter now attached to ttyUSB1 ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
可以看到,reset它,内核就replug该USB。