使用usbfs与内核驱动之间的冲突

usb驱动分为通过usbfs操作设备的用户空间驱动,内核空间的内核驱动。两者不能同时进行,否则容易引发对共享资源访问的问题,死锁!使用了内核驱动,就不能在usbfs里驱动该设备。libusb中须要先detach内核驱动后,才能claim interface,否则claim会返回的vice busy的错误。如果你不dettach,也不claim interface,也能使用libusb对设备进行访问,但是,容易导致内核usbfs瘫痪,这是不允许的。


如果不能dettach内核驱动,那么你不能通过usbfs访问设备,也就是不能使用libusb。若确实需要usbfs才能完成的操作,如控制传输,中断传输等,可以在内核驱动里给ioctl添加对应的功能,即可通过内核驱动完成usb设备的所有原始通信。


使用libusb读写ft232的eeprom,不允许把内核驱动dettach的情况下,经常导致usbfs瘫痪,所有usb都处于disk sleep状态。这里我之用得到control传输,经过一番思考,我在内核驱动里面的ioctl里添加了USBDEVFS_CONTROL选项,通过内核驱动完成usb control msg,测试了好几天,没发现任何问题。好,基本完成任务。


以下是我的操作:

在设备驱动文件ftdi_sio.c的ioctl函数里面添加:

[cpp]  view plain  copy
  1. static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)  
  2. {  
  3.     struct ftdi_private *priv = usb_get_serial_port_data(port);  
  4.   
  5.     int  ret, mask;  
  6.       
  7.     dbg("%s cmd 0x%04x", __FUNCTION__, cmd);  
  8.   
  9.     /* Based on code from acm.c and others */  
  10.     switch (cmd) {  
  11.   
  12.     /* To support usb_control_msg to ttyUSB */  
  13.     case USBDEVFS_CONTROL:  
  14.         dev_printk(KERN_DEBUG, &port->serial->dev->dev, "%s: CONTROL\n", __FUNCTION__);  
  15.         return tty_control(port, (void __user *)arg);  
  16.         break;  
  17.   
  18.     case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */  
  19.         。。。。。。  

以下是从usbfs的proc_control()移植过来的控制传输函数:

[cpp]  view plain  copy
  1. static int tty_control(struct usb_serial_port *port, void __user *arg)  
  2. {  
  3.     struct usb_device *dev = port->serial->dev;  
  4.     struct usbdevfs_ctrltransfer ctrl;  
  5.     unsigned int tmo;  
  6.     unsigned char *tbuf;  
  7.     int i, j, ret;  
  8.   
  9.     if (copy_from_user(&ctrl, arg, sizeof(ctrl)))  
  10.         return -EFAULT;  
  11.     //if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))  
  12.         //return ret;  
  13.     if (ctrl.wLength > PAGE_SIZE)  
  14.         return -EINVAL;  
  15.     if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))  
  16.         return -ENOMEM;  
  17.     tmo = (ctrl.timeout * HZ + 999) / 1000;  
  18.     if (ctrl.bRequestType & 0x80) {  
  19.         if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {  
  20.             free_page((unsigned long)tbuf);  
  21.             return -EINVAL;  
  22.         }  
  23.         dev_printk(KERN_DEBUG, &dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);  
  24.   
  25.         i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,  
  26.                        ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);  
  27.         if ((i > 0) && ctrl.wLength) {  
  28.             if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {  
  29.                 free_page((unsigned long)tbuf);  
  30.                 return -EFAULT;  
  31.             }  
  32.         }  
  33.     } else {  
  34.         if (ctrl.wLength) {  
  35.             if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {  
  36.                 free_page((unsigned long)tbuf);  
  37.                 return -EFAULT;  
  38.             }  
  39.         }  
  40.         dev_printk(KERN_DEBUG, &dev->dev, "control write: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);  
  41.         i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,  
  42.                        ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);  
  43.     }  
  44.     free_page((unsigned long)tbuf);  
  45.     if (i<0) {  
  46.         dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "  
  47.                "failed cmd %s rqt %u rq %u len %u ret %d\n",  
  48.                current->comm, ctrl.bRequestType, ctrl.bRequest,  
  49.                ctrl.wLength, i);  
  50.     }  
  51.     return i;  
  52. }  


好了,编译加载后,设备文件就支持usb_control_msg了。以下是用户程序的usb_control_msg

[cpp]  view plain  copy
  1. #define IOCTL_USB_CONTROL   _IOWR('U', 0, struct usb_ctrltransfer)  
  2.   
  3. struct usb_ctrltransfer {  
  4.     /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */  
  5.     u_int8_t  bRequestType;  
  6.     u_int8_t  bRequest;  
  7.     u_int16_t wValue;  
  8.     u_int16_t wIndex;  
  9.     u_int16_t wLength;  
  10.   
  11.     u_int32_t timeout;    /* in milliseconds */  
  12.   
  13.     /* pointer to data */  
  14.     void *data;  
  15. };  
  16.   
  17. static int usb_control_msg(int fd, int requesttype, int request,  
  18.     int value, int index, char *bytes, int size, int timeout)  
  19. {  
  20.   struct usb_ctrltransfer ctrl;  
  21.   int ret;  
  22.   
  23.   ctrl.bRequestType = requesttype;  
  24.   ctrl.bRequest = request;  
  25.   ctrl.wValue = value;  
  26.   ctrl.wIndex = index;  
  27.   ctrl.wLength = size;  
  28.   
  29.   ctrl.data = bytes;  
  30.   ctrl.timeout = timeout;  
  31.   
  32.   ret = ioctl(fd, IOCTL_USB_CONTROL, &ctrl);  
  33.   if (ret < 0)  
  34.     printf("usb_control_msg: %s\n", strerror(errno));  
  35.   
  36.   return ret;  
  37. }  

其实,上面的usb_ctrltransfer和usbdevice_fs.h 里的struct usbdevfs_ctrltransfer是一样的,只是为了方便查阅,才定义了另外一个在源文件里。

linux-2.6.8.1/include/linux/usbdevice_fs.h

[cpp]  view plain  copy
  1. /* usbdevfs ioctl codes */  
  2.   
  3. struct usbdevfs_ctrltransfer {  
  4.     __u8 bRequestType;  
  5.     __u8 bRequest;  
  6.     __u16 wValue;  
  7.     __u16 wIndex;  
  8.     __u16 wLength;  
  9.     __u32 timeout;  /* in milliseconds */  
  10.      void __user *data;  
  11. };  
  12.   
  13. #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)  
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值