1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#define DEBUG
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/module.h>
36#include <linux/serio.h>
37#include <linux/libps2.h>
38#include <linux/delay.h>
39#include <asm/olpc.h>
40
41#include "psmouse.h"
42#include "hgpk.h"
43
44#define ILLEGAL_XY 999999
45
46static bool tpdebug;
47module_param(tpdebug, bool, 0644);
48MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
49
50static int recalib_delta = 100;
51module_param(recalib_delta, int, 0644);
52MODULE_PARM_DESC(recalib_delta,
53 "packets containing a delta this large will be discarded, and a "
54 "recalibration may be scheduled.");
55
56static int jumpy_delay = 20;
57module_param(jumpy_delay, int, 0644);
58MODULE_PARM_DESC(jumpy_delay,
59 "delay (ms) before recal after jumpiness detected");
60
61static int spew_delay = 1;
62module_param(spew_delay, int, 0644);
63MODULE_PARM_DESC(spew_delay,
64 "delay (ms) before recal after packet spew detected");
65
66static int recal_guard_time;
67module_param(recal_guard_time, int, 0644);
68MODULE_PARM_DESC(recal_guard_time,
69 "interval (ms) during which recal will be restarted if packet received");
70
71static int post_interrupt_delay = 40;
72module_param(post_interrupt_delay, int, 0644);
73MODULE_PARM_DESC(post_interrupt_delay,
74 "delay (ms) before recal after recal interrupt detected");
75
76static bool autorecal = true;
77module_param(autorecal, bool, 0644);
78MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
79
80static char hgpk_mode_name[16];
81module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
82MODULE_PARM_DESC(hgpk_mode,
83 "default hgpk mode: mouse, glidesensor or pentablet");
84
85static int hgpk_default_mode = HGPK_MODE_MOUSE;
86
87static const char * const hgpk_mode_names[] = {
88 [HGPK_MODE_MOUSE] = "Mouse",
89 [HGPK_MODE_GLIDESENSOR] = "GlideSensor",
90 [HGPK_MODE_PENTABLET] = "PenTablet",
91};
92
93static int hgpk_mode_from_name(const char *buf, int len)
94{
95 int i;
96
97 for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
98 const char *name = hgpk_mode_names[i];
99 if (strlen(name) == len && !strncasecmp(name, buf, len))
100 return i;
101 }
102
103 return HGPK_MODE_INVALID;
104}
105
106
107
108
109static int approx_half(int curr, int prev)
110{
111 int belowhalf, abovehalf;
112
113 if (curr < 5 || prev < 5)
114 return 0;
115
116 belowhalf = (prev * 8) / 20;
117 abovehalf = (prev * 12) / 20;
118
119 return belowhalf < curr && curr <= abovehalf;
120}
121
122
123
124
125
126
127static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
128{
129 struct hgpk_data *priv = psmouse->private;
130 int avx, avy;
131 bool do_recal = false;
132
133 avx = abs(x);
134 avy = abs(y);
135
136
137 if (avx > recalib_delta ||
138 (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
139 psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
140 priv->xbigj = avx;
141 } else if (approx_half(avx, priv->xbigj)) {
142 psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
143 priv->xbigj = avx;
144 priv->xsaw_secondary++;
145 } else {
146 if (priv->xbigj && priv->xsaw_secondary > 1)
147 do_recal = true;
148 priv->xbigj = 0;
149 priv->xsaw_secondary = 0;
150 }
151
152 if (avy > recalib_delta ||
153 (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
154 psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
155 priv->ybigj = avy;
156 } else if (approx_half(avy, priv->ybigj)) {
157 psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
158 priv->ybigj = avy;
159 priv->ysaw_secondary++;
160 } else {
161 if (priv->ybigj && priv->ysaw_secondary > 1)
162 do_recal = true;
163 priv->ybigj = 0;
164 priv->ysaw_secondary = 0;
165 }
166
167 priv->xlast = avx;
168 priv->ylast = avy;
169
170 if (do_recal && jumpy_delay) {
171 psmouse_warn(psmouse, "scheduling recalibration\n");
172 psmouse_queue_work(psmouse, &priv->recalib_wq,
173 msecs_to_jiffies(jumpy_delay));
174 }
175
176 return priv->xbigj || priv->ybigj;
177}
178
179static void hgpk_reset_spew_detection(struct hgpk_data *priv)
180{
181 priv->spew_count = 0;
182 priv->dupe_count = 0;
183 priv->x_tally = 0;
184 priv->y_tally = 0;
185 priv->spew_flag = NO_SPEW;
186}
187
188static void hgpk_reset_hack_state(struct psmouse *psmouse)
189{
190 struct hgpk_data *priv = psmouse->private;
191
192 priv->abs_x = priv->abs_y = -1;
193 priv->xlast = priv->ylast = ILLEGAL_XY;
194 priv->xbigj = priv->ybigj = 0;
195 priv->xsaw_secondary = priv->ysaw_secondary = 0;
196 hgpk_reset_spew_detection(priv);
197}
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214static void hgpk_spewing_hack(struct psmouse *psmouse,
215 int l, int r, int x, int y)
216{
217 struct hgpk_data *priv = psmouse->private;
218
219
220
221 if (l || r)
222 return;
223
224
225 if (!spew_delay)
226 return;
227
228 if (abs(x) > 3 || abs(y) > 3) {
229
230 hgpk_reset_spew_detection(priv);
231 return;
232 }
233
234
235
236 priv->x_tally += x;
237 priv->y_tally += y;
238
239 switch (priv->spew_flag) {
240 case NO_SPEW:
241
242 priv->spew_flag = MAYBE_SPEWING;
243
244
245
246 case MAYBE_SPEWING:
247 priv->spew_count++;
248
249 if (priv->spew_count < SPEW_WATCH_COUNT)
250 break;
251
252
253 priv->spew_flag = SPEW_DETECTED;
254
255
256
257 case SPEW_DETECTED:
258
259
260
261
262 if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
263 psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
264 priv->x_tally, priv->y_tally);
265 priv->spew_flag = RECALIBRATING;
266 psmouse_queue_work(psmouse, &priv->recalib_wq,
267 msecs_to_jiffies(spew_delay));
268 }
269
270 break;
271 case RECALIBRATING:
272
273
274 break;
275 }
276}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
310{
311 struct hgpk_data *priv = psmouse->private;
312 int pktcnt = psmouse->pktcnt;
313 bool valid;
314
315 switch (priv->mode) {
316 case HGPK_MODE_MOUSE:
317 valid = (packet[0] & 0x0C) == 0x08;
318 break;
319
320 case HGPK_MODE_GLIDESENSOR:
321 valid = pktcnt == 1 ?
322 packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80);
323 break;
324
325 case HGPK_MODE_PENTABLET:
326 valid = pktcnt == 1 ?
327 packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80);
328 break;
329
330 default:
331 valid = false;
332 break;
333 }
334
335 if (!valid)
336 psmouse_dbg(psmouse,
337 "bad data, mode %d (%d) %*ph\n",
338 priv->mode, pktcnt, 6, psmouse->packet);
339
340 return valid;
341}
342
343static void hgpk_process_advanced_packet(struct psmouse *psmouse)
344{
345 struct hgpk_data *priv = psmouse->private;
346 struct input_dev *idev = psmouse->dev;
347 unsigned char *packet = psmouse->packet;
348 int down = !!(packet[2] & 2);
349 int left = !!(packet[3] & 1);
350 int right = !!(packet[3] & 2);
351 int x = packet[1] | ((packet[2] & 0x78) << 4);
352 int y = packet[4] | ((packet[3] & 0x70) << 3);
353
354 if (priv->mode == HGPK_MODE_GLIDESENSOR) {
355 int pt_down = !!(packet[2] & 1);
356 int finger_down = !!(packet[2] & 2);
357 int z = packet[5];
358
359 input_report_abs(idev, ABS_PRESSURE, z);
360 if (tpdebug)
361 psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
362 pt_down, finger_down, z);
363 } else {
364
365
366
367
368 if (tpdebug)
369 psmouse_dbg(psmouse, "pd=%d ", down);
370 }
371
372 if (tpdebug)
373 psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
374 left, right, x, y);
375
376 input_report_key(idev, BTN_TOUCH, down);
377 input_report_key(idev, BTN_LEFT, left);
378 input_report_key(idev, BTN_RIGHT, right);
379
380
381
382
383
384 if (!down) {
385 hgpk_reset_hack_state(psmouse);
386 goto done;
387 }
388
389
390
391
392
393 if (x == priv->abs_x && y == priv->abs_y) {
394 if (++priv->dupe_count > SPEW_WATCH_COUNT) {
395 if (tpdebug)
396 psmouse_dbg(psmouse, "hard spew detected\n");
397 priv->spew_flag = RECALIBRATING;
398 psmouse_queue_work(psmouse, &priv->recalib_wq,
399 msecs_to_jiffies(spew_delay));
400 }
401 goto done;
402 }
403
404
405 priv->dupe_count = 0;
406
407
408 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
409 int x_diff = priv->abs_x - x;
410 int y_diff = priv->abs_y - y;
411 if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
412 if (tpdebug)
413 psmouse_dbg(psmouse, "discarding\n");
414 goto done;
415 }
416 hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
417 }
418
419 input_report_abs(idev, ABS_X, x);
420 input_report_abs(idev, ABS_Y, y);
421 priv->abs_x = x;
422 priv->abs_y = y;
423
424done:
425 input_sync(idev);
426}
427
428static void hgpk_process_simple_packet(struct psmouse *psmouse)
429{
430 struct input_dev *dev = psmouse->dev;
431 unsigned char *packet = psmouse->packet;
432 int left = packet[0] & 1;
433 int right = (packet[0] >> 1) & 1;
434 int x = packet[1] - ((packet[0] << 4) & 0x100);
435 int y = ((packet[0] << 3) & 0x100) - packet[2];
436
437 if (packet[0] & 0xc0)
438 psmouse_dbg(psmouse,
439 "overflow -- 0x%02x 0x%02x 0x%02x\n",
440 packet[0], packet[1], packet[2]);
441
442 if (hgpk_discard_decay_hack(psmouse, x, y)) {
443 if (tpdebug)
444 psmouse_dbg(psmouse, "discarding\n");
445 return;
446 }
447
448 hgpk_spewing_hack(psmouse, left, right, x, y);
449
450 if (tpdebug)
451 psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
452 left, right, x, y);
453
454 input_report_key(dev, BTN_LEFT, left);
455 input_report_key(dev, BTN_RIGHT, right);
456
457 input_report_rel(dev, REL_X, x);
458 input_report_rel(dev, REL_Y, y);
459
460 input_sync(dev);
461}
462
463static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
464{
465 struct hgpk_data *priv = psmouse->private;
466
467 if (!hgpk_is_byte_valid(psmouse, psmouse->packet))
468 return PSMOUSE_BAD_DATA;
469
470 if (psmouse->pktcnt >= psmouse->pktsize) {
471 if (priv->mode == HGPK_MODE_MOUSE)
472 hgpk_process_simple_packet(psmouse);
473 else
474 hgpk_process_advanced_packet(psmouse);
475 return PSMOUSE_FULL_PACKET;
476 }
477
478 if (priv->recalib_window) {
479 if (time_before(jiffies, priv->recalib_window)) {
480
481
482
483
484 psmouse_dbg(psmouse,
485 "packet inside calibration window, queueing another recalibration\n");
486 psmouse_queue_work(psmouse, &priv->recalib_wq,
487 msecs_to_jiffies(post_interrupt_delay));
488 }
489 priv->recalib_window = 0;
490 }
491
492 return PSMOUSE_GOOD_DATA;
493}
494
495static int hgpk_select_mode(struct psmouse *psmouse)
496{
497 struct ps2dev *ps2dev = &psmouse->ps2dev;
498 struct hgpk_data *priv = psmouse->private;
499 int i;
500 int cmd;
501
502
503
504
505
506 const int advanced_init[] = {
507 PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
508 PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
509 0xf2, 0xf2, 0xf2,
510 };
511
512 switch (priv->mode) {
513 case HGPK_MODE_MOUSE:
514 psmouse->pktsize = 3;
515 break;
516
517 case HGPK_MODE_GLIDESENSOR:
518 case HGPK_MODE_PENTABLET:
519 psmouse->pktsize = 6;
520
521
522 for (i = 0; i < ARRAY_SIZE(advanced_init); i++)
523 if (ps2_command(ps2dev, NULL, advanced_init[i]))
524 return -EIO;
525
526
527 cmd = priv->mode == HGPK_MODE_GLIDESENSOR ?
528 PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21;
529
530 if (ps2_command(ps2dev, NULL, cmd))
531 return -EIO;
532 break;
533
534 default:
535 return -EINVAL;
536 }
537
538 return 0;
539}
540
541static void hgpk_setup_input_device(struct input_dev *input,
542 struct input_dev *old_input,
543 enum hgpk_mode mode)
544{
545 if (old_input) {
546 input->name = old_input->name;
547 input->phys = old_input->phys;
548 input->id = old_input->id;
549 input->dev.parent = old_input->dev.parent;
550 }
551
552 memset(input->evbit, 0, sizeof(input->evbit));
553 memset(input->relbit, 0, sizeof(input->relbit));
554 memset(input->keybit, 0, sizeof(input->keybit));
555
556
557 __set_bit(EV_KEY, input->evbit);
558 __set_bit(BTN_LEFT, input->keybit);
559 __set_bit(BTN_RIGHT, input->keybit);
560
561 switch (mode) {
562 case HGPK_MODE_MOUSE:
563 __set_bit(EV_REL, input->evbit);
564 __set_bit(REL_X, input->relbit);
565 __set_bit(REL_Y, input->relbit);
566 break;
567
568 case HGPK_MODE_GLIDESENSOR:
569 __set_bit(BTN_TOUCH, input->keybit);
570 __set_bit(BTN_TOOL_FINGER, input->keybit);
571
572 __set_bit(EV_ABS, input->evbit);
573
574
575 input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0);
576
577
578 input_set_abs_params(input, ABS_X, 0, 399, 0, 0);
579 input_set_abs_params(input, ABS_Y, 0, 290, 0, 0);
580
581
582 input_abs_set_res(input, ABS_X, 8);
583 input_abs_set_res(input, ABS_Y, 8);
584 break;
585
586 case HGPK_MODE_PENTABLET:
587 __set_bit(BTN_TOUCH, input->keybit);
588 __set_bit(BTN_TOOL_FINGER, input->keybit);
589
590 __set_bit(EV_ABS, input->evbit);
591
592
593 input_set_abs_params(input, ABS_X, 0, 999, 0, 0);
594 input_set_abs_params(input, ABS_Y, 5, 239, 0, 0);
595
596
597 input_abs_set_res(input, ABS_X, 6);
598 input_abs_set_res(input, ABS_Y, 8);
599 break;
600
601 default:
602 BUG();
603 }
604}
605
606static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
607{
608 int err;
609
610 psmouse_reset(psmouse);
611
612 if (recalibrate) {
613 struct ps2dev *ps2dev = &psmouse->ps2dev;
614
615
616 if (ps2_command(ps2dev, NULL, 0xf5) ||
617 ps2_command(ps2dev, NULL, 0xf5) ||
618 ps2_command(ps2dev, NULL, 0xe6) ||
619 ps2_command(ps2dev, NULL, 0xf5)) {
620 return -1;
621 }
622
623
624 msleep(150);
625 }
626
627 err = hgpk_select_mode(psmouse);
628 if (err) {
629 psmouse_err(psmouse, "failed to select mode\n");
630 return err;
631 }
632
633 hgpk_reset_hack_state(psmouse);
634
635 return 0;
636}
637
638static int hgpk_force_recalibrate(struct psmouse *psmouse)
639{
640 struct hgpk_data *priv = psmouse->private;
641 int err;
642
643
644 if (psmouse->model < HGPK_MODEL_C)
645 return 0;
646
647 if (!autorecal) {
648 psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
649 return 0;
650 }
651
652 psmouse_dbg(psmouse, "recalibrating touchpad..\n");
653
654
655 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
656
657
658 err = hgpk_reset_device(psmouse, true);
659 if (err)
660 return err;
661
662
663
664
665
666
667
668 if (psmouse_activate(psmouse))
669 return -1;
670
671 if (tpdebug)
672 psmouse_dbg(psmouse, "touchpad reactivated\n");
673
674
675
676
677
678
679 if (recal_guard_time)
680 priv->recalib_window = jiffies +
681 msecs_to_jiffies(recal_guard_time);
682
683 return 0;
684}
685
686
687
688
689
690
691
692
693
694
695static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
696{
697 struct ps2dev *ps2dev = &psmouse->ps2dev;
698 int timeo;
699 int err;
700
701
702 if (psmouse->model < HGPK_MODEL_D)
703 return 0;
704
705 if (enable) {
706 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
707
708
709
710
711
712
713
714
715 for (timeo = 20; timeo > 0; timeo--) {
716 if (!ps2_sendbyte(ps2dev, PSMOUSE_CMD_DISABLE, 20))
717 break;
718 msleep(25);
719 }
720
721 err = hgpk_reset_device(psmouse, false);
722 if (err) {
723 psmouse_err(psmouse, "Failed to reset device!\n");
724 return err;
725 }
726
727
728 psmouse_activate(psmouse);
729 psmouse_dbg(psmouse, "Touchpad powered up.\n");
730 } else {
731 psmouse_dbg(psmouse, "Powering off touchpad.\n");
732
733 if (ps2_command(ps2dev, NULL, 0xec) ||
734 ps2_command(ps2dev, NULL, 0xec) ||
735 ps2_command(ps2dev, NULL, 0xea)) {
736 return -1;
737 }
738
739 psmouse_set_state(psmouse, PSMOUSE_IGNORE);
740
741
742 ps2_sendbyte(ps2dev, 0xec, 20);
743 }
744
745 return 0;
746}
747
748static int hgpk_poll(struct psmouse *psmouse)
749{
750
751 return -1;
752}
753
754static int hgpk_reconnect(struct psmouse *psmouse)
755{
756 struct hgpk_data *priv = psmouse->private;
757
758
759
760
761
762
763 if (olpc_board_at_least(olpc_board(0xb2)))
764 if (psmouse->ps2dev.serio->dev.power.power_state.event !=
765 PM_EVENT_ON)
766 return 0;
767
768 priv->powered = 1;
769 return hgpk_reset_device(psmouse, false);
770}
771
772static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
773{
774 struct hgpk_data *priv = psmouse->private;
775
776 return sprintf(buf, "%d\n", priv->powered);
777}
778
779static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
780 const char *buf, size_t count)
781{
782 struct hgpk_data *priv = psmouse->private;
783 unsigned int value;
784 int err;
785
786 err = kstrtouint(buf, 10, &value);
787 if (err)
788 return err;
789
790 if (value > 1)
791 return -EINVAL;
792
793 if (value != priv->powered) {
794
795
796
797
798 err = hgpk_toggle_powersave(psmouse, value);
799 if (!err)
800 priv->powered = value;
801 }
802
803 return err ? err : count;
804}
805
806__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
807 hgpk_show_powered, hgpk_set_powered, false);
808
809static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
810{
811 struct hgpk_data *priv = psmouse->private;
812
813 return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
814}
815
816static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
817 const char *buf, size_t len)
818{
819 struct hgpk_data *priv = psmouse->private;
820 enum hgpk_mode old_mode = priv->mode;
821 enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
822 struct input_dev *old_dev = psmouse->dev;
823 struct input_dev *new_dev;
824 int err;
825
826 if (new_mode == HGPK_MODE_INVALID)
827 return -EINVAL;
828
829 if (old_mode == new_mode)
830 return len;
831
832 new_dev = input_allocate_device();
833 if (!new_dev)
834 return -ENOMEM;
835
836 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
837
838
839 priv->mode = new_mode;
840 err = hgpk_reset_device(psmouse, false);
841 if (err)
842 goto err_try_restore;
843
844 hgpk_setup_input_device(new_dev, old_dev, new_mode);
845
846 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
847
848 err = input_register_device(new_dev);
849 if (err)
850 goto err_try_restore;
851
852 psmouse->dev = new_dev;
853 input_unregister_device(old_dev);
854
855 return len;
856
857err_try_restore:
858 input_free_device(new_dev);
859 priv->mode = old_mode;
860 hgpk_reset_device(psmouse, false);
861
862 return err;
863}
864
865PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
866 attr_show_mode, attr_set_mode);
867
868static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
869 void *data, char *buf)
870{
871 return -EINVAL;
872}
873
874static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
875 const char *buf, size_t count)
876{
877 struct hgpk_data *priv = psmouse->private;
878 unsigned int value;
879 int err;
880
881 err = kstrtouint(buf, 10, &value);
882 if (err)
883 return err;
884
885 if (value != 1)
886 return -EINVAL;
887
888
889
890
891
892
893 psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
894 return count;
895}
896
897__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
898 hgpk_trigger_recal_show, hgpk_trigger_recal, false);
899
900static void hgpk_disconnect(struct psmouse *psmouse)
901{
902 struct hgpk_data *priv = psmouse->private;
903
904 device_remove_file(&psmouse->ps2dev.serio->dev,
905 &psmouse_attr_powered.dattr);
906 device_remove_file(&psmouse->ps2dev.serio->dev,
907 &psmouse_attr_hgpk_mode.dattr);
908
909 if (psmouse->model >= HGPK_MODEL_C)
910 device_remove_file(&psmouse->ps2dev.serio->dev,
911 &psmouse_attr_recalibrate.dattr);
912
913 psmouse_reset(psmouse);
914 kfree(priv);
915}
916
917static void hgpk_recalib_work(struct work_struct *work)
918{
919 struct delayed_work *w = to_delayed_work(work);
920 struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
921 struct psmouse *psmouse = priv->psmouse;
922
923 if (hgpk_force_recalibrate(psmouse))
924 psmouse_err(psmouse, "recalibration failed!\n");
925}
926
927static int hgpk_register(struct psmouse *psmouse)
928{
929 struct hgpk_data *priv = psmouse->private;
930 int err;
931
932
933 psmouse->protocol_handler = hgpk_process_byte;
934 psmouse->poll = hgpk_poll;
935 psmouse->disconnect = hgpk_disconnect;
936 psmouse->reconnect = hgpk_reconnect;
937
938
939 psmouse->resync_time = 0;
940
941 psmouse->resetafter = 1024;
942
943 hgpk_setup_input_device(psmouse->dev, NULL, priv->mode);
944
945 err = device_create_file(&psmouse->ps2dev.serio->dev,
946 &psmouse_attr_powered.dattr);
947 if (err) {
948 psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
949 return err;
950 }
951
952 err = device_create_file(&psmouse->ps2dev.serio->dev,
953 &psmouse_attr_hgpk_mode.dattr);
954 if (err) {
955 psmouse_err(psmouse,
956 "Failed creating 'hgpk_mode' sysfs node\n");
957 goto err_remove_powered;
958 }
959
960
961 if (psmouse->model >= HGPK_MODEL_C) {
962 err = device_create_file(&psmouse->ps2dev.serio->dev,
963 &psmouse_attr_recalibrate.dattr);
964 if (err) {
965 psmouse_err(psmouse,
966 "Failed creating 'recalibrate' sysfs node\n");
967 goto err_remove_mode;
968 }
969 }
970
971 return 0;
972
973err_remove_mode:
974 device_remove_file(&psmouse->ps2dev.serio->dev,
975 &psmouse_attr_hgpk_mode.dattr);
976err_remove_powered:
977 device_remove_file(&psmouse->ps2dev.serio->dev,
978 &psmouse_attr_powered.dattr);
979 return err;
980}
981
982int hgpk_init(struct psmouse *psmouse)
983{
984 struct hgpk_data *priv;
985 int err;
986
987 priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
988 if (!priv) {
989 err = -ENOMEM;
990 goto alloc_fail;
991 }
992
993 psmouse->private = priv;
994
995 priv->psmouse = psmouse;
996 priv->powered = true;
997 priv->mode = hgpk_default_mode;
998 INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
999
1000 err = hgpk_reset_device(psmouse, false);
1001 if (err)
1002 goto init_fail;
1003
1004 err = hgpk_register(psmouse);
1005 if (err)
1006 goto init_fail;
1007
1008 return 0;
1009
1010init_fail:
1011 kfree(priv);
1012alloc_fail:
1013 return err;
1014}
1015
1016static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
1017{
1018 struct ps2dev *ps2dev = &psmouse->ps2dev;
1019 unsigned char param[3];
1020
1021
1022 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1023 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1024 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1025 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
1026 return -EIO;
1027 }
1028
1029 psmouse_dbg(psmouse, "ID: %*ph\n", 3, param);
1030
1031
1032 if (param[0] != 0x67 || param[1] != 0x00)
1033 return -ENODEV;
1034
1035 psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
1036
1037 return param[2];
1038}
1039
1040int hgpk_detect(struct psmouse *psmouse, bool set_properties)
1041{
1042 int version;
1043
1044 version = hgpk_get_model(psmouse);
1045 if (version < 0)
1046 return version;
1047
1048 if (set_properties) {
1049 psmouse->vendor = "ALPS";
1050 psmouse->name = "HGPK";
1051 psmouse->model = version;
1052 }
1053
1054 return 0;
1055}
1056
1057void hgpk_module_init(void)
1058{
1059 hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name,
1060 strlen(hgpk_mode_name));
1061 if (hgpk_default_mode == HGPK_MODE_INVALID) {
1062 hgpk_default_mode = HGPK_MODE_MOUSE;
1063 strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
1064 sizeof(hgpk_mode_name));
1065 }
1066}
1067