Hi Steven,

Em Wed, 9 Aug 2006 14:50:54 +1000
Steven Haigh <[EMAIL PROTECTED]> escreveu:

|   Patch is against 2.6.17.7

 There's a hunk failing for the Makefile change when applying it in
the latest -rc kernel.

 As this will be applied there, I recomend you to rediff.

| + * History:
| + *
| + * 2006-08-07 - 0.0.13 - shaigh
| + *   - fixed various errors to compile on kernel 2.6.17.7
| + * 2006-02-19 - 0.0.12 - jhomppi
| + *   - remove the mode parameter from the usb_class_driver structure
| + *     (for kernel version 2.6.15)
| + * 2006-02-03 - 0.0.11 jhomppi
| + *   - remove the serial number retrieval "short-cut"
| + * 2006-01-16 - 0.0.10 jhomppi
| + *   - use vendor/product table in adu_probe
| + *   - check LINUX_VERSION_CODE for version of linux kernel
| + *     and utilize appropriate termination of transfer
| + * 2005-12-02 - 0.0.9 jhomppi
| + *   - pre-stage an input read URB to catch first read operation
| + * 2005-11-21 - 0.0.8 jhomppi
| + *   - add ADU120,ADU130,ADU208,ADU218 to supported device list
| + * 2005-11-20 - 0.0.7 jhomppi
| + *   - remove references to URB_ASYNC_UNLINK
| + *   - add MODULE_LICENSE macro to identify our license to kernel
| + * 2005-09-20 - 0.0.6 jhomppi
| + *   - replace deprecated usb_unlink_urb with usb_kill_urb
| + * 2003-12-23 - 0.0.5 jhomppi
| + *   - urb after each read and write
| + * 2003-12-02 - 0.0.4 jhomppi
| + *   - replace urb_submitted with urb status==-EINPROGRESS to stay
| + *     in synch with real urb state
| + *   - allow multiple open handles to the same device (now that
| + *     urb_submitted problem has been removed)
| + * 2003-11-28 - 0.0.3 jhomppi
| + *   - applied more changes suggested by Oliver Neukum
| + *       - pre-start read if a buffer is available
| + *       - correct the location of spin_unlock at end of a read
| + *   - added hack to return serial number to caller if read buffer
| + *     starts with an 's' (allows serial# retrieval without ioctl)
| + *   - check that udev was not nuked by an early disconnect 
| + *     (ie. check for a null dev->udev in adu_abort_transfers)
| + *   - increase scope of lock_irqsave in adu_read so that 
| + *     urb_submitted is protected versus the interrupt_in_callback
| + *   - use down_interruptible where appropriate to prevent locking
| + *     driver module into memory forever
| + * 2003-11-27 - 0.0.2 jhomppi
| + *   - applied changes suggested by Oliver Neukum to add
| + *     spin locks and double buffering to adu_interrupt_in_callback
| + * 2003-11-25 - 0.0.1 jhomppi
| + *   - copied from the Lego Tower USB driver for Kernel 2.6.0
| + *   - modified to support ADU devices (basically changed only 
| + *     the names and constants)
| + */

 You don't need this, we'll track history in GIT. ;)

| +/* prevent races between open() and disconnect */
| +static DECLARE_MUTEX (disconnect_sem);

 I think this can be a mutex intead of a semaphore.

| +/* local function prototypes */
| +static ssize_t adu_read (struct file *file, char *buffer, size_t count, 
loff_t *ppos);
| +static ssize_t adu_write (struct file *file, const char *buffer, size_t 
count, loff_t *ppos);
| +static int adu_ioctl (struct inode *inode, struct file *file, unsigned int 
cmd, unsigned long arg);
| +static inline void adu_delete (struct adu_device *dev);
| +static int adu_open(struct inode *inode, struct file *file);
| +static int adu_release(struct inode *inode, struct file *file);
| +static int adu_release_internal (struct adu_device *dev);
| +static void adu_abort_transfers (struct adu_device *dev);
| +static void adu_interrupt_in_callback (struct urb *urb, struct pt_regs 
*regs);
| +static void adu_interrupt_out_callback (struct urb *urb, struct pt_regs 
*regs);
| +
| +static int  adu_probe (struct usb_interface *interface, const struct 
usb_device_id *id);
| +static void adu_disconnect (struct usb_interface *interface);

 CodyingStyle hints:

