USB драйвер на ARM (x86 - работает, arm - не работает)

Взгляд изнутри

Модератор: Модераторы разделов

Ответить
Serik
Сообщения: 149
ОС: SuSE Linux

USB драйвер на ARM

Сообщение Serik »

Добрый день !

Есть драйвер для USB-устройства, написанный по образу и подобию usb-skeleton.c
Отлично работает на x86 (linux-2.6.27.7).
Возникла необходимость запустить на arm (linux-2.6.27.8). Без проблем собрался и запустился. Работает c Control EndPoint. Но при попытке отправить в Bulk EndPoint, после вызова
usb_submit_urb
весь USB-стэк отваливается, никакие USB-устройства не определяются и не работают.

Согласно документации, все USB-драйвера платформонезависимые, в моем коде тоже ничего такого нет.

Гугль по фразе "usb_submit_urb failed" выдает множество ссылок, но все обсуждения заканчиваются словами
"упс, что-то в моем драйвере не так..."

Что же в моем драйвере "не так" ?
Спасибо сказали:
Аватара пользователя
deadhead
Сообщения: 1913
Статус: zzz..z

Re: USB драйвер на ARM

Сообщение deadhead »

Serik писал(а):
15.10.2010 14:55
Что же в моем драйвере "не так" ?

код драйвера могбы облегчить задачу телепатам :-)
[x] close
Спасибо сказали:
Serik
Сообщения: 149
ОС: SuSE Linux

Re: USB драйвер на ARM

Сообщение Serik »

Громоздкое сообщение. Модераторы, если нужно, поправьте пожалуйста.

Код:

//#include <linux/config.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/kref.h> #include <asm/uaccess.h> #include <linux/usb.h> #include <linux/usb/ch9.h> #include "iocmd.h" static unsigned char end_point = 0; static unsigned int device_state = 0; static unsigned char transfer = IO_TRANSFER_BULK; static unsigned char direction = 0; // 0=host to device, 1=device to host static unsigned char request = 0; static unsigned char request_type = 0; static unsigned int value = 0; static unsigned int index = 0; static unsigned int timeout = 10; static unsigned char loglevel = IO_LOGLEVEL_WARNING; static unsigned char iotype = IO_IOTYPE_DIRECT; /* Define these values to match your devices */ #define USB_O103_VENDOR_ID 0x0547 #define USB_O103_PRODUCT_ID 0x1030 #define USB_O1031_PRODUCT_ID 0x1031 #define USB_R65_PRODUCT_ID 0x4040 /* table of devices that work with this driver */ static struct usb_device_id o103_table [] = { { USB_DEVICE(USB_O103_VENDOR_ID, USB_O103_PRODUCT_ID) }, /* */ { USB_DEVICE(USB_O103_VENDOR_ID, USB_O1031_PRODUCT_ID)}, /* */ { USB_DEVICE(USB_O103_VENDOR_ID, USB_R65_PRODUCT_ID)}, /**/ { USB_DEVICE(0x2226, 0x6500)}, /* */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, o103_table); /* Get a minor range for your devices from the usb maintainer */ #define USB_O103_MINOR_BASE 192 /* our private defines. if this grows any larger, use your own .h file */ #define MAX_TRANSFER ( PAGE_SIZE - 512 ) #define WRITES_IN_FLIGHT 8 /* set up all urbs so they can be used with either bulk or interrupt */ #define INTERRUPT_RATE 1 /* msec/transfer */ /* Structure to hold all of our device specific stuff */ struct usb_o103 { struct usb_device *udev; /* the usb device for this device */ struct usb_interface *interface; /* the interface for this device */ struct semaphore limit_sem; /* limiting the number of writes in progress */ unsigned char *bulk_in_buffer; /* the buffer to receive data */ size_t bulk_in_size; /* the size of the receive buffer */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ __u8 bulk_out_endpointAddr;/* the address of the bulk out endpoint */ unsigned char bulk_in_endpointNum; /* the number of the bulk in endpoint */ unsigned char bulk_out_endpointNum; /* the number of the bulk out endpoint */ __u8 ctrl_in_endpointAddr; /* the address of the control in endpoint */ __u8 ctrl_out_endpointAddr;/* the address of the control out endpoint */ unsigned char ctrl_in_endpointNum; unsigned char ctrl_out_endpointNum; // struct usb_ctrlrequest *dr; struct kref kref; }; #define to_o103_dev(d) container_of(d, struct usb_o103, kref) static struct usb_driver o103_driver; //--------------------------------------------------------------------------- static void o103_delete(struct kref *kref) { struct usb_o103 *dev = to_o103_dev(kref); if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_delete\n"); usb_put_dev(dev->udev); kfree (dev->bulk_in_buffer); kfree (dev); } //--------------------------------------------------------------------------- static int o103_open(struct inode *inode, struct file *file) { struct usb_o103 *dev; struct usb_interface *interface; int subminor; int retval = 0; if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_open\n"); subminor = iminor(inode); interface = usb_find_interface(&o103_driver, subminor); if (!interface) { err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); retval = -ENODEV; goto exit; } dev = usb_get_intfdata(interface); if (!dev) { retval = -ENODEV; goto exit; } /* increment our usage count for the device */ kref_get(&dev->kref); /* save our object in the file's private structure */ file->private_data = dev; // printk("dev->actconfig->bNumInterfaces=%d\n", dev->actconfig->bNumInterfaces); // usb_set_interface(dev, ) exit: return retval; } //--------------------------------------------------------------------------- static int o103_release(struct inode *inode, struct file *file) { struct usb_o103 *dev; if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_release\n"); dev = (struct usb_o103 *)file->private_data; if (dev == NULL) return -ENODEV; /* decrement the count on our device */ kref_put(&dev->kref, o103_delete); return 0; } //--------------------------------------------------------------------------- static ssize_t o103_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct usb_o103 *dev; int retval = 0; int bytes_read; dev = (struct usb_o103 *)file->private_data; if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_read\n"); switch(transfer) { case IO_TRANSFER_BULK: { // printk("o103_read bulk_in_endpointAddr=0x%x EP=%d buf_size=%d\n", // dev->bulk_in_endpointAddr, dev->bulk_in_endpointNum, count); /* do a blocking bulk read to get data from the device */ retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), dev->bulk_in_buffer, min(dev->bulk_in_size, count), &bytes_read, timeout /*2*/ * HZ); // printk("o103_read retval=%d\n", retval); /* if the read was successful, copy the data to userspace */ if (retval == 0) { if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read)) { printk("read bulk error copy_to_user\n"); retval = -EFAULT; } else retval = bytes_read; } // if else { printk("read bulk error %d\n", retval); } break; } // case IO_BULK_CONTROL: case IO_TRANSFER_CONTROL: { unsigned char * ctrl_in_buffer = NULL; // printk("o103_read control, buffer size = %d\n", count); if (count > 0) { ctrl_in_buffer = kmalloc(count, GFP_KERNEL); if (!ctrl_in_buffer) { printk("Could not allocate ctrl_in_buffer\n"); return(-ENOMEM); } // if (!ctrl_in_buffer) } // if (count > 0) /* do a blocking control read to get data from the device */ retval = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, dev->ctrl_in_endpointAddr), request, request_type, value, index, ctrl_in_buffer, count, timeout /*10*/ * HZ); // printk("o103_read retval=%d\n", retval); /* if the read was successful, copy the data to userspace */ if (retval >= 0) { if (copy_to_user(buffer, ctrl_in_buffer, retval)) retval = -EFAULT; //else // retval = bytes_read; } // if else { printk("read control error %d\n", retval); } if (ctrl_in_buffer != NULL) kfree(ctrl_in_buffer); break; } // case IO_TRANSFER_CONTROL: default: printk("unknown read mode\n"); } // switch return retval; } //--------------------------------------------------------------------------- static void o103_write_callback(struct urb *urb, struct pt_regs *regs) { // struct usb_o103 *dev; // dev = (struct usb_o103 *)urb->context; if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_write_callback\n"); /* sync/async unlink faults aren't errors */ if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { dbg("%s - nonzero write status received: %d", __FUNCTION__, urb->status); } // kfree(dev->dr); /* free up our allocated buffer */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); // up(&dev->limit_sem); } //--------------------------------------------------------------------------- static ssize_t o103_write_direct(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { struct usb_o103 *dev; int retval = 0; struct urb *urb = NULL; char *buf = NULL; struct usb_ctrlrequest *dr = NULL; size_t writesize = min(count, (size_t)MAX_TRANSFER); dev = (struct usb_o103 *)file->private_data; // printk("o103_write count=%d writesize=%d\n", count, writesize); /* verify that we actually have some data to write */ //if (count == 0) goto exit; /* limit the number of URBs in flight to stop a user from using up all RAM */ //if (down_interruptible(&dev->limit_sem)) //{ // retval = -ERESTARTSYS; // goto exit; // } // if (down_trylock(&dev->limit_sem) != 0) // { // printk("o103_write EINPROGRESS\n"); // retval = -EINPROGRESS; // goto exit; // } /* create a urb, and a buffer for it, and copy the data to the urb */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error; } buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } if (copy_from_user(buf, user_buffer, writesize)) { retval = -EFAULT; goto error; } /* initialize the urb properly */ switch(transfer) { case IO_TRANSFER_BULK: { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_write bulk writesize=%d\n", writesize); usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, writesize, o103_write_callback, dev); break; } // case IO_TRANSFER_BULK case IO_TRANSFER_CONTROL: { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103_write control v=%x req_type=%x request=%x value=%x index=%x size=%d\n", (unsigned char)buf[0],request_type,request,value,index,writesize); //printk("o103_write control\n"); dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); if (!dr) {retval = -ENOMEM; goto error;} dr->bRequestType = request_type; dr->bRequest = request; dr->wValue = /*cpu_to_le16*/ (value); dr->wIndex = /*cpu_to_le16*/ (index); dr->wLength = /*cpu_to_le16*/ (writesize); usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, dev->ctrl_out_endpointAddr), (unsigned char *)dr, buf, writesize, o103_write_callback, dev); break; } // // case IO_TRANSFER_BULK default: { printk("o103_write transfer is not defined\n"); break; } } // switch(transfer) urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); goto error; } /* release our reference to this urb, the USB core will eventually free it entirely */ usb_free_urb(urb); if (dr != NULL) kfree (dr); //exit: return writesize; error: usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); usb_free_urb(urb); if (dr != NULL) kfree (dr); up(&dev->limit_sem); return retval; } //----------------------------------------------------------------------------- /*static ssize_t o103_write_direct(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { const int MAX_PACKET = 512; int pos, size; int ret = 0, res; for(pos = 0; pos < count; pos += MAX_PACKET) { if ((count - (pos + MAX_PACKET)) > 0) {size = MAX_PACKET;} else {size = count - pos;} res = o103_write_block_direct(file, user_buffer, pos, size); if (res >= 0) {ret += res;} else {ret = res; break;} } return (ret); }*/ //----------------------------------------------------------------------------- static ssize_t o103_write_wait(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { struct usb_o103 *dev; int retval = 0; // struct urb *urb = NULL; char *buf = NULL; // struct usb_ctrlrequest *dr = NULL; size_t writesize = min(count, (size_t)MAX_TRANSFER); //dma_addr_t dma; dev = (struct usb_o103 *)file->private_data; /* verify that we actually have some data to write */ if (count < 0) goto exit; // buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &dma); buf = kmalloc(writesize, GFP_KERNEL); if (!buf) { retval = -ENOMEM; printk("Error write - no memory\n"); goto error; } if (copy_from_user(buf, user_buffer, writesize)) { retval = -EFAULT; printk("Error copy_from_user\n"); goto error; } switch(transfer) { case IO_TRANSFER_BULK: { // printk("o103_write bulk_msg\n"); int actual_length = 0, ret; // usb_fill_bulk_urb(urb, dev->udev, // usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), // buf, writesize, o103_write_callback, dev); ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, writesize, &actual_length, timeout /*10*/ * HZ); if (ret == 0) { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("Successfull bulk write %d\n", actual_length); retval = actual_length; } else { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("Error bulk write %d\n", ret); retval = ret; goto error; } break; } // case IO_TRANSFER_BULK case IO_TRANSFER_CONTROL: { int ret; ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), //dev->ctrl_out_endpointAddr), request, request_type, value, index, buf, writesize, timeout /*10*/ * HZ ); if (ret >= 0) { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("Successfull control write %d len=%d request=%x request_type=%x value=%x index=%x\n", ret, writesize, request, request_type, value, index); retval = ret; } else { retval = ret; if (loglevel >= IO_LOGLEVEL_DEBUG) printk("Error control write %d len=%d request=%x request_type=%x value=%x index=%x\n", ret, writesize, request, request_type, value, index); goto error; } break; } // // case IO_TRANSFER_CONTROL default: { printk("o103_write transfer is not defined\n"); break; } } // switch(transfer) // usb_buffer_free(dev->udev, writesize, buf, dma); kfree(buf); exit: return retval; error: // usb_buffer_free(dev->udev, writesize, buf, dma); kfree(buf); return retval; } //--------------------------------------------------------------------------- static ssize_t o103_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { if (iotype == IO_IOTYPE_WAIT) { return(o103_write_wait(file, user_buffer, count, ppos));} else {return(o103_write_direct(file, user_buffer, count, ppos));} } //--------------------------------------------------------------------------- static int ez_reset(struct file *file, unsigned long arg) { struct usb_o103 *dev; unsigned char buf; int ret; dev = (struct usb_o103 *)file->private_data; buf = arg; ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), //dev->ctrl_out_endpointAddr), 0xA0, // request, 0x40, // request_type, 0x7F92, // value, 0, // index, &buf, 1, timeout /*10*/ * HZ ); if (ret >= 0) { if (loglevel >= IO_LOGLEVEL_DEBUG) printk("Successfull set CPUCS = %d\n", buf); ret = 1; } else { printk("Error set CPUCS = %d error = %d\n", buf, ret); } return(ret); } //--------------------------------------------------------------------------- static int o103_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) // unsigned int cmd, void *arg) { int ret = 1; // printk("o103_ioctl cmd = %d arg = %ld\n", cmd, arg); switch (cmd) { case IO_CMD_SET_EP: end_point = arg; break; case IO_CMD_SET_STATE: device_state = arg; break; case IO_CMD_SET_TRANSFER: transfer = arg; break; case IO_CMD_SET_REQUEST: request = arg; break; case IO_CMD_SET_REQUEST_TYPE: request_type = arg; break; case IO_CMD_SET_VALUE: value = arg; break; case IO_CMD_SET_INDEX: index = arg; break; case IO_CMD_SET_DIRECTION: direction = arg; break; case IO_CMD_GET_CURRENT_FRAME_NUMBER: { struct usb_o103 *dev = (struct usb_o103 *)file->private_data; ret = usb_get_current_frame_number(dev->udev); break; } case IO_CMD_RESET: ret = ez_reset(file, arg); break; case IO_CMD_SET_LOGLEVEL: loglevel = arg; break; case IO_CMD_SET_IOTYPE: iotype = arg; break; case IO_CMD_SET_TIMEOUT: timeout = arg; break; default: ret = -1; break; } return (ret); } //--------------------------------------------------------------------------- /* defined in linux/fs.h*/ static struct file_operations o103_fops = { .owner = THIS_MODULE, .read = o103_read, // .write = o103_write_direct, .write = o103_write, .open = o103_open, .release = o103_release, .ioctl = o103_ioctl, }; /* * usb class driver info in order to get a minor number from the usb core, * and to have the device registered with the driver core */ static struct usb_class_driver o103_class = { .name = "o103%d", .fops = &o103_fops, .minor_base = USB_O103_MINOR_BASE, /* ??? */ // .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, }; //--------------------------------------------------------------------------- static int o103_probe(struct usb_interface *interface, const struct usb_device_id *id) { // linux/usb.h // struct usb_interface struct usb_o103 *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; size_t buffer_size; int i; int retval = -ENOMEM; if (loglevel >= IO_LOGLEVEL_DEBUG) dbg("o103_probe\n"); end_point = 0; device_state = 0; transfer = IO_TRANSFER_BULK; direction = 0; // 0=host to device, 1=device to host request = 0; request_type = 0; value = 0; index = 0; /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { err("Out of memory"); goto error; } kref_init(&dev->kref); sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; /* set up the endpoint information */ /* use only the first bulk-in and bulk-out endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (!dev->bulk_in_endpointAddr && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { err("Could not allocate bulk_in_buffer"); goto error; } dev->bulk_in_endpointNum = i; } // if (!dev->bulk_in_endpointAddr && if (!dev->bulk_out_endpointAddr && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk out endpoint */ dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; dev->bulk_out_endpointNum = i; } // if (!dev->bulk_out_endpointAddr && if (!dev->ctrl_in_endpointAddr && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL)) { dev->ctrl_in_endpointAddr = endpoint->bEndpointAddress; dev->ctrl_in_endpointNum = i; } if (!dev->ctrl_out_endpointAddr && ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL)) { dev->ctrl_out_endpointAddr = endpoint->bEndpointAddress; dev->ctrl_out_endpointNum = i; } } // for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { printk("Could not find both bulk-in and bulk-out endpoints: device without firmware\n"); //goto error; dev->ctrl_in_endpointNum = 0; dev->ctrl_in_endpointAddr = 0; dev->ctrl_out_endpointNum= 0; dev->ctrl_out_endpointAddr= 0; } else { if (loglevel >= IO_LOGLEVEL_DEBUG) { printk("EP bulk_in = %d (0x%x) bulk_out = %d (0x%x)\n", dev->bulk_in_endpointNum, dev->bulk_in_endpointAddr, dev->bulk_out_endpointNum, dev->bulk_out_endpointAddr); printk("EP ctrl_in = %d (0x%x) ctrl_out = %d (0x%x)\n", dev->ctrl_in_endpointNum, dev->ctrl_in_endpointAddr, dev->ctrl_out_endpointNum, dev->ctrl_out_endpointAddr); printk("Bulk_in_buffer size = %d\n", dev->bulk_in_size); printk("num_altsetting = %d\n", interface->num_altsetting); } // if (loglevel >= IO_LOGLEVEL_DEBUG) } //{ // int i; // for (i = 0; i < interface->num_altsetting; i++) // { //printk("num_altsetting = %d NumEndpoints = %d\n", i, interface -> altsetting->desc.bNumEndpoints); //interface -> alsetting[i] -> endpoint[j] -> desc -> bNumEndpoints; //interface -> alsetting[i] -> endpoint[j] -> desc; // } // for //} /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); /* we can register the device now, as it is ready */ retval = usb_register_dev(interface, &o103_class); if (retval) { /* something prevented us from registering this driver */ err("Not able to get a minor for this device."); usb_set_intfdata(interface, NULL); goto error; } /* let the user know what node this device is now attached to */ info("USB o103 device now attached to USB-%d", interface->minor); return 0; error: if (dev) {kref_put(&dev->kref, o103_delete);} return retval; } //--------------------------------------------------------------------------- static void o103_disconnect(struct usb_interface *interface) { struct usb_o103 *dev; int minor = interface->minor; /* prevent o103_open() from racing o103_disconnect() */ lock_kernel(); dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &o103_class); unlock_kernel(); /* decrement our usage count */ kref_put(&dev->kref, o103_delete); info("USB o103 #%d now disconnected", minor); } //--------------------------------------------------------------------------- static struct usb_driver o103_driver = { .name = "o103", .probe = o103_probe, .disconnect = o103_disconnect, .id_table = o103_table, }; //--------------------------------------------------------------------------- static int __init usb_o103_init(void) { int result; /* register this driver with the USB subsystem */ result = usb_register(&o103_driver); if (result) err("usb_register failed. Error number %d", result); else {printk("o103 driver is succefully registered\n");} return result; } //--------------------------------------------------------------------------- static void __exit usb_o103_exit(void) { /* deregister this driver with the USB subsystem */ usb_deregister(&o103_driver); if (loglevel >= IO_LOGLEVEL_DEBUG) printk("o103 driver is deregistered\n"); } //--------------------------------------------------------------------------- module_init (usb_o103_init); module_exit (usb_o103_exit); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("o103");
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: USB драйвер на ARM

Сообщение NickLion »

Первое что приходит в голову без чтения кода - порядок байтов совпадает на обоих платформах? Второе - размер типов.
Спасибо сказали:
Serik
Сообщения: 149
ОС: SuSE Linux

Re: USB драйвер на ARM

Сообщение Serik »

Ответ нашелся в конце 6 страницы гугля :)
Известная в узких кругах аппаратная особенность ARM: очень маленький буфер USB контроллера, нужно отправлять маленькими порциями.
Спасибо сказали:
Ответить