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>
26 #define dbg(fmt, ...) printk(KERN_DEBUG fmt, __VA_ARGS__);
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)
54 #define back_none(x) (x)
56 struct navpoint_data
{
60 unsigned int tap_time
;
61 unsigned int dtap_time
;
62 unsigned int rep_wait
;
63 unsigned int rep_rate
;
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 */
75 /* Used by mouse and keyboard modes */
76 spinlock_t timer_lock
;
77 struct timer_list tap_timer
;
80 unsigned int finger_count
;
84 /* Used by keyboard modes */
85 unsigned int rep_count
;
86 unsigned int rep_rate
;
91 send_parm( struct navpoint_dev
*nav_dev
, u_int8_t parm
) {
92 u_int8_t host_pkt
[MEP_HOST_PKT_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]);
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];
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 );
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
);
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];
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
;
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 */
193 navpt
->rep_count
= navpt
->rep_rate
;
195 case 3: /* Second accounted packet,
196 wait for start repeating */
197 navpt
->rep_rate
= navpt
->attrs
.rep_wait
;
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
++;
222 navpt
->finger_count
= 0;
224 navpt
->rep_rate
= navpt
->attrs
.rep_wait
;
227 navpt
->old_finger
= navpt
->finger
;
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 );
242 input_sync( navpt
->input
);
244 spin_unlock(&navpt
->timer_lock
);
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
;
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
) ) {
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
) {
271 input_report_key(navpt
->input
, BTN_LEFT
, 0);
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
;
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
);
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
;
322 ret
= mep_rx( ps
, octet
);
323 if (ret
== MEP_RX_PKT_DONE
) {
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) {
330 //} else printk("pkt\n");
331 if (navpt
->want_to_init
) {
332 if (navpt
->want_to_init
== 2 && cp
[0] != 0xFF
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
344 send_parm( nav_dev
, NP_RM_R80
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;
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
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;
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");
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],
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) \
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)); \
409 __set_attr_##name(struct class_device *cdev, const char *val, \
412 struct navpoint_data *navpt = (struct navpoint_data*) \
413 to_input_dev(cdev)->private; \
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); \
427 static CLASS_DEVICE_ATTR(name, S_IWUSR | S_IRUGO, __get_attr_##name, \
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
);
438 set_attr_mode(struct class_device
*cdev
, const char *val
,
441 struct navpoint_data
*navpt
= (struct navpoint_data
*)
442 to_input_dev(cdev
)->private;
445 if (count
> 10 || strnlen(val
, 11) > 10 || !sscanf(val
, "%s", tmp
)) {
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;
454 strcpy(navpt
->attrs
.mode_str
, tmp
);
456 navpt
->want_to_init
= 2;
460 static CLASS_DEVICE_ATTR(mode
, S_IWUSR
| S_IRUGO
, get_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
,
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
);
529 input_free_device( navpt
->input
);
533 printk(KERN_ERR
"navpoint: Failed to initialize\n");
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
);
549 EXPORT_SYMBOL(navpoint_rx
);
550 EXPORT_SYMBOL(navpoint_reset
);
551 EXPORT_SYMBOL(navpoint_init
);
552 EXPORT_SYMBOL(navpoint_exit
);
554 MODULE_LICENSE("GPL");