On Wed, Jan 04, 2012 at 10:56:20AM +0100, Oliver Neukum wrote: > Am Mittwoch, 4. Januar 2012, 10:41:03 schrieb Dmitry Torokhov: > > > > +static void synusb_irq(struct urb *urb) > > +{ > > + struct synusb *synusb = urb->context; > > + int error; > > + > > + /* Check our status in case we need to bail out early. */ > > + switch (urb->status) { > > + case 0: > > + usb_mark_last_busy(synusb->udev); > > + break; > > + > > + case -EOVERFLOW: > > + dev_err(&synusb->intf->dev, > > + "%s: OVERFLOW with data length %d, actual length is %d\n", > > + __func__, SYNUSB_RECV_SIZE, urb->actual_length); > > Do you really want to fall through here? Probably not. > > > + > > + /* Device went away so don't keep trying to read from it. */ > > + case -ECONNRESET: > > + case -ENOENT: > > + case -ESHUTDOWN: > > + return; > > + > > + default: > > + goto resubmit; > > + break; > > + } > > + > > + if (synusb->flags & SYNUSB_STICK) > > + synusb_report_stick(synusb); > > + else > > + synusb_report_touchpad(synusb); > > + > > +resubmit: > > + error = usb_submit_urb(urb, GFP_ATOMIC); > > + if (error && error != -EPERM) > > + dev_err(&synusb->intf->dev, > > + "%s - usb_submit_urb failed with result: %d", > > + __func__, error); > > +} > > + > > [..] > > +static int synusb_open(struct input_dev *dev) > > +{ > > + struct synusb *synusb = input_get_drvdata(dev); > > + int retval = 0; > > + > > + dev_err(&synusb->intf->dev, "%s\n", __func__); > > + > > + if (usb_autopm_get_interface(synusb->intf) < 0) > > + return -EIO; > > + > > + if (usb_submit_urb(synusb->urb, GFP_KERNEL)) { > > + dev_err(&synusb->intf->dev, > > + "%s - usb_submit_urb failed", __func__); > > + retval = -EIO; > > + goto out; > > + } > > + > > + synusb->intf->needs_remote_wakeup = 1; > > + > > +out: > > + usb_autopm_put_interface(synusb->intf); > > + dev_err(&synusb->intf->dev, "%s done: %d\n", __func__, retval); > > + return retval; > > +} > > + > > +static void synusb_close(struct input_dev *dev) > > +{ > > + struct synusb *synusb = input_get_drvdata(dev); > > + int autopm_error; > > + > > + autopm_error = usb_autopm_get_interface(synusb->intf); > > + > > + usb_kill_urb(synusb->urb); > > + synusb->intf->needs_remote_wakeup = 0; > > + > > + if (!autopm_error) > > + usb_autopm_put_interface(synusb->intf); > > +} > > + > > +static int synusb_probe(struct usb_interface *intf, > > + const struct usb_device_id *id) > > +{ > > + struct usb_device *udev = interface_to_usbdev(intf); > > + struct usb_endpoint_descriptor *ep; > > + struct synusb *synusb; > > + struct input_dev *input_dev; > > + unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber; > > + unsigned int altsetting = min(intf->num_altsetting, 1U); > > + int error; > > + > > + error = usb_set_interface(udev, intf_num, altsetting); > > + if (error) { > > + dev_err(&udev->dev, > > + "Can not set alternate setting to %i, error: %i", > > + altsetting, error); > > + return error; > > + } > > + > > + ep = synusb_get_in_endpoint(intf->cur_altsetting); > > + if (!ep) > > + return -ENODEV; > > + > > + synusb = kzalloc(sizeof(*synusb), GFP_KERNEL); > > + input_dev = input_allocate_device(); > > + if (!synusb || !input_dev) { > > + error = -ENOMEM; > > + goto err_free_mem; > > + } > > + > > + synusb->udev = udev; > > + synusb->intf = intf; > > + synusb->input = input_dev; > > + > > + synusb->flags = id->driver_info; > > + if (test_bit(SYNUSB_STICK, &synusb->flags) && > > + test_bit(SYNUSB_STICK, &synusb->flags)) { > > ??? Voodoo ??? Yeah, 2nd should be test_bit(SYNUSB_TOUCHPAD, ...) > > > + /* > > + * This is a combo device, we need to leave only proper > > + * capability, depending on the interface. > > + */ > > + clear_bit(intf_num == 1 ? SYNUSB_TOUCHPAD : SYNUSB_STICK, > > + &synusb->flags); > > + } > > + > > + synusb->urb = usb_alloc_urb(0, GFP_KERNEL); > > + if (!synusb->urb) { > > + error = -ENOMEM; > > + goto err_free_mem; > > + } > > + > > + synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL, > > + &synusb->urb->transfer_dma); > > + if (!synusb->data) { > > + error = -ENOMEM; > > + goto err_free_urb; > > + } > > + > > + usb_fill_int_urb(synusb->urb, udev, > > + usb_rcvintpipe(udev, ep->bEndpointAddress), > > + synusb->data, SYNUSB_RECV_SIZE, > > + synusb_irq, synusb, > > + ep->bInterval); > > + synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > > According to the comment in the original driver you must submit the URB. > Are you sure not doing so is save? Seems to work here... > > > + > > + if (udev->manufacturer) > > + strlcpy(synusb->name, udev->manufacturer, > > + sizeof(synusb->name)); > > + > > + if (udev->product) { > > + if (udev->manufacturer) > > + strlcat(synusb->name, " ", sizeof(synusb->name)); > > + strlcat(synusb->name, udev->product, sizeof(synusb->name)); > > + } > > + > > + if (!strlen(synusb->name)) > > + snprintf(synusb->name, sizeof(synusb->name), > > + "USB Synaptics Device %04x:%04x", > > + le16_to_cpu(udev->descriptor.idVendor), > > + le16_to_cpu(udev->descriptor.idProduct)); > > + > > + if (synusb->flags & SYNUSB_STICK) > > + strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); > > + > > + usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); > > + strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); > > + > > + input_dev->name = synusb->name; // synusb_get_name(synusb); > > + input_dev->phys = synusb->phys; > > + usb_to_input_id(udev, &input_dev->id); > > + input_dev->dev.parent = &synusb->intf->dev; > > + > > + input_dev->open = synusb_open; > > + input_dev->close = synusb_close; > > + > > + input_set_drvdata(input_dev, synusb); > > + > > + __set_bit(EV_ABS, input_dev->evbit); > > + __set_bit(EV_KEY, input_dev->evbit); > > + > > + if (synusb->flags & SYNUSB_STICK) { > > + __set_bit(EV_REL, input_dev->evbit); > > + __set_bit(REL_X, input_dev->relbit); > > + __set_bit(REL_Y, input_dev->relbit); > > + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); > > + } else { > > + input_set_abs_params(input_dev, ABS_X, xmin, xmax, 0, 0); > > + input_set_abs_params(input_dev, ABS_Y, ymin, ymax, 0, 0); > > + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); > > + input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); > > + __set_bit(BTN_TOUCH, input_dev->keybit); > > + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); > > + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); > > + __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); > > + } > > + > > + __set_bit(BTN_LEFT, input_dev->keybit); > > + __set_bit(BTN_RIGHT, input_dev->keybit); > > + __set_bit(BTN_MIDDLE, input_dev->keybit); > > + if (synusb->flags & SYNUSB_AUXDISPLAY) > > + __set_bit(BTN_MISC, input_dev->keybit); > > + > > + error = input_register_device(input_dev); > > + if (error) { > > + dev_err(&udev->dev, "Failed to register input device, error %d\n", > > + error); > > + goto err_free_dma; > > + } > > + > > + usb_set_intfdata(intf, synusb); > > + return 0; > > + > > +err_free_dma: > > + usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, > > + synusb->urb->transfer_dma); > > +err_free_urb: > > + usb_free_urb(synusb->urb); > > +err_free_mem: > > + input_free_device(input_dev); > > + kfree(synusb); > > + > > + return error; > > +} > > + > > [..] > > +static struct usb_driver synusb_driver = { > > + .name = "synaptics_usb", > > + .probe = synusb_probe, > > + .disconnect = synusb_disconnect, > > + .id_table = synusb_idtable, > > + .suspend = synusb_suspend, > > + .resume = synusb_resume, > > + .reset_resume = synusb_reset_resume, > > You've killed the support for reset. That is not cool. OK. Thanks. -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html