1*f89bd95cSHenrik Rydberg /* 2*f89bd95cSHenrik Rydberg * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver 3*f89bd95cSHenrik Rydberg * 4*f89bd95cSHenrik Rydberg * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se) 5*f89bd95cSHenrik Rydberg * 6*f89bd95cSHenrik Rydberg * The USB initialization and package decoding was made by 7*f89bd95cSHenrik Rydberg * Scott Shawcroft as part of the touchd user-space driver project: 8*f89bd95cSHenrik Rydberg * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com) 9*f89bd95cSHenrik Rydberg * 10*f89bd95cSHenrik Rydberg * The BCM5974 driver is based on the appletouch driver: 11*f89bd95cSHenrik Rydberg * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) 12*f89bd95cSHenrik Rydberg * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) 13*f89bd95cSHenrik Rydberg * Copyright (C) 2005 Stelian Pop (stelian@popies.net) 14*f89bd95cSHenrik Rydberg * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) 15*f89bd95cSHenrik Rydberg * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) 16*f89bd95cSHenrik Rydberg * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) 17*f89bd95cSHenrik Rydberg * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) 18*f89bd95cSHenrik Rydberg * 19*f89bd95cSHenrik Rydberg * This program is free software; you can redistribute it and/or modify 20*f89bd95cSHenrik Rydberg * it under the terms of the GNU General Public License as published by 21*f89bd95cSHenrik Rydberg * the Free Software Foundation; either version 2 of the License, or 22*f89bd95cSHenrik Rydberg * (at your option) any later version. 23*f89bd95cSHenrik Rydberg * 24*f89bd95cSHenrik Rydberg * This program is distributed in the hope that it will be useful, 25*f89bd95cSHenrik Rydberg * but WITHOUT ANY WARRANTY; without even the implied warranty of 26*f89bd95cSHenrik Rydberg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27*f89bd95cSHenrik Rydberg * GNU General Public License for more details. 28*f89bd95cSHenrik Rydberg * 29*f89bd95cSHenrik Rydberg * You should have received a copy of the GNU General Public License 30*f89bd95cSHenrik Rydberg * along with this program; if not, write to the Free Software 31*f89bd95cSHenrik Rydberg * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 32*f89bd95cSHenrik Rydberg * 33*f89bd95cSHenrik Rydberg */ 34*f89bd95cSHenrik Rydberg 35*f89bd95cSHenrik Rydberg #include <linux/kernel.h> 36*f89bd95cSHenrik Rydberg #include <linux/errno.h> 37*f89bd95cSHenrik Rydberg #include <linux/init.h> 38*f89bd95cSHenrik Rydberg #include <linux/slab.h> 39*f89bd95cSHenrik Rydberg #include <linux/module.h> 40*f89bd95cSHenrik Rydberg #include <linux/usb/input.h> 41*f89bd95cSHenrik Rydberg #include <linux/hid.h> 42*f89bd95cSHenrik Rydberg #include <linux/mutex.h> 43*f89bd95cSHenrik Rydberg 44*f89bd95cSHenrik Rydberg #define USB_VENDOR_ID_APPLE 0x05ac 45*f89bd95cSHenrik Rydberg 46*f89bd95cSHenrik Rydberg /* MacbookAir, aka wellspring */ 47*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 48*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 49*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 50*f89bd95cSHenrik Rydberg /* MacbookProPenryn, aka wellspring2 */ 51*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 52*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 53*f89bd95cSHenrik Rydberg #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 54*f89bd95cSHenrik Rydberg 55*f89bd95cSHenrik Rydberg #define BCM5974_DEVICE(prod) { \ 56*f89bd95cSHenrik Rydberg .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ 57*f89bd95cSHenrik Rydberg USB_DEVICE_ID_MATCH_INT_CLASS | \ 58*f89bd95cSHenrik Rydberg USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ 59*f89bd95cSHenrik Rydberg .idVendor = USB_VENDOR_ID_APPLE, \ 60*f89bd95cSHenrik Rydberg .idProduct = (prod), \ 61*f89bd95cSHenrik Rydberg .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 62*f89bd95cSHenrik Rydberg .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ 63*f89bd95cSHenrik Rydberg } 64*f89bd95cSHenrik Rydberg 65*f89bd95cSHenrik Rydberg /* table of devices that work with this driver */ 66*f89bd95cSHenrik Rydberg static const struct usb_device_id bcm5974_table [] = { 67*f89bd95cSHenrik Rydberg /* MacbookAir1.1 */ 68*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), 69*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), 70*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS), 71*f89bd95cSHenrik Rydberg /* MacbookProPenryn */ 72*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), 73*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), 74*f89bd95cSHenrik Rydberg BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), 75*f89bd95cSHenrik Rydberg /* Terminating entry */ 76*f89bd95cSHenrik Rydberg {} 77*f89bd95cSHenrik Rydberg }; 78*f89bd95cSHenrik Rydberg MODULE_DEVICE_TABLE(usb, bcm5974_table); 79*f89bd95cSHenrik Rydberg 80*f89bd95cSHenrik Rydberg MODULE_AUTHOR("Henrik Rydberg"); 81*f89bd95cSHenrik Rydberg MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); 82*f89bd95cSHenrik Rydberg MODULE_LICENSE("GPL"); 83*f89bd95cSHenrik Rydberg 84*f89bd95cSHenrik Rydberg #define dprintk(level, format, a...)\ 85*f89bd95cSHenrik Rydberg { if (debug >= level) printk(KERN_DEBUG format, ##a); } 86*f89bd95cSHenrik Rydberg 87*f89bd95cSHenrik Rydberg static int debug = 1; 88*f89bd95cSHenrik Rydberg module_param(debug, int, 0644); 89*f89bd95cSHenrik Rydberg MODULE_PARM_DESC(debug, "Activate debugging output"); 90*f89bd95cSHenrik Rydberg 91*f89bd95cSHenrik Rydberg /* button data structure */ 92*f89bd95cSHenrik Rydberg struct bt_data { 93*f89bd95cSHenrik Rydberg u8 unknown1; /* constant */ 94*f89bd95cSHenrik Rydberg u8 button; /* left button */ 95*f89bd95cSHenrik Rydberg u8 rel_x; /* relative x coordinate */ 96*f89bd95cSHenrik Rydberg u8 rel_y; /* relative y coordinate */ 97*f89bd95cSHenrik Rydberg }; 98*f89bd95cSHenrik Rydberg 99*f89bd95cSHenrik Rydberg /* trackpad header structure */ 100*f89bd95cSHenrik Rydberg struct tp_header { 101*f89bd95cSHenrik Rydberg u8 unknown1[16]; /* constants, timers, etc */ 102*f89bd95cSHenrik Rydberg u8 fingers; /* number of fingers on trackpad */ 103*f89bd95cSHenrik Rydberg u8 unknown2[9]; /* constants, timers, etc */ 104*f89bd95cSHenrik Rydberg }; 105*f89bd95cSHenrik Rydberg 106*f89bd95cSHenrik Rydberg /* trackpad finger structure */ 107*f89bd95cSHenrik Rydberg struct tp_finger { 108*f89bd95cSHenrik Rydberg __le16 origin; /* left/right origin? */ 109*f89bd95cSHenrik Rydberg __le16 abs_x; /* absolute x coodinate */ 110*f89bd95cSHenrik Rydberg __le16 abs_y; /* absolute y coodinate */ 111*f89bd95cSHenrik Rydberg __le16 rel_x; /* relative x coodinate */ 112*f89bd95cSHenrik Rydberg __le16 rel_y; /* relative y coodinate */ 113*f89bd95cSHenrik Rydberg __le16 size_major; /* finger size, major axis? */ 114*f89bd95cSHenrik Rydberg __le16 size_minor; /* finger size, minor axis? */ 115*f89bd95cSHenrik Rydberg __le16 orientation; /* 16384 when point, else 15 bit angle */ 116*f89bd95cSHenrik Rydberg __le16 force_major; /* trackpad force, major axis? */ 117*f89bd95cSHenrik Rydberg __le16 force_minor; /* trackpad force, minor axis? */ 118*f89bd95cSHenrik Rydberg __le16 unused[3]; /* zeros */ 119*f89bd95cSHenrik Rydberg __le16 multi; /* one finger: varies, more fingers: constant */ 120*f89bd95cSHenrik Rydberg }; 121*f89bd95cSHenrik Rydberg 122*f89bd95cSHenrik Rydberg /* trackpad data structure, empirically at least ten fingers */ 123*f89bd95cSHenrik Rydberg struct tp_data { 124*f89bd95cSHenrik Rydberg struct tp_header header; 125*f89bd95cSHenrik Rydberg struct tp_finger finger[16]; 126*f89bd95cSHenrik Rydberg }; 127*f89bd95cSHenrik Rydberg 128*f89bd95cSHenrik Rydberg /* device-specific parameters */ 129*f89bd95cSHenrik Rydberg struct bcm5974_param { 130*f89bd95cSHenrik Rydberg int dim; /* logical dimension */ 131*f89bd95cSHenrik Rydberg int fuzz; /* logical noise value */ 132*f89bd95cSHenrik Rydberg int devmin; /* device minimum reading */ 133*f89bd95cSHenrik Rydberg int devmax; /* device maximum reading */ 134*f89bd95cSHenrik Rydberg }; 135*f89bd95cSHenrik Rydberg 136*f89bd95cSHenrik Rydberg /* device-specific configuration */ 137*f89bd95cSHenrik Rydberg struct bcm5974_config { 138*f89bd95cSHenrik Rydberg int ansi, iso, jis; /* the product id of this device */ 139*f89bd95cSHenrik Rydberg int bt_ep; /* the endpoint of the button interface */ 140*f89bd95cSHenrik Rydberg int bt_datalen; /* data length of the button interface */ 141*f89bd95cSHenrik Rydberg int tp_ep; /* the endpoint of the trackpad interface */ 142*f89bd95cSHenrik Rydberg int tp_datalen; /* data length of the trackpad interface */ 143*f89bd95cSHenrik Rydberg struct bcm5974_param p; /* finger pressure limits */ 144*f89bd95cSHenrik Rydberg struct bcm5974_param w; /* finger width limits */ 145*f89bd95cSHenrik Rydberg struct bcm5974_param x; /* horizontal limits */ 146*f89bd95cSHenrik Rydberg struct bcm5974_param y; /* vertical limits */ 147*f89bd95cSHenrik Rydberg }; 148*f89bd95cSHenrik Rydberg 149*f89bd95cSHenrik Rydberg /* logical device structure */ 150*f89bd95cSHenrik Rydberg struct bcm5974 { 151*f89bd95cSHenrik Rydberg char phys[64]; 152*f89bd95cSHenrik Rydberg struct usb_device *udev; /* usb device */ 153*f89bd95cSHenrik Rydberg struct input_dev *input; /* input dev */ 154*f89bd95cSHenrik Rydberg struct bcm5974_config cfg; /* device configuration */ 155*f89bd95cSHenrik Rydberg struct mutex pm_mutex; /* serialize access to open/suspend */ 156*f89bd95cSHenrik Rydberg int opened; /* 1: opened, 0: closed */ 157*f89bd95cSHenrik Rydberg struct urb *bt_urb; /* button usb request block */ 158*f89bd95cSHenrik Rydberg struct bt_data *bt_data; /* button transferred data */ 159*f89bd95cSHenrik Rydberg struct urb *tp_urb; /* trackpad usb request block */ 160*f89bd95cSHenrik Rydberg struct tp_data *tp_data; /* trackpad transferred data */ 161*f89bd95cSHenrik Rydberg }; 162*f89bd95cSHenrik Rydberg 163*f89bd95cSHenrik Rydberg /* logical dimensions */ 164*f89bd95cSHenrik Rydberg #define DIM_PRESSURE 256 /* maximum finger pressure */ 165*f89bd95cSHenrik Rydberg #define DIM_WIDTH 16 /* maximum finger width */ 166*f89bd95cSHenrik Rydberg #define DIM_X 1280 /* maximum trackpad x value */ 167*f89bd95cSHenrik Rydberg #define DIM_Y 800 /* maximum trackpad y value */ 168*f89bd95cSHenrik Rydberg 169*f89bd95cSHenrik Rydberg /* logical signal quality */ 170*f89bd95cSHenrik Rydberg #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ 171*f89bd95cSHenrik Rydberg #define SN_WIDTH 100 /* width signal-to-noise ratio */ 172*f89bd95cSHenrik Rydberg #define SN_COORD 250 /* coordinate signal-to-noise ratio */ 173*f89bd95cSHenrik Rydberg 174*f89bd95cSHenrik Rydberg /* device constants */ 175*f89bd95cSHenrik Rydberg static const struct bcm5974_config bcm5974_config_table[] = { 176*f89bd95cSHenrik Rydberg { 177*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, 178*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING_ISO, 179*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING_JIS, 180*f89bd95cSHenrik Rydberg 0x84, sizeof(struct bt_data), 181*f89bd95cSHenrik Rydberg 0x81, sizeof(struct tp_data), 182*f89bd95cSHenrik Rydberg { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, 183*f89bd95cSHenrik Rydberg { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, 184*f89bd95cSHenrik Rydberg { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, 185*f89bd95cSHenrik Rydberg { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } 186*f89bd95cSHenrik Rydberg }, 187*f89bd95cSHenrik Rydberg { 188*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, 189*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, 190*f89bd95cSHenrik Rydberg USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, 191*f89bd95cSHenrik Rydberg 0x84, sizeof(struct bt_data), 192*f89bd95cSHenrik Rydberg 0x81, sizeof(struct tp_data), 193*f89bd95cSHenrik Rydberg { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, 194*f89bd95cSHenrik Rydberg { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, 195*f89bd95cSHenrik Rydberg { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, 196*f89bd95cSHenrik Rydberg { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } 197*f89bd95cSHenrik Rydberg }, 198*f89bd95cSHenrik Rydberg {} 199*f89bd95cSHenrik Rydberg }; 200*f89bd95cSHenrik Rydberg 201*f89bd95cSHenrik Rydberg /* return the device-specific configuration by device */ 202*f89bd95cSHenrik Rydberg static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev) 203*f89bd95cSHenrik Rydberg { 204*f89bd95cSHenrik Rydberg u16 id = le16_to_cpu(udev->descriptor.idProduct); 205*f89bd95cSHenrik Rydberg const struct bcm5974_config *cfg; 206*f89bd95cSHenrik Rydberg 207*f89bd95cSHenrik Rydberg for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) 208*f89bd95cSHenrik Rydberg if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) 209*f89bd95cSHenrik Rydberg return cfg; 210*f89bd95cSHenrik Rydberg 211*f89bd95cSHenrik Rydberg return bcm5974_config_table; 212*f89bd95cSHenrik Rydberg } 213*f89bd95cSHenrik Rydberg 214*f89bd95cSHenrik Rydberg /* convert 16-bit little endian to signed integer */ 215*f89bd95cSHenrik Rydberg static inline int raw2int(__le16 x) 216*f89bd95cSHenrik Rydberg { 217*f89bd95cSHenrik Rydberg return (signed short)le16_to_cpu(x); 218*f89bd95cSHenrik Rydberg } 219*f89bd95cSHenrik Rydberg 220*f89bd95cSHenrik Rydberg /* scale device data to logical dimensions (asserts devmin < devmax) */ 221*f89bd95cSHenrik Rydberg static inline int int2scale(const struct bcm5974_param *p, int x) 222*f89bd95cSHenrik Rydberg { 223*f89bd95cSHenrik Rydberg return x * p->dim / (p->devmax - p->devmin); 224*f89bd95cSHenrik Rydberg } 225*f89bd95cSHenrik Rydberg 226*f89bd95cSHenrik Rydberg /* all logical value ranges are [0,dim). */ 227*f89bd95cSHenrik Rydberg static inline int int2bound(const struct bcm5974_param *p, int x) 228*f89bd95cSHenrik Rydberg { 229*f89bd95cSHenrik Rydberg int s = int2scale(p, x); 230*f89bd95cSHenrik Rydberg 231*f89bd95cSHenrik Rydberg return clamp_val(s, 0, p->dim - 1); 232*f89bd95cSHenrik Rydberg } 233*f89bd95cSHenrik Rydberg 234*f89bd95cSHenrik Rydberg /* setup which logical events to report */ 235*f89bd95cSHenrik Rydberg static void setup_events_to_report(struct input_dev *input_dev, 236*f89bd95cSHenrik Rydberg const struct bcm5974_config *cfg) 237*f89bd95cSHenrik Rydberg { 238*f89bd95cSHenrik Rydberg __set_bit(EV_ABS, input_dev->evbit); 239*f89bd95cSHenrik Rydberg 240*f89bd95cSHenrik Rydberg input_set_abs_params(input_dev, ABS_PRESSURE, 241*f89bd95cSHenrik Rydberg 0, cfg->p.dim, cfg->p.fuzz, 0); 242*f89bd95cSHenrik Rydberg input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 243*f89bd95cSHenrik Rydberg 0, cfg->w.dim, cfg->w.fuzz, 0); 244*f89bd95cSHenrik Rydberg input_set_abs_params(input_dev, ABS_X, 245*f89bd95cSHenrik Rydberg 0, cfg->x.dim, cfg->x.fuzz, 0); 246*f89bd95cSHenrik Rydberg input_set_abs_params(input_dev, ABS_Y, 247*f89bd95cSHenrik Rydberg 0, cfg->y.dim, cfg->y.fuzz, 0); 248*f89bd95cSHenrik Rydberg 249*f89bd95cSHenrik Rydberg __set_bit(EV_KEY, input_dev->evbit); 250*f89bd95cSHenrik Rydberg __set_bit(BTN_TOOL_FINGER, input_dev->keybit); 251*f89bd95cSHenrik Rydberg __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); 252*f89bd95cSHenrik Rydberg __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); 253*f89bd95cSHenrik Rydberg __set_bit(BTN_LEFT, input_dev->keybit); 254*f89bd95cSHenrik Rydberg } 255*f89bd95cSHenrik Rydberg 256*f89bd95cSHenrik Rydberg /* report button data as logical button state */ 257*f89bd95cSHenrik Rydberg static int report_bt_state(struct bcm5974 *dev, int size) 258*f89bd95cSHenrik Rydberg { 259*f89bd95cSHenrik Rydberg if (size != sizeof(struct bt_data)) 260*f89bd95cSHenrik Rydberg return -EIO; 261*f89bd95cSHenrik Rydberg 262*f89bd95cSHenrik Rydberg input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); 263*f89bd95cSHenrik Rydberg input_sync(dev->input); 264*f89bd95cSHenrik Rydberg 265*f89bd95cSHenrik Rydberg return 0; 266*f89bd95cSHenrik Rydberg } 267*f89bd95cSHenrik Rydberg 268*f89bd95cSHenrik Rydberg /* report trackpad data as logical trackpad state */ 269*f89bd95cSHenrik Rydberg static int report_tp_state(struct bcm5974 *dev, int size) 270*f89bd95cSHenrik Rydberg { 271*f89bd95cSHenrik Rydberg const struct bcm5974_config *c = &dev->cfg; 272*f89bd95cSHenrik Rydberg const struct tp_finger *f = dev->tp_data->finger; 273*f89bd95cSHenrik Rydberg struct input_dev *input = dev->input; 274*f89bd95cSHenrik Rydberg const int fingers = (size - 26) / 28; 275*f89bd95cSHenrik Rydberg int p = 0, w, x, y, n = 0; 276*f89bd95cSHenrik Rydberg 277*f89bd95cSHenrik Rydberg if (size < 26 || (size - 26) % 28 != 0) 278*f89bd95cSHenrik Rydberg return -EIO; 279*f89bd95cSHenrik Rydberg 280*f89bd95cSHenrik Rydberg if (fingers) { 281*f89bd95cSHenrik Rydberg p = raw2int(f->force_major); 282*f89bd95cSHenrik Rydberg w = raw2int(f->size_major); 283*f89bd95cSHenrik Rydberg x = raw2int(f->abs_x); 284*f89bd95cSHenrik Rydberg y = raw2int(f->abs_y); 285*f89bd95cSHenrik Rydberg n = p > 0 ? fingers : 0; 286*f89bd95cSHenrik Rydberg 287*f89bd95cSHenrik Rydberg dprintk(9, 288*f89bd95cSHenrik Rydberg "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", 289*f89bd95cSHenrik Rydberg p, w, x, y, n); 290*f89bd95cSHenrik Rydberg 291*f89bd95cSHenrik Rydberg input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); 292*f89bd95cSHenrik Rydberg input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); 293*f89bd95cSHenrik Rydberg input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); 294*f89bd95cSHenrik Rydberg } 295*f89bd95cSHenrik Rydberg 296*f89bd95cSHenrik Rydberg input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); 297*f89bd95cSHenrik Rydberg 298*f89bd95cSHenrik Rydberg input_report_key(input, BTN_TOOL_FINGER, n == 1); 299*f89bd95cSHenrik Rydberg input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); 300*f89bd95cSHenrik Rydberg input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); 301*f89bd95cSHenrik Rydberg 302*f89bd95cSHenrik Rydberg input_sync(input); 303*f89bd95cSHenrik Rydberg 304*f89bd95cSHenrik Rydberg return 0; 305*f89bd95cSHenrik Rydberg } 306*f89bd95cSHenrik Rydberg 307*f89bd95cSHenrik Rydberg /* Wellspring initialization constants */ 308*f89bd95cSHenrik Rydberg #define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 309*f89bd95cSHenrik Rydberg #define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 310*f89bd95cSHenrik Rydberg #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 311*f89bd95cSHenrik Rydberg #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 312*f89bd95cSHenrik Rydberg #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 313*f89bd95cSHenrik Rydberg 314*f89bd95cSHenrik Rydberg static int bcm5974_wellspring_mode(struct bcm5974 *dev) 315*f89bd95cSHenrik Rydberg { 316*f89bd95cSHenrik Rydberg char *data = kmalloc(8, GFP_KERNEL); 317*f89bd95cSHenrik Rydberg int retval = 0, size; 318*f89bd95cSHenrik Rydberg 319*f89bd95cSHenrik Rydberg if (!data) { 320*f89bd95cSHenrik Rydberg err("bcm5974: out of memory"); 321*f89bd95cSHenrik Rydberg retval = -ENOMEM; 322*f89bd95cSHenrik Rydberg goto out; 323*f89bd95cSHenrik Rydberg } 324*f89bd95cSHenrik Rydberg 325*f89bd95cSHenrik Rydberg /* read configuration */ 326*f89bd95cSHenrik Rydberg size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), 327*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, 328*f89bd95cSHenrik Rydberg USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 329*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_REQUEST_VALUE, 330*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 331*f89bd95cSHenrik Rydberg 332*f89bd95cSHenrik Rydberg if (size != 8) { 333*f89bd95cSHenrik Rydberg err("bcm5974: could not read from device"); 334*f89bd95cSHenrik Rydberg retval = -EIO; 335*f89bd95cSHenrik Rydberg goto out; 336*f89bd95cSHenrik Rydberg } 337*f89bd95cSHenrik Rydberg 338*f89bd95cSHenrik Rydberg /* apply the mode switch */ 339*f89bd95cSHenrik Rydberg data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE; 340*f89bd95cSHenrik Rydberg 341*f89bd95cSHenrik Rydberg /* write configuration */ 342*f89bd95cSHenrik Rydberg size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 343*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, 344*f89bd95cSHenrik Rydberg USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 345*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_REQUEST_VALUE, 346*f89bd95cSHenrik Rydberg BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 347*f89bd95cSHenrik Rydberg 348*f89bd95cSHenrik Rydberg if (size != 8) { 349*f89bd95cSHenrik Rydberg err("bcm5974: could not write to device"); 350*f89bd95cSHenrik Rydberg retval = -EIO; 351*f89bd95cSHenrik Rydberg goto out; 352*f89bd95cSHenrik Rydberg } 353*f89bd95cSHenrik Rydberg 354*f89bd95cSHenrik Rydberg dprintk(2, "bcm5974: switched to wellspring mode.\n"); 355*f89bd95cSHenrik Rydberg 356*f89bd95cSHenrik Rydberg out: 357*f89bd95cSHenrik Rydberg kfree(data); 358*f89bd95cSHenrik Rydberg return retval; 359*f89bd95cSHenrik Rydberg } 360*f89bd95cSHenrik Rydberg 361*f89bd95cSHenrik Rydberg static void bcm5974_irq_button(struct urb *urb) 362*f89bd95cSHenrik Rydberg { 363*f89bd95cSHenrik Rydberg struct bcm5974 *dev = urb->context; 364*f89bd95cSHenrik Rydberg int error; 365*f89bd95cSHenrik Rydberg 366*f89bd95cSHenrik Rydberg switch (urb->status) { 367*f89bd95cSHenrik Rydberg case 0: 368*f89bd95cSHenrik Rydberg break; 369*f89bd95cSHenrik Rydberg case -EOVERFLOW: 370*f89bd95cSHenrik Rydberg case -ECONNRESET: 371*f89bd95cSHenrik Rydberg case -ENOENT: 372*f89bd95cSHenrik Rydberg case -ESHUTDOWN: 373*f89bd95cSHenrik Rydberg dbg("bcm5974: button urb shutting down: %d", urb->status); 374*f89bd95cSHenrik Rydberg return; 375*f89bd95cSHenrik Rydberg default: 376*f89bd95cSHenrik Rydberg dbg("bcm5974: button urb status: %d", urb->status); 377*f89bd95cSHenrik Rydberg goto exit; 378*f89bd95cSHenrik Rydberg } 379*f89bd95cSHenrik Rydberg 380*f89bd95cSHenrik Rydberg if (report_bt_state(dev, dev->bt_urb->actual_length)) 381*f89bd95cSHenrik Rydberg dprintk(1, "bcm5974: bad button package, length: %d\n", 382*f89bd95cSHenrik Rydberg dev->bt_urb->actual_length); 383*f89bd95cSHenrik Rydberg 384*f89bd95cSHenrik Rydberg exit: 385*f89bd95cSHenrik Rydberg error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); 386*f89bd95cSHenrik Rydberg if (error) 387*f89bd95cSHenrik Rydberg err("bcm5974: button urb failed: %d", error); 388*f89bd95cSHenrik Rydberg } 389*f89bd95cSHenrik Rydberg 390*f89bd95cSHenrik Rydberg static void bcm5974_irq_trackpad(struct urb *urb) 391*f89bd95cSHenrik Rydberg { 392*f89bd95cSHenrik Rydberg struct bcm5974 *dev = urb->context; 393*f89bd95cSHenrik Rydberg int error; 394*f89bd95cSHenrik Rydberg 395*f89bd95cSHenrik Rydberg switch (urb->status) { 396*f89bd95cSHenrik Rydberg case 0: 397*f89bd95cSHenrik Rydberg break; 398*f89bd95cSHenrik Rydberg case -EOVERFLOW: 399*f89bd95cSHenrik Rydberg case -ECONNRESET: 400*f89bd95cSHenrik Rydberg case -ENOENT: 401*f89bd95cSHenrik Rydberg case -ESHUTDOWN: 402*f89bd95cSHenrik Rydberg dbg("bcm5974: trackpad urb shutting down: %d", urb->status); 403*f89bd95cSHenrik Rydberg return; 404*f89bd95cSHenrik Rydberg default: 405*f89bd95cSHenrik Rydberg dbg("bcm5974: trackpad urb status: %d", urb->status); 406*f89bd95cSHenrik Rydberg goto exit; 407*f89bd95cSHenrik Rydberg } 408*f89bd95cSHenrik Rydberg 409*f89bd95cSHenrik Rydberg /* control response ignored */ 410*f89bd95cSHenrik Rydberg if (dev->tp_urb->actual_length == 2) 411*f89bd95cSHenrik Rydberg goto exit; 412*f89bd95cSHenrik Rydberg 413*f89bd95cSHenrik Rydberg if (report_tp_state(dev, dev->tp_urb->actual_length)) 414*f89bd95cSHenrik Rydberg dprintk(1, "bcm5974: bad trackpad package, length: %d\n", 415*f89bd95cSHenrik Rydberg dev->tp_urb->actual_length); 416*f89bd95cSHenrik Rydberg 417*f89bd95cSHenrik Rydberg exit: 418*f89bd95cSHenrik Rydberg error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); 419*f89bd95cSHenrik Rydberg if (error) 420*f89bd95cSHenrik Rydberg err("bcm5974: trackpad urb failed: %d", error); 421*f89bd95cSHenrik Rydberg } 422*f89bd95cSHenrik Rydberg 423*f89bd95cSHenrik Rydberg /* 424*f89bd95cSHenrik Rydberg * The Wellspring trackpad, like many recent Apple trackpads, share 425*f89bd95cSHenrik Rydberg * the usb device with the keyboard. Since keyboards are usually 426*f89bd95cSHenrik Rydberg * handled by the HID system, the device ends up being handled by two 427*f89bd95cSHenrik Rydberg * modules. Setting up the device therefore becomes slightly 428*f89bd95cSHenrik Rydberg * complicated. To enable multitouch features, a mode switch is 429*f89bd95cSHenrik Rydberg * required, which is usually applied via the control interface of the 430*f89bd95cSHenrik Rydberg * device. It can be argued where this switch should take place. In 431*f89bd95cSHenrik Rydberg * some drivers, like appletouch, the switch is made during 432*f89bd95cSHenrik Rydberg * probe. However, the hid module may also alter the state of the 433*f89bd95cSHenrik Rydberg * device, resulting in trackpad malfunction under certain 434*f89bd95cSHenrik Rydberg * circumstances. To get around this problem, there is at least one 435*f89bd95cSHenrik Rydberg * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to 436*f89bd95cSHenrik Rydberg * recieve a reset_resume request rather than the normal resume. 437*f89bd95cSHenrik Rydberg * Since the implementation of reset_resume is equal to mode switch 438*f89bd95cSHenrik Rydberg * plus start_traffic, it seems easier to always do the switch when 439*f89bd95cSHenrik Rydberg * starting traffic on the device. 440*f89bd95cSHenrik Rydberg */ 441*f89bd95cSHenrik Rydberg static int bcm5974_start_traffic(struct bcm5974 *dev) 442*f89bd95cSHenrik Rydberg { 443*f89bd95cSHenrik Rydberg if (bcm5974_wellspring_mode(dev)) { 444*f89bd95cSHenrik Rydberg dprintk(1, "bcm5974: mode switch failed\n"); 445*f89bd95cSHenrik Rydberg goto error; 446*f89bd95cSHenrik Rydberg } 447*f89bd95cSHenrik Rydberg 448*f89bd95cSHenrik Rydberg if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) 449*f89bd95cSHenrik Rydberg goto error; 450*f89bd95cSHenrik Rydberg 451*f89bd95cSHenrik Rydberg if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) 452*f89bd95cSHenrik Rydberg goto err_kill_bt; 453*f89bd95cSHenrik Rydberg 454*f89bd95cSHenrik Rydberg return 0; 455*f89bd95cSHenrik Rydberg 456*f89bd95cSHenrik Rydberg err_kill_bt: 457*f89bd95cSHenrik Rydberg usb_kill_urb(dev->bt_urb); 458*f89bd95cSHenrik Rydberg error: 459*f89bd95cSHenrik Rydberg return -EIO; 460*f89bd95cSHenrik Rydberg } 461*f89bd95cSHenrik Rydberg 462*f89bd95cSHenrik Rydberg static void bcm5974_pause_traffic(struct bcm5974 *dev) 463*f89bd95cSHenrik Rydberg { 464*f89bd95cSHenrik Rydberg usb_kill_urb(dev->tp_urb); 465*f89bd95cSHenrik Rydberg usb_kill_urb(dev->bt_urb); 466*f89bd95cSHenrik Rydberg } 467*f89bd95cSHenrik Rydberg 468*f89bd95cSHenrik Rydberg /* 469*f89bd95cSHenrik Rydberg * The code below implements open/close and manual suspend/resume. 470*f89bd95cSHenrik Rydberg * All functions may be called in random order. 471*f89bd95cSHenrik Rydberg * 472*f89bd95cSHenrik Rydberg * Opening a suspended device fails with EACCES - permission denied. 473*f89bd95cSHenrik Rydberg * 474*f89bd95cSHenrik Rydberg * Failing a resume leaves the device resumed but closed. 475*f89bd95cSHenrik Rydberg */ 476*f89bd95cSHenrik Rydberg static int bcm5974_open(struct input_dev *input) 477*f89bd95cSHenrik Rydberg { 478*f89bd95cSHenrik Rydberg struct bcm5974 *dev = input_get_drvdata(input); 479*f89bd95cSHenrik Rydberg int error; 480*f89bd95cSHenrik Rydberg 481*f89bd95cSHenrik Rydberg mutex_lock(&dev->pm_mutex); 482*f89bd95cSHenrik Rydberg 483*f89bd95cSHenrik Rydberg error = bcm5974_start_traffic(dev); 484*f89bd95cSHenrik Rydberg if (!error) 485*f89bd95cSHenrik Rydberg dev->opened = 1; 486*f89bd95cSHenrik Rydberg 487*f89bd95cSHenrik Rydberg mutex_unlock(&dev->pm_mutex); 488*f89bd95cSHenrik Rydberg 489*f89bd95cSHenrik Rydberg return error; 490*f89bd95cSHenrik Rydberg } 491*f89bd95cSHenrik Rydberg 492*f89bd95cSHenrik Rydberg static void bcm5974_close(struct input_dev *input) 493*f89bd95cSHenrik Rydberg { 494*f89bd95cSHenrik Rydberg struct bcm5974 *dev = input_get_drvdata(input); 495*f89bd95cSHenrik Rydberg 496*f89bd95cSHenrik Rydberg mutex_lock(&dev->pm_mutex); 497*f89bd95cSHenrik Rydberg 498*f89bd95cSHenrik Rydberg bcm5974_pause_traffic(dev); 499*f89bd95cSHenrik Rydberg dev->opened = 0; 500*f89bd95cSHenrik Rydberg 501*f89bd95cSHenrik Rydberg mutex_unlock(&dev->pm_mutex); 502*f89bd95cSHenrik Rydberg } 503*f89bd95cSHenrik Rydberg 504*f89bd95cSHenrik Rydberg static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) 505*f89bd95cSHenrik Rydberg { 506*f89bd95cSHenrik Rydberg struct bcm5974 *dev = usb_get_intfdata(iface); 507*f89bd95cSHenrik Rydberg 508*f89bd95cSHenrik Rydberg mutex_lock(&dev->pm_mutex); 509*f89bd95cSHenrik Rydberg 510*f89bd95cSHenrik Rydberg if (dev->opened) 511*f89bd95cSHenrik Rydberg bcm5974_pause_traffic(dev); 512*f89bd95cSHenrik Rydberg 513*f89bd95cSHenrik Rydberg mutex_unlock(&dev->pm_mutex); 514*f89bd95cSHenrik Rydberg 515*f89bd95cSHenrik Rydberg return 0; 516*f89bd95cSHenrik Rydberg } 517*f89bd95cSHenrik Rydberg 518*f89bd95cSHenrik Rydberg static int bcm5974_resume(struct usb_interface *iface) 519*f89bd95cSHenrik Rydberg { 520*f89bd95cSHenrik Rydberg struct bcm5974 *dev = usb_get_intfdata(iface); 521*f89bd95cSHenrik Rydberg int error = 0; 522*f89bd95cSHenrik Rydberg 523*f89bd95cSHenrik Rydberg mutex_lock(&dev->pm_mutex); 524*f89bd95cSHenrik Rydberg 525*f89bd95cSHenrik Rydberg if (dev->opened) 526*f89bd95cSHenrik Rydberg error = bcm5974_start_traffic(dev); 527*f89bd95cSHenrik Rydberg 528*f89bd95cSHenrik Rydberg mutex_unlock(&dev->pm_mutex); 529*f89bd95cSHenrik Rydberg 530*f89bd95cSHenrik Rydberg return error; 531*f89bd95cSHenrik Rydberg } 532*f89bd95cSHenrik Rydberg 533*f89bd95cSHenrik Rydberg static int bcm5974_probe(struct usb_interface *iface, 534*f89bd95cSHenrik Rydberg const struct usb_device_id *id) 535*f89bd95cSHenrik Rydberg { 536*f89bd95cSHenrik Rydberg struct usb_device *udev = interface_to_usbdev(iface); 537*f89bd95cSHenrik Rydberg const struct bcm5974_config *cfg; 538*f89bd95cSHenrik Rydberg struct bcm5974 *dev; 539*f89bd95cSHenrik Rydberg struct input_dev *input_dev; 540*f89bd95cSHenrik Rydberg int error = -ENOMEM; 541*f89bd95cSHenrik Rydberg 542*f89bd95cSHenrik Rydberg /* find the product index */ 543*f89bd95cSHenrik Rydberg cfg = bcm5974_get_config(udev); 544*f89bd95cSHenrik Rydberg 545*f89bd95cSHenrik Rydberg /* allocate memory for our device state and initialize it */ 546*f89bd95cSHenrik Rydberg dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); 547*f89bd95cSHenrik Rydberg input_dev = input_allocate_device(); 548*f89bd95cSHenrik Rydberg if (!dev || !input_dev) { 549*f89bd95cSHenrik Rydberg err("bcm5974: out of memory"); 550*f89bd95cSHenrik Rydberg goto err_free_devs; 551*f89bd95cSHenrik Rydberg } 552*f89bd95cSHenrik Rydberg 553*f89bd95cSHenrik Rydberg dev->udev = udev; 554*f89bd95cSHenrik Rydberg dev->input = input_dev; 555*f89bd95cSHenrik Rydberg dev->cfg = *cfg; 556*f89bd95cSHenrik Rydberg mutex_init(&dev->pm_mutex); 557*f89bd95cSHenrik Rydberg 558*f89bd95cSHenrik Rydberg /* setup urbs */ 559*f89bd95cSHenrik Rydberg dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); 560*f89bd95cSHenrik Rydberg if (!dev->bt_urb) 561*f89bd95cSHenrik Rydberg goto err_free_devs; 562*f89bd95cSHenrik Rydberg 563*f89bd95cSHenrik Rydberg dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); 564*f89bd95cSHenrik Rydberg if (!dev->tp_urb) 565*f89bd95cSHenrik Rydberg goto err_free_bt_urb; 566*f89bd95cSHenrik Rydberg 567*f89bd95cSHenrik Rydberg dev->bt_data = usb_buffer_alloc(dev->udev, 568*f89bd95cSHenrik Rydberg dev->cfg.bt_datalen, GFP_KERNEL, 569*f89bd95cSHenrik Rydberg &dev->bt_urb->transfer_dma); 570*f89bd95cSHenrik Rydberg if (!dev->bt_data) 571*f89bd95cSHenrik Rydberg goto err_free_urb; 572*f89bd95cSHenrik Rydberg 573*f89bd95cSHenrik Rydberg dev->tp_data = usb_buffer_alloc(dev->udev, 574*f89bd95cSHenrik Rydberg dev->cfg.tp_datalen, GFP_KERNEL, 575*f89bd95cSHenrik Rydberg &dev->tp_urb->transfer_dma); 576*f89bd95cSHenrik Rydberg if (!dev->tp_data) 577*f89bd95cSHenrik Rydberg goto err_free_bt_buffer; 578*f89bd95cSHenrik Rydberg 579*f89bd95cSHenrik Rydberg usb_fill_int_urb(dev->bt_urb, udev, 580*f89bd95cSHenrik Rydberg usb_rcvintpipe(udev, cfg->bt_ep), 581*f89bd95cSHenrik Rydberg dev->bt_data, dev->cfg.bt_datalen, 582*f89bd95cSHenrik Rydberg bcm5974_irq_button, dev, 1); 583*f89bd95cSHenrik Rydberg 584*f89bd95cSHenrik Rydberg usb_fill_int_urb(dev->tp_urb, udev, 585*f89bd95cSHenrik Rydberg usb_rcvintpipe(udev, cfg->tp_ep), 586*f89bd95cSHenrik Rydberg dev->tp_data, dev->cfg.tp_datalen, 587*f89bd95cSHenrik Rydberg bcm5974_irq_trackpad, dev, 1); 588*f89bd95cSHenrik Rydberg 589*f89bd95cSHenrik Rydberg /* create bcm5974 device */ 590*f89bd95cSHenrik Rydberg usb_make_path(udev, dev->phys, sizeof(dev->phys)); 591*f89bd95cSHenrik Rydberg strlcat(dev->phys, "/input0", sizeof(dev->phys)); 592*f89bd95cSHenrik Rydberg 593*f89bd95cSHenrik Rydberg input_dev->name = "bcm5974"; 594*f89bd95cSHenrik Rydberg input_dev->phys = dev->phys; 595*f89bd95cSHenrik Rydberg usb_to_input_id(dev->udev, &input_dev->id); 596*f89bd95cSHenrik Rydberg input_dev->dev.parent = &iface->dev; 597*f89bd95cSHenrik Rydberg 598*f89bd95cSHenrik Rydberg input_set_drvdata(input_dev, dev); 599*f89bd95cSHenrik Rydberg 600*f89bd95cSHenrik Rydberg input_dev->open = bcm5974_open; 601*f89bd95cSHenrik Rydberg input_dev->close = bcm5974_close; 602*f89bd95cSHenrik Rydberg 603*f89bd95cSHenrik Rydberg setup_events_to_report(input_dev, cfg); 604*f89bd95cSHenrik Rydberg 605*f89bd95cSHenrik Rydberg error = input_register_device(dev->input); 606*f89bd95cSHenrik Rydberg if (error) 607*f89bd95cSHenrik Rydberg goto err_free_buffer; 608*f89bd95cSHenrik Rydberg 609*f89bd95cSHenrik Rydberg /* save our data pointer in this interface device */ 610*f89bd95cSHenrik Rydberg usb_set_intfdata(iface, dev); 611*f89bd95cSHenrik Rydberg 612*f89bd95cSHenrik Rydberg return 0; 613*f89bd95cSHenrik Rydberg 614*f89bd95cSHenrik Rydberg err_free_buffer: 615*f89bd95cSHenrik Rydberg usb_buffer_free(dev->udev, dev->cfg.tp_datalen, 616*f89bd95cSHenrik Rydberg dev->tp_data, dev->tp_urb->transfer_dma); 617*f89bd95cSHenrik Rydberg err_free_bt_buffer: 618*f89bd95cSHenrik Rydberg usb_buffer_free(dev->udev, dev->cfg.bt_datalen, 619*f89bd95cSHenrik Rydberg dev->bt_data, dev->bt_urb->transfer_dma); 620*f89bd95cSHenrik Rydberg err_free_urb: 621*f89bd95cSHenrik Rydberg usb_free_urb(dev->tp_urb); 622*f89bd95cSHenrik Rydberg err_free_bt_urb: 623*f89bd95cSHenrik Rydberg usb_free_urb(dev->bt_urb); 624*f89bd95cSHenrik Rydberg err_free_devs: 625*f89bd95cSHenrik Rydberg usb_set_intfdata(iface, NULL); 626*f89bd95cSHenrik Rydberg input_free_device(input_dev); 627*f89bd95cSHenrik Rydberg kfree(dev); 628*f89bd95cSHenrik Rydberg return error; 629*f89bd95cSHenrik Rydberg } 630*f89bd95cSHenrik Rydberg 631*f89bd95cSHenrik Rydberg static void bcm5974_disconnect(struct usb_interface *iface) 632*f89bd95cSHenrik Rydberg { 633*f89bd95cSHenrik Rydberg struct bcm5974 *dev = usb_get_intfdata(iface); 634*f89bd95cSHenrik Rydberg 635*f89bd95cSHenrik Rydberg usb_set_intfdata(iface, NULL); 636*f89bd95cSHenrik Rydberg 637*f89bd95cSHenrik Rydberg input_unregister_device(dev->input); 638*f89bd95cSHenrik Rydberg usb_buffer_free(dev->udev, dev->cfg.tp_datalen, 639*f89bd95cSHenrik Rydberg dev->tp_data, dev->tp_urb->transfer_dma); 640*f89bd95cSHenrik Rydberg usb_buffer_free(dev->udev, dev->cfg.bt_datalen, 641*f89bd95cSHenrik Rydberg dev->bt_data, dev->bt_urb->transfer_dma); 642*f89bd95cSHenrik Rydberg usb_free_urb(dev->tp_urb); 643*f89bd95cSHenrik Rydberg usb_free_urb(dev->bt_urb); 644*f89bd95cSHenrik Rydberg kfree(dev); 645*f89bd95cSHenrik Rydberg } 646*f89bd95cSHenrik Rydberg 647*f89bd95cSHenrik Rydberg static struct usb_driver bcm5974_driver = { 648*f89bd95cSHenrik Rydberg .name = "bcm5974", 649*f89bd95cSHenrik Rydberg .probe = bcm5974_probe, 650*f89bd95cSHenrik Rydberg .disconnect = bcm5974_disconnect, 651*f89bd95cSHenrik Rydberg .suspend = bcm5974_suspend, 652*f89bd95cSHenrik Rydberg .resume = bcm5974_resume, 653*f89bd95cSHenrik Rydberg .reset_resume = bcm5974_resume, 654*f89bd95cSHenrik Rydberg .id_table = bcm5974_table, 655*f89bd95cSHenrik Rydberg }; 656*f89bd95cSHenrik Rydberg 657*f89bd95cSHenrik Rydberg static int __init bcm5974_init(void) 658*f89bd95cSHenrik Rydberg { 659*f89bd95cSHenrik Rydberg return usb_register(&bcm5974_driver); 660*f89bd95cSHenrik Rydberg } 661*f89bd95cSHenrik Rydberg 662*f89bd95cSHenrik Rydberg static void __exit bcm5974_exit(void) 663*f89bd95cSHenrik Rydberg { 664*f89bd95cSHenrik Rydberg usb_deregister(&bcm5974_driver); 665*f89bd95cSHenrik Rydberg } 666*f89bd95cSHenrik Rydberg 667*f89bd95cSHenrik Rydberg module_init(bcm5974_init); 668*f89bd95cSHenrik Rydberg module_exit(bcm5974_exit); 669*f89bd95cSHenrik Rydberg 670