Path: blob/master/drivers/input/mouse/appletouch.c
15109 views
/*1* Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver2*3* Copyright (C) 2001-2004 Greg Kroah-Hartman ([email protected])4* Copyright (C) 2005-2008 Johannes Berg ([email protected])5* Copyright (C) 2005-2008 Stelian Pop ([email protected])6* Copyright (C) 2005 Frank Arnold ([email protected])7* Copyright (C) 2005 Peter Osterlund ([email protected])8* Copyright (C) 2005 Michael Hanselmann ([email protected])9* Copyright (C) 2006 Nicolas Boichat ([email protected])10* Copyright (C) 2007-2008 Sven Anders ([email protected])11*12* Thanks to Alex Harper <[email protected]> for his inputs.13*14* This program is free software; you can redistribute it and/or modify15* it under the terms of the GNU General Public License as published by16* the Free Software Foundation; either version 2 of the License, or17* (at your option) any later version.18*19* This program is distributed in the hope that it will be useful,20* but WITHOUT ANY WARRANTY; without even the implied warranty of21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the22* GNU General Public License for more details.23*24* You should have received a copy of the GNU General Public License25* along with this program; if not, write to the Free Software26* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.27*28*/2930#include <linux/kernel.h>31#include <linux/errno.h>32#include <linux/init.h>33#include <linux/slab.h>34#include <linux/module.h>35#include <linux/usb/input.h>3637/*38* Note: We try to keep the touchpad aspect ratio while still doing only39* simple arithmetics:40* 0 <= x <= (xsensors - 1) * xfact41* 0 <= y <= (ysensors - 1) * yfact42*/43struct atp_info {44int xsensors; /* number of X sensors */45int xsensors_17; /* 17" models have more sensors */46int ysensors; /* number of Y sensors */47int xfact; /* X multiplication factor */48int yfact; /* Y multiplication factor */49int datalen; /* size of USB transfers */50void (*callback)(struct urb *); /* callback function */51};5253static void atp_complete_geyser_1_2(struct urb *urb);54static void atp_complete_geyser_3_4(struct urb *urb);5556static const struct atp_info fountain_info = {57.xsensors = 16,58.xsensors_17 = 26,59.ysensors = 16,60.xfact = 64,61.yfact = 43,62.datalen = 81,63.callback = atp_complete_geyser_1_2,64};6566static const struct atp_info geyser1_info = {67.xsensors = 16,68.xsensors_17 = 26,69.ysensors = 16,70.xfact = 64,71.yfact = 43,72.datalen = 81,73.callback = atp_complete_geyser_1_2,74};7576static const struct atp_info geyser2_info = {77.xsensors = 15,78.xsensors_17 = 20,79.ysensors = 9,80.xfact = 64,81.yfact = 43,82.datalen = 64,83.callback = atp_complete_geyser_1_2,84};8586static const struct atp_info geyser3_info = {87.xsensors = 20,88.ysensors = 10,89.xfact = 64,90.yfact = 64,91.datalen = 64,92.callback = atp_complete_geyser_3_4,93};9495static const struct atp_info geyser4_info = {96.xsensors = 20,97.ysensors = 10,98.xfact = 64,99.yfact = 64,100.datalen = 64,101.callback = atp_complete_geyser_3_4,102};103104#define ATP_DEVICE(prod, info) \105{ \106.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \107USB_DEVICE_ID_MATCH_INT_CLASS | \108USB_DEVICE_ID_MATCH_INT_PROTOCOL, \109.idVendor = 0x05ac, /* Apple */ \110.idProduct = (prod), \111.bInterfaceClass = 0x03, \112.bInterfaceProtocol = 0x02, \113.driver_info = (unsigned long) &info, \114}115116/*117* Table of devices (Product IDs) that work with this driver.118* (The names come from Info.plist in AppleUSBTrackpad.kext,119* According to Info.plist Geyser IV is the same as Geyser III.)120*/121122static struct usb_device_id atp_table[] = {123/* PowerBooks Feb 2005, iBooks G4 */124ATP_DEVICE(0x020e, fountain_info), /* FOUNTAIN ANSI */125ATP_DEVICE(0x020f, fountain_info), /* FOUNTAIN ISO */126ATP_DEVICE(0x030a, fountain_info), /* FOUNTAIN TP ONLY */127ATP_DEVICE(0x030b, geyser1_info), /* GEYSER 1 TP ONLY */128129/* PowerBooks Oct 2005 */130ATP_DEVICE(0x0214, geyser2_info), /* GEYSER 2 ANSI */131ATP_DEVICE(0x0215, geyser2_info), /* GEYSER 2 ISO */132ATP_DEVICE(0x0216, geyser2_info), /* GEYSER 2 JIS */133134/* Core Duo MacBook & MacBook Pro */135ATP_DEVICE(0x0217, geyser3_info), /* GEYSER 3 ANSI */136ATP_DEVICE(0x0218, geyser3_info), /* GEYSER 3 ISO */137ATP_DEVICE(0x0219, geyser3_info), /* GEYSER 3 JIS */138139/* Core2 Duo MacBook & MacBook Pro */140ATP_DEVICE(0x021a, geyser4_info), /* GEYSER 4 ANSI */141ATP_DEVICE(0x021b, geyser4_info), /* GEYSER 4 ISO */142ATP_DEVICE(0x021c, geyser4_info), /* GEYSER 4 JIS */143144/* Core2 Duo MacBook3,1 */145ATP_DEVICE(0x0229, geyser4_info), /* GEYSER 4 HF ANSI */146ATP_DEVICE(0x022a, geyser4_info), /* GEYSER 4 HF ISO */147ATP_DEVICE(0x022b, geyser4_info), /* GEYSER 4 HF JIS */148149/* Terminating entry */150{ }151};152MODULE_DEVICE_TABLE(usb, atp_table);153154/* maximum number of sensors */155#define ATP_XSENSORS 26156#define ATP_YSENSORS 16157158/* amount of fuzz this touchpad generates */159#define ATP_FUZZ 16160161/* maximum pressure this driver will report */162#define ATP_PRESSURE 300163164/*165* Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is166* ignored.167*/168#define ATP_THRESHOLD 5169170/* Geyser initialization constants */171#define ATP_GEYSER_MODE_READ_REQUEST_ID 1172#define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9173#define ATP_GEYSER_MODE_REQUEST_VALUE 0x300174#define ATP_GEYSER_MODE_REQUEST_INDEX 0175#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04176177/**178* enum atp_status_bits - status bit meanings179*180* These constants represent the meaning of the status bits.181* (only Geyser 3/4)182*183* @ATP_STATUS_BUTTON: The button was pressed184* @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad)185* @ATP_STATUS_FROM_RESET: Reset previously performed186*/187enum atp_status_bits {188ATP_STATUS_BUTTON = BIT(0),189ATP_STATUS_BASE_UPDATE = BIT(2),190ATP_STATUS_FROM_RESET = BIT(4),191};192193/* Structure to hold all of our device specific stuff */194struct atp {195char phys[64];196struct usb_device *udev; /* usb device */197struct urb *urb; /* usb request block */198u8 *data; /* transferred data */199struct input_dev *input; /* input dev */200const struct atp_info *info; /* touchpad model */201bool open;202bool valid; /* are the samples valid? */203bool size_detect_done;204bool overflow_warned;205int x_old; /* last reported x/y, */206int y_old; /* used for smoothing */207signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];208signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];209int xy_acc[ATP_XSENSORS + ATP_YSENSORS];210int idlecount; /* number of empty packets */211struct work_struct work;212};213214#define dbg_dump(msg, tab) \215if (debug > 1) { \216int __i; \217printk(KERN_DEBUG "appletouch: %s", msg); \218for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++) \219printk(" %02x", tab[__i]); \220printk("\n"); \221}222223#define dprintk(format, a...) \224do { \225if (debug) \226printk(KERN_DEBUG format, ##a); \227} while (0)228229MODULE_AUTHOR("Johannes Berg");230MODULE_AUTHOR("Stelian Pop");231MODULE_AUTHOR("Frank Arnold");232MODULE_AUTHOR("Michael Hanselmann");233MODULE_AUTHOR("Sven Anders");234MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver");235MODULE_LICENSE("GPL");236237/*238* Make the threshold a module parameter239*/240static int threshold = ATP_THRESHOLD;241module_param(threshold, int, 0644);242MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor"243" (the trackpad has many of these sensors)"244" less than this value.");245246static int debug;247module_param(debug, int, 0644);248MODULE_PARM_DESC(debug, "Activate debugging output");249250/*251* By default newer Geyser devices send standard USB HID mouse252* packets (Report ID 2). This code changes device mode, so it253* sends raw sensor reports (Report ID 5).254*/255static int atp_geyser_init(struct usb_device *udev)256{257char *data;258int size;259int i;260int ret;261262data = kmalloc(8, GFP_KERNEL);263if (!data) {264err("Out of memory");265return -ENOMEM;266}267268size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),269ATP_GEYSER_MODE_READ_REQUEST_ID,270USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,271ATP_GEYSER_MODE_REQUEST_VALUE,272ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);273274if (size != 8) {275dprintk("atp_geyser_init: read error\n");276for (i = 0; i < 8; i++)277dprintk("appletouch[%d]: %d\n", i, data[i]);278279err("Failed to read mode from device.");280ret = -EIO;281goto out_free;282}283284/* Apply the mode switch */285data[0] = ATP_GEYSER_MODE_VENDOR_VALUE;286287size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),288ATP_GEYSER_MODE_WRITE_REQUEST_ID,289USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,290ATP_GEYSER_MODE_REQUEST_VALUE,291ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);292293if (size != 8) {294dprintk("atp_geyser_init: write error\n");295for (i = 0; i < 8; i++)296dprintk("appletouch[%d]: %d\n", i, data[i]);297298err("Failed to request geyser raw mode");299ret = -EIO;300goto out_free;301}302ret = 0;303out_free:304kfree(data);305return ret;306}307308/*309* Reinitialise the device. This usually stops stream of empty packets310* coming from it.311*/312static void atp_reinit(struct work_struct *work)313{314struct atp *dev = container_of(work, struct atp, work);315struct usb_device *udev = dev->udev;316int retval;317318dprintk("appletouch: putting appletouch to sleep (reinit)\n");319atp_geyser_init(udev);320321retval = usb_submit_urb(dev->urb, GFP_ATOMIC);322if (retval)323err("atp_reinit: usb_submit_urb failed with error %d",324retval);325}326327static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,328int *z, int *fingers)329{330int i;331/* values to calculate mean */332int pcum = 0, psum = 0;333int is_increasing = 0;334335*fingers = 0;336337for (i = 0; i < nb_sensors; i++) {338if (xy_sensors[i] < threshold) {339if (is_increasing)340is_increasing = 0;341342continue;343}344345/*346* Makes the finger detection more versatile. For example,347* two fingers with no gap will be detected. Also, my348* tests show it less likely to have intermittent loss349* of multiple finger readings while moving around (scrolling).350*351* Changes the multiple finger detection to counting humps on352* sensors (transitions from nonincreasing to increasing)353* instead of counting transitions from low sensors (no354* finger reading) to high sensors (finger above355* sensor)356*357* - Jason Parekh <[email protected]>358*/359if (i < 1 ||360(!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {361(*fingers)++;362is_increasing = 1;363} else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) {364is_increasing = 0;365}366367/*368* Subtracts threshold so a high sensor that just passes the369* threshold won't skew the calculated absolute coordinate.370* Fixes an issue where slowly moving the mouse would371* occasionally jump a number of pixels (slowly moving the372* finger makes this issue most apparent.)373*/374pcum += (xy_sensors[i] - threshold) * i;375psum += (xy_sensors[i] - threshold);376}377378if (psum > 0) {379*z = psum;380return pcum * fact / psum;381}382383return 0;384}385386static inline void atp_report_fingers(struct input_dev *input, int fingers)387{388input_report_key(input, BTN_TOOL_FINGER, fingers == 1);389input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);390input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);391}392393/* Check URB status and for correct length of data package */394395#define ATP_URB_STATUS_SUCCESS 0396#define ATP_URB_STATUS_ERROR 1397#define ATP_URB_STATUS_ERROR_FATAL 2398399static int atp_status_check(struct urb *urb)400{401struct atp *dev = urb->context;402403switch (urb->status) {404case 0:405/* success */406break;407case -EOVERFLOW:408if (!dev->overflow_warned) {409printk(KERN_WARNING "appletouch: OVERFLOW with data "410"length %d, actual length is %d\n",411dev->info->datalen, dev->urb->actual_length);412dev->overflow_warned = true;413}414case -ECONNRESET:415case -ENOENT:416case -ESHUTDOWN:417/* This urb is terminated, clean up */418dbg("atp_complete: urb shutting down with status: %d",419urb->status);420return ATP_URB_STATUS_ERROR_FATAL;421422default:423dbg("atp_complete: nonzero urb status received: %d",424urb->status);425return ATP_URB_STATUS_ERROR;426}427428/* drop incomplete datasets */429if (dev->urb->actual_length != dev->info->datalen) {430dprintk("appletouch: incomplete data package"431" (first byte: %d, length: %d).\n",432dev->data[0], dev->urb->actual_length);433return ATP_URB_STATUS_ERROR;434}435436return ATP_URB_STATUS_SUCCESS;437}438439static void atp_detect_size(struct atp *dev)440{441int i;442443/* 17" Powerbooks have extra X sensors */444for (i = dev->info->xsensors; i < ATP_XSENSORS; i++) {445if (dev->xy_cur[i]) {446447printk(KERN_INFO "appletouch: 17\" model detected.\n");448449input_set_abs_params(dev->input, ABS_X, 0,450(dev->info->xsensors_17 - 1) *451dev->info->xfact - 1,452ATP_FUZZ, 0);453break;454}455}456}457458/*459* USB interrupt callback functions460*/461462/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */463464static void atp_complete_geyser_1_2(struct urb *urb)465{466int x, y, x_z, y_z, x_f, y_f;467int retval, i, j;468int key;469struct atp *dev = urb->context;470int status = atp_status_check(urb);471472if (status == ATP_URB_STATUS_ERROR_FATAL)473return;474else if (status == ATP_URB_STATUS_ERROR)475goto exit;476477/* reorder the sensors values */478if (dev->info == &geyser2_info) {479memset(dev->xy_cur, 0, sizeof(dev->xy_cur));480481/*482* The values are laid out like this:483* Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...484* '-' is an unused value.485*/486487/* read X values */488for (i = 0, j = 19; i < 20; i += 2, j += 3) {489dev->xy_cur[i] = dev->data[j];490dev->xy_cur[i + 1] = dev->data[j + 1];491}492493/* read Y values */494for (i = 0, j = 1; i < 9; i += 2, j += 3) {495dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];496dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];497}498} else {499for (i = 0; i < 8; i++) {500/* X values */501dev->xy_cur[i + 0] = dev->data[5 * i + 2];502dev->xy_cur[i + 8] = dev->data[5 * i + 4];503dev->xy_cur[i + 16] = dev->data[5 * i + 42];504if (i < 2)505dev->xy_cur[i + 24] = dev->data[5 * i + 44];506507/* Y values */508dev->xy_cur[ATP_XSENSORS + i] = dev->data[5 * i + 1];509dev->xy_cur[ATP_XSENSORS + i + 8] = dev->data[5 * i + 3];510}511}512513dbg_dump("sample", dev->xy_cur);514515if (!dev->valid) {516/* first sample */517dev->valid = true;518dev->x_old = dev->y_old = -1;519520/* Store first sample */521memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));522523/* Perform size detection, if not done already */524if (unlikely(!dev->size_detect_done)) {525atp_detect_size(dev);526dev->size_detect_done = 1;527goto exit;528}529}530531for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {532/* accumulate the change */533signed char change = dev->xy_old[i] - dev->xy_cur[i];534dev->xy_acc[i] -= change;535536/* prevent down drifting */537if (dev->xy_acc[i] < 0)538dev->xy_acc[i] = 0;539}540541memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));542543dbg_dump("accumulator", dev->xy_acc);544545x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,546dev->info->xfact, &x_z, &x_f);547y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,548dev->info->yfact, &y_z, &y_f);549key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;550551if (x && y) {552if (dev->x_old != -1) {553x = (dev->x_old * 3 + x) >> 2;554y = (dev->y_old * 3 + y) >> 2;555dev->x_old = x;556dev->y_old = y;557558if (debug > 1)559printk(KERN_DEBUG "appletouch: "560"X: %3d Y: %3d Xz: %3d Yz: %3d\n",561x, y, x_z, y_z);562563input_report_key(dev->input, BTN_TOUCH, 1);564input_report_abs(dev->input, ABS_X, x);565input_report_abs(dev->input, ABS_Y, y);566input_report_abs(dev->input, ABS_PRESSURE,567min(ATP_PRESSURE, x_z + y_z));568atp_report_fingers(dev->input, max(x_f, y_f));569}570dev->x_old = x;571dev->y_old = y;572573} else if (!x && !y) {574575dev->x_old = dev->y_old = -1;576input_report_key(dev->input, BTN_TOUCH, 0);577input_report_abs(dev->input, ABS_PRESSURE, 0);578atp_report_fingers(dev->input, 0);579580/* reset the accumulator on release */581memset(dev->xy_acc, 0, sizeof(dev->xy_acc));582}583584input_report_key(dev->input, BTN_LEFT, key);585input_sync(dev->input);586587exit:588retval = usb_submit_urb(dev->urb, GFP_ATOMIC);589if (retval)590err("atp_complete: usb_submit_urb failed with result %d",591retval);592}593594/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */595596static void atp_complete_geyser_3_4(struct urb *urb)597{598int x, y, x_z, y_z, x_f, y_f;599int retval, i, j;600int key;601struct atp *dev = urb->context;602int status = atp_status_check(urb);603604if (status == ATP_URB_STATUS_ERROR_FATAL)605return;606else if (status == ATP_URB_STATUS_ERROR)607goto exit;608609/* Reorder the sensors values:610*611* The values are laid out like this:612* -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...613* '-' is an unused value.614*/615616/* read X values */617for (i = 0, j = 19; i < 20; i += 2, j += 3) {618dev->xy_cur[i] = dev->data[j + 1];619dev->xy_cur[i + 1] = dev->data[j + 2];620}621/* read Y values */622for (i = 0, j = 1; i < 9; i += 2, j += 3) {623dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];624dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];625}626627dbg_dump("sample", dev->xy_cur);628629/* Just update the base values (i.e. touchpad in untouched state) */630if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) {631632dprintk("appletouch: updated base values\n");633634memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));635goto exit;636}637638for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {639/* calculate the change */640dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i];641642/* this is a round-robin value, so couple with that */643if (dev->xy_acc[i] > 127)644dev->xy_acc[i] -= 256;645646if (dev->xy_acc[i] < -127)647dev->xy_acc[i] += 256;648649/* prevent down drifting */650if (dev->xy_acc[i] < 0)651dev->xy_acc[i] = 0;652}653654dbg_dump("accumulator", dev->xy_acc);655656x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,657dev->info->xfact, &x_z, &x_f);658y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,659dev->info->yfact, &y_z, &y_f);660key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;661662if (x && y) {663if (dev->x_old != -1) {664x = (dev->x_old * 3 + x) >> 2;665y = (dev->y_old * 3 + y) >> 2;666dev->x_old = x;667dev->y_old = y;668669if (debug > 1)670printk(KERN_DEBUG "appletouch: X: %3d Y: %3d "671"Xz: %3d Yz: %3d\n",672x, y, x_z, y_z);673674input_report_key(dev->input, BTN_TOUCH, 1);675input_report_abs(dev->input, ABS_X, x);676input_report_abs(dev->input, ABS_Y, y);677input_report_abs(dev->input, ABS_PRESSURE,678min(ATP_PRESSURE, x_z + y_z));679atp_report_fingers(dev->input, max(x_f, y_f));680}681dev->x_old = x;682dev->y_old = y;683684} else if (!x && !y) {685686dev->x_old = dev->y_old = -1;687input_report_key(dev->input, BTN_TOUCH, 0);688input_report_abs(dev->input, ABS_PRESSURE, 0);689atp_report_fingers(dev->input, 0);690691/* reset the accumulator on release */692memset(dev->xy_acc, 0, sizeof(dev->xy_acc));693}694695input_report_key(dev->input, BTN_LEFT, key);696input_sync(dev->input);697698/*699* Geysers 3/4 will continue to send packets continually after700* the first touch unless reinitialised. Do so if it's been701* idle for a while in order to avoid waking the kernel up702* several hundred times a second.703*/704705/*706* Button must not be pressed when entering suspend,707* otherwise we will never release the button.708*/709if (!x && !y && !key) {710dev->idlecount++;711if (dev->idlecount == 10) {712dev->x_old = dev->y_old = -1;713dev->idlecount = 0;714schedule_work(&dev->work);715/* Don't resubmit urb here, wait for reinit */716return;717}718} else719dev->idlecount = 0;720721exit:722retval = usb_submit_urb(dev->urb, GFP_ATOMIC);723if (retval)724err("atp_complete: usb_submit_urb failed with result %d",725retval);726}727728static int atp_open(struct input_dev *input)729{730struct atp *dev = input_get_drvdata(input);731732if (usb_submit_urb(dev->urb, GFP_ATOMIC))733return -EIO;734735dev->open = 1;736return 0;737}738739static void atp_close(struct input_dev *input)740{741struct atp *dev = input_get_drvdata(input);742743usb_kill_urb(dev->urb);744cancel_work_sync(&dev->work);745dev->open = 0;746}747748static int atp_handle_geyser(struct atp *dev)749{750struct usb_device *udev = dev->udev;751752if (dev->info != &fountain_info) {753/* switch to raw sensor mode */754if (atp_geyser_init(udev))755return -EIO;756757printk(KERN_INFO "appletouch: Geyser mode initialized.\n");758}759760return 0;761}762763static int atp_probe(struct usb_interface *iface,764const struct usb_device_id *id)765{766struct atp *dev;767struct input_dev *input_dev;768struct usb_device *udev = interface_to_usbdev(iface);769struct usb_host_interface *iface_desc;770struct usb_endpoint_descriptor *endpoint;771int int_in_endpointAddr = 0;772int i, error = -ENOMEM;773const struct atp_info *info = (const struct atp_info *)id->driver_info;774775/* set up the endpoint information */776/* use only the first interrupt-in endpoint */777iface_desc = iface->cur_altsetting;778for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {779endpoint = &iface_desc->endpoint[i].desc;780if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {781/* we found an interrupt in endpoint */782int_in_endpointAddr = endpoint->bEndpointAddress;783break;784}785}786if (!int_in_endpointAddr) {787err("Could not find int-in endpoint");788return -EIO;789}790791/* allocate memory for our device state and initialize it */792dev = kzalloc(sizeof(struct atp), GFP_KERNEL);793input_dev = input_allocate_device();794if (!dev || !input_dev) {795err("Out of memory");796goto err_free_devs;797}798799dev->udev = udev;800dev->input = input_dev;801dev->info = info;802dev->overflow_warned = false;803804dev->urb = usb_alloc_urb(0, GFP_KERNEL);805if (!dev->urb)806goto err_free_devs;807808dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL,809&dev->urb->transfer_dma);810if (!dev->data)811goto err_free_urb;812813usb_fill_int_urb(dev->urb, udev,814usb_rcvintpipe(udev, int_in_endpointAddr),815dev->data, dev->info->datalen,816dev->info->callback, dev, 1);817818error = atp_handle_geyser(dev);819if (error)820goto err_free_buffer;821822usb_make_path(udev, dev->phys, sizeof(dev->phys));823strlcat(dev->phys, "/input0", sizeof(dev->phys));824825input_dev->name = "appletouch";826input_dev->phys = dev->phys;827usb_to_input_id(dev->udev, &input_dev->id);828input_dev->dev.parent = &iface->dev;829830input_set_drvdata(input_dev, dev);831832input_dev->open = atp_open;833input_dev->close = atp_close;834835set_bit(EV_ABS, input_dev->evbit);836837input_set_abs_params(input_dev, ABS_X, 0,838(dev->info->xsensors - 1) * dev->info->xfact - 1,839ATP_FUZZ, 0);840input_set_abs_params(input_dev, ABS_Y, 0,841(dev->info->ysensors - 1) * dev->info->yfact - 1,842ATP_FUZZ, 0);843input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);844845set_bit(EV_KEY, input_dev->evbit);846set_bit(BTN_TOUCH, input_dev->keybit);847set_bit(BTN_TOOL_FINGER, input_dev->keybit);848set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);849set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);850set_bit(BTN_LEFT, input_dev->keybit);851852error = input_register_device(dev->input);853if (error)854goto err_free_buffer;855856/* save our data pointer in this interface device */857usb_set_intfdata(iface, dev);858859INIT_WORK(&dev->work, atp_reinit);860861return 0;862863err_free_buffer:864usb_free_coherent(dev->udev, dev->info->datalen,865dev->data, dev->urb->transfer_dma);866err_free_urb:867usb_free_urb(dev->urb);868err_free_devs:869usb_set_intfdata(iface, NULL);870kfree(dev);871input_free_device(input_dev);872return error;873}874875static void atp_disconnect(struct usb_interface *iface)876{877struct atp *dev = usb_get_intfdata(iface);878879usb_set_intfdata(iface, NULL);880if (dev) {881usb_kill_urb(dev->urb);882input_unregister_device(dev->input);883usb_free_coherent(dev->udev, dev->info->datalen,884dev->data, dev->urb->transfer_dma);885usb_free_urb(dev->urb);886kfree(dev);887}888printk(KERN_INFO "input: appletouch disconnected\n");889}890891static int atp_recover(struct atp *dev)892{893int error;894895error = atp_handle_geyser(dev);896if (error)897return error;898899if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))900return -EIO;901902return 0;903}904905static int atp_suspend(struct usb_interface *iface, pm_message_t message)906{907struct atp *dev = usb_get_intfdata(iface);908909usb_kill_urb(dev->urb);910return 0;911}912913static int atp_resume(struct usb_interface *iface)914{915struct atp *dev = usb_get_intfdata(iface);916917if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))918return -EIO;919920return 0;921}922923static int atp_reset_resume(struct usb_interface *iface)924{925struct atp *dev = usb_get_intfdata(iface);926927return atp_recover(dev);928}929930static struct usb_driver atp_driver = {931.name = "appletouch",932.probe = atp_probe,933.disconnect = atp_disconnect,934.suspend = atp_suspend,935.resume = atp_resume,936.reset_resume = atp_reset_resume,937.id_table = atp_table,938};939940static int __init atp_init(void)941{942return usb_register(&atp_driver);943}944945static void __exit atp_exit(void)946{947usb_deregister(&atp_driver);948}949950module_init(atp_init);951module_exit(atp_exit);952953954