usb_get_intfdata方法后Lin​​ux USB驱动程序崩溃

问题描述:

我正在写一个USB设备的自己的字符驱动程序,它需要使用ctrl传输和使用中断传输进行读取的简单写入。我的设备有2个接口,其中零接口我可以得到中断端点,所以基本上我不需要处理包含bulk,ISCO的第二个接口,所以当bInterfaceNumber为1时,我从探测函数返回-ENODEV 。下面的代码片段usb_get_intfdata方法后Lin​​ux USB驱动程序崩溃

static int USBTestMode_Probe(struct usb_interface *interface, const struct usb_device_id *id) 
{ 
    if(interface->cur_altsetting->desc.bInterfaceNumber != 0) 
    { 
     return -ENODEV; 
    } 
    struct usb_device *udev = interface_to_usbdev(interface); 
    struct usb_test_mode_dev * testModeDev = NULL; 

    struct usb_host_interface *iface_desc; 
    struct usb_endpoint_descriptor *endpoint; 
    int i, int_end_size; 
    int retval = -ENODEV; 



    TestModeclass.name = "testmode%d"; 
    TestModeclass.fops = &USBTestModefops; 

    testModeDev = kzalloc(sizeof(struct usb_test_mode_dev),GFP_KERNEL); 
    strcpy(testModeDev->buffer , "mydata"); 
    printk("size::%d\n", sizeof(struct usb_test_mode_dev)); 
    printk("testModeDev size::%d\n", sizeof(testModeDev)); 
    printk("name :%s\n",testModeDev->buffer); 
    if(testModeDev == NULL) 
    { 
     printk("No Memory):"); 
     goto exit; 
    } 

    testModeDev->udev = usb_get_dev(udev); 
    testModeDev->interface = interface; 
    iface_desc = interface->cur_altsetting; 
    testModeDev->int_in_endpoint = kzalloc(sizeof(struct usb_endpoint_descriptor),GFP_KERNEL); 


    for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 
     endpoint = &iface_desc->endpoint[i].desc; 

     if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 
      == USB_DIR_IN) 
      && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 
       == USB_ENDPOINT_XFER_INT)) 
      memcpy(testModeDev->int_in_endpoint , endpoint ,sizeof(endpoint)); 

    } 
    if (! testModeDev->int_in_endpoint) { 
     printk("could not find interrupt in endpoint"); 
     goto error; 
    } 

     printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize); 
     printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress); 

    int_end_size = le16_to_cpu(testModeDev->int_in_endpoint->wMaxPacketSize); 

    testModeDev->int_in_buffer = kzalloc(int_end_size, GFP_KERNEL); 

     printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize); 
     printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress); 

    if (! testModeDev->int_in_buffer) { 
     printk("could not allocate int_in_buffer"); 
     retval = -ENOMEM; 
     goto error; 
    } 

    testModeDev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); 
    if (! testModeDev->int_in_urb) { 
     printk("could not allocate int_in_urb"); 
     retval = -ENOMEM; 
     goto error; 
    } 

     printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize); 
     printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress); 


    // Save our data pointer in this interface device. 
    usb_set_intfdata(interface, testModeDev); 

     printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize); 
     printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress); 

    // We can register the device now, as it is ready. 
    retval = usb_register_dev(interface, &TestModeclass); 
    if (retval) { 
     printk("not able to get a minor for this device."); 
     usb_set_intfdata(interface, NULL); 
     goto error; 
    } 

    testModeDev->minor = interface->minor; 

    printk("TestUSB now attached to /dev/TestMode%d\n", 
      interface->minor - 0); 


error: 
    TestMode_delete(testModeDev); 
exit: 
    return retval; 
return 0; 
} 

当过我试图访问下面的Open方法保存在探头usb_test_mode_dev数据,我得到错误:无法处理内核NULL指针引用在0000000000000048

static int TestMode_open(struct inode *inode, struct file *file) 
{ 
     struct usb_test_mode_dev *dev = NULL; 
    struct usb_interface *interface; 
    int subminor; 
    int retval = 0; 
    subminor = iminor(inode); 

     printk(" i came here %d\n" , subminor); 


    interface = usb_find_interface(&USBTestMode_driver, subminor); 

     printk("interface->cur_altsetting->desc.bInterfaceNumber : %d \n" ,interface->cur_altsetting->desc.bInterfaceNumber); 
    if (! interface) { 
     printk("can't find device for minor %d", subminor); 
     retval = -ENODEV; 
     return retval; 
    } 

     printk(" i came here .....1\n"); 
    dev = usb_get_intfdata(interface); 
     printk("name :%s\n",dev->buffer); 
    if (! dev) { 
     retval = -ENODEV; 
     return retval; 
    } 

     printk("Dev size::%d\n", sizeof(*dev)); 

     printk(" i came here .....2\n"); 

     //dev->int_in_endpoint->bEndpointAddress = 129; 
     //dev->int_in_endpoint->wMaxPacketSize = 64; 

     if(dev->int_in_endpoint != NULL) 
     { 
      printk(" i came here .....8\n"); 
      printk("endpoint value :%d\n",dev->int_in_endpoint->bEndpointAddress); 
      printk("endpoint value :%d\n",dev->int_in_endpoint->wMaxPacketSize); 
     }  

     printk(" i came here .....7\n"); 

     if(!dev->int_in_endpoint->bEndpointAddress || !dev->int_in_endpoint->wMaxPacketSize) 
       return -1; 

    /* Initialize interrupt URB. */ 
    usb_fill_int_urb(dev->int_in_urb, dev->udev, 
      usb_rcvintpipe(dev->udev, 
         dev->int_in_endpoint->bEndpointAddress), 
      dev->int_in_buffer, 
      le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize), 
      TestMode_init_callback, 
      dev, 
      dev->int_in_endpoint->bInterval); 
     printk(" i came here .....3\n"); 
    mb(); 
     printk(" i came here .....6\n"); 
    retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL); 
    if (retval) { 
     printk("submitting int urb failed (%d)", retval); 
     return retval; 
    } 

     printk(" i came here .....4\n"); 

    /* Save our object in the file's private structure. */ 
    file->private_data = dev; 

     printk(" i came here .....5\n"); 

     return retval; 
} 

当我尝试访问dev-> int_in_endpoint时,模块会崩溃,即使缓冲区仍然为空。为什么我的数据结构保存在探针中正在被覆盖。这是由于我的设备的多个界面。请帮帮我。如果你想要下面我的char设备的数据结构是代码。

struct usb_test_mode_dev { 
     struct usb_device *udev; 
     unsigned char *int_in_buffer; 
     struct usb_interface *interface; 
     struct usb_endpoint_descriptor *int_in_endpoint; 
     struct urb *int_in_urb; 
     unsigned char minor; 
     char buffer[20]; 
}; 

在此先感谢。

usb_set_intfdata(interface, testModeDev); is at wrong place , should be called before return in probe method