summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES12
-rw-r--r--bcm5974-dkms-mkdeb/debian/changelog7
-rw-r--r--bcm5974.c392
-rw-r--r--dkms.conf2
4 files changed, 226 insertions, 187 deletions
diff --git a/CHANGES b/CHANGES
index 89f02c1..42031d1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,19 @@
1bcm5974 (0.58) unstable; urgency=low
2
3 * Name changes; use usbhid definitions, rename atp to bcm5974
4 * Input syncing moved to report functions, event type setup broken out
5 * Traffic functions added for open/close and suspend/resume logic
6 * Open/close and suspend/resume transition logic corrected
7 * Open/close serialized with respect to suspend/resume
8
9 -- Henrik Rydberg <rydberg@euromail.se> Wed, 23 Jul 2008 02:20:10 +0200
10
1bcm5974 (0.57) unstable; urgency=low 11bcm5974 (0.57) unstable; urgency=low
2 12
3 * Keep reset_resume around 13 * Keep reset_resume around
4 * Submitted to kernel.org 14 * Submitted to kernel.org
5 15
6 -- Henrik Rydberg <rydberg@euromail.se> Fri, 18 Jul 2008 02:42:52 +0200 16 -- Henrik Rydberg <rydberg@euromail.se> Sat, 19 Jul 2008 01:42:52 +0200
7 17
8bcm5974 (0.56) unstable; urgency=low 18bcm5974 (0.56) unstable; urgency=low
9 19
diff --git a/bcm5974-dkms-mkdeb/debian/changelog b/bcm5974-dkms-mkdeb/debian/changelog
index 76304fd..b0211af 100644
--- a/bcm5974-dkms-mkdeb/debian/changelog
+++ b/bcm5974-dkms-mkdeb/debian/changelog
@@ -1,6 +1,9 @@
1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low 1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low
2 2
3 * Keep reset_resume around 3 * Name changes; use usbhid definitions, rename atp to bcm5974
4 * Submitted to kernel.org 4 * Input syncing moved to report functions, event type setup broken out
5 * Traffic functions added for open/close and suspend/resume logic
6 * Open/close and suspend/resume transition logic corrected
7 * Open/close serialized with respect to suspend/resume
5 8
6 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP 9 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP
diff --git a/bcm5974.c b/bcm5974.c
index 1e1cf04..55c1f60 100644
--- a/bcm5974.c
+++ b/bcm5974.c
@@ -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 */
65static const struct usb_device_id atp_table [] = { 66static 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};
77MODULE_DEVICE_TABLE(usb, atp_table); 78MODULE_DEVICE_TABLE(usb, bcm5974_table);
78 79
79MODULE_AUTHOR("Henrik Rydberg"); 80MODULE_AUTHOR("Henrik Rydberg");
80MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); 81MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver");
@@ -125,7 +126,7 @@ struct tp_data {
125}; 126};
126 127
127/* device-specific parameters */ 128/* device-specific parameters */
128struct atp_params { 129struct bcm5974_param {
129 int dim; /* logical dimension */ 130 int dim; /* logical dimension */
130 int fuzz; /* logical noise value */ 131 int fuzz; /* logical noise value */
131 int devmin; /* device minimum reading */ 132 int devmin; /* device minimum reading */
@@ -133,26 +134,27 @@ struct atp_params {
133}; 134};
134 135
135/* device-specific configuration */ 136/* device-specific configuration */
136struct atp_config { 137struct bcm5974_config {
137 int ansi, iso, jis; /* the product id of this device */ 138 int ansi, iso, jis; /* the product id of this device */
138 int bt_ep; /* the endpoint of the button interface */ 139 int bt_ep; /* the endpoint of the button interface */
139 int bt_datalen; /* data length of the button interface */ 140 int bt_datalen; /* data length of the button interface */
140 int tp_ep; /* the endpoint of the trackpad interface */ 141 int tp_ep; /* the endpoint of the trackpad interface */
141 int tp_datalen; /* data length of the trackpad interface */ 142 int tp_datalen; /* data length of the trackpad interface */
142 struct atp_params p; /* finger pressure limits */ 143 struct bcm5974_param p; /* finger pressure limits */
143 struct atp_params w; /* finger width limits */ 144 struct bcm5974_param w; /* finger width limits */
144 struct atp_params x; /* horizontal limits */ 145 struct bcm5974_param x; /* horizontal limits */
145 struct atp_params y; /* vertical limits */ 146 struct bcm5974_param y; /* vertical limits */
146}; 147};
147 148
148/* logical device structure */ 149/* logical device structure */
149struct atp { 150struct bcm5974 {
150 char phys[64]; 151 char phys[64];
151 struct usb_device *udev; /* usb device */ 152 struct usb_device *udev; /* usb device */
152 struct input_dev *input; /* input dev */ 153 struct input_dev *input; /* input dev */
153 struct atp_config cfg; /* device configuration */ 154 struct bcm5974_config cfg; /* device configuration */
154 int open; /* >0: open, else closed */ 155 struct mutex mutex; /* serialize access to open/suspend */
155 int suspended; /* >0: suspended, else open */ 156 int opened; /* >0: opened, else closed */
157 int manually_suspended; /* >0: manually suspended */
156 struct urb *bt_urb; /* button usb request block */ 158 struct urb *bt_urb; /* button usb request block */
157 struct bt_data *bt_data; /* button transferred data */ 159 struct bt_data *bt_data; /* button transferred data */
158 struct urb *tp_urb; /* trackpad usb request block */ 160 struct urb *tp_urb; /* trackpad usb request block */
@@ -171,11 +173,11 @@ struct atp {
171#define SN_COORD 250 /* coordinate signal-to-noise ratio */ 173#define SN_COORD 250 /* coordinate signal-to-noise ratio */
172 174
173/* device constants */ 175/* device constants */
174static const struct atp_config atp_config_table[] = { 176static const struct bcm5974_config bcm5974_config_table[] = {
175 { 177 {
176 ATP_WELLSPRING_ANSI, 178 USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
177 ATP_WELLSPRING_ISO, 179 USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
178 ATP_WELLSPRING_JIS, 180 USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
179 0x84, sizeof(struct bt_data), 181 0x84, sizeof(struct bt_data),
180 0x81, sizeof(struct tp_data), 182 0x81, sizeof(struct tp_data),
181 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, 183 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
@@ -184,9 +186,9 @@ static const struct atp_config atp_config_table[] = {
184 { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } 186 { DIM_Y, DIM_Y / SN_COORD, -172, 5820 }
185 }, 187 },
186 { 188 {
187 ATP_WELLSPRING2_ANSI, 189 USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
188 ATP_WELLSPRING2_ISO, 190 USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
189 ATP_WELLSPRING2_JIS, 191 USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
190 0x84, sizeof(struct bt_data), 192 0x84, sizeof(struct bt_data),
191 0x81, sizeof(struct tp_data), 193 0x81, sizeof(struct tp_data),
192 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, 194 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
@@ -198,15 +200,14 @@ static const struct atp_config atp_config_table[] = {
198}; 200};
199 201
200/* return the device-specific configuration by device */ 202/* return the device-specific configuration by device */
201static const struct atp_config *atp_product_config(struct usb_device *udev) 203static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev)
202{ 204{
203 u16 id = le16_to_cpu(udev->descriptor.idProduct); 205 u16 id = le16_to_cpu(udev->descriptor.idProduct);
204 const struct atp_config *config; 206 const struct bcm5974_config *cfg;
205 for (config = atp_config_table; config->ansi; ++config) 207 for (cfg = bcm5974_config_table; cfg->ansi; ++cfg)
206 if (config->ansi == id || config->iso == id || 208 if (cfg->ansi == id || cfg->iso == id || cfg->jis == id)
207 config->jis == id) 209 return cfg;
208 return config; 210 return bcm5974_config_table;
209 return atp_config_table;
210} 211}
211 212
212/* convert 16-bit little endian to signed integer */ 213/* convert 16-bit little endian to signed integer */
@@ -216,33 +217,55 @@ static inline int raw2int(__le16 x)
216} 217}
217 218
218/* scale device data to logical dimensions (asserts devmin < devmax) */ 219/* scale device data to logical dimensions (asserts devmin < devmax) */
219static inline int int2scale(const struct atp_params *p, int x) 220static inline int int2scale(const struct bcm5974_param *p, int x)
220{ 221{
221 return x * p->dim / (p->devmax - p->devmin); 222 return x * p->dim / (p->devmax - p->devmin);
222} 223}
223 224
224/* all logical value ranges are [0,dim). */ 225/* all logical value ranges are [0,dim). */
225static inline int int2bound(const struct atp_params *p, int x) 226static inline int int2bound(const struct bcm5974_param *p, int x)
226{ 227{
227 int s = int2scale(p, x); 228 int s = int2scale(p, x);
228 return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; 229 return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s;
229} 230}
230 231
232/* setup which logical events to report */
233static void setup_events_to_report(struct input_dev *input_dev,
234 const struct bcm5974_config *cfg)
235{
236 set_bit(EV_ABS, input_dev->evbit);
237 input_set_abs_params(input_dev, ABS_PRESSURE,
238 0, cfg->p.dim, cfg->p.fuzz, 0);
239 input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
240 0, cfg->w.dim, cfg->w.fuzz, 0);
241 input_set_abs_params(input_dev, ABS_X,
242 0, cfg->x.dim, cfg->x.fuzz, 0);
243 input_set_abs_params(input_dev, ABS_Y,
244 0, cfg->y.dim, cfg->y.fuzz, 0);
245
246 set_bit(EV_KEY, input_dev->evbit);
247 set_bit(BTN_TOOL_FINGER, input_dev->keybit);
248 set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
249 set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
250 set_bit(BTN_LEFT, input_dev->keybit);
251}
252
231/* report button data as logical button state */ 253/* report button data as logical button state */
232static int report_bt_state(struct atp *dev, int size) 254static int report_bt_state(struct bcm5974 *dev, int size)
233{ 255{
234 if (size != sizeof(struct bt_data)) 256 if (size != sizeof(struct bt_data))
235 return -EIO; 257 return -EIO;
236 258
237 input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); 259 input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
260 input_sync(dev->input);
238 261
239 return 0; 262 return 0;
240} 263}
241 264
242/* report trackpad data as logical trackpad state */ 265/* report trackpad data as logical trackpad state */
243static int report_tp_state(struct atp *dev, int size) 266static int report_tp_state(struct bcm5974 *dev, int size)
244{ 267{
245 const struct atp_config *c = &dev->cfg; 268 const struct bcm5974_config *c = &dev->cfg;
246 const struct tp_finger *f = dev->tp_data->finger; 269 const struct tp_finger *f = dev->tp_data->finger;
247 const int fingers = (size - 26) / 28; 270 const int fingers = (size - 26) / 28;
248 int p, w, x, y, n; 271 int p, w, x, y, n;
@@ -255,6 +278,7 @@ static int report_tp_state(struct atp *dev, int size)
255 input_report_key(dev->input, BTN_TOOL_FINGER, false); 278 input_report_key(dev->input, BTN_TOOL_FINGER, false);
256 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, false); 279 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, false);
257 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, false); 280 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, false);
281 input_sync(dev->input);
258 return 0; 282 return 0;
259 } 283 }
260 284
@@ -274,17 +298,18 @@ static int report_tp_state(struct atp *dev, int size)
274 input_report_key(dev->input, BTN_TOOL_FINGER, n == 1); 298 input_report_key(dev->input, BTN_TOOL_FINGER, n == 1);
275 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, n == 2); 299 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, n == 2);
276 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, n > 2); 300 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, n > 2);
301 input_sync(dev->input);
277 return 0; 302 return 0;
278} 303}
279 304
280/* Wellspring initialization constants */ 305/* Wellspring initialization constants */
281#define ATP_WELLSPRING_MODE_READ_REQUEST_ID 1 306#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
282#define ATP_WELLSPRING_MODE_WRITE_REQUEST_ID 9 307#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
283#define ATP_WELLSPRING_MODE_REQUEST_VALUE 0x300 308#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
284#define ATP_WELLSPRING_MODE_REQUEST_INDEX 0 309#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
285#define ATP_WELLSPRING_MODE_VENDOR_VALUE 0x01 310#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
286 311
287static int atp_wellspring_mode(struct atp *dev) 312static int bcm5974_wellspring_mode(struct bcm5974 *dev)
288{ 313{
289 char *data = kmalloc(8, GFP_KERNEL); 314 char *data = kmalloc(8, GFP_KERNEL);
290 int error = 0, size; 315 int error = 0, size;
@@ -297,10 +322,10 @@ static int atp_wellspring_mode(struct atp *dev)
297 322
298 /* read configuration */ 323 /* read configuration */
299 size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), 324 size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
300 ATP_WELLSPRING_MODE_READ_REQUEST_ID, 325 BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
301 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 326 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
302 ATP_WELLSPRING_MODE_REQUEST_VALUE, 327 BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
303 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 328 BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
304 329
305 if (size != 8) { 330 if (size != 8) {
306 err("bcm5974: could not read from device"); 331 err("bcm5974: could not read from device");
@@ -309,14 +334,14 @@ static int atp_wellspring_mode(struct atp *dev)
309 } 334 }
310 335
311 /* apply the mode switch */ 336 /* apply the mode switch */
312 data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE; 337 data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE;
313 338
314 /* write configuration */ 339 /* write configuration */
315 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 340 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
316 ATP_WELLSPRING_MODE_WRITE_REQUEST_ID, 341 BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
317 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 342 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
318 ATP_WELLSPRING_MODE_REQUEST_VALUE, 343 BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
319 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 344 BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
320 345
321 if (size != 8) { 346 if (size != 8) {
322 err("bcm5974: could not write to device"); 347 err("bcm5974: could not write to device");
@@ -336,7 +361,7 @@ error:
336 361
337static void irq_button(struct urb *urb) 362static void irq_button(struct urb *urb)
338{ 363{
339 struct atp *dev = urb->context; 364 struct bcm5974 *dev = urb->context;
340 int error; 365 int error;
341 366
342 switch (urb->status) { 367 switch (urb->status) {
@@ -353,13 +378,9 @@ static void irq_button(struct urb *urb)
353 goto exit; 378 goto exit;
354 } 379 }
355 380
356 if (report_bt_state(dev, dev->bt_urb->actual_length)) { 381 if (report_bt_state(dev, dev->bt_urb->actual_length))
357 dprintk(1, "bcm5974: bad button package, length: %d\n", 382 dprintk(1, "bcm5974: bad button package, length: %d\n",
358 dev->bt_urb->actual_length); 383 dev->bt_urb->actual_length);
359 goto exit;
360 }
361
362 input_sync(dev->input);
363 384
364exit: 385exit:
365 error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); 386 error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC);
@@ -369,7 +390,7 @@ exit:
369 390
370static void irq_trackpad(struct urb *urb) 391static void irq_trackpad(struct urb *urb)
371{ 392{
372 struct atp *dev = urb->context; 393 struct bcm5974 *dev = urb->context;
373 int error; 394 int error;
374 395
375 switch (urb->status) { 396 switch (urb->status) {
@@ -390,13 +411,9 @@ static void irq_trackpad(struct urb *urb)
390 if (dev->tp_urb->actual_length == 2) 411 if (dev->tp_urb->actual_length == 2)
391 goto exit; 412 goto exit;
392 413
393 if (report_tp_state(dev, dev->tp_urb->actual_length)) { 414 if (report_tp_state(dev, dev->tp_urb->actual_length))
394 dprintk(1, "bcm5974: bad trackpad package, length: %d\n", 415 dprintk(1, "bcm5974: bad trackpad package, length: %d\n",
395 dev->tp_urb->actual_length); 416 dev->tp_urb->actual_length);
396 goto exit;
397 }
398
399 input_sync(dev->input);
400 417
401exit: 418exit:
402 error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); 419 error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
@@ -417,99 +434,149 @@ exit:
417 * device, resulting in trackpad malfunction under certain 434 * device, resulting in trackpad malfunction under certain
418 * circumstances. To get around this problem, there is at least one 435 * circumstances. To get around this problem, there is at least one
419 * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to 436 * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to
420 * recieve a reset_resume request rather than the normal resume. Since 437 * recieve a reset_resume request rather than the normal resume.
421 * the implementation of reset_resume is equal to mode switch plus 438 * Since the implementation of reset_resume is equal to mode switch
422 * open, it seems easier to always do the switch while opening the 439 * plus start_traffic, it seems easier to always do the switch when
423 * device. 440 * starting traffic on the device.
424 */ 441 */
425static int atp_open(struct input_dev *input) 442static int start_traffic(struct bcm5974 *dev)
426{ 443{
427 struct atp *dev = input_get_drvdata(input); 444 if (bcm5974_wellspring_mode(dev)) {
428 445 dprintk(1, "bcm5974: mode switch failed\n");
429 if (!dev->open) { 446 goto error;
430 if (atp_wellspring_mode(dev)) {
431 dprintk(1, "bcm5974: mode switch failed\n");
432 goto error;
433 }
434 if (usb_submit_urb(dev->bt_urb, GFP_KERNEL))
435 goto error;
436 if (usb_submit_urb(dev->tp_urb, GFP_KERNEL))
437 goto err_kill_bt;
438 } 447 }
448 if (usb_submit_urb(dev->bt_urb, GFP_KERNEL))
449 goto error;
450 if (usb_submit_urb(dev->tp_urb, GFP_KERNEL))
451 goto err_kill_bt;
439 452
440 dev->open = 1;
441 dev->suspended = 0;
442 return 0; 453 return 0;
443
444err_kill_bt: 454err_kill_bt:
445 usb_kill_urb(dev->bt_urb); 455 usb_kill_urb(dev->bt_urb);
446error: 456error:
447 return -EIO; 457 return -EIO;
448} 458}
449 459
450static void atp_close(struct input_dev *input) 460static void pause_traffic(struct bcm5974 *dev)
451{ 461{
452 struct atp *dev = input_get_drvdata(input);
453
454 usb_kill_urb(dev->tp_urb); 462 usb_kill_urb(dev->tp_urb);
455 usb_kill_urb(dev->bt_urb); 463 usb_kill_urb(dev->bt_urb);
464}
456 465
457 dev->open = 0; 466/*
458 dev->suspended = 0; 467 * The code below implements open/close and manual suspend/resume.
468 * All functions may be called in random order.
469 *
470 * Opening a suspended device fails with EACCES - permission denied.
471 *
472 * Failing a resume leaves the device resumed but closed.
473 */
474static int bcm5974_open(struct input_dev *input)
475{
476 struct bcm5974 *dev = input_get_drvdata(input);
477 int error = 0;
478
479 mutex_lock(&dev->mutex);
480 if (dev->manually_suspended)
481 error = -EACCES;
482 else if (!dev->opened)
483 error = start_traffic(dev);
484 dev->opened = !error;
485 mutex_unlock(&dev->mutex);
486
487 return error;
459} 488}
460 489
461static int atp_probe(struct usb_interface *iface, 490static void bcm5974_close(struct input_dev *input)
491{
492 struct bcm5974 *dev = input_get_drvdata(input);
493
494 mutex_lock(&dev->mutex);
495 if (!dev->manually_suspended)
496 pause_traffic(dev);
497 dev->opened = 0;
498 mutex_unlock(&dev->mutex);
499}
500
501static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message)
502{
503 struct bcm5974 *dev = usb_get_intfdata(iface);
504
505 if (dev) {
506 mutex_lock(&dev->mutex);
507 if (dev->opened && !dev->manually_suspended)
508 pause_traffic(dev);
509 dev->manually_suspended++;
510 mutex_unlock(&dev->mutex);
511 }
512
513 return 0;
514}
515
516static int bcm5974_resume(struct usb_interface *iface)
517{
518 struct bcm5974 *dev = usb_get_intfdata(iface);
519 int error = 0;
520
521 if (dev) {
522 mutex_lock(&dev->mutex);
523 if (dev->manually_suspended)
524 dev->manually_suspended--;
525 if (dev->opened && !dev->manually_suspended)
526 error = start_traffic(dev);
527 if (error)
528 dev->opened = 0;
529 mutex_unlock(&dev->mutex);
530 }
531
532 return error;
533}
534
535static int bcm5974_probe(struct usb_interface *iface,
462 const struct usb_device_id *id) 536 const struct usb_device_id *id)
463{ 537{
464 struct usb_device *udev = interface_to_usbdev(iface); 538 struct usb_device *udev = interface_to_usbdev(iface);
465 const struct atp_config *cfg; 539 const struct bcm5974_config *cfg;
466 struct atp *dev; 540 struct bcm5974 *dev;
467 struct input_dev *input_dev; 541 struct input_dev *input_dev;
468 int error = 0; 542 int error = -ENOMEM;
469 543
470 /* find the product index */ 544 /* find the product index */
471 cfg = atp_product_config(udev); 545 cfg = bcm5974_get_config(udev);
472 546
473 /* allocate memory for our device state and initialize it */ 547 /* allocate memory for our device state and initialize it */
474 dev = kzalloc(sizeof(struct atp), GFP_KERNEL); 548 dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
475 input_dev = input_allocate_device(); 549 input_dev = input_allocate_device();
476 if (!dev || !input_dev) { 550 if (!dev || !input_dev) {
477 err("bcm5974: out of memory"); 551 err("bcm5974: out of memory");
478 error = -ENOMEM;
479 goto err_free_devs; 552 goto err_free_devs;
480 } 553 }
481 554
482 dev->udev = udev; 555 dev->udev = udev;
483 dev->input = input_dev; 556 dev->input = input_dev;
484 dev->cfg = *cfg; 557 dev->cfg = *cfg;
558 mutex_init(&dev->mutex);
485 559
560 /* setup urbs */
486 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); 561 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
487 if (!dev->bt_urb) { 562 if (!dev->bt_urb)
488 error = -ENOMEM;
489 goto err_free_devs; 563 goto err_free_devs;
490 }
491 564
492 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); 565 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
493 if (!dev->tp_urb) { 566 if (!dev->tp_urb)
494 error = -ENOMEM;
495 goto err_free_bt_urb; 567 goto err_free_bt_urb;
496 }
497 568
498 dev->bt_data = usb_buffer_alloc(dev->udev, 569 dev->bt_data = usb_buffer_alloc(dev->udev,
499 dev->cfg.bt_datalen, GFP_KERNEL, 570 dev->cfg.bt_datalen, GFP_KERNEL,
500 &dev->bt_urb->transfer_dma); 571 &dev->bt_urb->transfer_dma);
501 if (!dev->bt_data) { 572 if (!dev->bt_data)
502 error = -ENOMEM;
503 goto err_free_urb; 573 goto err_free_urb;
504 }
505 574
506 dev->tp_data = usb_buffer_alloc(dev->udev, 575 dev->tp_data = usb_buffer_alloc(dev->udev,
507 dev->cfg.tp_datalen, GFP_KERNEL, 576 dev->cfg.tp_datalen, GFP_KERNEL,
508 &dev->tp_urb->transfer_dma); 577 &dev->tp_urb->transfer_dma);
509 if (!dev->tp_data) { 578 if (!dev->tp_data)
510 error = -ENOMEM;
511 goto err_free_bt_buffer; 579 goto err_free_bt_buffer;
512 }
513 580
514 usb_fill_int_urb(dev->bt_urb, udev, 581 usb_fill_int_urb(dev->bt_urb, udev,
515 usb_rcvintpipe(udev, cfg->bt_ep), 582 usb_rcvintpipe(udev, cfg->bt_ep),
@@ -521,6 +588,7 @@ static int atp_probe(struct usb_interface *iface,
521 dev->tp_data, dev->cfg.tp_datalen, 588 dev->tp_data, dev->cfg.tp_datalen,
522 irq_trackpad, dev, 1); 589 irq_trackpad, dev, 1);
523 590
591 /* create bcm5974 device */
524 usb_make_path(udev, dev->phys, sizeof(dev->phys)); 592 usb_make_path(udev, dev->phys, sizeof(dev->phys));
525 strlcat(dev->phys, "/input0", sizeof(dev->phys)); 593 strlcat(dev->phys, "/input0", sizeof(dev->phys));
526 594
@@ -531,24 +599,10 @@ static int atp_probe(struct usb_interface *iface,
531 599
532 input_set_drvdata(input_dev, dev); 600 input_set_drvdata(input_dev, dev);
533 601
534 input_dev->open = atp_open; 602 input_dev->open = bcm5974_open;
535 input_dev->close = atp_close; 603 input_dev->close = bcm5974_close;
536 604
537 set_bit(EV_ABS, input_dev->evbit); 605 setup_events_to_report(input_dev, cfg);
538 input_set_abs_params(input_dev, ABS_PRESSURE,
539 0, cfg->p.dim, cfg->p.fuzz, 0);
540 input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
541 0, cfg->w.dim, cfg->w.fuzz, 0);
542 input_set_abs_params(input_dev, ABS_X,
543 0, cfg->x.dim, cfg->x.fuzz, 0);
544 input_set_abs_params(input_dev, ABS_Y,
545 0, cfg->y.dim, cfg->y.fuzz, 0);
546
547 set_bit(EV_KEY, input_dev->evbit);
548 set_bit(BTN_TOOL_FINGER, input_dev->keybit);
549 set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
550 set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
551 set_bit(BTN_LEFT, input_dev->keybit);
552 606
553 error = input_register_device(dev->input); 607 error = input_register_device(dev->input);
554 if (error) 608 if (error)
@@ -571,77 +625,49 @@ err_free_bt_urb:
571 usb_free_urb(dev->bt_urb); 625 usb_free_urb(dev->bt_urb);
572err_free_devs: 626err_free_devs:
573 usb_set_intfdata(iface, NULL); 627 usb_set_intfdata(iface, NULL);
574 kfree(dev);
575 input_free_device(input_dev); 628 input_free_device(input_dev);
629 kfree(dev);
576 return error; 630 return error;
577} 631}
578 632
579static void atp_disconnect(struct usb_interface *iface) 633static void bcm5974_disconnect(struct usb_interface *iface)
580{ 634{
581 struct atp *dev = usb_get_intfdata(iface); 635 struct bcm5974 *dev = usb_get_intfdata(iface);
582 636
583 usb_set_intfdata(iface, NULL); 637 usb_set_intfdata(iface, NULL);
584 638
585 if (dev) { 639 input_unregister_device(dev->input);
586 input_unregister_device(dev->input); 640 usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
587 usb_buffer_free(dev->udev, dev->cfg.tp_datalen, 641 dev->tp_data, dev->tp_urb->transfer_dma);
588 dev->tp_data, dev->tp_urb->transfer_dma); 642 usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
589 usb_buffer_free(dev->udev, dev->cfg.bt_datalen, 643 dev->bt_data, dev->bt_urb->transfer_dma);
590 dev->bt_data, dev->bt_urb->transfer_dma); 644 usb_free_urb(dev->tp_urb);
591 usb_free_urb(dev->tp_urb); 645 usb_free_urb(dev->bt_urb);
592 usb_free_urb(dev->bt_urb); 646 kfree(dev);
593 kfree(dev);
594 }
595 647
596 printk(KERN_INFO "bcm5974: disconnected\n"); 648 printk(KERN_INFO "bcm5974: disconnected\n");
597} 649}
598 650
599static int atp_suspend(struct usb_interface *iface, pm_message_t message) 651static struct usb_driver bcm5974_driver = {
600{
601 struct atp *dev = usb_get_intfdata(iface);
602
603 if (dev) {
604 if (!dev->suspended)
605 atp_close(dev->input);
606 dev->suspended++;
607 }
608
609 return 0;
610}
611
612static int atp_resume(struct usb_interface *iface)
613{
614 struct atp *dev = usb_get_intfdata(iface);
615 int error = 0;
616
617 if (dev && dev->suspended) {
618 if (!--dev->suspended)
619 error = atp_open(dev->input);
620 }
621
622 return error;
623}
624
625static struct usb_driver atp_driver = {
626 .name = "bcm5974", 652 .name = "bcm5974",
627 .probe = atp_probe, 653 .probe = bcm5974_probe,
628 .disconnect = atp_disconnect, 654 .disconnect = bcm5974_disconnect,
629 .suspend = atp_suspend, 655 .suspend = bcm5974_suspend,
630 .resume = atp_resume, 656 .resume = bcm5974_resume,
631 .reset_resume = atp_resume, 657 .reset_resume = bcm5974_resume,
632 .id_table = atp_table, 658 .id_table = bcm5974_table,
633}; 659};
634 660
635static int __init atp_init(void) 661static int __init bcm5974_init(void)
636{ 662{
637 return usb_register(&atp_driver); 663 return usb_register(&bcm5974_driver);
638} 664}
639 665
640static void __exit atp_exit(void) 666static void __exit bcm5974_exit(void)
641{ 667{
642 usb_deregister(&atp_driver); 668 usb_deregister(&bcm5974_driver);
643} 669}
644 670
645module_init(atp_init); 671module_init(bcm5974_init);
646module_exit(atp_exit); 672module_exit(bcm5974_exit);
647 673
diff --git a/dkms.conf b/dkms.conf
index 2d5c9f4..251efb1 100644
--- a/dkms.conf
+++ b/dkms.conf
@@ -1,5 +1,5 @@
1PACKAGE_NAME="bcm5974" 1PACKAGE_NAME="bcm5974"
2PACKAGE_VERSION="0.57" 2PACKAGE_VERSION="0.58"
3MAKE[0]="make -C ${kernel_source_dir} 3MAKE[0]="make -C ${kernel_source_dir}
4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" 4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules"
5BUILT_MODULE_NAME[0]="bcm5974" 5BUILT_MODULE_NAME[0]="bcm5974"