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(&psmouse->ps2dev,
717 PSMOUSE_CMD_DISABLE, 20))
718 break;
719 msleep(25);
720 }
721
722 err = hgpk_reset_device(psmouse, false);
723 if (err) {
724 psmouse_err(psmouse, "Failed to reset device!\n");
725 return err;
726 }
727
728
729 psmouse_activate(psmouse);
730 psmouse_dbg(psmouse, "Touchpad powered up.\n");
731 } else {
732 psmouse_dbg(psmouse, "Powering off touchpad.\n");
733
734 if (ps2_command(ps2dev, NULL, 0xec) ||
735 ps2_command(ps2dev, NULL, 0xec) ||
736 ps2_command(ps2dev, NULL, 0xea)) {
737 return -1;
738 }
739
740 psmouse_set_state(psmouse, PSMOUSE_IGNORE);
741
742
743 ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
744 }
745
746 return 0;
747}
748
749static int hgpk_poll(struct psmouse *psmouse)
750{
751
752 return -1;
753}
754
755static int hgpk_reconnect(struct psmouse *psmouse)
756{
757 struct hgpk_data *priv = psmouse->private;
758
759
760
761
762
763
764 if (olpc_board_at_least(olpc_board(0xb2)))
765 if (psmouse->ps2dev.serio->dev.power.power_state.event !=
766 PM_EVENT_ON)
767 return 0;
768
769 priv->powered = 1;
770 return hgpk_reset_device(psmouse, false);
771}
772
773static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
774{
775 struct hgpk_data *priv = psmouse->private;
776
777 return sprintf(buf, "%d\n", priv->powered);
778}
779
780static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
781 const char *buf, size_t count)
782{
783 struct hgpk_data *priv = psmouse->private;
784 unsigned int value;
785 int err;
786
787 err = kstrtouint(buf, 10, &value);
788 if (err)
789 return err;
790
791 if (value > 1)
792 return -EINVAL;
793
794 if (value != priv->powered) {
795
796
797
798
799 err = hgpk_toggle_powersave(psmouse, value);
800 if (!err)
801 priv->powered = value;
802 }
803
804 return err ? err : count;
805}
806
807__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
808 hgpk_show_powered, hgpk_set_powered, false);
809
810static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
811{
812 struct hgpk_data *priv = psmouse->private;
813
814 return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
815}
816
817static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
818 const char *buf, size_t len)
819{
820 struct hgpk_data *priv = psmouse->private;
821 enum hgpk_mode old_mode = priv->mode;
822 enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
823 struct input_dev *old_dev = psmouse->dev;
824 struct input_dev *new_dev;
825 int err;
826
827 if (new_mode == HGPK_MODE_INVALID)
828 return -EINVAL;
829
830 if (old_mode == new_mode)
831 return len;
832
833 new_dev = input_allocate_device();
834 if (!new_dev)
835 return -ENOMEM;
836
837 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
838
839
840 priv->mode = new_mode;
841 err = hgpk_reset_device(psmouse, false);
842 if (err)
843 goto err_try_restore;
844
845 hgpk_setup_input_device(new_dev, old_dev, new_mode);
846
847 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
848
849 err = input_register_device(new_dev);
850 if (err)
851 goto err_try_restore;
852
853 psmouse->dev = new_dev;
854 input_unregister_device(old_dev);
855
856 return len;
857
858err_try_restore:
859 input_free_device(new_dev);
860 priv->mode = old_mode;
861 hgpk_reset_device(psmouse, false);
862
863 return err;
864}
865
866PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
867 attr_show_mode, attr_set_mode);
868
869static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
870 void *data, char *buf)
871{
872 return -EINVAL;
873}
874
875static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
876 const char *buf, size_t count)
877{
878 struct hgpk_data *priv = psmouse->private;
879 unsigned int value;
880 int err;
881
882 err = kstrtouint(buf, 10, &value);
883 if (err)
884 return err;
885
886 if (value != 1)
887 return -EINVAL;
888
889
890
891
892
893
894 psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
895 return count;
896}
897
898__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
899 hgpk_trigger_recal_show, hgpk_trigger_recal, false);
900
901static void hgpk_disconnect(struct psmouse *psmouse)
902{
903 struct hgpk_data *priv = psmouse->private;
904
905 device_remove_file(&psmouse->ps2dev.serio->dev,
906 &psmouse_attr_powered.dattr);
907 device_remove_file(&psmouse->ps2dev.serio->dev,
908 &psmouse_attr_hgpk_mode.dattr);
909
910 if (psmouse->model >= HGPK_MODEL_C)
911 device_remove_file(&psmouse->ps2dev.serio->dev,
912 &psmouse_attr_recalibrate.dattr);
913
914 psmouse_reset(psmouse);
915 kfree(priv);
916}
917
918static void hgpk_recalib_work(struct work_struct *work)
919{
920 struct delayed_work *w = to_delayed_work(work);
921 struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
922 struct psmouse *psmouse = priv->psmouse;
923
924 if (hgpk_force_recalibrate(psmouse))
925 psmouse_err(psmouse, "recalibration failed!\n");
926}
927
928static int hgpk_register(struct psmouse *psmouse)
929{
930 struct hgpk_data *priv = psmouse->private;
931 int err;
932
933
934 psmouse->protocol_handler = hgpk_process_byte;
935 psmouse->poll = hgpk_poll;
936 psmouse->disconnect = hgpk_disconnect;
937 psmouse->reconnect = hgpk_reconnect;
938
939
940 psmouse->resync_time = 0;
941
942 psmouse->resetafter = 1024;
943
944 hgpk_setup_input_device(psmouse->dev, NULL, priv->mode);
945
946 err = device_create_file(&psmouse->ps2dev.serio->dev,
947 &psmouse_attr_powered.dattr);
948 if (err) {
949 psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
950 return err;
951 }
952
953 err = device_create_file(&psmouse->ps2dev.serio->dev,
954 &psmouse_attr_hgpk_mode.dattr);
955 if (err) {
956 psmouse_err(psmouse,
957 "Failed creating 'hgpk_mode' sysfs node\n");
958 goto err_remove_powered;
959 }
960
961
962 if (psmouse->model >= HGPK_MODEL_C) {
963 err = device_create_file(&psmouse->ps2dev.serio->dev,
964 &psmouse_attr_recalibrate.dattr);
965 if (err) {
966 psmouse_err(psmouse,
967 "Failed creating 'recalibrate' sysfs node\n");
968 goto err_remove_mode;
969 }
970 }
971
972 return 0;
973
974err_remove_mode:
975 device_remove_file(&psmouse->ps2dev.serio->dev,
976 &psmouse_attr_hgpk_mode.dattr);
977err_remove_powered:
978 device_remove_file(&psmouse->ps2dev.serio->dev,
979 &psmouse_attr_powered.dattr);
980 return err;
981}
982
983int hgpk_init(struct psmouse *psmouse)
984{
985 struct hgpk_data *priv;
986 int err;
987
988 priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
989 if (!priv) {
990 err = -ENOMEM;
991 goto alloc_fail;
992 }
993
994 psmouse->private = priv;
995
996 priv->psmouse = psmouse;
997 priv->powered = true;
998 priv->mode = hgpk_default_mode;
999 INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
1000
1001 err = hgpk_reset_device(psmouse, false);
1002 if (err)
1003 goto init_fail;
1004
1005 err = hgpk_register(psmouse);
1006 if (err)
1007 goto init_fail;
1008
1009 return 0;
1010
1011init_fail:
1012 kfree(priv);
1013alloc_fail:
1014 return err;
1015}
1016
1017static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
1018{
1019 struct ps2dev *ps2dev = &psmouse->ps2dev;
1020 unsigned char param[3];
1021
1022
1023 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1024 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1025 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1026 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
1027 return -EIO;
1028 }
1029
1030 psmouse_dbg(psmouse, "ID: %*ph\n", 3, param);
1031
1032
1033 if (param[0] != 0x67 || param[1] != 0x00)
1034 return -ENODEV;
1035
1036 psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
1037
1038 return param[2];
1039}
1040
1041int hgpk_detect(struct psmouse *psmouse, bool set_properties)
1042{
1043 int version;
1044
1045 version = hgpk_get_model(psmouse);
1046 if (version < 0)
1047 return version;
1048
1049 if (set_properties) {
1050 psmouse->vendor = "ALPS";
1051 psmouse->name = "HGPK";
1052 psmouse->model = version;
1053 }
1054
1055 return 0;
1056}
1057
1058void hgpk_module_init(void)
1059{
1060 hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name,
1061 strlen(hgpk_mode_name));
1062 if (hgpk_default_mode == HGPK_MODE_INVALID) {
1063 hgpk_default_mode = HGPK_MODE_MOUSE;
1064 strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
1065 sizeof(hgpk_mode_name));
1066 }
1067}
1068