> + * Called when opening the input device. This will submit the URB to > + * the usb system so we start getting reports > + */ > +static int gtco_input_open(struct input_dev *inputdev) > +{ > + struct gtco *device; > + device = inputdev->private; > + > + /* Prevent us from submitting the one Urb more than once */ > + if (device->openCount++) > + return 0; > + > + device->urbinfo->dev = device->usbdev; > + if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) {
This is a race condition in the error case. A second open may suceed while the first open is sleeping allocating memory for URB submission. If submitting the first open's URB then fails, no URB is submitted. > + device->openCount--; > + return -EIO; > + } > + return 0; > +} > + > +/** > + Called when closing the input device. This will unlink the URB > +*/ > +static void gtco_input_close(struct input_dev *inputdev) > +{ > + struct gtco *device = inputdev->private; > + > + /* Decrement the open count and release the urb */ > + device->openCount--; > + if (device->openCount==0){ > + usb_unlink_urb(device->urbinfo); Please use usb_kill_urb() [..] > + /* All reports have X and Y coords in the same place */ > + val = le16_to_cpu(*(__le16 *) &(device->buffer[1])); unaligned access. Please use get_unaligned(). > + input_report_abs(inputdev, ABS_X, val); > + > + val = le16_to_cpu(*(__le16 *) &(device->buffer[3])); unaligned > + buttonbyte = (device->buffer[5])>>1; > + }else{ > + > + val = le16_to_cpu(*(__le16 *) > (&(device->buffer[1]))); unaligned > + input_report_abs(inputdev, ABS_X, val); > + > + val = le16_to_cpu(*(__le16 *) > (&(device->buffer[3]))); unaligned > + /* Allocate memory for device structure */ > + device = kzalloc(sizeof(struct gtco), GFP_KERNEL); > + if (device == NULL) { > + err("No more memory"); > + return -ENOMEM; > + } > + > + > + device->inputdevice = input_allocate_device(); > + if (!device->inputdevice){ > + kfree(device); > + err("No more memory"); > + return -ENOMEM; > + } Please gather all the deallocations at the end and use goto for errors. > + > + /* Get pointer to the input device */ > + inputdev = device->inputdevice; > + > + /* Save interface information */ > + device->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); > + > + > + /* Allocate some data for incoming reports */ > + device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE, > + GFP_ATOMIC, &(device->buf_dma)); GFP_KERNEL is sufficient. > +/* > + * This function is a standard USB function called when the USB device > + * is disconnected. We will get rid of the URV, de-register the input > + * device, and free up allocated memory > + */ > +static void gtco_disconnect(struct usb_interface *interface) > +{ > + > + /* Grab private device ptr */ > + struct gtco *device = usb_get_intfdata (interface); > + struct input_dev *inputdev; > + > + inputdev = device->inputdevice; > + > + /* Now reverse all the registration stuff */ > + if (device) { > + usb_unlink_urb(device->urbinfo); usb_kill_urb() HTH Oliver ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel