usb_get_intfdata方法

时间:2017-06-16 09:05:27

标签: linux-kernel linux-device-driver

我正在为USB设备编写自己的字符驱动程序,需要使用ctrl传输进行简单写入并使用中断传输进行读取。我的设备有2个接口,其中对于零接口我可以获得中断端点,所以基本上我不需要处理包含批量ISCO的第二个接口,所以我在bInterfaceNumber时从探测器函数返回-ENODEV是1。以下是代码段

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数据时,我收到BUG:无法在0000000000000048处理内核NULL指针取消引用

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-&gt; 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];
};

提前致谢。

1 个答案:

答案 0 :(得分:0)

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