diff options
Diffstat (limited to 'bcm5974.c')
| -rw-r--r-- | bcm5974.c | 667 |
1 files changed, 352 insertions, 315 deletions
| @@ -39,42 +39,43 @@ | |||
| 39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <linux/usb/input.h> | 40 | #include <linux/usb/input.h> |
| 41 | #include <linux/hid.h> | 41 | #include <linux/hid.h> |
| 42 | #include <linux/mutex.h> | ||
| 42 | 43 | ||
| 43 | #define APPLE_VENDOR_ID 0x05AC | 44 | #define USB_VENDOR_ID_APPLE 0x05ac |
| 44 | 45 | ||
| 45 | /* MacbookAir, aka wellspring */ | 46 | /* MacbookAir, aka wellspring */ |
| 46 | #define ATP_WELLSPRING_ANSI 0x0223 | 47 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 |
| 47 | #define ATP_WELLSPRING_ISO 0x0224 | 48 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 |
| 48 | #define ATP_WELLSPRING_JIS 0x0225 | 49 | #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 |
| 49 | /* MacbookProPenryn, aka wellspring2 */ | 50 | /* MacbookProPenryn, aka wellspring2 */ |
| 50 | #define ATP_WELLSPRING2_ANSI 0x0230 | 51 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 |
| 51 | #define ATP_WELLSPRING2_ISO 0x0231 | 52 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 |
| 52 | #define ATP_WELLSPRING2_JIS 0x0232 | 53 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 |
| 53 | 54 | ||
| 54 | #define ATP_DEVICE(prod) { \ | 55 | #define BCM5974_DEVICE(prod) { \ |
| 55 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | 56 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ |
| 56 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | 57 | USB_DEVICE_ID_MATCH_INT_CLASS | \ |
| 57 | USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ | 58 | USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ |
| 58 | .idVendor = APPLE_VENDOR_ID, \ | 59 | .idVendor = USB_VENDOR_ID_APPLE, \ |
| 59 | .idProduct = (prod), \ | 60 | .idProduct = (prod), \ |
| 60 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ | 61 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ |
| 61 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ | 62 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | /* table of devices that work with this driver */ | 65 | /* table of devices that work with this driver */ |
| 65 | static const struct usb_device_id atp_table [] = { | 66 | static const struct usb_device_id bcm5974_table[] = { |
| 66 | /* MacbookAir1.1 */ | 67 | /* MacbookAir1.1 */ |
| 67 | ATP_DEVICE(ATP_WELLSPRING_ANSI), | 68 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), |
| 68 | ATP_DEVICE(ATP_WELLSPRING_ISO), | 69 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), |
| 69 | ATP_DEVICE(ATP_WELLSPRING_JIS), | 70 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS), |
| 70 | /* MacbookProPenryn */ | 71 | /* MacbookProPenryn */ |
| 71 | ATP_DEVICE(ATP_WELLSPRING2_ANSI), | 72 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), |
| 72 | ATP_DEVICE(ATP_WELLSPRING2_ISO), | 73 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), |
| 73 | ATP_DEVICE(ATP_WELLSPRING2_JIS), | 74 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), |
| 74 | /* Terminating entry */ | 75 | /* Terminating entry */ |
| 75 | {} | 76 | {} |
| 76 | }; | 77 | }; |
| 77 | MODULE_DEVICE_TABLE(usb, atp_table); | 78 | MODULE_DEVICE_TABLE(usb, bcm5974_table); |
| 78 | 79 | ||
| 79 | MODULE_AUTHOR("Henrik Rydberg"); | 80 | MODULE_AUTHOR("Henrik Rydberg"); |
| 80 | MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); | 81 | MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); |
| @@ -104,7 +105,7 @@ struct tp_header { | |||
| 104 | 105 | ||
| 105 | /* trackpad finger structure */ | 106 | /* trackpad finger structure */ |
| 106 | struct tp_finger { | 107 | struct tp_finger { |
| 107 | __le16 origin; /* left/right origin? */ | 108 | __le16 origin; /* zero when switching track finger */ |
| 108 | __le16 abs_x; /* absolute x coodinate */ | 109 | __le16 abs_x; /* absolute x coodinate */ |
| 109 | __le16 abs_y; /* absolute y coodinate */ | 110 | __le16 abs_y; /* absolute y coodinate */ |
| 110 | __le16 rel_x; /* relative x coodinate */ | 111 | __le16 rel_x; /* relative x coodinate */ |
| @@ -125,50 +126,40 @@ struct tp_data { | |||
| 125 | }; | 126 | }; |
| 126 | 127 | ||
| 127 | /* device-specific parameters */ | 128 | /* device-specific parameters */ |
| 128 | struct atp_params { | 129 | struct bcm5974_param { |
| 129 | int dim; /* logical dimension */ | 130 | int dim; /* logical dimension */ |
| 131 | int fuzz; /* logical noise value */ | ||
| 130 | int devmin; /* device minimum reading */ | 132 | int devmin; /* device minimum reading */ |
| 131 | int devmax; /* device maximum reading */ | 133 | int devmax; /* device maximum reading */ |
| 132 | }; | 134 | }; |
| 133 | 135 | ||
| 134 | /* device-specific configuration */ | 136 | /* device-specific configuration */ |
| 135 | struct atp_config { | 137 | struct bcm5974_config { |
| 136 | int ansi, iso, jis; /* the product id of this device */ | 138 | int ansi, iso, jis; /* the product id of this device */ |
| 137 | int bt_ep; /* the endpoint of the button interface */ | 139 | int bt_ep; /* the endpoint of the button interface */ |
| 138 | int bt_datalen; /* data length of the button interface */ | 140 | int bt_datalen; /* data length of the button interface */ |
| 139 | int tp_ep; /* the endpoint of the trackpad interface */ | 141 | int tp_ep; /* the endpoint of the trackpad interface */ |
| 140 | int tp_datalen; /* data length of the trackpad interface */ | 142 | int tp_datalen; /* data length of the trackpad interface */ |
| 141 | struct atp_params p; /* finger pressure limits */ | 143 | struct bcm5974_param p; /* finger pressure limits */ |
| 142 | struct atp_params w; /* finger width limits */ | 144 | struct bcm5974_param w; /* finger width limits */ |
| 143 | struct atp_params x; /* horizontal limits */ | 145 | struct bcm5974_param x; /* horizontal limits */ |
| 144 | struct atp_params y; /* vertical limits */ | 146 | struct bcm5974_param y; /* vertical limits */ |
| 145 | }; | ||
| 146 | |||
| 147 | /* logical trackpad state */ | ||
| 148 | struct tp_state { | ||
| 149 | int pressure; /* finger pressure value */ | ||
| 150 | int width; /* finger width value */ | ||
| 151 | int abs_x; /* absolute x coordinate */ | ||
| 152 | int abs_y; /* absolute y coordinate */ | ||
| 153 | int fingers; /* number of fingers on trackpad */ | ||
| 154 | }; | 147 | }; |
| 155 | 148 | ||
| 156 | /* logical device structure */ | 149 | /* logical device structure */ |
| 157 | struct atp { | 150 | struct bcm5974 { |
| 158 | char phys[64]; | 151 | char phys[64]; |
| 159 | struct usb_device *udev; /* usb device */ | 152 | struct usb_device *udev; /* usb device */ |
| 153 | struct usb_interface *intf; /* our interface */ | ||
| 160 | struct input_dev *input; /* input dev */ | 154 | struct input_dev *input; /* input dev */ |
| 161 | struct atp_config cfg; /* device configuration */ | 155 | struct bcm5974_config cfg; /* device configuration */ |
| 162 | int open; /* >0: open, else closed */ | 156 | struct mutex pm_mutex; /* serialize access to open/suspend */ |
| 163 | int suspended; /* >0: suspended, else open */ | 157 | int opened; /* 1: opened, 0: closed */ |
| 164 | struct urb *bt_urb; /* button usb request block */ | 158 | struct urb *bt_urb; /* button usb request block */ |
| 165 | struct bt_data *bt_data; /* button transferred data */ | 159 | struct bt_data *bt_data; /* button transferred data */ |
| 166 | unsigned bt_prev_state; /* logical button previous state */ | ||
| 167 | unsigned bt_state; /* logical button state */ | ||
| 168 | struct urb *tp_urb; /* trackpad usb request block */ | 160 | struct urb *tp_urb; /* trackpad usb request block */ |
| 169 | struct tp_data *tp_data; /* trackpad transferred data */ | 161 | struct tp_data *tp_data; /* trackpad transferred data */ |
| 170 | struct tp_state tp_state; /* logical trackpad state */ | 162 | int fingers; /* number of fingers on trackpad */ |
| 171 | unsigned tp_valid; /* trackpad sensors valid */ | ||
| 172 | }; | 163 | }; |
| 173 | 164 | ||
| 174 | /* logical dimensions */ | 165 | /* logical dimensions */ |
| @@ -176,45 +167,54 @@ struct atp { | |||
| 176 | #define DIM_WIDTH 16 /* maximum finger width */ | 167 | #define DIM_WIDTH 16 /* maximum finger width */ |
| 177 | #define DIM_X 1280 /* maximum trackpad x value */ | 168 | #define DIM_X 1280 /* maximum trackpad x value */ |
| 178 | #define DIM_Y 800 /* maximum trackpad y value */ | 169 | #define DIM_Y 800 /* maximum trackpad y value */ |
| 179 | #define SNRATIO 50 /* signal to noise ratio */ | 170 | |
| 171 | /* logical signal quality */ | ||
| 172 | #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ | ||
| 173 | #define SN_WIDTH 100 /* width signal-to-noise ratio */ | ||
| 174 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ | ||
| 175 | |||
| 176 | /* pressure thresholds */ | ||
| 177 | #define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) | ||
| 178 | #define PRESSURE_HIGH (3 * PRESSURE_LOW) | ||
| 180 | 179 | ||
| 181 | /* device constants */ | 180 | /* device constants */ |
| 182 | static const struct atp_config atp_config_table[] = { | 181 | static const struct bcm5974_config bcm5974_config_table[] = { |
| 183 | { | 182 | { |
| 184 | ATP_WELLSPRING_ANSI, | 183 | USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, |
| 185 | ATP_WELLSPRING_ISO, | 184 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, |
| 186 | ATP_WELLSPRING_JIS, | 185 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, |
| 187 | 0x84, sizeof(struct bt_data), | 186 | 0x84, sizeof(struct bt_data), |
| 188 | 0x81, sizeof(struct tp_data), | 187 | 0x81, sizeof(struct tp_data), |
| 189 | { DIM_PRESSURE, 0, 256 }, | 188 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
| 190 | { DIM_WIDTH, 0, 2048 }, | 189 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
| 191 | { DIM_X, -4824, 5342 }, | 190 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, |
| 192 | { DIM_Y, -172, 5820 } | 191 | { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } |
| 193 | }, | 192 | }, |
| 194 | { | 193 | { |
| 195 | ATP_WELLSPRING2_ANSI, | 194 | USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, |
| 196 | ATP_WELLSPRING2_ISO, | 195 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, |
| 197 | ATP_WELLSPRING2_JIS, | 196 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, |
| 198 | 0x84, sizeof(struct bt_data), | 197 | 0x84, sizeof(struct bt_data), |
| 199 | 0x81, sizeof(struct tp_data), | 198 | 0x81, sizeof(struct tp_data), |
| 200 | { DIM_PRESSURE, 0, 256 }, | 199 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
| 201 | { DIM_WIDTH, 0, 2048 }, | 200 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
| 202 | { DIM_X, -4824, 5342 }, | 201 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, |
| 203 | { DIM_Y, -172, 5820 } | 202 | { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } |
| 204 | }, | 203 | }, |
| 205 | {} | 204 | {} |
| 206 | }; | 205 | }; |
| 207 | 206 | ||
| 208 | /* return the device-specific configuration by device */ | 207 | /* return the device-specific configuration by device */ |
| 209 | static const struct atp_config *atp_product_config(struct usb_device *udev) | 208 | static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev) |
| 210 | { | 209 | { |
| 211 | u16 id = le16_to_cpu(udev->descriptor.idProduct); | 210 | u16 id = le16_to_cpu(udev->descriptor.idProduct); |
| 212 | const struct atp_config *config; | 211 | const struct bcm5974_config *cfg; |
| 213 | for (config = atp_config_table; config->ansi; ++config) | 212 | |
| 214 | if (config->ansi == id || config->iso == id || | 213 | for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) |
| 215 | config->jis == id) | 214 | if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) |
| 216 | return config; | 215 | return cfg; |
| 217 | return atp_config_table; | 216 | |
| 217 | return bcm5974_config_table; | ||
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | /* convert 16-bit little endian to signed integer */ | 220 | /* convert 16-bit little endian to signed integer */ |
| @@ -224,142 +224,189 @@ static inline int raw2int(__le16 x) | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | /* scale device data to logical dimensions (asserts devmin < devmax) */ | 226 | /* scale device data to logical dimensions (asserts devmin < devmax) */ |
| 227 | static inline int int2scale(const struct atp_params *p, int x) | 227 | static inline int int2scale(const struct bcm5974_param *p, int x) |
| 228 | { | 228 | { |
| 229 | return x * p->dim / (p->devmax - p->devmin); | 229 | return x * p->dim / (p->devmax - p->devmin); |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | /* all logical value ranges are [0,dim). */ | 232 | /* all logical value ranges are [0,dim). */ |
| 233 | static inline int int2bound(const struct atp_params *p, int x) | 233 | static inline int int2bound(const struct bcm5974_param *p, int x) |
| 234 | { | 234 | { |
| 235 | int s = int2scale(p, x); | 235 | int s = int2scale(p, x); |
| 236 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; | 236 | |
| 237 | //return clamp_val(s, 0, p->dim - 1); | ||
| 238 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; | ||
| 237 | } | 239 | } |
| 238 | 240 | ||
| 239 | /* convert button data to logical button state */ | 241 | /* setup which logical events to report */ |
| 240 | static int compute_bt_state(struct atp *dev, int size) | 242 | static void setup_events_to_report(struct input_dev *input_dev, |
| 243 | const struct bcm5974_config *cfg) | ||
| 244 | { | ||
| 245 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 246 | |||
| 247 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
| 248 | 0, cfg->p.dim, cfg->p.fuzz, 0); | ||
| 249 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, | ||
| 250 | 0, cfg->w.dim, cfg->w.fuzz, 0); | ||
| 251 | input_set_abs_params(input_dev, ABS_X, | ||
| 252 | 0, cfg->x.dim, cfg->x.fuzz, 0); | ||
| 253 | input_set_abs_params(input_dev, ABS_Y, | ||
| 254 | 0, cfg->y.dim, cfg->y.fuzz, 0); | ||
| 255 | |||
| 256 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 257 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 258 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
| 259 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 260 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
| 261 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
| 262 | } | ||
| 263 | |||
| 264 | /* report button data as logical button state */ | ||
| 265 | static int report_bt_state(struct bcm5974 *dev, int size) | ||
| 241 | { | 266 | { |
| 242 | if (size != sizeof(struct bt_data)) | 267 | if (size != sizeof(struct bt_data)) |
| 243 | return -EIO; | 268 | return -EIO; |
| 244 | 269 | ||
| 245 | dev->bt_prev_state = dev->bt_state; | 270 | input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); |
| 246 | dev->bt_state = dev->bt_data->button; | 271 | input_sync(dev->input); |
| 247 | 272 | ||
| 248 | return 0; | 273 | return 0; |
| 249 | } | 274 | } |
| 250 | 275 | ||
| 251 | /* convert trackpad data to logical trackpad state */ | 276 | /* report trackpad data as logical trackpad state */ |
| 252 | static int compute_tp_state(struct atp *dev, int size) | 277 | static int report_tp_state(struct bcm5974 *dev, int size) |
| 253 | { | 278 | { |
| 254 | const struct atp_config *c = &dev->cfg; | 279 | const struct bcm5974_config *c = &dev->cfg; |
| 255 | const struct tp_finger *f = dev->tp_data->finger; | 280 | const struct tp_finger *f = dev->tp_data->finger; |
| 281 | struct input_dev *input = dev->input; | ||
| 256 | const int fingers = (size - 26) / 28; | 282 | const int fingers = (size - 26) / 28; |
| 257 | struct tp_state *s = &dev->tp_state; | 283 | int raw_p, raw_w, raw_x, raw_y; |
| 284 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; | ||
| 285 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | ||
| 258 | 286 | ||
| 259 | if (size < 26 || (size - 26) % 28 != 0) | 287 | if (size < 26 || (size - 26) % 28 != 0) |
| 260 | return -EIO; | 288 | return -EIO; |
| 261 | 289 | ||
| 262 | if (!fingers) { | 290 | /* always track the first finger; when detached, start over */ |
| 263 | s->pressure = 0; | 291 | if (fingers) { |
| 264 | s->fingers = 0; | 292 | raw_p = raw2int(f->force_major); |
| 265 | return 0; | 293 | raw_w = raw2int(f->size_major); |
| 294 | raw_x = raw2int(f->abs_x); | ||
| 295 | raw_y = raw2int(f->abs_y); | ||
| 296 | |||
| 297 | dprintk(9, | ||
| 298 | "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", | ||
| 299 | raw_p, raw_w, raw_x, raw_y); | ||
| 300 | |||
| 301 | ptest = int2bound(&c->p, raw_p); | ||
| 302 | origin = raw2int(f->origin); | ||
| 303 | } | ||
| 304 | |||
| 305 | /* while tracking finger still valid, count all fingers */ | ||
| 306 | if (ptest > PRESSURE_LOW && origin) { | ||
| 307 | abs_p = ptest; | ||
| 308 | abs_w = int2bound(&c->w, raw_w); | ||
| 309 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | ||
| 310 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | ||
| 311 | for (; f != dev->tp_data->finger + fingers; f++) { | ||
| 312 | ptest = int2bound(&c->p, raw2int(f->force_major)); | ||
| 313 | if (ptest > PRESSURE_LOW) | ||
| 314 | nmax++; | ||
| 315 | if (ptest > PRESSURE_HIGH) | ||
| 316 | nmin++; | ||
| 317 | } | ||
| 266 | } | 318 | } |
| 267 | 319 | ||
| 268 | dprintk(9, "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d f: %d\n", | 320 | if (dev->fingers < nmin) |
| 269 | raw2int(f->force_major), raw2int(f->size_major), | 321 | dev->fingers = nmin; |
| 270 | raw2int(f->abs_x), raw2int(f->abs_y), fingers); | 322 | if (dev->fingers > nmax) |
| 323 | dev->fingers = nmax; | ||
| 324 | |||
| 325 | input_report_key(input, BTN_TOUCH, dev->fingers > 0); | ||
| 326 | input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); | ||
| 327 | input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); | ||
| 328 | input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); | ||
| 329 | |||
| 330 | input_report_abs(input, ABS_PRESSURE, abs_p); | ||
| 331 | input_report_abs(input, ABS_TOOL_WIDTH, abs_w); | ||
| 332 | |||
| 333 | if (abs_p) { | ||
| 334 | input_report_abs(input, ABS_X, abs_x); | ||
| 335 | input_report_abs(input, ABS_Y, abs_y); | ||
| 336 | |||
| 337 | dprintk(8, | ||
| 338 | "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " | ||
| 339 | "nmin: %d nmax: %d n: %d\n", | ||
| 340 | abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); | ||
| 271 | 341 | ||
| 272 | s->pressure = int2bound(&c->p, raw2int(f->force_major)); | 342 | } |
| 273 | s->width = int2bound(&c->w, raw2int(f->size_major)); | 343 | |
| 274 | s->abs_x = int2bound(&c->x, raw2int(f->abs_x) - c->x.devmin); | 344 | input_sync(input); |
| 275 | s->abs_y = int2bound(&c->y, c->y.devmax - raw2int(f->abs_y)); | ||
| 276 | s->fingers = s->pressure > 0 ? fingers : 0; | ||
| 277 | 345 | ||
| 278 | return 0; | 346 | return 0; |
| 279 | } | 347 | } |
| 280 | 348 | ||
| 281 | /* Wellspring initialization constants */ | 349 | /* Wellspring initialization constants */ |
| 282 | #define ATP_WELLSPRING_MODE_READ_REQUEST_ID 1 | 350 | #define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 |
| 283 | #define ATP_WELLSPRING_MODE_WRITE_REQUEST_ID 9 | 351 | #define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 |
| 284 | #define ATP_WELLSPRING_MODE_REQUEST_VALUE 0x300 | 352 | #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 |
| 285 | #define ATP_WELLSPRING_MODE_REQUEST_INDEX 0 | 353 | #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 |
| 286 | #define ATP_WELLSPRING_MODE_VENDOR_VALUE_1 0x01 | 354 | #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 |
| 287 | #define ATP_WELLSPRING_MODE_VENDOR_VALUE_2 0x05 | 355 | #define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 |
| 288 | 356 | ||
| 289 | static int atp_wellspring_init(struct atp *dev) | 357 | static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) |
| 290 | { | 358 | { |
| 291 | char *data = kmalloc(8, GFP_KERNEL); | 359 | char *data = kmalloc(8, GFP_KERNEL); |
| 292 | int error = 0, size; | 360 | int retval = 0, size; |
| 293 | 361 | ||
| 294 | if (!data) { | 362 | if (!data) { |
| 295 | err("bcm5974: out of memory"); | 363 | err("bcm5974: out of memory"); |
| 296 | error = -ENOMEM; | 364 | retval = -ENOMEM; |
| 297 | goto error; | 365 | goto out; |
| 298 | } | ||
| 299 | |||
| 300 | /* reset button endpoint */ | ||
| 301 | if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
| 302 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, | ||
| 303 | 0, dev->cfg.bt_ep, NULL, 0, 5000)) { | ||
| 304 | err("bcm5974: could not reset button endpoint"); | ||
| 305 | error = -EIO; | ||
| 306 | goto error; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* reset trackpad endpoint */ | ||
| 310 | if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
| 311 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, | ||
| 312 | 0, dev->cfg.tp_ep, NULL, 0, 5000)) { | ||
| 313 | err("bcm5974: could not reset trackpad endpoint"); | ||
| 314 | error = -EIO; | ||
| 315 | goto error; | ||
| 316 | } | 366 | } |
| 317 | 367 | ||
| 318 | /* read configuration */ | 368 | /* read configuration */ |
| 319 | size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | 369 | size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), |
| 320 | ATP_WELLSPRING_MODE_READ_REQUEST_ID, | 370 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, |
| 321 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 371 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 322 | ATP_WELLSPRING_MODE_REQUEST_VALUE, | 372 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, |
| 323 | ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | 373 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); |
| 324 | 374 | ||
| 325 | if (size != 8) { | 375 | if (size != 8) { |
| 326 | err("bcm5974: could not read from device"); | 376 | err("bcm5974: could not read from device"); |
| 327 | error = -EIO; | 377 | retval = -EIO; |
| 328 | goto error; | 378 | goto out; |
| 329 | } | 379 | } |
| 330 | 380 | ||
| 331 | /* apply the mode switch */ | 381 | /* apply the mode switch */ |
| 332 | data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE_1; | 382 | data[0] = on ? |
| 333 | data[1] = ATP_WELLSPRING_MODE_VENDOR_VALUE_2; | 383 | BCM5974_WELLSPRING_MODE_VENDOR_VALUE : |
| 384 | BCM5974_WELLSPRING_MODE_NORMAL_VALUE; | ||
| 334 | 385 | ||
| 335 | /* write configuration */ | 386 | /* write configuration */ |
| 336 | size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | 387 | size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), |
| 337 | ATP_WELLSPRING_MODE_WRITE_REQUEST_ID, | 388 | BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, |
| 338 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 389 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 339 | ATP_WELLSPRING_MODE_REQUEST_VALUE, | 390 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, |
| 340 | ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | 391 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); |
| 341 | 392 | ||
| 342 | if (size != 8) { | 393 | if (size != 8) { |
| 343 | err("bcm5974: could not write to device"); | 394 | err("bcm5974: could not write to device"); |
| 344 | error = -EIO; | 395 | retval = -EIO; |
| 345 | goto error; | 396 | goto out; |
| 346 | } | 397 | } |
| 347 | 398 | ||
| 348 | dev->tp_valid = 0; | 399 | dprintk(2, "bcm5974: switched to %s mode.\n", |
| 349 | 400 | on ? "wellspring" : "normal"); | |
| 350 | printk(KERN_INFO "bcm5974: Wellspring mode initialized.\n"); | ||
| 351 | 401 | ||
| 402 | out: | ||
| 352 | kfree(data); | 403 | kfree(data); |
| 353 | return 0; | 404 | return retval; |
| 354 | |||
| 355 | error: | ||
| 356 | kfree(data); | ||
| 357 | return error; | ||
| 358 | } | 405 | } |
| 359 | 406 | ||
| 360 | static void irq_button(struct urb *urb) | 407 | static void bcm5974_irq_button(struct urb *urb) |
| 361 | { | 408 | { |
| 362 | struct atp *dev = urb->context; | 409 | struct bcm5974 *dev = urb->context; |
| 363 | int error; | 410 | int error; |
| 364 | 411 | ||
| 365 | switch (urb->status) { | 412 | switch (urb->status) { |
| @@ -376,17 +423,9 @@ static void irq_button(struct urb *urb) | |||
| 376 | goto exit; | 423 | goto exit; |
| 377 | } | 424 | } |
| 378 | 425 | ||
| 379 | if (compute_bt_state(dev, dev->bt_urb->actual_length)) { | 426 | if (report_bt_state(dev, dev->bt_urb->actual_length)) |
| 380 | dprintk(1, "bcm5974: bad button package, length: %d)\n", | 427 | dprintk(1, "bcm5974: bad button package, length: %d\n", |
| 381 | dev->bt_urb->actual_length); | 428 | dev->bt_urb->actual_length); |
| 382 | goto exit; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* only report button state changes */ | ||
| 386 | if (dev->bt_state != dev->bt_prev_state) { | ||
| 387 | input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); | ||
| 388 | input_sync(dev->input); | ||
| 389 | } | ||
| 390 | 429 | ||
| 391 | exit: | 430 | exit: |
| 392 | error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); | 431 | error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); |
| @@ -394,10 +433,9 @@ exit: | |||
| 394 | err("bcm5974: button urb failed: %d", error); | 433 | err("bcm5974: button urb failed: %d", error); |
| 395 | } | 434 | } |
| 396 | 435 | ||
| 397 | static void irq_trackpad(struct urb *urb) | 436 | static void bcm5974_irq_trackpad(struct urb *urb) |
| 398 | { | 437 | { |
| 399 | struct atp *dev = urb->context; | 438 | struct bcm5974 *dev = urb->context; |
| 400 | struct tp_state *state = &dev->tp_state; | ||
| 401 | int error; | 439 | int error; |
| 402 | 440 | ||
| 403 | switch (urb->status) { | 441 | switch (urb->status) { |
| @@ -414,26 +452,13 @@ static void irq_trackpad(struct urb *urb) | |||
| 414 | goto exit; | 452 | goto exit; |
| 415 | } | 453 | } |
| 416 | 454 | ||
| 417 | /* first sample data ignored */ | 455 | /* control response ignored */ |
| 418 | if (!dev->tp_valid) { | 456 | if (dev->tp_urb->actual_length == 2) |
| 419 | dev->tp_valid = 1; | ||
| 420 | goto exit; | 457 | goto exit; |
| 421 | } | ||
| 422 | 458 | ||
| 423 | if (compute_tp_state(dev, dev->tp_urb->actual_length)) { | 459 | if (report_tp_state(dev, dev->tp_urb->actual_length)) |
| 424 | dprintk(1, "bcm5974: bad trackpad package, length: %d)\n", | 460 | dprintk(1, "bcm5974: bad trackpad package, length: %d\n", |
| 425 | dev->tp_urb->actual_length); | 461 | dev->tp_urb->actual_length); |
| 426 | goto exit; | ||
| 427 | } | ||
| 428 | |||
| 429 | input_report_abs(dev->input, ABS_PRESSURE, state->pressure); | ||
| 430 | input_report_abs(dev->input, ABS_TOOL_WIDTH, state->width); | ||
| 431 | input_report_abs(dev->input, ABS_X, state->abs_x); | ||
| 432 | input_report_abs(dev->input, ABS_Y, state->abs_y); | ||
| 433 | input_report_key(dev->input, BTN_TOOL_FINGER, state->fingers == 1); | ||
| 434 | input_report_key(dev->input, BTN_TOOL_DOUBLETAP, state->fingers == 2); | ||
| 435 | input_report_key(dev->input, BTN_TOOL_TRIPLETAP, state->fingers > 2); | ||
| 436 | input_sync(dev->input); | ||
| 437 | 462 | ||
| 438 | exit: | 463 | exit: |
| 439 | error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); | 464 | error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); |
| @@ -441,107 +466,184 @@ exit: | |||
| 441 | err("bcm5974: trackpad urb failed: %d", error); | 466 | err("bcm5974: trackpad urb failed: %d", error); |
| 442 | } | 467 | } |
| 443 | 468 | ||
| 444 | static int atp_open(struct input_dev *input) | 469 | /* |
| 470 | * The Wellspring trackpad, like many recent Apple trackpads, share | ||
| 471 | * the usb device with the keyboard. Since keyboards are usually | ||
| 472 | * handled by the HID system, the device ends up being handled by two | ||
| 473 | * modules. Setting up the device therefore becomes slightly | ||
| 474 | * complicated. To enable multitouch features, a mode switch is | ||
| 475 | * required, which is usually applied via the control interface of the | ||
| 476 | * device. It can be argued where this switch should take place. In | ||
| 477 | * some drivers, like appletouch, the switch is made during | ||
| 478 | * probe. However, the hid module may also alter the state of the | ||
| 479 | * device, resulting in trackpad malfunction under certain | ||
| 480 | * circumstances. To get around this problem, there is at least one | ||
| 481 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to | ||
| 482 | * recieve a reset_resume request rather than the normal resume. | ||
| 483 | * Since the implementation of reset_resume is equal to mode switch | ||
| 484 | * plus start_traffic, it seems easier to always do the switch when | ||
| 485 | * starting traffic on the device. | ||
| 486 | */ | ||
| 487 | static int bcm5974_start_traffic(struct bcm5974 *dev) | ||
| 445 | { | 488 | { |
| 446 | struct atp *dev = input_get_drvdata(input); | 489 | if (bcm5974_wellspring_mode(dev, true)) { |
| 447 | 490 | dprintk(1, "bcm5974: mode switch failed\n"); | |
| 448 | if (!dev->open) { | 491 | goto error; |
| 449 | if (usb_submit_urb(dev->bt_urb, GFP_ATOMIC)) | ||
| 450 | goto error; | ||
| 451 | if (usb_submit_urb(dev->tp_urb, GFP_ATOMIC)) | ||
| 452 | goto err_free_bt_urb; | ||
| 453 | } | 492 | } |
| 454 | 493 | ||
| 455 | dev->open = 1; | 494 | if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) |
| 456 | dev->suspended = 0; | 495 | goto error; |
| 496 | |||
| 497 | if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) | ||
| 498 | goto err_kill_bt; | ||
| 499 | |||
| 457 | return 0; | 500 | return 0; |
| 458 | 501 | ||
| 459 | err_free_bt_urb: | 502 | err_kill_bt: |
| 460 | usb_free_urb(dev->bt_urb); | 503 | usb_kill_urb(dev->bt_urb); |
| 461 | error: | 504 | error: |
| 462 | return -EIO; | 505 | return -EIO; |
| 463 | } | 506 | } |
| 464 | 507 | ||
| 465 | static void atp_close(struct input_dev *input) | 508 | static void bcm5974_pause_traffic(struct bcm5974 *dev) |
| 466 | { | 509 | { |
| 467 | struct atp *dev = input_get_drvdata(input); | ||
| 468 | |||
| 469 | usb_kill_urb(dev->tp_urb); | 510 | usb_kill_urb(dev->tp_urb); |
| 470 | usb_kill_urb(dev->bt_urb); | 511 | usb_kill_urb(dev->bt_urb); |
| 512 | bcm5974_wellspring_mode(dev, false); | ||
| 513 | } | ||
| 514 | |||
| 515 | /* | ||
| 516 | * The code below implements open/close and manual suspend/resume. | ||
| 517 | * All functions may be called in random order. | ||
| 518 | * | ||
| 519 | * Opening a suspended device fails with EACCES - permission denied. | ||
| 520 | * | ||
| 521 | * Failing a resume leaves the device resumed but closed. | ||
| 522 | */ | ||
| 523 | static int bcm5974_open(struct input_dev *input) | ||
| 524 | { | ||
| 525 | struct bcm5974 *dev = input_get_drvdata(input); | ||
| 526 | int error; | ||
| 527 | |||
| 528 | error = usb_autopm_get_interface(dev->intf); | ||
| 529 | if (error) | ||
| 530 | return error; | ||
| 471 | 531 | ||
| 472 | dev->open = 0; | 532 | mutex_lock(&dev->pm_mutex); |
| 473 | dev->suspended = 0; | 533 | |
| 534 | error = bcm5974_start_traffic(dev); | ||
| 535 | if (!error) | ||
| 536 | dev->opened = 1; | ||
| 537 | |||
| 538 | mutex_unlock(&dev->pm_mutex); | ||
| 539 | |||
| 540 | if (error) | ||
| 541 | usb_autopm_put_interface(dev->intf); | ||
| 542 | |||
| 543 | return error; | ||
| 544 | } | ||
| 545 | |||
| 546 | static void bcm5974_close(struct input_dev *input) | ||
| 547 | { | ||
| 548 | struct bcm5974 *dev = input_get_drvdata(input); | ||
| 549 | |||
| 550 | mutex_lock(&dev->pm_mutex); | ||
| 551 | |||
| 552 | bcm5974_pause_traffic(dev); | ||
| 553 | dev->opened = 0; | ||
| 554 | |||
| 555 | mutex_unlock(&dev->pm_mutex); | ||
| 556 | |||
| 557 | usb_autopm_put_interface(dev->intf); | ||
| 474 | } | 558 | } |
| 475 | 559 | ||
| 476 | static int atp_probe(struct usb_interface *iface, | 560 | static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) |
| 477 | const struct usb_device_id *id) | 561 | { |
| 562 | struct bcm5974 *dev = usb_get_intfdata(iface); | ||
| 563 | |||
| 564 | mutex_lock(&dev->pm_mutex); | ||
| 565 | |||
| 566 | if (dev->opened) | ||
| 567 | bcm5974_pause_traffic(dev); | ||
| 568 | |||
| 569 | mutex_unlock(&dev->pm_mutex); | ||
| 570 | |||
| 571 | return 0; | ||
| 572 | } | ||
| 573 | |||
| 574 | static int bcm5974_resume(struct usb_interface *iface) | ||
| 575 | { | ||
| 576 | struct bcm5974 *dev = usb_get_intfdata(iface); | ||
| 577 | int error = 0; | ||
| 578 | |||
| 579 | mutex_lock(&dev->pm_mutex); | ||
| 580 | |||
| 581 | if (dev->opened) | ||
| 582 | error = bcm5974_start_traffic(dev); | ||
| 583 | |||
| 584 | mutex_unlock(&dev->pm_mutex); | ||
| 585 | |||
| 586 | return error; | ||
| 587 | } | ||
| 588 | |||
| 589 | static int bcm5974_probe(struct usb_interface *iface, | ||
| 590 | const struct usb_device_id *id) | ||
| 478 | { | 591 | { |
| 479 | struct usb_device *udev = interface_to_usbdev(iface); | 592 | struct usb_device *udev = interface_to_usbdev(iface); |
| 480 | const struct atp_config *cfg; | 593 | const struct bcm5974_config *cfg; |
| 481 | struct atp *dev; | 594 | struct bcm5974 *dev; |
| 482 | struct input_dev *input_dev; | 595 | struct input_dev *input_dev; |
| 483 | int error = 0; | 596 | int error = -ENOMEM; |
| 484 | 597 | ||
| 485 | /* find the product index */ | 598 | /* find the product index */ |
| 486 | cfg = atp_product_config(udev); | 599 | cfg = bcm5974_get_config(udev); |
| 487 | 600 | ||
| 488 | /* allocate memory for our device state and initialize it */ | 601 | /* allocate memory for our device state and initialize it */ |
| 489 | dev = kzalloc(sizeof(struct atp), GFP_KERNEL); | 602 | dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); |
| 490 | input_dev = input_allocate_device(); | 603 | input_dev = input_allocate_device(); |
| 491 | if (!dev || !input_dev) { | 604 | if (!dev || !input_dev) { |
| 492 | err("bcm5974: out of memory"); | 605 | err("bcm5974: out of memory"); |
| 493 | error = -ENOMEM; | ||
| 494 | goto err_free_devs; | 606 | goto err_free_devs; |
| 495 | } | 607 | } |
| 496 | 608 | ||
| 497 | dev->udev = udev; | 609 | dev->udev = udev; |
| 610 | dev->intf = iface; | ||
| 498 | dev->input = input_dev; | 611 | dev->input = input_dev; |
| 499 | dev->cfg = *cfg; | 612 | dev->cfg = *cfg; |
| 613 | mutex_init(&dev->pm_mutex); | ||
| 500 | 614 | ||
| 501 | /* switch to raw sensor mode */ | 615 | /* setup urbs */ |
| 502 | if (atp_wellspring_init(dev)) { | ||
| 503 | error = -EIO; | ||
| 504 | goto err_free_devs; | ||
| 505 | } | ||
| 506 | |||
| 507 | dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); | 616 | dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); |
| 508 | if (!dev->bt_urb) { | 617 | if (!dev->bt_urb) |
| 509 | error = -ENOMEM; | ||
| 510 | goto err_free_devs; | 618 | goto err_free_devs; |
| 511 | } | ||
| 512 | 619 | ||
| 513 | dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); | 620 | dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); |
| 514 | if (!dev->tp_urb) { | 621 | if (!dev->tp_urb) |
| 515 | error = -ENOMEM; | ||
| 516 | goto err_free_bt_urb; | 622 | goto err_free_bt_urb; |
| 517 | } | ||
| 518 | 623 | ||
| 519 | dev->bt_data = usb_buffer_alloc(dev->udev, | 624 | dev->bt_data = usb_buffer_alloc(dev->udev, |
| 520 | dev->cfg.bt_datalen, GFP_KERNEL, | 625 | dev->cfg.bt_datalen, GFP_KERNEL, |
| 521 | &dev->bt_urb->transfer_dma); | 626 | &dev->bt_urb->transfer_dma); |
| 522 | if (!dev->bt_data) { | 627 | if (!dev->bt_data) |
| 523 | error = -ENOMEM; | ||
| 524 | goto err_free_urb; | 628 | goto err_free_urb; |
| 525 | } | ||
| 526 | 629 | ||
| 527 | dev->tp_data = usb_buffer_alloc(dev->udev, | 630 | dev->tp_data = usb_buffer_alloc(dev->udev, |
| 528 | dev->cfg.tp_datalen, GFP_KERNEL, | 631 | dev->cfg.tp_datalen, GFP_KERNEL, |
| 529 | &dev->tp_urb->transfer_dma); | 632 | &dev->tp_urb->transfer_dma); |
| 530 | if (!dev->tp_data) { | 633 | if (!dev->tp_data) |
| 531 | error = -ENOMEM; | ||
| 532 | goto err_free_bt_buffer; | 634 | goto err_free_bt_buffer; |
| 533 | } | ||
| 534 | 635 | ||
| 535 | usb_fill_int_urb(dev->bt_urb, udev, | 636 | usb_fill_int_urb(dev->bt_urb, udev, |
| 536 | usb_rcvintpipe(udev, cfg->bt_ep), | 637 | usb_rcvintpipe(udev, cfg->bt_ep), |
| 537 | dev->bt_data, dev->cfg.bt_datalen, | 638 | dev->bt_data, dev->cfg.bt_datalen, |
| 538 | irq_button, dev, 1); | 639 | bcm5974_irq_button, dev, 1); |
| 539 | 640 | ||
| 540 | usb_fill_int_urb(dev->tp_urb, udev, | 641 | usb_fill_int_urb(dev->tp_urb, udev, |
| 541 | usb_rcvintpipe(udev, cfg->tp_ep), | 642 | usb_rcvintpipe(udev, cfg->tp_ep), |
| 542 | dev->tp_data, dev->cfg.tp_datalen, | 643 | dev->tp_data, dev->cfg.tp_datalen, |
| 543 | irq_trackpad, dev, 1); | 644 | bcm5974_irq_trackpad, dev, 1); |
| 544 | 645 | ||
| 646 | /* create bcm5974 device */ | ||
| 545 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | 647 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); |
| 546 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | 648 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); |
| 547 | 649 | ||
| @@ -552,24 +654,10 @@ static int atp_probe(struct usb_interface *iface, | |||
| 552 | 654 | ||
| 553 | input_set_drvdata(input_dev, dev); | 655 | input_set_drvdata(input_dev, dev); |
| 554 | 656 | ||
| 555 | input_dev->open = atp_open; | 657 | input_dev->open = bcm5974_open; |
| 556 | input_dev->close = atp_close; | 658 | input_dev->close = bcm5974_close; |
| 557 | |||
| 558 | set_bit(EV_ABS, input_dev->evbit); | ||
| 559 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
| 560 | 0, cfg->p.dim, cfg->p.dim / SNRATIO, 0); | ||
| 561 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, | ||
| 562 | 0, cfg->w.dim, cfg->w.dim / SNRATIO, 0); | ||
| 563 | input_set_abs_params(input_dev, ABS_X, | ||
| 564 | 0, cfg->x.dim, cfg->x.dim / SNRATIO, 0); | ||
| 565 | input_set_abs_params(input_dev, ABS_Y, | ||
| 566 | 0, cfg->y.dim, cfg->y.dim / SNRATIO, 0); | ||
| 567 | 659 | ||
| 568 | set_bit(EV_KEY, input_dev->evbit); | 660 | setup_events_to_report(input_dev, cfg); |
| 569 | set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
| 570 | set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 571 | set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
| 572 | set_bit(BTN_LEFT, input_dev->keybit); | ||
| 573 | 661 | ||
| 574 | error = input_register_device(dev->input); | 662 | error = input_register_device(dev->input); |
| 575 | if (error) | 663 | if (error) |
| @@ -592,99 +680,48 @@ err_free_bt_urb: | |||
| 592 | usb_free_urb(dev->bt_urb); | 680 | usb_free_urb(dev->bt_urb); |
| 593 | err_free_devs: | 681 | err_free_devs: |
| 594 | usb_set_intfdata(iface, NULL); | 682 | usb_set_intfdata(iface, NULL); |
| 595 | kfree(dev); | ||
| 596 | input_free_device(input_dev); | 683 | input_free_device(input_dev); |
| 684 | kfree(dev); | ||
| 597 | return error; | 685 | return error; |
| 598 | } | 686 | } |
| 599 | 687 | ||
| 600 | static void atp_disconnect(struct usb_interface *iface) | 688 | static void bcm5974_disconnect(struct usb_interface *iface) |
| 601 | { | 689 | { |
| 602 | struct atp *dev = usb_get_intfdata(iface); | 690 | struct bcm5974 *dev = usb_get_intfdata(iface); |
| 603 | 691 | ||
| 604 | usb_set_intfdata(iface, NULL); | 692 | usb_set_intfdata(iface, NULL); |
| 605 | 693 | ||
| 606 | if (dev) { | 694 | input_unregister_device(dev->input); |
| 607 | input_unregister_device(dev->input); | 695 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, |
| 608 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | ||
| 609 | dev->tp_data, dev->tp_urb->transfer_dma); | 696 | dev->tp_data, dev->tp_urb->transfer_dma); |
| 610 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | 697 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, |
| 611 | dev->bt_data, dev->bt_urb->transfer_dma); | 698 | dev->bt_data, dev->bt_urb->transfer_dma); |
| 612 | usb_free_urb(dev->tp_urb); | 699 | usb_free_urb(dev->tp_urb); |
| 613 | usb_free_urb(dev->bt_urb); | 700 | usb_free_urb(dev->bt_urb); |
| 614 | kfree(dev); | 701 | kfree(dev); |
| 615 | } | ||
| 616 | |||
| 617 | printk(KERN_INFO "bcm5974: disconnected\n"); | ||
| 618 | } | ||
| 619 | |||
| 620 | static int atp_suspend(struct usb_interface *iface, pm_message_t message) | ||
| 621 | { | ||
| 622 | struct atp *dev = usb_get_intfdata(iface); | ||
| 623 | |||
| 624 | if (dev) { | ||
| 625 | if (!dev->suspended) | ||
| 626 | atp_close(dev->input); | ||
| 627 | dev->suspended++; | ||
| 628 | } | ||
| 629 | |||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | |||
| 633 | static int atp_resume(struct usb_interface *iface) | ||
| 634 | { | ||
| 635 | struct atp *dev = usb_get_intfdata(iface); | ||
| 636 | int error = 0; | ||
| 637 | |||
| 638 | if (dev && dev->suspended) { | ||
| 639 | if (!--dev->suspended) | ||
| 640 | error = atp_open(dev->input); | ||
| 641 | } | ||
| 642 | |||
| 643 | return error; | ||
| 644 | } | ||
| 645 | |||
| 646 | static int atp_reset_resume(struct usb_interface *iface) | ||
| 647 | { | ||
| 648 | struct atp *dev = usb_get_intfdata(iface); | ||
| 649 | |||
| 650 | if (dev && atp_wellspring_init(dev)) | ||
| 651 | printk(KERN_INFO "bcm5974: warning: reset failed\n"); | ||
| 652 | |||
| 653 | return atp_resume(iface); | ||
| 654 | } | ||
| 655 | |||
| 656 | static int atp_pre_reset(struct usb_interface *iface) | ||
| 657 | { | ||
| 658 | return atp_suspend(iface, PMSG_ON); | ||
| 659 | } | ||
| 660 | |||
| 661 | static int atp_post_reset(struct usb_interface *iface) | ||
| 662 | { | ||
| 663 | return atp_reset_resume(iface); | ||
| 664 | } | 702 | } |
| 665 | 703 | ||
| 666 | static struct usb_driver atp_driver = { | 704 | static struct usb_driver bcm5974_driver = { |
| 667 | .name = "bcm5974", | 705 | .name = "bcm5974", |
| 668 | .probe = atp_probe, | 706 | .probe = bcm5974_probe, |
| 669 | .disconnect = atp_disconnect, | 707 | .disconnect = bcm5974_disconnect, |
| 670 | .suspend = atp_suspend, | 708 | .suspend = bcm5974_suspend, |
| 671 | .resume = atp_resume, | 709 | .resume = bcm5974_resume, |
| 672 | .reset_resume = atp_reset_resume, | 710 | .reset_resume = bcm5974_resume, |
| 673 | .pre_reset = atp_pre_reset, | 711 | .id_table = bcm5974_table, |
| 674 | .post_reset = atp_post_reset, | 712 | .supports_autosuspend = 1, |
| 675 | .id_table = atp_table, | ||
| 676 | }; | 713 | }; |
| 677 | 714 | ||
| 678 | static int __init atp_init(void) | 715 | static int __init bcm5974_init(void) |
| 679 | { | 716 | { |
| 680 | return usb_register(&atp_driver); | 717 | return usb_register(&bcm5974_driver); |
| 681 | } | 718 | } |
| 682 | 719 | ||
| 683 | static void __exit atp_exit(void) | 720 | static void __exit bcm5974_exit(void) |
| 684 | { | 721 | { |
| 685 | usb_deregister(&atp_driver); | 722 | usb_deregister(&bcm5974_driver); |
| 686 | } | 723 | } |
| 687 | 724 | ||
| 688 | module_init(atp_init); | 725 | module_init(bcm5974_init); |
| 689 | module_exit(atp_exit); | 726 | module_exit(bcm5974_exit); |
| 690 | 727 | ||
