sync hh.org
[hh.org.git] / drivers / input / mouse / navpoint.c
bloba690c9a682af9194fae09beb14235da48ff3f5a8
1 /*
2 * Synaptics NavPoint (tm)
3 * Uses Modular Embedded Protocol (MEP)
5 * Copyright (c) 2005 SDG Systems, LLC
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/errno.h>
15 #include <linux/navpoint.h>
16 #include <linux/slab.h>
17 #include <linux/wait.h>
18 #include <linux/device.h>
19 #include <linux/sysfs.h>
21 #include <asm/memory.h>
23 #include "mep.h"
25 #ifdef DEBUG
26 #define dbg(fmt, ...) printk(KERN_DEBUG fmt, __VA_ARGS__);
27 #else
28 #define dbg(fmt, ...)
29 #endif
31 #define NP_CMD_TOUCHPAD_INFO (MEP_HOST_CMD_TYPE_QUERY | 0x20)
33 #define NP_PKT_ABS_FINGER_ON 0x01
34 #define NP_PKT_ABS_GESTURE 0x02
35 #define NP_PKT_ABS_RELXY 0x04
36 #define NP_PKT_ABS_W(byte) ((byte) >> 4)
37 #define NP_PKT_REL (0x08 << 4)
38 #define NP_PKT_HLO 0x10
40 /* Reporting mode parameter and modes itself */
41 #define NP_PARM_REPMODE 0x20
42 #define NP_RM_ABS (1 << 0)
43 #define NP_RM_REL (1 << 1)
44 #define NP_RM_BUT (1 << 2)
45 #define NP_RM_SCR (1 << 3)
46 #define NP_RM_RES (1 << 4)
47 #define NP_RM_NFI (1 << 5)
48 #define NP_RM_R40 (1 << 6)
49 #define NP_RM_R80 (1 << 7)
51 #define ms2p(msecs) ((80*msecs)/1000)
52 #define back_ms2p(packets) ((packets*1000)/80)
53 #define none(x) (x)
54 #define back_none(x) (x)
56 struct navpoint_data {
57 struct {
58 char *mode_str;
59 unsigned int mode;
60 unsigned int tap_time;
61 unsigned int dtap_time;
62 unsigned int rep_wait;
63 unsigned int rep_rate;
64 u_int8_t pressure;
65 u_int8_t threshold;
66 } attrs;
67 unsigned int want_to_init;
69 struct mep_pkt_stream_desc ps;
70 struct input_dev *input;
71 void *mep_dev; /* private data for MEP protocol */
73 int wait_ack_tries;
75 /* Used by mouse and keyboard modes */
76 spinlock_t timer_lock;
77 struct timer_list tap_timer;
78 int8_t finger;
79 int8_t old_finger;
80 unsigned int finger_count;
81 unsigned int tapped;
82 u_int8_t z;
84 /* Used by keyboard modes */
85 unsigned int rep_count;
86 unsigned int rep_rate;
87 unsigned int key;
90 static void
91 send_parm( struct navpoint_dev *nav_dev, u_int8_t parm ) {
92 u_int8_t host_pkt[MEP_HOST_PKT_SIZE];
93 int size;
94 u_int8_t mep_para[2] = { 0x00, parm };
95 /* command sending must be syncronized with acknowledgement from the
96 * previous command. But sometimes navpoint forgets or delay ACK. As
97 * long this function used inside navpoint_rx it is safe, because we
98 * send params only when there is enough room in queue for incoming
99 * packets, so there is no risk of queue overrun. */
100 size = mep_host_format_cmd( host_pkt, nav_dev->unit,
101 MEP_HOST_CMD_TYPE_PARM | NP_PARM_REPMODE, 2, mep_para );
102 nav_dev->cb_func = NULL;
103 nav_dev->priv = NULL;
104 nav_dev->tx_func( host_pkt, size );
105 dbg("txed: size: %d, data: %02x %02x %02x %02x \n",
106 size, host_pkt[0], host_pkt[1], host_pkt[2], host_pkt[3]);
107 return;
110 static void
111 process_keyboard( struct navpoint_dev *nav_dev )
113 struct navpoint_data *navpt = nav_dev->driver_data;
114 u_int8_t *cp=navpt->ps.pkt.data;
116 int x = (int)cp[1] << 8 | cp[2];
117 int y = (int)cp[3] << 8 | cp[4];
118 u_int8_t z = cp[5];
119 navpt->finger = cp[0] & 1;
121 dbg("f: %d x: %d y: %d\n", navpt->finger, x, y);
123 if (navpt->finger && z < navpt->attrs.threshold) return;
125 if (x == 0 && y == 0);
126 else if (x > 4000) navpt->key = KEY_RIGHT;
127 else if (x < 2500) navpt->key = KEY_LEFT;
128 else if (y > 3000) navpt->key = KEY_UP;
129 else if (y < 2500) navpt->key = KEY_DOWN;
130 else navpt->key = KEY_ENTER;
132 if (navpt->finger && !navpt->old_finger && !navpt->tapped) {
133 dbg("%d press\n", navpt->key);
134 input_report_key( navpt->input, navpt->key, 1 );
135 navpt->tapped = navpt->key;
136 navpt->rep_count = 0;
137 navpt->rep_rate = navpt->attrs.rep_wait;
139 else if (!navpt->finger && navpt->old_finger && navpt->tapped) {
140 dbg("%d release\n", navpt->key);
141 input_report_key( navpt->input, navpt->tapped, 0 );
142 navpt->tapped = 0;
144 else if (navpt->finger && navpt->old_finger && navpt->tapped) {
145 if (navpt->rep_count >= navpt->rep_rate) {
146 dbg("%d rep\n", navpt->key);
147 navpt->rep_count = 0;
148 navpt->rep_rate = navpt->attrs.rep_rate;
149 if (navpt->tapped != KEY_ENTER && navpt->key != KEY_ENTER) {
150 input_report_key( navpt->input, navpt->tapped, 0 );
151 navpt->tapped = navpt->key;
152 input_report_key( navpt->input, navpt->tapped, 1 );
154 else if (navpt->tapped == KEY_ENTER) {
155 input_report_key( navpt->input, navpt->tapped, 0 );
156 input_report_key( navpt->input, navpt->tapped, 1 );
159 else navpt->rep_count++;
162 navpt->old_finger = navpt->finger;
163 input_sync( navpt->input );
164 return;
167 static void
168 process_keyboard2( struct navpoint_dev *nav_dev )
170 struct navpoint_data *navpt = nav_dev->driver_data;
171 u_int8_t *cp=navpt->ps.pkt.data;
173 int x = (int)cp[1] << 8 | cp[2];
174 int y = (int)cp[3] << 8 | cp[4];
175 u_int8_t z = cp[5];
176 navpt->finger = cp[0] & 1;
178 if (navpt->finger && z < navpt->attrs.threshold) return;
180 if (x == 0 && y == 0);
181 else if (x > 4000) navpt->key = KEY_RIGHT;
182 else if (x < 2500) navpt->key = KEY_LEFT;
183 else if (y > 3000) navpt->key = KEY_UP;
184 else if (y < 2500) navpt->key = KEY_DOWN;
185 else navpt->key = 0;
187 if ( navpt->finger ) {
188 /* First two packets are ignored to get genuine Z value. */
189 switch ( navpt->finger_count ) {
190 case 2: /* First accounted packet,
191 send event immediately */
192 navpt->z = z;
193 navpt->rep_count = navpt->rep_rate;
194 break;
195 case 3: /* Second accounted packet,
196 wait for start repeating */
197 navpt->rep_rate = navpt->attrs.rep_wait;
198 break;
199 default: break;
202 if ( navpt->finger_count >= 2 ) {
203 if (navpt->z > navpt->attrs.pressure) {
204 navpt->key = KEY_ENTER;
207 if (navpt->rep_count >= navpt->rep_rate && navpt->key) {
208 dbg("%d press&release or repeat\n", navpt->key);
209 input_report_key(navpt->input, navpt->key, 1);
210 input_report_key(navpt->input, navpt->key, 0);
211 input_sync( navpt->input );
212 navpt->rep_rate = navpt->attrs.rep_rate;
213 navpt->rep_count = 0;
215 else navpt->rep_count++;
217 if ( navpt->finger_count <= navpt->attrs.tap_time ) {
218 navpt->finger_count++;
221 else {
222 navpt->finger_count = 0;
223 navpt->z = 0;
224 navpt->rep_rate = navpt->attrs.rep_wait;
227 navpt->old_finger = navpt->finger;
229 return;
232 void
233 tap_timer( unsigned long arg )
235 struct navpoint_dev *nav_dev = (struct navpoint_dev *)arg;
236 struct navpoint_data *navpt = nav_dev->driver_data;
238 spin_lock(&navpt->timer_lock);
239 if (navpt->tapped && !navpt->finger) {
240 input_report_key( navpt->input, navpt->tapped, 0 );
241 navpt->tapped = 0;
242 input_sync( navpt->input );
244 spin_unlock(&navpt->timer_lock);
246 return;
249 static void
250 process_mouse_taps( struct navpoint_dev *nav_dev )
252 struct navpoint_data *navpt = nav_dev->driver_data;
253 u_int8_t *cp=navpt->ps.pkt.data;
254 navpt->z = cp[5];
255 navpt->finger = cp[0] & 1;
257 dbg("f: %d z: %d\n", navpt->finger, navpt->z);
259 if ( !navpt->finger && navpt->old_finger
260 && navpt->finger_count > 0
261 && navpt->finger_count < navpt->attrs.tap_time ) {
262 spin_lock(&navpt->timer_lock);
263 if ( timer_pending(&navpt->tap_timer) ) {
264 navpt->tapped = 0;
265 input_report_key(navpt->input, BTN_LEFT, 0);
266 input_report_key(navpt->input, BTN_LEFT, 1);
267 input_report_key(navpt->input, BTN_LEFT, 0);
269 else if ( navpt->tapped ) {
270 navpt->tapped = 0;
271 input_report_key(navpt->input, BTN_LEFT, 0);
273 else {
274 navpt->tapped = BTN_LEFT;
275 input_report_key(navpt->input, BTN_LEFT, 1);
276 init_timer(&navpt->tap_timer);
277 navpt->tap_timer.data = (unsigned long)nav_dev;
278 navpt->tap_timer.expires = jiffies + msecs_to_jiffies(
279 back_ms2p(navpt->attrs.dtap_time) );
280 navpt->tap_timer.function = tap_timer;
281 add_timer(&navpt->tap_timer);
283 spin_unlock(&navpt->timer_lock);
284 input_sync( navpt->input );
287 if (navpt->finger && navpt->finger_count <= navpt->attrs.tap_time
288 && navpt->z > navpt->attrs.threshold) {
289 navpt->finger_count++;
291 else if ( !navpt->finger ) navpt->finger_count = 0;
293 navpt->old_finger = navpt->finger;
295 return;
298 static void
299 process_mouse_rel( struct navpoint_dev *nav_dev )
301 struct navpoint_data *navpt = nav_dev->driver_data;
302 u_int8_t *cp=navpt->ps.pkt.data;
304 if (navpt->finger && navpt->z < navpt->attrs.threshold) return;
306 input_report_rel( navpt->input, REL_X, (int8_t)cp[1] );
307 input_report_rel( navpt->input, REL_Y, -(int8_t)cp[2] );
308 input_sync( navpt->input );
310 return;
313 void
314 navpoint_rx( struct navpoint_dev *nav_dev, u_int8_t octet,
315 unsigned int pending )
317 struct navpoint_data *navpt = nav_dev->driver_data;
318 struct mep_pkt_stream_desc *ps = &navpt->ps;
319 enum mep_rx_result ret;
320 u_int8_t *cp;
322 ret = mep_rx( ps, octet );
323 if (ret == MEP_RX_PKT_DONE) {
324 cp = ps->pkt.data;
325 //printk( "navpoint: ctrl=%d len=%d data=%02x %02x %02x %02x "
326 // "%02x %02x %02x\n", ps->ctrl, ps->len, cp[0], cp[1],
327 // cp[2], cp[3], cp[4], cp[5], cp[6] );
328 //if (ps->len == 0 && ps->ctrl == MEP_MODULE_PKT_CTRL_GEN) {
329 // printk("ack\n");
330 //} else printk("pkt\n");
331 if (navpt->want_to_init) {
332 if (navpt->want_to_init == 2 && cp[0] != 0xFF
333 && pending < 10) {
334 /* cp[0] == 0xFF is startup-garbage packet,
335 * driver must eat all 0xFF and do not send
336 * anything. Next packet is always HELLO. */
338 if (navpt->attrs.mode == 2) {
339 send_parm( nav_dev, NP_RM_R80
340 | NP_RM_ABS
341 | NP_RM_REL );
343 else {
344 send_parm( nav_dev, NP_RM_R80
345 | NP_RM_ABS );
348 navpt->want_to_init = 1;
349 navpt->wait_ack_tries = 0;
351 else if (navpt->want_to_init == 1) { // wait for ack
352 if (ps->len == 0 && ps->ctrl == MEP_MODULE_PKT_CTRL_GEN) {
353 navpt->old_finger = 0;
354 navpt->finger_count = 0;
355 navpt->tapped = 0;
356 navpt->want_to_init = 0;
358 else if (navpt->wait_ack_tries >= 4) {
359 navpt->wait_ack_tries = 0;
360 navpt->want_to_init = 2;
362 else navpt->wait_ack_tries++;
365 else if (ps->ctrl == MEP_MODULE_PKT_CTRL_NATIVE
366 && ps->len == 6) {
367 switch ( navpt->attrs.mode ) {
368 case 0: process_keyboard( nav_dev ); break;
369 case 1: process_keyboard2( nav_dev ); break;
370 case 2: process_mouse_taps( nav_dev ); break;
371 default: break;
374 else if (ps->ctrl == MEP_MODULE_PKT_CTRL_GEN
375 && (cp[0] & 0xF0) == NP_PKT_REL && ps->len == 3) {
376 if (navpt->attrs.mode == 2) process_mouse_rel( nav_dev );
377 else printk("navpoint: unexpected relative packet\n");
379 else {
380 printk("navpoint: completely unexpected packet "
381 "ctrl=%d len=%d data=%02x %02x %02x "
382 "%02x %02x %02x %02x\n", ps->ctrl, ps->len,
383 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
384 cp[6]);
387 return;
390 void
391 navpoint_reset( struct navpoint_dev *nav_dev )
393 struct navpoint_data *navpt = nav_dev->driver_data;
394 navpt->want_to_init = 2;
397 #define DEFINE_INT_ATTR(name, min, max, converter) \
398 static ssize_t \
399 __get_attr_##name(struct class_device *cdev, char *buf) \
401 struct navpoint_data *navpt = (struct navpoint_data*) \
402 to_input_dev(cdev)->private; \
403 return sprintf(buf, "%d\n", \
404 back_##converter(navpt->attrs.name)); \
408 static ssize_t \
409 __set_attr_##name(struct class_device *cdev, const char *val, \
410 size_t count) \
412 struct navpoint_data *navpt = (struct navpoint_data*) \
413 to_input_dev(cdev)->private; \
414 unsigned long l; \
415 char *tmp; \
417 if (!val) goto failed; \
418 l = simple_strtoul(val, &tmp, 0); \
419 if (val == tmp || (unsigned int)l != l) goto failed; \
420 if (l < min && l > max) goto failed; \
421 navpt->attrs.name = converter(l); \
423 return count; \
424 failed: \
425 return -EINVAL; \
427 static CLASS_DEVICE_ATTR(name, S_IWUSR | S_IRUGO, __get_attr_##name, \
428 __set_attr_##name );
430 static ssize_t
431 get_attr_mode(struct class_device *cdev, char *buf) {
432 struct navpoint_data *navpt = (struct navpoint_data*)
433 to_input_dev(cdev)->private;
434 return sprintf(buf, "%s\n", navpt->attrs.mode_str);
437 static ssize_t
438 set_attr_mode(struct class_device *cdev, const char *val,
439 size_t count)
441 struct navpoint_data *navpt = (struct navpoint_data*)
442 to_input_dev(cdev)->private;
443 char tmp[11];
445 if (count > 10 || strnlen(val, 11) > 10 || !sscanf(val, "%s", tmp)) {
446 return -EINVAL;
449 if (strcmp(tmp, "keyboard") == 0) navpt->attrs.mode = 0;
450 else if (strcmp(tmp, "keyboard2") == 0) navpt->attrs.mode = 1;
451 else if (strcmp(tmp, "mouse") == 0) navpt->attrs.mode = 2;
452 else return -EINVAL;
454 strcpy(navpt->attrs.mode_str, tmp);
456 navpt->want_to_init = 2;
457 return count;
460 static CLASS_DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, get_attr_mode,
461 set_attr_mode );
463 DEFINE_INT_ATTR(tap_time, 25, 1000, ms2p);
464 DEFINE_INT_ATTR(dtap_time, 25, navpt->attrs.tap_time, ms2p);
465 DEFINE_INT_ATTR(rep_wait, 25, 10000, ms2p);
466 DEFINE_INT_ATTR(rep_rate, 0, 10000, ms2p);
467 DEFINE_INT_ATTR(pressure, 0, 255, none);
468 DEFINE_INT_ATTR(threshold, 0, 255, none);
470 static struct attribute *navpoint_attrs[] = {
471 &class_device_attr_mode.attr,
472 &class_device_attr_tap_time.attr,
473 &class_device_attr_dtap_time.attr,
474 &class_device_attr_rep_wait.attr,
475 &class_device_attr_rep_rate.attr,
476 &class_device_attr_pressure.attr,
477 &class_device_attr_threshold.attr,
478 NULL
481 static struct attribute_group navpoint_attr_group = {
482 .attrs = navpoint_attrs,
486 navpoint_init( struct navpoint_dev *nav_dev )
488 struct navpoint_data *navpt;
490 navpt = nav_dev->driver_data = kmalloc( sizeof *navpt, GFP_KERNEL );
491 if (navpt == NULL) goto navpt_failed;
492 memset( navpt, 0, sizeof *navpt );
494 navpt->input = input_allocate_device();
495 if (navpt->input == NULL) goto input_failed;
497 navpt->attrs.mode_str = kmalloc( 11, GFP_KERNEL );
498 if (navpt->attrs.mode_str == NULL) goto mode_str_failed;
499 strcpy(navpt->attrs.mode_str, "keyboard");
501 navpt->attrs.mode = 0;
502 navpt->attrs.tap_time = ms2p(100);
503 navpt->attrs.dtap_time = ms2p(175);
504 navpt->attrs.rep_wait = ms2p(625);
505 navpt->attrs.rep_rate = ms2p(75);
506 navpt->attrs.pressure = 140;
507 navpt->attrs.threshold = 45;
508 navpt->want_to_init = 2;
510 navpt->input->name = "NavPoint Device";
511 navpt->input->private = navpt;
512 navpt->input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
513 navpt->input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
514 navpt->input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT);
515 navpt->input->keybit[LONG(KEY_UP)] |= BIT(KEY_UP);
516 navpt->input->keybit[LONG(KEY_DOWN)] |= BIT(KEY_DOWN);
517 navpt->input->keybit[LONG(KEY_RIGHT)] |= BIT(KEY_RIGHT);
518 navpt->input->keybit[LONG(KEY_LEFT)] |= BIT(KEY_LEFT);
519 navpt->input->keybit[LONG(KEY_ENTER)] |= BIT(KEY_ENTER);
521 input_register_device( navpt->input );
522 sysfs_create_group(&navpt->input->cdev.kobj, &navpoint_attr_group);
524 spin_lock_init(&navpt->timer_lock);
526 return 0;
528 mode_str_failed:
529 input_free_device( navpt->input );
530 input_failed:
531 kfree( navpt );
532 navpt_failed:
533 printk(KERN_ERR "navpoint: Failed to initialize\n");
534 return -ENOMEM;
537 void
538 navpoint_exit( struct navpoint_dev *nav_dev )
540 struct navpoint_data *navpt = nav_dev->driver_data;
542 sysfs_remove_group( &navpt->input->cdev.kobj, &navpoint_attr_group );
543 input_unregister_device( navpt->input );
544 kfree( nav_dev->driver_data );
546 return;
549 EXPORT_SYMBOL(navpoint_rx);
550 EXPORT_SYMBOL(navpoint_reset);
551 EXPORT_SYMBOL(navpoint_init);
552 EXPORT_SYMBOL(navpoint_exit);
554 MODULE_LICENSE("GPL");