Добрый день !
Есть драйвер для 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" выдает множество ссылок, но все обсуждения заканчиваются словами
"упс, что-то в моем драйвере не так..."
Что же в моем драйвере "не так" ?
USB драйвер на ARM (x86 - работает, arm - не работает)
Модератор: Модераторы разделов
Re: USB драйвер на ARM
Громоздкое сообщение. Модераторы, если нужно, поправьте пожалуйста.
Код:
//#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");
Re: USB драйвер на ARM
Первое что приходит в голову без чтения кода - порядок байтов совпадает на обоих платформах? Второе - размер типов.
Re: USB драйвер на ARM
Ответ нашелся в конце 6 страницы гугля
Известная в узких кругах аппаратная особенность ARM: очень маленький буфер USB контроллера, нужно отправлять маленькими порциями.
Известная в узких кругах аппаратная особенность ARM: очень маленький буфер USB контроллера, нужно отправлять маленькими порциями.
Спасибо сказали: