18491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff/* 28491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * USB Synaptics device driver 38491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 48491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk) 58491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Copyright (c) 2003 Ron Lee (ron@debian.org) 68491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * cPad driver for kernel 2.4 78491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 88491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de) 98491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Copyright (c) 2004 Ron Lee (ron@debian.org) 108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * rewritten for kernel 2.6 118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * cPad display character device part is not included. It can be found at 138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * http://jan-steinhoff.de/linux/synaptics-usb.html 148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Bases on: usb_skeleton.c v2.2 by Greg Kroah-Hartman 168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik 178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * drivers/input/mouse/synaptics.c by Peter Osterlund 188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * This program is free software; you can redistribute it and/or modify it 208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * under the terms of the GNU General Public License as published by the Free 218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Software Foundation; either version 2 of the License, or (at your option) 228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * any later version. 238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Trademarks are the property of their respective owners. 258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */ 268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff/* 288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * There are three different types of Synaptics USB devices: Touchpads, 298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * touchsticks (or trackpoints), and touchscreens. Touchpads are well supported 308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * by this driver, touchstick support has not been tested much yet, and 318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * touchscreens have not been tested at all. 328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * 338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Up to three alternate settings are possible: 348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * setting 0: one int endpoint for relative movement (used by usbhid.ko) 358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * setting 1: one int endpoint for absolute finger position 368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * setting 2 (cPad only): one int endpoint for absolute finger position and 378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * two bulk endpoints for the display (in/out) 388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * This driver uses setting 1. 398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */ 408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/kernel.h> 428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/init.h> 438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/slab.h> 448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/module.h> 458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/moduleparam.h> 468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/usb.h> 478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/input.h> 488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/usb/input.h> 498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_VENDOR_ID_SYNAPTICS 0x06cb 518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 /* Synaptics USB TouchPad */ 528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 /* Integrated USB TouchPad */ 538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 /* Synaptics cPad */ 548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 /* Synaptics TouchScreen */ 558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 /* Synaptics USB Styk */ 568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 /* Synaptics USB WheelPad */ 578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 /* Composite USB TouchPad */ 588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 /* Wireless TouchPad */ 598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 /* DisplayPad */ 608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_TOUCHPAD (1 << 0) 628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_STICK (1 << 1) 638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_TOUCHSCREEN (1 << 2) 648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_AUXDISPLAY (1 << 3) /* For cPad */ 658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_COMBO (1 << 4) /* Composite device (TP + stick) */ 668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_IO_ALWAYS (1 << 5) 678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_SYNAPTICS(prod, kind) \ 698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, \ 708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff USB_DEVICE_ID_SYNAPTICS_##prod), \ 718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .driver_info = (kind), 728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_RECV_SIZE 8 748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define XMIN_NOMINAL 1472 768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define XMAX_NOMINAL 5472 778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define YMIN_NOMINAL 1408 788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define YMAX_NOMINAL 4448 798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstruct synusb { 818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_device *udev; 828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_interface *intf; 838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct urb *urb; 848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned char *data; 858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* input device related data structures */ 878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input; 888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff char name[128]; 898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff char phys[64]; 908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* characteristics of the device */ 928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned long flags; 938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}; 948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_buttons(struct synusb *synusb) 968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04); 1008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01); 1018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02); 1028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 1038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_stick(struct synusb *synusb) 1058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 1068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 1078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int x, y; 1088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int pressure; 1098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff pressure = synusb->data[6]; 1118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7; 1128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7; 1138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (pressure > 0) { 1158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_rel(input_dev, REL_X, x); 1168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_rel(input_dev, REL_Y, -y); 1178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 1188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_abs(input_dev, ABS_PRESSURE, pressure); 1208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_report_buttons(synusb); 1228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_sync(input_dev); 1248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 1258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_touchpad(struct synusb *synusb) 1278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 1288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 1298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int num_fingers, tool_width; 1308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int x, y; 1318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int pressure, w; 1328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff pressure = synusb->data[6]; 1348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff x = be16_to_cpup((__be16 *)&synusb->data[2]); 1358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff y = be16_to_cpup((__be16 *)&synusb->data[4]); 1368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff w = synusb->data[0] & 0x0f; 1378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (pressure > 0) { 1398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff num_fingers = 1; 1408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff tool_width = 5; 1418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff switch (w) { 1428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case 0 ... 1: 1438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff num_fingers = 2 + w; 1448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff break; 1458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case 2: /* pen, pretend its a finger */ 1478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff break; 1488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case 4 ... 15: 1508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff tool_width = w; 1518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff break; 1528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 1538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } else { 1548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff num_fingers = 0; 1558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff tool_width = 0; 1568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 1578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* 1598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Post events 1608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * BTN_TOUCH has to be first as mousedev relies on it when doing 1618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * absolute -> relative conversion 1628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */ 1638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (pressure > 30) 1658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_TOUCH, 1); 1668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (pressure < 25) 1678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_TOUCH, 0); 1688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (num_fingers > 0) { 1708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_abs(input_dev, ABS_X, x); 1718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_abs(input_dev, ABS_Y, 1728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff YMAX_NOMINAL + YMIN_NOMINAL - y); 1738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 1748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_abs(input_dev, ABS_PRESSURE, pressure); 1768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width); 1778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1); 1798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); 1808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); 1818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_report_buttons(synusb); 1838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_AUXDISPLAY) 1848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08); 1858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_sync(input_dev); 1878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 1888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_irq(struct urb *urb) 1908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 1918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = urb->context; 1928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int error; 1938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 1948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* Check our status in case we need to bail out early. */ 1958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff switch (urb->status) { 1968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case 0: 1978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_mark_last_busy(synusb->udev); 1988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff break; 1998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* Device went away so don't keep trying to read from it. */ 2018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case -ECONNRESET: 2028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case -ENOENT: 2038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff case -ESHUTDOWN: 2048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return; 2058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff default: 2078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto resubmit; 2088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff break; 2098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 2108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_STICK) 2128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_report_stick(synusb); 2138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff else 2148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_report_touchpad(synusb); 2158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffresubmit: 2178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = usb_submit_urb(urb, GFP_ATOMIC); 2188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (error && error != -EPERM) 2198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff dev_err(&synusb->intf->dev, 2208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "%s - usb_submit_urb failed with result: %d", 2218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __func__, error); 2228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 2238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_endpoint_descriptor * 2258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffsynusb_get_in_endpoint(struct usb_host_interface *iface) 2268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 2278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_endpoint_descriptor *endpoint; 2298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int i; 2308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff for (i = 0; i < iface->desc.bNumEndpoints; ++i) { 2328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff endpoint = &iface->endpoint[i].desc; 2338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (usb_endpoint_is_int_in(endpoint)) { 2358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* we found our interrupt in endpoint */ 2368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return endpoint; 2378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 2388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 2398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return NULL; 2418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 2428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_open(struct input_dev *dev) 2448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 2458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = input_get_drvdata(dev); 2468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int retval; 2478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff retval = usb_autopm_get_interface(synusb->intf); 2498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (retval) { 2508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff dev_err(&synusb->intf->dev, 2518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "%s - usb_autopm_get_interface failed, error: %d\n", 2528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __func__, retval); 2538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return retval; 2548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 2558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff retval = usb_submit_urb(synusb->urb, GFP_KERNEL); 2578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (retval) { 2588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff dev_err(&synusb->intf->dev, 2598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "%s - usb_submit_urb failed, error: %d\n", 2608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __func__, retval); 2618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff retval = -EIO; 2628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto out; 2638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 2648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->intf->needs_remote_wakeup = 1; 2668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffout: 2688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_autopm_put_interface(synusb->intf); 2698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return retval; 2708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 2718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_close(struct input_dev *dev) 2738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 2748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = input_get_drvdata(dev); 2758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int autopm_error; 2768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff autopm_error = usb_autopm_get_interface(synusb->intf); 2788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_kill_urb(synusb->urb); 2808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->intf->needs_remote_wakeup = 0; 2818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!autopm_error) 2838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_autopm_put_interface(synusb->intf); 2848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 2858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_probe(struct usb_interface *intf, 2878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff const struct usb_device_id *id) 2888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 2898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_device *udev = interface_to_usbdev(intf); 2908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_endpoint_descriptor *ep; 2918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb; 2928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev; 2938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber; 2948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff unsigned int altsetting = min(intf->num_altsetting, 1U); 2958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int error; 2968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 2978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = usb_set_interface(udev, intf_num, altsetting); 2988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (error) { 2998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff dev_err(&udev->dev, 3008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "Can not set alternate setting to %i, error: %i", 3018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff altsetting, error); 3028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return error; 3038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff ep = synusb_get_in_endpoint(intf->cur_altsetting); 3068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!ep) 3078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return -ENODEV; 3088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb = kzalloc(sizeof(*synusb), GFP_KERNEL); 3108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev = input_allocate_device(); 3118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!synusb || !input_dev) { 3128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = -ENOMEM; 3138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto err_free_mem; 3148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->udev = udev; 3178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->intf = intf; 3188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->input = input_dev; 3198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->flags = id->driver_info; 3218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_COMBO) { 3228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff /* 3238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * This is a combo device, we need to set proper 3248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * capability, depending on the interface. 3258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */ 3268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->flags |= intf_num == 1 ? 3278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff SYNUSB_STICK : SYNUSB_TOUCHPAD; 3288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->urb = usb_alloc_urb(0, GFP_KERNEL); 3318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!synusb->urb) { 3328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = -ENOMEM; 3338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto err_free_mem; 3348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL, 3378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff &synusb->urb->transfer_dma); 3388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!synusb->data) { 3398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = -ENOMEM; 3408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto err_free_urb; 3418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_fill_int_urb(synusb->urb, udev, 3448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_rcvintpipe(udev, ep->bEndpointAddress), 3458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->data, SYNUSB_RECV_SIZE, 3468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_irq, synusb, 3478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff ep->bInterval); 3488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 3498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (udev->manufacturer) 3518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff strlcpy(synusb->name, udev->manufacturer, 3528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff sizeof(synusb->name)); 3538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (udev->product) { 3558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (udev->manufacturer) 3568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff strlcat(synusb->name, " ", sizeof(synusb->name)); 3578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff strlcat(synusb->name, udev->product, sizeof(synusb->name)); 3588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!strlen(synusb->name)) 3618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff snprintf(synusb->name, sizeof(synusb->name), 3628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "USB Synaptics Device %04x:%04x", 3638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff le16_to_cpu(udev->descriptor.idVendor), 3648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff le16_to_cpu(udev->descriptor.idProduct)); 3658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_STICK) 3678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); 3688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); 3708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); 3718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev->name = synusb->name; 3738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev->phys = synusb->phys; 3748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_to_input_id(udev, &input_dev->id); 3758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev->dev.parent = &synusb->intf->dev; 3768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (!(synusb->flags & SYNUSB_IO_ALWAYS)) { 3788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev->open = synusb_open; 3798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_dev->close = synusb_close; 3808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 3818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_drvdata(input_dev, synusb); 3838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(EV_ABS, input_dev->evbit); 3858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(EV_KEY, input_dev->evbit); 3868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 3878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_STICK) { 3888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(EV_REL, input_dev->evbit); 3898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(REL_X, input_dev->relbit); 3908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(REL_Y, input_dev->relbit); 3918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); 3928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } else { 3938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_abs_params(input_dev, ABS_X, 3948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); 3958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_abs_params(input_dev, ABS_Y, 3968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); 3978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); 3988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); 3998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_TOUCH, input_dev->keybit); 4008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_TOOL_FINGER, input_dev->keybit); 4018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); 4028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); 4038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 4048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_LEFT, input_dev->keybit); 4068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_RIGHT, input_dev->keybit); 4078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff __set_bit(BTN_MIDDLE, input_dev->keybit); 4088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_set_intfdata(intf, synusb); 4108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_IO_ALWAYS) { 4128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = synusb_open(input_dev); 4138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (error) 4148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto err_free_dma; 4158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 4168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error = input_register_device(input_dev); 4188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (error) { 4198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff dev_err(&udev->dev, 4208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "Failed to register input device, error %d\n", 4218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff error); 4228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff goto err_stop_io; 4238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 4248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return 0; 4268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_stop_io: 4288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_IO_ALWAYS) 4298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_close(synusb->input); 4308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_dma: 4318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, 4328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->urb->transfer_dma); 4338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_urb: 4348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_free_urb(synusb->urb); 4358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_mem: 4368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_free_device(input_dev); 4378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff kfree(synusb); 4388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_set_intfdata(intf, NULL); 4398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return error; 4418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 4428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_disconnect(struct usb_interface *intf) 4448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 4458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = usb_get_intfdata(intf); 4468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct usb_device *udev = interface_to_usbdev(intf); 4478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if (synusb->flags & SYNUSB_IO_ALWAYS) 4498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb_close(synusb->input); 4508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff input_unregister_device(synusb->input); 4528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, 4548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff synusb->urb->transfer_dma); 4558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_free_urb(synusb->urb); 4568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff kfree(synusb); 4578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_set_intfdata(intf, NULL); 4598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 4608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_suspend(struct usb_interface *intf, pm_message_t message) 4628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 4638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = usb_get_intfdata(intf); 4648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 4658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_lock(&input_dev->mutex); 4678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_kill_urb(synusb->urb); 4688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_unlock(&input_dev->mutex); 4698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return 0; 4718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 4728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_resume(struct usb_interface *intf) 4748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 4758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = usb_get_intfdata(intf); 4768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 4778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int retval = 0; 4788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_lock(&input_dev->mutex); 4808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && 4828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { 4838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff retval = -EIO; 4848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 4858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_unlock(&input_dev->mutex); 4878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return retval; 4898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 4908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_pre_reset(struct usb_interface *intf) 4928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 4938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = usb_get_intfdata(intf); 4948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 4958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_lock(&input_dev->mutex); 4978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_kill_urb(synusb->urb); 4988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 4998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return 0; 5008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 5018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_post_reset(struct usb_interface *intf) 5038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 5048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct synusb *synusb = usb_get_intfdata(intf); 5058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff struct input_dev *input_dev = synusb->input; 5068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff int retval = 0; 5078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && 5098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { 5108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff retval = -EIO; 5118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff } 5128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff mutex_unlock(&input_dev->mutex); 5148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return retval; 5168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 5178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_reset_resume(struct usb_interface *intf) 5198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{ 5208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff return synusb_resume(intf); 5218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff} 5228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_device_id synusb_idtable[] = { 5248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) }, 5258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) }, 5268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(CPAD, 5278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) }, 5288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) }, 5298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) }, 5308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) }, 5318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) }, 5328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) }, 5338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) }, 5348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff { } 5358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}; 5368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_DEVICE_TABLE(usb, synusb_idtable); 5378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_driver synusb_driver = { 5398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .name = "synaptics_usb", 5408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .probe = synusb_probe, 5418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .disconnect = synusb_disconnect, 5428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .id_table = synusb_idtable, 5438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .suspend = synusb_suspend, 5448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .resume = synusb_resume, 5458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .pre_reset = synusb_pre_reset, 5468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .post_reset = synusb_post_reset, 5478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .reset_resume = synusb_reset_resume, 5488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff .supports_autosuspend = 1, 5498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}; 5508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5514a53383565e340254479ce4d47bc181884ddf6c3Dmitry Torokhovmodule_usb_driver(synusb_driver); 5528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff 5538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_AUTHOR("Rob Miller <rob@inpharmatica.co.uk>, " 5548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "Ron Lee <ron@debian.org>, " 5558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff "Jan Steinhoff <cpad@jan-steinhoff.de>"); 5568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_DESCRIPTION("Synaptics USB device driver"); 5578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_LICENSE("GPL"); 558