From: Greg KH To: torvalds@transmeta.com Cc: linux-usb-devel@lists.sourceforge.net Subject: [PATCH 07 of 16] USB iforce driver change Hi, Here's a patch against 2.5.3-pre3 for the USB iforce driver that converts it to dynamically allocate its urbs. thanks, greg k-h diff -Nru a/drivers/char/joystick/iforce.c b/drivers/char/joystick/iforce.c --- a/drivers/char/joystick/iforce.c Tue Jan 22 12:54:25 2002 +++ b/drivers/char/joystick/iforce.c Tue Jan 22 12:54:25 2002 @@ -133,7 +133,7 @@ #endif #ifdef IFORCE_USB struct usb_device *usbdev; /* USB transfer */ - struct urb irq, out, ctrl; + struct urb *irq, *out, *ctrl; struct usb_ctrlrequest dr; #endif /* Force Feedback */ @@ -196,28 +196,28 @@ DECLARE_WAITQUEUE(wait, current); int timeout = HZ; /* 1 second */ - memcpy(iforce->out.transfer_buffer + 1, data, LO(cmd)); - ((char*)iforce->out.transfer_buffer)[0] = HI(cmd); - iforce->out.transfer_buffer_length = LO(cmd) + 2; - iforce->out.dev = iforce->usbdev; + memcpy(iforce->out->transfer_buffer + 1, data, LO(cmd)); + ((char*)iforce->out->transfer_buffer)[0] = HI(cmd); + iforce->out->transfer_buffer_length = LO(cmd) + 2; + iforce->out->dev = iforce->usbdev; set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&iforce->wait, &wait); - if (usb_submit_urb(&iforce->out)) { + if (usb_submit_urb(iforce->out)) { set_current_state(TASK_RUNNING); remove_wait_queue(&iforce->wait, &wait); return; } - while (timeout && iforce->out.status == -EINPROGRESS) + while (timeout && iforce->out->status == -EINPROGRESS) timeout = schedule_timeout(timeout); set_current_state(TASK_RUNNING); remove_wait_queue(&iforce->wait, &wait); if (!timeout) - usb_unlink_urb(&iforce->out); + usb_unlink_urb(iforce->out); return; } @@ -284,25 +284,25 @@ case IFORCE_USB: iforce->dr.bRequest = packet[0]; - iforce->ctrl.dev = iforce->usbdev; + iforce->ctrl->dev = iforce->usbdev; set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&iforce->wait, &wait); - if (usb_submit_urb(&iforce->ctrl)) { + if (usb_submit_urb(iforce->ctrl)) { set_current_state(TASK_RUNNING); remove_wait_queue(&iforce->wait, &wait); return -1; } - while (timeout && iforce->ctrl.status == -EINPROGRESS) + while (timeout && iforce->ctrl->status == -EINPROGRESS) timeout = schedule_timeout(timeout); set_current_state(TASK_RUNNING); remove_wait_queue(&iforce->wait, &wait); if (!timeout) { - usb_unlink_urb(&iforce->ctrl); + usb_unlink_urb(iforce->ctrl); return -1; } @@ -344,8 +344,8 @@ case IFORCE_USB: if (iforce->open++) break; - iforce->irq.dev = iforce->usbdev; - if (usb_submit_urb(&iforce->irq)) + iforce->irq->dev = iforce->usbdev; + if (usb_submit_urb(iforce->irq)) return -EIO; break; #endif @@ -361,7 +361,7 @@ #ifdef IFORCE_USB case IFORCE_USB: if (!--iforce->open) - usb_unlink_urb(&iforce->irq); + usb_unlink_urb(iforce->irq); break; #endif } @@ -1024,6 +1024,25 @@ if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL; memset(iforce, 0, sizeof(struct iforce)); + iforce->irq = usb_alloc_urb(0); + if (!iforce->irq) { + kfree(iforce); + return NULL; + } + iforce->out = usb_alloc_urb(0); + if (!iforce->out) { + usb_free_urb(iforce->irq); + kfree(iforce); + return NULL; + } + iforce->ctrl = usb_alloc_urb(0); + if (!iforce->ctrl) { + usb_free_urb(iforce->out); + usb_free_urb(iforce->irq); + kfree(iforce); + return NULL; + } + iforce->bus = IFORCE_USB; iforce->usbdev = dev; @@ -1031,16 +1050,19 @@ iforce->dr.wIndex = 0; iforce->dr.wLength = 16; - FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), + FILL_INT_URB(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval); - FILL_BULK_URB(&iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress), + FILL_BULK_URB(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress), iforce + 1, 32, iforce_usb_out, iforce); - FILL_CONTROL_URB(&iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), + FILL_CONTROL_URB(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), (void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce); if (iforce_init_device(iforce)) { + usb_free_urb(iforce->ctrl); + usb_free_urb(iforce->out); + usb_free_urb(iforce->irq); kfree(iforce); return NULL; } @@ -1055,8 +1077,11 @@ static void iforce_usb_disconnect(struct usb_device *dev, void *ptr) { struct iforce *iforce = ptr; - usb_unlink_urb(&iforce->irq); + usb_unlink_urb(iforce->irq); input_unregister_device(&iforce->dev); + usb_free_urb(iforce->ctrl); + usb_free_urb(iforce->out); + usb_free_urb(iforce->irq); kfree(iforce); }