Functions prototypes and definitions are:

 my_func()

 and not

my_func ()

| +/* file operations needed when we register this driver */
| +static struct file_operations adu_fops = {
| +     .owner = THIS_MODULE,
| +     .read  = adu_read,
| +     .write = adu_write,
| +     .ioctl = adu_ioctl,
| +     .open = adu_open,
| +     .release = adu_release,
| +};

 make this const please.

| +/**
| + * adu_debug_data
| + */
| +static inline void adu_debug_data (int level, const char *function, int 
size, const unsigned char *data)
| +{
| +     int i;
| +
| +     if (debug < level)
| +     return; 
| +
| +     printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, 
size);
| +     for (i = 0; i < size; ++i) {
| +             printk ("%.2x ", data[i]);
| +     }
| +     printk ("\n");
| +} /* end adu_debug_data */

 Are you sure you want this inline?

| +/**
| + * adu_delete
| + */
| +static inline void adu_delete (struct adu_device *dev)
| +{

 Ditto.

| +     /* free data structures */
| +     if (dev->interrupt_in_urb != NULL) {
| +             usb_free_urb (dev->interrupt_in_urb);
| +     }
| +     if (dev->interrupt_out_urb != NULL) {
| +             usb_free_urb (dev->interrupt_out_urb);
| +     }

 usb_free_urb() already does the check for you.

| +static int adu_open (struct inode *inode, struct file *file)
| +{
| +     struct adu_device *dev = NULL;

 Why the NULL init here?

| +     down (&disconnect_sem); /* not interruptible */

 No need for the comment.

| +     interface = usb_find_interface (&adu_driver, subminor);
| +
| +     if (!interface) {
| +             err ("%s - error, can't find device for minor %d",
| +                     __FUNCTION__, subminor);
| +             retval = -ENODEV;
| +             goto exit_no_device;
| +     }

 Why the blank line?

| +     dev = usb_get_intfdata(interface);
| +
| +     if (!dev) {
| +             retval = -ENODEV;
| +             goto exit_no_device;
| +     }

 Ditto.

| +             int iCount;
| +             iCount = atomic_read(&dev->sem.count);
| +             dbg(2,"%s : sem down failed, count %d", __FUNCTION__, iCount);

 Are you sure you need this?

| +/**
| + * adu_release
| + */
| +static int adu_release (struct inode *inode, struct file *file)
| +{
| +     struct adu_device *dev = NULL;
| +     int retval = 0;
| +
| +     dbg(2," %s : enter", __FUNCTION__);
| +     
| +     if (file == NULL) {
| +             dbg(1," %s : file is NULL", __FUNCTION__);
| +             retval = -ENODEV;
| +             goto exit;
| +     }

'if (!file)' is preferred.

| +     if (dev->open_count <= 0) {
| +             dbg(1," %s : device not opened", __FUNCTION__);
| +             retval = -ENODEV;
| +             goto exit;
| +     }

 This is an error, you should print it with err() IMO.

 Also, how could 'dev->open_count' become negative? Maybe you should
WARN_ON() here.

| +/**
| + * adu_abort_transfers
| + *      aborts transfers and frees associated data structures
| + */
| +static void adu_abort_transfers (struct adu_device *dev)
| +{
| +     dbg(2," %s : enter", __FUNCTION__);
| +
| +     if (dev == NULL) {
| +             dbg(1," %s : dev is null", __FUNCTION__);
| +             goto exit;
| +     }
| +     
| +     if (dev->udev == NULL) {
| +             dbg(1," %s : udev is null", __FUNCTION__);
| +             goto exit;
| +     }
| +     
| +     dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
| +     if (dev->udev->state == USB_STATE_NOTATTACHED) {
| +             dbg(1," %s : udev is not attached", __FUNCTION__);
| +             goto exit;
| +     }
| +
| +     /* shutdown transfer */
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
| +     if (dev->interrupt_in_urb != NULL) {
| +             usb_unlink_urb (dev->interrupt_in_urb);
| +     }
| +     if (dev->interrupt_out_urb != NULL) {
| +             usb_unlink_urb (dev->interrupt_out_urb);
| +     }
| +#else
| +     if (dev->interrupt_in_urb != NULL) {
| +             usb_kill_urb (dev->interrupt_in_urb);
| +     }
| +     if (dev->interrupt_out_urb != NULL) {
| +             usb_kill_urb (dev->interrupt_out_urb);
| +     }
| +#endif

 Hmm. Why the #if/#endif?
 
| +/**
| + * adu_read
| + */
| +static ssize_t adu_read (struct file *file, char *buffer, size_t count, 
loff_t *ppos)
| +{
| +     struct adu_device *dev;
| +     size_t bytes_read = 0;
| +     size_t bytes_to_read = count;
| +     int i;
| +     int retval = 0;
| +     int timeout = 0;
| +     int should_submit = 0;
| +     unsigned long flags;
| +     DECLARE_WAITQUEUE(wait, current);
| +
| +     dbg(2," %s : enter, count = %d, file=&%08x", __FUNCTION__, count, file);
| +
| +     dev = (struct adu_device *)file->private_data;
| +     dbg(2," %s : dev=%08x", __FUNCTION__, dev);
| +     /* lock this object */
| +     if (down_interruptible(&dev->sem))
| +             return -ERESTARTSYS;
| +
| +     /* verify that the device wasn't unplugged */
| +     if (dev->udev == NULL || dev->minor == 0) {
| +             retval = -ENODEV;
| +             err("No device or device unplugged %d", retval);
| +             goto exit;
| +     }
| +     
| +     /* verify that some data was requested */
| +     if (count == 0) {
| +             dbg(1," %s : read request of 0 bytes", __FUNCTION__);
| +             goto exit;
| +     }
| +
| +     timeout = COMMAND_TIMEOUT;
| +     dbg(2," %s : about to start looping", __FUNCTION__);
| +     while (bytes_to_read) {
| +             int data_in_secondary = dev->secondary_tail - 
dev->secondary_head;
| +             dbg(2," %s : while, data_in_secondary=%d, status=%d", 
__FUNCTION__, data_in_secondary,
| +                     dev->interrupt_in_urb->status);
| +             if (data_in_secondary) { /* drain secondary buffer */
| +                     int amount = bytes_to_read < data_in_secondary ? 
bytes_to_read : data_in_secondary; 
| +                     i = copy_to_user (buffer, 
dev->read_buffer_secondary+dev->secondary_head, amount);
| +                     dev->secondary_head += (amount - i);
| +                     bytes_read += (amount - i);
| +                     bytes_to_read -= (amount - i);
| +                     if (i) {
| +                             retval = bytes_read ? bytes_read : -EFAULT;
| +                             goto exit;
| +                     }
| +             } else { /* we check the primary buffer */
| +                     spin_lock_irqsave (&dev->buflock, flags);
| +                     if (dev->read_buffer_length) { /* we secure access to 
the primary */
| +                             char *tmp;
| +                             dbg(2," %s : swap, read_buffer_length = %d", 
__FUNCTION__, dev->read_buffer_length);
| +                             tmp = dev->read_buffer_secondary;
| +                             dev->read_buffer_secondary = 
dev->read_buffer_primary;
| +                             dev->read_buffer_primary = tmp;
| +                             dev->secondary_head = 0;
| +                             dev->secondary_tail = dev->read_buffer_length;
| +                             dev->read_buffer_length = 0;
| +                             spin_unlock_irqrestore (&dev->buflock, flags);
| +                             should_submit = 1; /* we have a free buffer so 
use it */
| +                     } else { /* even the primary was empty - we may need to 
do IO */
| +                             if (dev->interrupt_in_urb->status == 
-EINPROGRESS) { /*somebody is doing IO*/
| +                                     spin_unlock_irqrestore (&dev->buflock, 
flags);
| +                                     dbg(2," %s : submitted already", 
__FUNCTION__); 
| +                             } else { /* we must initiate input */
| +                                     dbg(2," %s : initiate input", 
__FUNCTION__); 
| +                                     dev->read_urb_finished = 0;
| +                                     
| +                                     usb_fill_int_urb 
(dev->interrupt_in_urb,dev->udev,
| +                                             usb_rcvintpipe(dev->udev, 
dev->interrupt_in_endpoint->bEndpointAddress),
| +                                             dev->interrupt_in_buffer,
| +                                             
dev->interrupt_in_endpoint->wMaxPacketSize,
| +                                             adu_interrupt_in_callback,
| +                                             dev,
| +                                             
dev->interrupt_in_endpoint->bInterval);
| +                                     retval = 
usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
| +                                     if (!retval) {
| +                                             spin_unlock_irqrestore 
(&dev->buflock, flags);
| +                                             dbg(2," %s : submitted OK", 
__FUNCTION__); 
| +                                     } else {
| +                                             if (retval == -ENOMEM) {
| +                                                     retval = bytes_read ? 
bytes_read : -ENOMEM;
| +                                             }
| +                                             spin_unlock_irqrestore 
(&dev->buflock, flags);
| +                                             dbg(2," %s : submit failed", 
__FUNCTION__); 
| +                                             goto exit;
| +                                     }
| +                             }
| +
| +                             /* we wait for I/O to complete */
| +                             set_current_state(TASK_INTERRUPTIBLE);
| +                             add_wait_queue(&dev->read_wait, &wait);
| +                             if (!dev->read_urb_finished) {
| +                                     timeout = 
schedule_timeout(COMMAND_TIMEOUT);
| +                             }
| +                             else
| +                                     set_current_state(TASK_RUNNING);
| +                             remove_wait_queue(&dev->read_wait, &wait);
| +                             
| +                             if (timeout <= 0) {
| +                                     dbg(2," %s : timeout", __FUNCTION__); 
| +                                     retval = bytes_read ? bytes_read : 
-ETIMEDOUT;
| +                                     goto exit;
| +                             }
| +
| +                             if (signal_pending(current)) {
| +                                     dbg(2," %s : signal pending", 
__FUNCTION__); 
| +                                     retval = bytes_read ? bytes_read : 
-EINTR;
| +                                     goto exit;
| +                             }
| +                     }
| +             }
| +     }
| +
| +     retval = bytes_read;
| +     /* if the primary buffer is empty then use it */
| +     if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
| +             usb_fill_int_urb (dev->interrupt_in_urb,dev->udev,
| +                             usb_rcvintpipe(dev->udev, 
dev->interrupt_in_endpoint->bEndpointAddress),
| +                             dev->interrupt_in_buffer,
| +                             dev->interrupt_in_endpoint->wMaxPacketSize,
| +                             adu_interrupt_in_callback,
| +                             dev,
| +                             dev->interrupt_in_endpoint->bInterval);
| +             /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
| +             dev->read_urb_finished = 0;
| +             usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
| +                     /* we ignore failure */
| +     }
| +
| + exit:
| +     /* unlock the device */
| +     up (&dev->sem);
| +
| +     dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
| +     return retval;
| +} /* end adu_read */

 At first, this function looks pretty big, and some 'if' bodies goes too
deep. You might consider breaking it in small pieces and/or review its
logic.

| +static int adu_ioctl (struct inode *inode, struct file *file, unsigned int 
cmd, unsigned long arg)
| +{
| +     int retval =  -ENOTTY;  /* default: we don't understand ioctl */
| +
| +     return retval;
| +} /* end adu_ioctl */

 Return -ENOIOCTLCMD please.

 Hmmm can't you omit the ioctl()?

| +/**
| + * adu_probe
| + *
| + * Called by the usb core when a new device is connected that it thinks
| + * this driver might be interested in.
| + */
| +static int adu_probe (struct usb_interface *interface, const struct 
usb_device_id *id)
| +{
| +     struct usb_device *udev = interface_to_usbdev(interface);
| +     struct adu_device *dev = NULL;
| +     struct usb_host_interface *iface_desc;
| +     struct usb_endpoint_descriptor *endpoint;
| +     int i;
| +     int iSize;
| +     int retval = -ENOMEM;
| +
| +     dbg(2," %s : enter", __FUNCTION__);
| +
| +     if (udev == NULL) {
| +             info ("udev is NULL.");
| +             retval = -ENODEV;
| +             goto exit;
| +     }
| +
| +     iSize = sizeof(device_table) / sizeof(device_table[0]);
| +     for (i = 0; i < iSize; i++) {
| +             if ((udev->descriptor.idVendor == device_table[i].idVendor) &&
| +             (udev->descriptor.idProduct == device_table[i].idProduct))
| +             break;
| +     }
| +     if (i >= iSize) return -ENODEV;
| +     
| +     /* allocate memory for our device state and intialize it */
| +
| +     dev = kmalloc (sizeof(struct adu_device), GFP_KERNEL);
| +
| +     if (dev == NULL) {
| +             err ("Out of memory");
| +             goto exit;
| +     }
| +
| +     init_MUTEX (&dev->sem);
| +     spin_lock_init (&dev->buflock);
| +
| +     dev->udev = udev;
| +     dev->open_count = 0;
| +
| +     dev->read_buffer_primary = NULL;
| +     dev->read_buffer_secondary = NULL;
| +     dev->read_buffer_length = 0;
| +     dev->secondary_head = 0;
| +     dev->secondary_tail = 0;
| +
| +     init_waitqueue_head (&dev->read_wait);
| +     init_waitqueue_head (&dev->write_wait);
| +
| +     dev->interrupt_in_buffer = NULL;
| +     dev->interrupt_in_endpoint = NULL;
| +     dev->interrupt_in_urb = NULL;
| +     dev->read_urb_finished = 0;
| +
| +     dev->interrupt_out_buffer = NULL;
| +     dev->interrupt_out_endpoint = NULL;
| +     dev->interrupt_out_urb = NULL;

 If you use kzalloc() here, you can drop most of this init code.

| +     // JJH - debug code prime the buffer
| +     memset(dev->read_buffer_primary, 'a', 
dev->interrupt_in_endpoint->wMaxPacketSize);
| +     
memset(dev->read_buffer_primary+dev->interrupt_in_endpoint->wMaxPacketSize, 'b',
| +                     dev->interrupt_in_endpoint->wMaxPacketSize);
| +     
memset(dev->read_buffer_primary+2*dev->interrupt_in_endpoint->wMaxPacketSize, 
'c', 
| +                     dev->interrupt_in_endpoint->wMaxPacketSize);
| +     
memset(dev->read_buffer_primary+3*dev->interrupt_in_endpoint->wMaxPacketSize, 
'd', 
| +                     dev->interrupt_in_endpoint->wMaxPacketSize);
| +                     
| +     dev->read_buffer_secondary = kmalloc 
((4*dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL);
| +     if (!dev->read_buffer_secondary) {
| +             err("Couldn't allocate read_buffer_secondary");
| +             goto error;
| +     }

 We do this already, don't we?

-- 
Luiz Fernando N. Capitulino

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to