aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2007-11-01 22:13:32 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2007-11-01 22:13:32 -0400
commit2a3e480d4b3392ce8907089094bd074575f9bb2a (patch)
tree617c06b1b19090a1b08178b5b56c0fc8fe687a13 /drivers/input/mouse
parent167ebf760fcecf72824756c8235e2d30f050bedd (diff)
Input: appletouch - idle reset logic broke older Fountains
Fountains do not support change mode request and therefore should be excluded from idle reset attempts. Also: - do not re-submit URB when we decide that touchpad needs to be reinicialized - do not repeat size detection when reinitializing the touchpad - Add missing KERN_* prefixes to messages Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Acked-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/appletouch.c125
1 files changed, 77 insertions, 48 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index f132702d137d..b4423a471f02 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -129,12 +129,12 @@ MODULE_DEVICE_TABLE (usb, atp_table);
129 */ 129 */
130#define ATP_THRESHOLD 5 130#define ATP_THRESHOLD 5
131 131
132/* MacBook Pro (Geyser 3 & 4) initialization constants */ 132/* Geyser initialization constants */
133#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 133#define ATP_GEYSER_MODE_READ_REQUEST_ID 1
134#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 134#define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9
135#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 135#define ATP_GEYSER_MODE_REQUEST_VALUE 0x300
136#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 136#define ATP_GEYSER_MODE_REQUEST_INDEX 0
137#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 137#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04
138 138
139/* Structure to hold all of our device specific stuff */ 139/* Structure to hold all of our device specific stuff */
140struct atp { 140struct atp {
@@ -142,9 +142,11 @@ struct atp {
142 struct usb_device * udev; /* usb device */ 142 struct usb_device * udev; /* usb device */
143 struct urb * urb; /* usb request block */ 143 struct urb * urb; /* usb request block */
144 signed char * data; /* transferred data */ 144 signed char * data; /* transferred data */
145 int open; /* non-zero if opened */ 145 struct input_dev * input; /* input dev */
146 struct input_dev *input; /* input dev */ 146 unsigned char open; /* non-zero if opened */
147 int valid; /* are the sensors valid ? */ 147 unsigned char valid; /* are the sensors valid ? */
148 unsigned char size_detect_done;
149 unsigned char overflowwarn; /* overflow warning printed? */
148 int x_old; /* last reported x/y, */ 150 int x_old; /* last reported x/y, */
149 int y_old; /* used for smoothing */ 151 int y_old; /* used for smoothing */
150 /* current value of the sensors */ 152 /* current value of the sensors */
@@ -153,7 +155,6 @@ struct atp {
153 signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; 155 signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
154 /* accumulated sensors */ 156 /* accumulated sensors */
155 int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; 157 int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
156 int overflowwarn; /* overflow warning printed? */
157 int datalen; /* size of an USB urb transfer */ 158 int datalen; /* size of an USB urb transfer */
158 int idlecount; /* number of empty packets */ 159 int idlecount; /* number of empty packets */
159 struct work_struct work; 160 struct work_struct work;
@@ -170,7 +171,7 @@ struct atp {
170 171
171#define dprintk(format, a...) \ 172#define dprintk(format, a...) \
172 do { \ 173 do { \
173 if (debug) printk(format, ##a); \ 174 if (debug) printk(KERN_DEBUG format, ##a); \
174 } while (0) 175 } while (0)
175 176
176MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); 177MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
@@ -188,6 +189,15 @@ static int debug = 1;
188module_param(debug, int, 0644); 189module_param(debug, int, 0644);
189MODULE_PARM_DESC(debug, "Activate debugging output"); 190MODULE_PARM_DESC(debug, "Activate debugging output");
190 191
192static inline int atp_is_fountain(struct atp *dev)
193{
194 u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
195
196 return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
197 productId == FOUNTAIN_ISO_PRODUCT_ID ||
198 productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
199}
200
191/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ 201/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
192static inline int atp_is_geyser_2(struct atp *dev) 202static inline int atp_is_geyser_2(struct atp *dev)
193{ 203{
@@ -211,52 +221,63 @@ static inline int atp_is_geyser_3(struct atp *dev)
211} 221}
212 222
213/* 223/*
214 * By default Geyser 3 device sends standard USB HID mouse 224 * By default newer Geyser devices send standard USB HID mouse
215 * packets (Report ID 2). This code changes device mode, so it 225 * packets (Report ID 2). This code changes device mode, so it
216 * sends raw sensor reports (Report ID 5). 226 * sends raw sensor reports (Report ID 5).
217 */ 227 */
218static int atp_geyser3_init(struct usb_device *udev) 228static int atp_geyser_init(struct usb_device *udev)
219{ 229{
220 char data[8]; 230 char data[8];
221 int size; 231 int size;
222 232
223 size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 233 size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
224 ATP_GEYSER3_MODE_READ_REQUEST_ID, 234 ATP_GEYSER_MODE_READ_REQUEST_ID,
225 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 235 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
226 ATP_GEYSER3_MODE_REQUEST_VALUE, 236 ATP_GEYSER_MODE_REQUEST_VALUE,
227 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); 237 ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
228 238
229 if (size != 8) { 239 if (size != 8) {
230 err("Could not do mode read request from device" 240 err("Could not do mode read request from device"
231 " (Geyser 3 mode)"); 241 " (Geyser Raw mode)");
232 return -EIO; 242 return -EIO;
233 } 243 }
234 244
235 /* Apply the mode switch */ 245 /* Apply the mode switch */
236 data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; 246 data[0] = ATP_GEYSER_MODE_VENDOR_VALUE;
237 247
238 size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 248 size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
239 ATP_GEYSER3_MODE_WRITE_REQUEST_ID, 249 ATP_GEYSER_MODE_WRITE_REQUEST_ID,
240 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 250 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
241 ATP_GEYSER3_MODE_REQUEST_VALUE, 251 ATP_GEYSER_MODE_REQUEST_VALUE,
242 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); 252 ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
243 253
244 if (size != 8) { 254 if (size != 8) {
245 err("Could not do mode write request to device" 255 err("Could not do mode write request to device"
246 " (Geyser 3 mode)"); 256 " (Geyser Raw mode)");
247 return -EIO; 257 return -EIO;
248 } 258 }
249 return 0; 259 return 0;
250} 260}
251 261
252/* Reinitialise the device if it's a geyser 3 */ 262/*
263 * Reinitialise the device. This usually stops stream of empty packets
264 * coming from it.
265 */
253static void atp_reinit(struct work_struct *work) 266static void atp_reinit(struct work_struct *work)
254{ 267{
255 struct atp *dev = container_of(work, struct atp, work); 268 struct atp *dev = container_of(work, struct atp, work);
256 struct usb_device *udev = dev->udev; 269 struct usb_device *udev = dev->udev;
270 int retval;
257 271
258 dev->idlecount = 0; 272 dev->idlecount = 0;
259 atp_geyser3_init(udev); 273
274 atp_geyser_init(udev);
275
276 retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
277 if (retval) {
278 err("%s - usb_submit_urb failed with result %d",
279 __FUNCTION__, retval);
280 }
260} 281}
261 282
262static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, 283static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -337,7 +358,7 @@ static void atp_complete(struct urb* urb)
337 break; 358 break;
338 case -EOVERFLOW: 359 case -EOVERFLOW:
339 if(!dev->overflowwarn) { 360 if(!dev->overflowwarn) {
340 printk("appletouch: OVERFLOW with data " 361 printk(KERN_WARNING "appletouch: OVERFLOW with data "
341 "length %d, actual length is %d\n", 362 "length %d, actual length is %d\n",
342 dev->datalen, dev->urb->actual_length); 363 dev->datalen, dev->urb->actual_length);
343 dev->overflowwarn = 1; 364 dev->overflowwarn = 1;
@@ -426,15 +447,17 @@ static void atp_complete(struct urb* urb)
426 dev->x_old = dev->y_old = -1; 447 dev->x_old = dev->y_old = -1;
427 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); 448 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
428 449
429 if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ 450 if (dev->size_detect_done ||
451 atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
430 goto exit; 452 goto exit;
431 453
432 /* 17" Powerbooks have extra X sensors */ 454 /* 17" Powerbooks have extra X sensors */
433 for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { 455 for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
434 if (!dev->xy_cur[i]) continue; 456 if (!dev->xy_cur[i])
457 continue;
435 458
436 printk("appletouch: 17\" model detected.\n"); 459 printk(KERN_INFO "appletouch: 17\" model detected.\n");
437 if(atp_is_geyser_2(dev)) 460 if (atp_is_geyser_2(dev))
438 input_set_abs_params(dev->input, ABS_X, 0, 461 input_set_abs_params(dev->input, ABS_X, 0,
439 (20 - 1) * 462 (20 - 1) *
440 ATP_XFACT - 1, 463 ATP_XFACT - 1,
@@ -444,10 +467,10 @@ static void atp_complete(struct urb* urb)
444 (ATP_XSENSORS - 1) * 467 (ATP_XSENSORS - 1) *
445 ATP_XFACT - 1, 468 ATP_XFACT - 1,
446 ATP_FUZZ, 0); 469 ATP_FUZZ, 0);
447
448 break; 470 break;
449 } 471 }
450 472
473 dev->size_detect_done = 1;
451 goto exit; 474 goto exit;
452 } 475 }
453 476
@@ -479,7 +502,7 @@ static void atp_complete(struct urb* urb)
479 dev->y_old = y; 502 dev->y_old = y;
480 503
481 if (debug > 1) 504 if (debug > 1)
482 printk("appletouch: X: %3d Y: %3d " 505 printk(KERN_DEBUG "appletouch: X: %3d Y: %3d "
483 "Xz: %3d Yz: %3d\n", 506 "Xz: %3d Yz: %3d\n",
484 x, y, x_z, y_z); 507 x, y, x_z, y_z);
485 508
@@ -507,19 +530,25 @@ static void atp_complete(struct urb* urb)
507 input_report_key(dev->input, BTN_LEFT, key); 530 input_report_key(dev->input, BTN_LEFT, key);
508 input_sync(dev->input); 531 input_sync(dev->input);
509 532
510 /* Many Geysers will continue to send packets continually after 533 /*
511 the first touch unless reinitialised. Do so if it's been 534 * Many Geysers will continue to send packets continually after
512 idle for a while in order to avoid waking the kernel up 535 * the first touch unless reinitialised. Do so if it's been
513 several hundred times a second */ 536 * idle for a while in order to avoid waking the kernel up
514 537 * several hundred times a second. Re-initialization does not
515 if (!x && !y && !key) { 538 * work on Fountain touchpads.
516 dev->idlecount++; 539 */
517 if (dev->idlecount == 10) { 540 if (!atp_is_fountain(dev)) {
518 dev->valid = 0; 541 if (!x && !y && !key) {
519 schedule_work(&dev->work); 542 dev->idlecount++;
520 } 543 if (dev->idlecount == 10) {
521 } else 544 dev->valid = 0;
522 dev->idlecount = 0; 545 schedule_work(&dev->work);
546 /* Don't resubmit urb here, wait for reinit */
547 return;
548 }
549 } else
550 dev->idlecount = 0;
551 }
523 552
524exit: 553exit:
525 retval = usb_submit_urb(dev->urb, GFP_ATOMIC); 554 retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -593,12 +622,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
593 else 622 else
594 dev->datalen = 81; 623 dev->datalen = 81;
595 624
596 if (atp_is_geyser_3(dev)) { 625 if (!atp_is_fountain(dev)) {
597 /* switch to raw sensor mode */ 626 /* switch to raw sensor mode */
598 if (atp_geyser3_init(udev)) 627 if (atp_geyser_init(udev))
599 goto err_free_devs; 628 goto err_free_devs;
600 629
601 printk("appletouch Geyser 3 inited.\n"); 630 printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
602 } 631 }
603 632
604 dev->urb = usb_alloc_urb(0, GFP_KERNEL); 633 dev->urb = usb_alloc_urb(0, GFP_KERNEL);