in touchscreen/usbtouchscreen.c [1643:1819]
static int usbtouch_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usbtouch_usb *usbtouch;
struct input_dev *input_dev;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
struct usbtouch_device_info *type;
int err = -ENOMEM;
/* some devices are ignored */
if (id->driver_info == DEVTYPE_IGNORE)
return -ENODEV;
endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
if (!endpoint)
return -ENXIO;
usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
input_dev = input_allocate_device();
if (!usbtouch || !input_dev)
goto out_free;
mutex_init(&usbtouch->pm_mutex);
type = &usbtouch_dev_info[id->driver_info];
usbtouch->type = type;
if (!type->process_pkt)
type->process_pkt = usbtouch_process_pkt;
usbtouch->data_size = type->rept_size;
if (type->get_pkt_len) {
/*
* When dealing with variable-length packets we should
* not request more than wMaxPacketSize bytes at once
* as we do not know if there is more data coming or
* we filled exactly wMaxPacketSize bytes and there is
* nothing else.
*/
usbtouch->data_size = min(usbtouch->data_size,
usb_endpoint_maxp(endpoint));
}
usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
GFP_KERNEL, &usbtouch->data_dma);
if (!usbtouch->data)
goto out_free;
if (type->get_pkt_len) {
usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
if (!usbtouch->buffer)
goto out_free_buffers;
}
usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!usbtouch->irq) {
dev_dbg(&intf->dev,
"%s - usb_alloc_urb failed: usbtouch->irq\n", __func__);
goto out_free_buffers;
}
usbtouch->interface = intf;
usbtouch->input = input_dev;
if (udev->manufacturer)
strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
if (udev->product) {
if (udev->manufacturer)
strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
}
if (!strlen(usbtouch->name))
snprintf(usbtouch->name, sizeof(usbtouch->name),
"USB Touchscreen %04x:%04x",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
input_dev->name = usbtouch->name;
input_dev->phys = usbtouch->phys;
usb_to_input_id(udev, &input_dev->id);
input_dev->dev.parent = &intf->dev;
input_set_drvdata(input_dev, usbtouch);
input_dev->open = usbtouch_open;
input_dev->close = usbtouch_close;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
if (type->max_press)
input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
type->max_press, 0, 0);
if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
usb_fill_int_urb(usbtouch->irq, udev,
usb_rcvintpipe(udev, endpoint->bEndpointAddress),
usbtouch->data, usbtouch->data_size,
usbtouch_irq, usbtouch, endpoint->bInterval);
else
usb_fill_bulk_urb(usbtouch->irq, udev,
usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
usbtouch->data, usbtouch->data_size,
usbtouch_irq, usbtouch);
usbtouch->irq->dev = udev;
usbtouch->irq->transfer_dma = usbtouch->data_dma;
usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* device specific allocations */
if (type->alloc) {
err = type->alloc(usbtouch);
if (err) {
dev_dbg(&intf->dev,
"%s - type->alloc() failed, err: %d\n",
__func__, err);
goto out_free_urb;
}
}
/* device specific initialisation*/
if (type->init) {
err = type->init(usbtouch);
if (err) {
dev_dbg(&intf->dev,
"%s - type->init() failed, err: %d\n",
__func__, err);
goto out_do_exit;
}
}
err = input_register_device(usbtouch->input);
if (err) {
dev_dbg(&intf->dev,
"%s - input_register_device failed, err: %d\n",
__func__, err);
goto out_do_exit;
}
usb_set_intfdata(intf, usbtouch);
if (usbtouch->type->irq_always) {
/* this can't fail */
usb_autopm_get_interface(intf);
err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
if (err) {
usb_autopm_put_interface(intf);
dev_err(&intf->dev,
"%s - usb_submit_urb failed with result: %d\n",
__func__, err);
goto out_unregister_input;
}
}
return 0;
out_unregister_input:
input_unregister_device(input_dev);
input_dev = NULL;
out_do_exit:
if (type->exit)
type->exit(usbtouch);
out_free_urb:
usb_free_urb(usbtouch->irq);
out_free_buffers:
usbtouch_free_buffers(udev, usbtouch);
out_free:
input_free_device(input_dev);
kfree(usbtouch);
return err;
}