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/serio.h>
36#include <linux/libps2.h>
37#include <linux/delay.h>
38#include <asm/olpc.h>
39
40#include "psmouse.h"
41#include "hgpk.h"
42
43#define ILLEGAL_XY 999999
44
45static bool tpdebug;
46module_param(tpdebug, bool, 0644);
47MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
48
49static int recalib_delta = 100;
50module_param(recalib_delta, int, 0644);
51MODULE_PARM_DESC(recalib_delta,
52 "packets containing a delta this large will be discarded, and a "
53 "recalibration may be scheduled.");
54
55static int jumpy_delay = 20;
56module_param(jumpy_delay, int, 0644);
57MODULE_PARM_DESC(jumpy_delay,
58 "delay (ms) before recal after jumpiness detected");
59
60static int spew_delay = 1;
61module_param(spew_delay, int, 0644);
62MODULE_PARM_DESC(spew_delay,
63 "delay (ms) before recal after packet spew detected");
64
65static int recal_guard_time;
66module_param(recal_guard_time, int, 0644);
67MODULE_PARM_DESC(recal_guard_time,
68 "interval (ms) during which recal will be restarted if packet received");
69
70static int post_interrupt_delay = 40;
71module_param(post_interrupt_delay, int, 0644);
72MODULE_PARM_DESC(post_interrupt_delay,
73 "delay (ms) before recal after recal interrupt detected");
74
75static bool autorecal = true;
76module_param(autorecal, bool, 0644);
77MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
78
79static char hgpk_mode_name[16];
80module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
81MODULE_PARM_DESC(hgpk_mode,
82 "default hgpk mode: mouse, glidesensor or pentablet");
83
84static int hgpk_default_mode = HGPK_MODE_MOUSE;
85
86static const char * const hgpk_mode_names[] = {
87 [HGPK_MODE_MOUSE] = "Mouse",
88 [HGPK_MODE_GLIDESENSOR] = "GlideSensor",
89 [HGPK_MODE_PENTABLET] = "PenTablet",
90};
91
92static int hgpk_mode_from_name(const char *buf, int len)
93{
94 int i;
95
96 for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
97 const char *name = hgpk_mode_names[i];
98 if (strlen(name) == len && !strncasecmp(name, buf, len))
99 return i;
100 }
101
102 return HGPK_MODE_INVALID;
103}
104
105
106
107
108static int approx_half(int curr, int prev)
109{
110 int belowhalf, abovehalf;
111
112 if (curr < 5 || prev < 5)
113 return 0;
114
115 belowhalf = (prev * 8) / 20;
116 abovehalf = (prev * 12) / 20;
117
118 return belowhalf < curr && curr <= abovehalf;
119}
120
121
122
123
124
125
126static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
127{
128 struct hgpk_data *priv = psmouse->private;
129 int avx, avy;
130 bool do_recal = false;
131
132 avx = abs(x);
133 avy = abs(y);
134
135
136 if (avx > recalib_delta ||
137 (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
138 hgpk_err(psmouse, "detected %dpx jump in x\n", x);
139 priv->xbigj = avx;
140 } else if (approx_half(avx, priv->xbigj)) {
141 hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
142 priv->xbigj = avx;
143 priv->xsaw_secondary++;
144 } else {
145 if (priv->xbigj && priv->xsaw_secondary > 1)
146 do_recal = true;
147 priv->xbigj = 0;
148 priv->xsaw_secondary = 0;
149 }
150
151 if (avy > recalib_delta ||
152 (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
153 hgpk_err(psmouse, "detected %dpx jump in y\n", y);
154 priv->ybigj = avy;
155 } else if (approx_half(avy, priv->ybigj)) {
156 hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
157 priv->ybigj = avy;
158 priv->ysaw_secondary++;
159 } else {
160 if (priv->ybigj && priv->ysaw_secondary > 1)
161 do_recal = true;
162 priv->ybigj = 0;
163 priv->ysaw_secondary = 0;
164 }
165
166 priv->xlast = avx;
167 priv->ylast = avy;
168
169 if (do_recal && jumpy_delay) {
170 hgpk_err(psmouse, "scheduling recalibration\n");
171 psmouse_queue_work(psmouse, &priv->recalib_wq,
172 msecs_to_jiffies(jumpy_delay));
173 }
174
175 return priv->xbigj || priv->ybigj;
176}
177
178static void hgpk_reset_spew_detection(struct hgpk_data *priv)
179{
180 priv->spew_count = 0;
181 priv->dupe_count = 0;
182 priv->x_tally = 0;
183 priv->y_tally = 0;
184 priv->spew_flag = NO_SPEW;
185}
186
187static void hgpk_reset_hack_state(struct psmouse *psmouse)
188{
189 struct hgpk_data *priv = psmouse->private;
190
191 priv->abs_x = priv->abs_y = -1;
192 priv->xlast = priv->ylast = ILLEGAL_XY;
193 priv->xbigj = priv->ybigj = 0;
194 priv->xsaw_secondary = priv->ysaw_secondary = 0;
195 hgpk_reset_spew_detection(priv);
196}
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213static void hgpk_spewing_hack(struct psmouse *psmouse,
214 int l, int r, int x, int y)
215{
216 struct hgpk_data *priv = psmouse->private;
217
218
219
220 if (l || r)
221 return;
222
223
224 if (!spew_delay)
225 return;
226
227 if (abs(x) > 3 || abs(y) > 3) {
228
229 hgpk_reset_spew_detection(priv);
230 return;
231 }
232
233
234
235 priv->x_tally += x;
236 priv->y_tally += y;
237
238 switch (priv->spew_flag) {
239 case NO_SPEW:
240
241 priv->spew_flag = MAYBE_SPEWING;
242
243
244
245 case MAYBE_SPEWING:
246 priv->spew_count++;
247
248 if (priv->spew_count < SPEW_WATCH_COUNT)
249 break;
250
251
252 priv->spew_flag = SPEW_DETECTED;
253
254
255
256 case SPEW_DETECTED:
257
258
259
260
261 if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
262 hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
263 priv->x_tally, priv->y_tally);
264 priv->spew_flag = RECALIBRATING;
265 psmouse_queue_work(psmouse, &priv->recalib_wq,
266 msecs_to_jiffies(spew_delay));
267 }
268
269 break;
270 case RECALIBRATING:
271
272
273 break;
274 }
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
308static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
309{
310 struct hgpk_data *priv = psmouse->private;
311 int pktcnt = psmouse->pktcnt;
312 bool valid;
313
314 switch (priv->mode) {
315 case HGPK_MODE_MOUSE:
316 valid = (packet[0] & 0x0C) == 0x08;
317 break;
318
319 case HGPK_MODE_GLIDESENSOR:
320 valid = pktcnt == 1 ?
321 packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80);
322 break;
323
324 case HGPK_MODE_PENTABLET:
325 valid = pktcnt == 1 ?
326 packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80);
327 break;
328
329 default:
330 valid = false;
331 break;
332 }
333
334 if (!valid)
335 hgpk_dbg(psmouse,
336 "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
337 priv->mode, pktcnt,
338 psmouse->packet[0], psmouse->packet[1],
339 psmouse->packet[2], psmouse->packet[3],
340 psmouse->packet[4], psmouse->packet[5]);
341
342 return valid;
343}
344
345static void hgpk_process_advanced_packet(struct psmouse *psmouse)
346{
347 struct hgpk_data *priv = psmouse->private;
348 struct input_dev *idev = psmouse->dev;
349 unsigned char *packet = psmouse->packet;
350 int down = !!(packet[2] & 2);
351 int left = !!(packet[3] & 1);
352 int right = !!(packet[3] & 2);
353 int x = packet[1] | ((packet[2] & 0x78) << 4);
354 int y = packet[4] | ((packet[3] & 0x70) << 3);
355
356 if (priv->mode == HGPK_MODE_GLIDESENSOR) {
357 int pt_down = !!(packet[2] & 1);
358 int finger_down = !!(packet[2] & 2);
359 int z = packet[5];
360
361 input_report_abs(idev, ABS_PRESSURE, z);
362 if (tpdebug)
363 hgpk_dbg(psmouse, "pd=%d fd=%d z=%d",
364 pt_down, finger_down, z);
365 } else {
366
367
368
369
370 if (tpdebug)
371 hgpk_dbg(psmouse, "pd=%d ", down);
372 }
373
374 if (tpdebug)
375 hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
376
377 input_report_key(idev, BTN_TOUCH, down);
378 input_report_key(idev, BTN_LEFT, left);
379 input_report_key(idev, BTN_RIGHT, right);
380
381
382
383
384
385 if (!down) {
386 hgpk_reset_hack_state(psmouse);
387 goto done;
388 }
389
390
391
392
393
394 if (x == priv->abs_x && y == priv->abs_y) {
395 if (++priv->dupe_count > SPEW_WATCH_COUNT) {
396 if (tpdebug)
397 hgpk_dbg(psmouse, "hard spew detected\n");
398 priv->spew_flag = RECALIBRATING;
399 psmouse_queue_work(psmouse, &priv->recalib_wq,
400 msecs_to_jiffies(spew_delay));
401 }
402 goto done;
403 }
404
405
406 priv->dupe_count = 0;
407
408
409 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
410 int x_diff = priv->abs_x - x;
411 int y_diff = priv->abs_y - y;
412 if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
413 if (tpdebug)
414 hgpk_dbg(psmouse, "discarding\n");
415 goto done;
416 }
417 hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
418 }
419
420 input_report_abs(idev, ABS_X, x);
421 input_report_abs(idev, ABS_Y, y);
422 priv->abs_x = x;
423 priv->abs_y = y;
424
425done:
426 input_sync(idev);
427}
428
429static void hgpk_process_simple_packet(struct psmouse *psmouse)
430{
431 struct input_dev *dev = psmouse->dev;
432 unsigned char *packet = psmouse->packet;
433 int left = packet[0] & 1;
434 int right = (packet[0] >> 1) & 1;
435 int x = packet[1] - ((packet[0] << 4) & 0x100);
436 int y = ((packet[0] << 3) & 0x100) - packet[2];
437
438 if (packet[0] & 0xc0)
439 hgpk_dbg(psmouse,
440 "overflow -- 0x%02x 0x%02x 0x%02x\n",
441 packet[0], packet[1], packet[2]);
442
443 if (hgpk_discard_decay_hack(psmouse, x, y)) {
444 if (tpdebug)
445 hgpk_dbg(psmouse, "discarding\n");
446 return;
447 }
448
449 hgpk_spewing_hack(psmouse, left, right, x, y);
450
451 if (tpdebug)
452 hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", 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 hgpk_dbg(psmouse,
485 "packet inside calibration window, "
486 "queueing another recalibration\n");
487 psmouse_queue_work(psmouse, &priv->recalib_wq,
488 msecs_to_jiffies(post_interrupt_delay));
489 }
490 priv->recalib_window = 0;
491 }
492
493 return PSMOUSE_GOOD_DATA;
494}
495
496static int hgpk_select_mode(struct psmouse *psmouse)
497{
498 struct ps2dev *ps2dev = &psmouse->ps2dev;
499 struct hgpk_data *priv = psmouse->private;
500 int i;
501 int cmd;
502
503
504
505
506
507 const int advanced_init[] = {
508 PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
509 PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
510 0xf2, 0xf2, 0xf2,
511 };
512
513 switch (priv->mode) {
514 case HGPK_MODE_MOUSE:
515 psmouse->pktsize = 3;
516 break;
517
518 case HGPK_MODE_GLIDESENSOR:
519 case HGPK_MODE_PENTABLET:
520 psmouse->pktsize = 6;
521
522
523 for (i = 0; i < ARRAY_SIZE(advanced_init); i++)
524 if (ps2_command(ps2dev, NULL, advanced_init[i]))
525 return -EIO;
526
527
528 cmd = priv->mode == HGPK_MODE_GLIDESENSOR ?
529 PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21;
530
531 if (ps2_command(ps2dev, NULL, cmd))
532 return -EIO;
533 break;
534
535 default:
536 return -EINVAL;
537 }
538
539 return 0;
540}
541
542static void hgpk_setup_input_device(struct input_dev *input,
543 struct input_dev *old_input,
544 enum hgpk_mode mode)
545{
546 if (old_input) {
547 input->name = old_input->name;
548 input->phys = old_input->phys;
549 input->id = old_input->id;
550 input->dev.parent = old_input->dev.parent;
551 }
552
553 memset(input->evbit, 0, sizeof(input->evbit));
554 memset(input->relbit, 0, sizeof(input->relbit));
555 memset(input->keybit, 0, sizeof(input->keybit));
556
557
558 __set_bit(EV_KEY, input->evbit);
559 __set_bit(BTN_LEFT, input->keybit);
560 __set_bit(BTN_RIGHT, input->keybit);
561
562 switch (mode) {
563 case HGPK_MODE_MOUSE:
564 __set_bit(EV_REL, input->evbit);
565 __set_bit(REL_X, input->relbit);
566 __set_bit(REL_Y, input->relbit);
567 break;
568
569 case HGPK_MODE_GLIDESENSOR:
570 __set_bit(BTN_TOUCH, input->keybit);
571 __set_bit(BTN_TOOL_FINGER, input->keybit);
572
573 __set_bit(EV_ABS, input->evbit);
574
575
576 input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0);
577
578
579 input_set_abs_params(input, ABS_X, 0, 399, 0, 0);
580 input_set_abs_params(input, ABS_Y, 0, 290, 0, 0);
581
582
583 input_abs_set_res(input, ABS_X, 8);
584 input_abs_set_res(input, ABS_Y, 8);
585 break;
586
587 case HGPK_MODE_PENTABLET:
588 __set_bit(BTN_TOUCH, input->keybit);
589 __set_bit(BTN_TOOL_FINGER, input->keybit);
590
591 __set_bit(EV_ABS, input->evbit);
592
593
594 input_set_abs_params(input, ABS_X, 0, 999, 0, 0);
595 input_set_abs_params(input, ABS_Y, 5, 239, 0, 0);
596
597
598 input_abs_set_res(input, ABS_X, 6);
599 input_abs_set_res(input, ABS_Y, 8);
600 break;
601
602 default:
603 BUG();
604 }
605}
606
607static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
608{
609 int err;
610
611 psmouse_reset(psmouse);
612
613 if (recalibrate) {
614 struct ps2dev *ps2dev = &psmouse->ps2dev;
615
616
617 if (ps2_command(ps2dev, NULL, 0xf5) ||
618 ps2_command(ps2dev, NULL, 0xf5) ||
619 ps2_command(ps2dev, NULL, 0xe6) ||
620 ps2_command(ps2dev, NULL, 0xf5)) {
621 return -1;
622 }
623
624
625 msleep(150);
626 }
627
628 err = hgpk_select_mode(psmouse);
629 if (err) {
630 hgpk_err(psmouse, "failed to select mode\n");
631 return err;
632 }
633
634 hgpk_reset_hack_state(psmouse);
635
636 return 0;
637}
638
639static int hgpk_force_recalibrate(struct psmouse *psmouse)
640{
641 struct ps2dev *ps2dev = &psmouse->ps2dev;
642 struct hgpk_data *priv = psmouse->private;
643 int err;
644
645
646 if (psmouse->model < HGPK_MODEL_C)
647 return 0;
648
649 if (!autorecal) {
650 hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
651 return 0;
652 }
653
654 hgpk_dbg(psmouse, "recalibrating touchpad..\n");
655
656
657 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
658
659
660 err = hgpk_reset_device(psmouse, true);
661 if (err)
662 return err;
663
664
665
666
667
668
669
670
671 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
672 return -1;
673
674 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
675
676 if (tpdebug)
677 hgpk_dbg(psmouse, "touchpad reactivated\n");
678
679
680
681
682
683
684 if (recal_guard_time)
685 priv->recalib_window = jiffies +
686 msecs_to_jiffies(recal_guard_time);
687
688 return 0;
689}
690
691
692
693
694
695
696
697
698
699
700static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
701{
702 struct ps2dev *ps2dev = &psmouse->ps2dev;
703 int timeo;
704 int err;
705
706
707 if (psmouse->model < HGPK_MODEL_D)
708 return 0;
709
710 if (enable) {
711 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
712
713
714
715
716
717
718
719
720 for (timeo = 20; timeo > 0; timeo--) {
721 if (!ps2_sendbyte(&psmouse->ps2dev,
722 PSMOUSE_CMD_DISABLE, 20))
723 break;
724 msleep(25);
725 }
726
727 err = hgpk_reset_device(psmouse, false);
728 if (err) {
729 hgpk_err(psmouse, "Failed to reset device!\n");
730 return err;
731 }
732
733
734 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
735 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
736 hgpk_dbg(psmouse, "Touchpad powered up.\n");
737 } else {
738 hgpk_dbg(psmouse, "Powering off touchpad.\n");
739
740 if (ps2_command(ps2dev, NULL, 0xec) ||
741 ps2_command(ps2dev, NULL, 0xec) ||
742 ps2_command(ps2dev, NULL, 0xea)) {
743 return -1;
744 }
745
746 psmouse_set_state(psmouse, PSMOUSE_IGNORE);
747
748
749 ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
750 }
751
752 return 0;
753}
754
755static int hgpk_poll(struct psmouse *psmouse)
756{
757
758 return -1;
759}
760
761static int hgpk_reconnect(struct psmouse *psmouse)
762{
763 struct hgpk_data *priv = psmouse->private;
764
765
766
767
768
769
770 if (olpc_board_at_least(olpc_board(0xb2)))
771 if (psmouse->ps2dev.serio->dev.power.power_state.event !=
772 PM_EVENT_ON)
773 return 0;
774
775 priv->powered = 1;
776 return hgpk_reset_device(psmouse, false);
777}
778
779static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
780{
781 struct hgpk_data *priv = psmouse->private;
782
783 return sprintf(buf, "%d\n", priv->powered);
784}
785
786static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
787 const char *buf, size_t count)
788{
789 struct hgpk_data *priv = psmouse->private;
790 unsigned long value;
791 int err;
792
793 err = strict_strtoul(buf, 10, &value);
794 if (err || value > 1)
795 return -EINVAL;
796
797 if (value != priv->powered) {
798
799
800
801
802 err = hgpk_toggle_powersave(psmouse, value);
803 if (!err)
804 priv->powered = value;
805 }
806
807 return err ? err : count;
808}
809
810__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
811 hgpk_show_powered, hgpk_set_powered, false);
812
813static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
814{
815 struct hgpk_data *priv = psmouse->private;
816
817 return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
818}
819
820static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
821 const char *buf, size_t len)
822{
823 struct hgpk_data *priv = psmouse->private;
824 enum hgpk_mode old_mode = priv->mode;
825 enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
826 struct input_dev *old_dev = psmouse->dev;
827 struct input_dev *new_dev;
828 int err;
829
830 if (new_mode == HGPK_MODE_INVALID)
831 return -EINVAL;
832
833 if (old_mode == new_mode)
834 return len;
835
836 new_dev = input_allocate_device();
837 if (!new_dev)
838 return -ENOMEM;
839
840 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
841
842
843 priv->mode = new_mode;
844 err = hgpk_reset_device(psmouse, false);
845 if (err)
846 goto err_try_restore;
847
848 hgpk_setup_input_device(new_dev, old_dev, new_mode);
849
850 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
851
852 err = input_register_device(new_dev);
853 if (err)
854 goto err_try_restore;
855
856 psmouse->dev = new_dev;
857 input_unregister_device(old_dev);
858
859 return len;
860
861err_try_restore:
862 input_free_device(new_dev);
863 priv->mode = old_mode;
864 hgpk_reset_device(psmouse, false);
865
866 return err;
867}
868
869PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
870 attr_show_mode, attr_set_mode);
871
872static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
873 void *data, char *buf)
874{
875 return -EINVAL;
876}
877
878static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
879 const char *buf, size_t count)
880{
881 struct hgpk_data *priv = psmouse->private;
882 unsigned long value;
883 int err;
884
885 err = strict_strtoul(buf, 10, &value);
886 if (err || 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 hgpk_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 hgpk_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 hgpk_err(psmouse, "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 hgpk_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 hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
1030
1031
1032 if (param[0] != 0x67 || param[1] != 0x00)
1033 return -ENODEV;
1034
1035 hgpk_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