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