2 * Compaq Microkeyboard serial driver for the iPAQ H3800
4 * Copyright 2002 Compaq Computer Corporation.
6 * Use consistent with the GNU GPL is permitted,
7 * provided that this copyright notice is
8 * preserved in its entirety in all copies and derived works.
10 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12 * FITNESS FOR ANY PARTICULAR PURPOSE.
14 * Author: Andrew Christian
15 * <andyc@handhelds.org>
18 * ---------- CHANGES-----------------------
19 * 2002-05-19 Marcus Wolschon <Suran@gmx.net>
20 * - added proper support for the Compaq foldable keyboard
22 * 2002-Fall Andrew Christian <andrew.christian@hp.com>
23 * - cleaned up a bunch of things, added new keyboards
25 * 2002-10 Andrew Christian <andrew.christian@hp.com>
26 * - added Flexis FX100, PocketVIK
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
33 #include <linux/devfs_fs_kernel.h>
34 #include <linux/kbd_ll.h>
35 #include <linux/init.h>
36 #include <linux/kbd_kern.h>
37 #include <linux/interrupt.h>
38 #include <linux/proc_fs.h>
39 #include <linux/sysctl.h>
40 #include <linux/h3600_keyboard.h>
43 #include <asm/bitops.h>
45 #include <asm/hardware.h>
47 MODULE_AUTHOR("Andrew Christian <andyc@handhelds.org>");
49 #define MKBD_PRESS 0x7f
50 #define MKBD_RELEASE 0x80
52 #define MKBD_FUNCTION 128 /* Magic key = function down */
53 #define MKBD_IGNORE 129 /* A keyboard to be ignored */
55 #define MKBD_MAX_KEYCODES 128 /* 128 possible keycodes */
56 #define MKBD_BITMAP_SIZE MKBD_MAX_KEYCODES / BITS_PER_LONG
61 void (*init
)( struct microkbd_dev
*dev
);
62 void (*release
)( struct microkbd_dev
*dev
);
74 void (*process_char
)(struct mkbd_data
*, unsigned char);
77 struct uart_reg
*uart
;
82 #define MODIFIER_FUNCTION (1<<0)
83 #define MODIFIER_NUMLOCK (1<<1)
86 struct microkbd_dev
*dev
;
87 unsigned long key_down
[MKBD_BITMAP_SIZE
]; /* _keycodes_ sent */
90 int modifiers
; /* Can be set by NUMLOCK callback */
91 /* These variables are internal to each driver
92 On release_all_keys(), we set state = modifiers = 0 */
94 unsigned char last
; /* Last character received */
99 #define MKBD_BITMASK 2
101 struct mkbd_statistics
{
102 u32 isr
; /* RX interrupts */
103 u32 rx
; /* Bytes received */
104 u32 frame
; /* Frame errors */
105 u32 overrun
; /* Overrun errors */
106 u32 parity
; /* Parity errors */
115 static struct mkbd_statistics g_statistics
;
117 #define MKBD_DLEVEL 4
118 #define SDEBUG(x) if ( x < MKBD_DLEVEL ) printk(__FUNCTION__ "\n")
119 #define SFDEBUG(x, format, args...) if ( x < MKBD_DLEVEL ) printk(__FUNCTION__ ": " format, ## args )
121 #define SERIAL_BAUD_BASE 230400
123 /***********************************************************************************/
124 /* Interrupt handlers */
125 /***********************************************************************************/
127 static void h3600_microkbd_rx_chars( struct mkbd_data
*mkbd
)
129 unsigned int status
, ch
;
130 struct uart_reg
*uart
= mkbd
->dev
->uart
;
133 while ( (status
= *uart
->utsr1
) & UTSR1_RNE
) {
137 if ( status
& UTSR1_PRE
) { /* Parity error */
138 g_statistics
.parity
++;
139 } else if ( status
& UTSR1_FRE
) { /* Framing error */
140 g_statistics
.frame
++;
142 if ( status
& UTSR1_ROR
) /* Overrun error */
143 g_statistics
.overrun
++;
146 mkbd
->dev
->process_char( mkbd
, ch
);
151 static void h3600_microkbd_data_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
153 struct mkbd_data
*mkbd
= (struct mkbd_data
*) dev_id
;
154 struct uart_reg
*uart
= mkbd
->dev
->uart
;
155 unsigned int status
; /* UTSR0 */
157 SFDEBUG(4,"data interrupt %p\n", mkbd
);
159 status
= *uart
->utsr0
;
161 if ( status
& (UTSR0_RID
| UTSR0_RFS
) ) {
162 if ( status
& UTSR0_RID
)
163 *uart
->utsr0
= UTSR0_RID
; /* Clear the Receiver IDLE bit */
164 h3600_microkbd_rx_chars( mkbd
);
167 /* Clear break bits */
168 if (status
& (UTSR0_RBB
| UTSR0_REB
))
169 *uart
->utsr0
= status
& (UTSR0_RBB
| UTSR0_REB
);
173 /***********************************************************************************/
174 /* Initialization and shutdown code */
175 /***********************************************************************************/
177 static void h3600_microkbd_init_uart2( struct microkbd_dev
*dev
)
179 u32 brd
= (SERIAL_BAUD_BASE
/ dev
->baud
) - 1;
181 SFDEBUG(2,"initializing serial port 2\n");
187 Ser2UTCR3
= 0; /* Clean up CR3 */
189 Ser2HSCR0
= HSCR0_UART
;
190 Ser2UTCR4
= UTCR4_HPSIR
| UTCR4_Z1_6us
;
192 Ser2UTCR0
= dev
->cflag
;
194 Ser2UTCR1
= (brd
& 0xf00) >> 8;
195 Ser2UTCR2
= brd
& 0xff;
197 Ser2UTSR0
= 0xff; /* Clear SR0 */
198 Ser2UTCR3
= UTCR3_RXE
| UTCR3_RIE
; /* Enable receive interrupt */
200 set_h3600_egpio(IPAQ_EGPIO_IR_ON
);
203 static void h3600_microkbd_release_uart2( struct microkbd_dev
*dev
)
205 clr_h3600_egpio(IPAQ_EGPIO_IR_ON
);
209 static void h3600_microkbd_init_uart3( struct microkbd_dev
*dev
)
211 u32 brd
= (SERIAL_BAUD_BASE
/ dev
->baud
) - 1;
213 SFDEBUG(2,"initializing serial port 3\n");
215 /* Turn on power to the RS232 chip */
216 set_h3600_egpio(IPAQ_EGPIO_RS232_ON
);
218 /* Set up interrupts */
219 Ser3UTCR3
= 0; /* Clean up CR3 */
220 Ser3UTCR0
= dev
->cflag
;
222 Ser3UTCR1
= (brd
& 0xf00) >> 8;
223 Ser3UTCR2
= brd
& 0xff;
225 Ser3UTSR0
= 0xff; /* Clear SR0 */
226 Ser3UTCR3
= UTCR3_RXE
| UTCR3_RIE
; /* Enable receive interrupt */
229 static void h3600_microkbd_release_uart3( struct microkbd_dev
*dev
)
231 clr_h3600_egpio(IPAQ_EGPIO_RS232_ON
);
234 static struct uart_reg g_uart_2
= {
235 init
: h3600_microkbd_init_uart2
,
236 release
: h3600_microkbd_release_uart2
,
243 static struct uart_reg g_uart_3
= {
244 init
: h3600_microkbd_init_uart3
,
245 release
: h3600_microkbd_release_uart3
,
253 /***********************************************************************************/
254 /* Utility routine */
255 /***********************************************************************************/
257 static int do_keycode_down( struct mkbd_data
*mkbd
, unsigned char keycode
)
259 SFDEBUG(3,"keycode=0x%02x\n", keycode
);
264 if (test_bit(keycode
,mkbd
->key_down
)) {
265 g_statistics
.already_down
++;
266 SFDEBUG(2,"already down keycode=0x%02x\n", keycode
);
270 set_bit(keycode
,mkbd
->key_down
);
271 g_statistics
.valid
++;
272 handle_scancode(keycode
,1);
273 tasklet_schedule(&keyboard_tasklet
);
277 static int do_keycode_up( struct mkbd_data
*mkbd
, unsigned char keycode
)
279 SFDEBUG(3,"keycode=0x%02x\n", keycode
);
284 if (!test_bit(keycode
,mkbd
->key_down
)) {
285 g_statistics
.already_up
++;
286 SFDEBUG(2,"already up keycode=0x%02x\n", keycode
);
290 clear_bit(keycode
,mkbd
->key_down
);
291 g_statistics
.valid
++;
292 handle_scancode(keycode
,0);
293 tasklet_schedule(&keyboard_tasklet
);
297 static inline int do_keycode( struct mkbd_data
*mkbd
, unsigned char keycode
, int down
)
300 return do_keycode_down(mkbd
,keycode
);
302 return do_keycode_up(mkbd
,keycode
);
305 static int try_keycode_up( struct mkbd_data
*mkbd
, unsigned char keycode
)
307 if ( keycode
> 0 && keycode
< 128 && test_bit(keycode
,mkbd
->key_down
))
308 return do_keycode_up( mkbd
, keycode
);
312 static void release_all_keys( struct mkbd_data
*mkbd
)
315 unsigned long *bitfield
= mkbd
->key_down
;
317 SFDEBUG(2,"releasing all keys.\n");
320 for ( i
= 0 ; i
< MKBD_MAX_KEYCODES
; i
+=BITS_PER_LONG
, bitfield
++ ) {
321 if ( *bitfield
) { /* Should fix this to use the ffs() function */
322 for (j
=0 ; j
<BITS_PER_LONG
; j
++)
323 if (test_and_clear_bit(j
,bitfield
))
324 handle_scancode(i
+j
, 0);
327 tasklet_schedule(&keyboard_tasklet
);
328 g_statistics
.forced_release
++;
331 static inline int valid_keycode( int keycode
)
334 g_statistics
.invalid
++;
335 SFDEBUG(3," invalid keycode 0x%02x\n", keycode
);
342 /***********************************************************************************
348 * The shift, control, alt, and fn keys are the only keys that can be held
349 * down while pressing another key.
350 * All other keys generate keycode for down and "0x85 0x85" for up.
352 * It seems to want an ACK of some kind?
356 * Function 2 9d 9d (we use this as AltGr)
358 * Alt 4 9b 9b (we use this as Meta or Alt)
359 * OTHERS keycode 85 85
361 ***********************************************************************************/
363 static unsigned char iconcepts_normal
[128] = {
364 0, 29, 100, 42, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
365 2, 10, 34, 24, 4, 30, 23, 16, 6, 46, 37, 31, 8, 18, 50, 22,
366 0, 0, 0, 0, 0, 0, 0, 0, 45, 39, 28, 105, 44, 51, 1, 123,
367 13, 53, 111, 125, 26, 15, 108, 87, 0, 0, 0, 0, 0, 0, 0, 0,
368 47, 49, 33, 9, 20, 38, 32, 7, 19, 36, 48, 5, 25, 35, 11, 3,
369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370 122, 110, 52, 12, 124, 57, 40, 21, 106, 58, 43, 17, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 103, 41, 27, };
373 static unsigned char iconcepts_numlock
[128] = {
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 73, 0, 77, 0, 0, 76, 0, 0, 0, 80, 0, 75, 0, 82, 75,
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 51, 0, 0,
377 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 72, 0, 81, 0, 0, 0, 79, 0, 0, 55, 0, 98, 0,
379 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
380 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
381 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
383 static void h3600_iconcepts_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
385 unsigned char key
= data
;
386 unsigned int key_down
= !(data
& 0x80);
387 unsigned char keycode
;
390 SFDEBUG(2,"Read 0x%02x (%ld)\n", data
, jiffies
);
392 if ( data
>= 0x9b && data
<= 0x9e ) {
394 SFDEBUG(3,"set key to 0x%02x\n", key
);
396 else if ( data
== 0x85 ) {
398 SFDEBUG(3,"last key to 0x%02x\n", key
);
402 keycode
= iconcepts_normal
[key
];
404 if ( valid_keycode(keycode
) ) {
406 if ( (mkbd
->modifiers
& MODIFIER_NUMLOCK
) && iconcepts_numlock
[key
])
407 keycode
= iconcepts_numlock
[key
];
408 release_all
= do_keycode_down( mkbd
, keycode
);
413 release_all
= try_keycode_up( mkbd
, keycode
) +
414 try_keycode_up( mkbd
, iconcepts_numlock
[key
] );
419 release_all_keys(mkbd
);
422 /***********************************************************************************
423 * Snap N Type keyboard
425 * Key down sends single byte: KEY
426 * Key up sends two bytes: (KEY | 0x80), 0x7f
428 ***********************************************************************************/
430 static unsigned char snapntype_normal
[128] = {
431 0, 0, 0, 0, 0, 29, 0, 0, 14, 0, 28, 104, 109, 0, 0, 1,
432 42, 0, 122, 123, 124, 125, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0,
433 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
437 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24,
438 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 0, 0, 0, 0, 0, };
440 static void h3600_snapntype_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
442 unsigned char key
= data
& 0x7f;
443 unsigned int key_down
= !(data
& 0x80);
444 unsigned char keycode
;
447 SFDEBUG(2,"Read 0x%02x\n", data
);
452 keycode
= snapntype_normal
[key
];
453 if ( valid_keycode(keycode
) )
454 release_all
= do_keycode(mkbd
,keycode
,key_down
);
457 release_all_keys(mkbd
);
460 /***********************************************************************************
461 * Compaq Microkeyboard
465 * Key down sends two bytes: KEY ~KEY (complement of KEY)
466 * Key up sends two bytes: (KEY | 0x80) ~KEY
467 ***********************************************************************************/
469 static unsigned char compaq_normal
[128] = {
470 0, 0, 100, 0, 124, 122, 123, 0, 0, 0, 0, 0, 125, 0, 0, 0,
471 0, 0, 42, 0, 0, 16, 0, 0, 0, 29, 44, 31, 30, 17, 0, 0,
472 0, 46, 45, 32, 18, 0, 0, 0, 103, 0, 47, 33, 20, 19, 0, 106,
473 0, 49, 48, 35, 34, 21, 0, 0, 0, 0, 50, 36, 22, 0, 0, 0,
474 0, 0, 37, 23, 24, 0, 0, 0, 0, 0, 0, 38, 0, 25, 0, 0,
475 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 28, 0, 57, 0, 105, 0,
476 108, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
477 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
479 static void h3600_compaq_process_char(struct mkbd_data
*mkbd
, unsigned char data
)
481 unsigned char key
= data
& 0x7f;
482 unsigned char keycode
;
486 switch (mkbd
->state
) {
488 SFDEBUG(2,"Read 0x%02x\n", data
);
489 keycode
= compaq_normal
[key
];
490 if ( valid_keycode(keycode
) ) {
491 mkbd
->state
= MKBD_CHKSUM
;
497 key
= mkbd
->last
& 0x7f;
498 key_down
= !(mkbd
->last
& 0x80);
500 SFDEBUG(3,"Checking read 0x%02x with 0x%02x\n", mkbd
->last
, data
);
501 if ( (key
^ data
) != 0xff ) {
502 g_statistics
.bad_xor
++;
503 SFDEBUG(3," XOR doesn't match last=0x%02x data=0x%02x XOR=0x%02x\n",
504 key
, data
, (key
^ data
));
506 else if ( key
== 0x75 ) {
507 SFDEBUG(3," Valid keyboard restart\n");
510 release_all
= do_keycode(mkbd
, compaq_normal
[key
], key_down
);
511 mkbd
->state
= MKBD_READ
;
517 release_all_keys(mkbd
);
518 mkbd
->state
= MKBD_READ
;
522 /***********************************************************************************
523 * HP foldable keyboard
527 * Key down sends two bytes: KEY ~KEY (complement of KEY)
528 * Key up sends two bytes: (KEY | 0x80) ~KEY
529 ***********************************************************************************/
531 static unsigned char foldable_normal
[128] = {
532 0, 0, 128, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 15, 40, 0,
533 0, 56, 42, 0, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
534 0, 46, 45, 32, 18, 5, 4, 0, 103, 0, 47, 33, 20, 19, 6, 106,
535 0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
536 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
537 0, 0, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 57, 43, 105, 0,
538 108, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
539 92, 14, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
541 static unsigned char foldable_function
[128] = {
542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
543 0, 0, 0, 0, 0, 124, 59, 0, 0, 0, 0, 0, 123, 85, 60, 0,
544 0, 0, 0, 0, 89, 62, 61, 0, 104, 0, 0, 0, 125, 122, 63, 107,
545 0, 0, 0, 0, 0, 90, 64, 0, 0, 0, 0, 0, 0, 65, 66, 0,
546 0, 0, 0, 0, 0, 68, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0,
547 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 91, 0, 0, 0, 102, 0,
548 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
549 125, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
551 static unsigned char foldable_numlock
[128] = {
552 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
553 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
554 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
555 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 79, 75, 71, 72, 0,
556 0, 0, 80, 76, 77, 55, 73, 0, 0, 83, 98, 81, 78, 74, 0, 0,
557 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
558 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
561 static void h3600_foldable_process_char(struct mkbd_data
*mkbd
, unsigned char data
)
564 unsigned char keycode
;
568 switch (mkbd
->state
) {
570 SFDEBUG(2,"Read 0x%02x\n", data
);
572 keycode
= foldable_normal
[key
];
573 if ( valid_keycode(keycode
) ) {
574 mkbd
->state
= MKBD_CHKSUM
;
580 key
= mkbd
->last
& 0x7f;
581 key_down
= !(mkbd
->last
& 0x80);
583 SFDEBUG(3,"Checking read 0x%02x with 0x%02x\n", mkbd
->last
, data
);
584 if ( (key
^ data
) != 0xff ) {
585 g_statistics
.bad_xor
++;
586 SFDEBUG(3," XOR doesn't match last=0x%02x data=0x%02x XOR=0x%02x\n",
587 key
, data
, (key
^ data
));
589 else if ( key
== 0x75 ) {
590 SFDEBUG(3," Valid keyboard restart\n");
593 keycode
= foldable_normal
[key
];
594 if ( keycode
== MKBD_FUNCTION
) {
596 mkbd
->modifiers
|= MODIFIER_FUNCTION
;
598 mkbd
->modifiers
&= ~MODIFIER_FUNCTION
;
599 mkbd
->state
= MKBD_READ
;
604 if ( (mkbd
->modifiers
& MODIFIER_NUMLOCK
) && foldable_numlock
[key
])
605 keycode
= foldable_numlock
[key
];
606 else if ( (mkbd
->modifiers
& MODIFIER_FUNCTION
) && foldable_function
[key
])
607 keycode
= foldable_function
[key
];
608 release_all
= do_keycode_down( mkbd
, keycode
);
611 release_all
= try_keycode_up( mkbd
, keycode
) +
612 try_keycode_up( mkbd
, foldable_numlock
[key
] ) +
613 try_keycode_up( mkbd
, foldable_function
[key
] );
615 mkbd
->state
= MKBD_READ
;
621 release_all_keys(mkbd
);
622 mkbd
->state
= MKBD_READ
;
627 /***********************************************************************************
628 * Eagle-Touch Portable PDA keyboard
632 * Key down sends: KEY
635 * After a delay, keyboard sends 74 to indicate it's going low power
636 * When you press a key after the delay, it sends: 75 6d 61 78
637 * followed by the normal KEY, ~KEY
638 ***********************************************************************************/
640 static unsigned char eagletouch_normal
[128] = {
641 0, 0, 128, 122, 88, 87, 124, 0, 85, 0, 89, 123, 90, 15, 40, 0,
642 0, 125, 42, 0, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 111,
643 0, 46, 45, 32, 18, 5, 4, 0, 103, 57, 47, 33, 20, 19, 6, 106,
644 100, 49, 48, 35, 34, 21, 7, 0, 91, 0, 50, 36, 22, 8, 9, 0,
645 56, 51, 37, 23, 24, 11, 10, 1, 0, 52, 53, 38, 39, 25, 12, 0,
646 0, 0, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 105, 0,
647 108, 129, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 129, 0, 0,
648 0, 0, 0, 0, 129, 129, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, };
650 static unsigned char eagletouch_function
[128] = {
651 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
652 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 60, 0,
653 0, 0, 0, 0, 0, 62, 61, 0, 104, 0, 0, 0, 0, 0, 63, 107,
654 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 65, 66, 0,
655 0, 0, 0, 0, 0, 68, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0,
656 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 0,
657 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
658 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
660 static void h3600_eagletouch_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
662 unsigned int key_down
= (data
& 0x80) ? 1 : 0;
663 unsigned char key
= (key_down
? ~data
: data
);
664 unsigned char keycode
= eagletouch_normal
[key
];
667 SFDEBUG(2,"Read 0x%02x key=%x down=%d keycode=%d\n", data
, key
, key_down
, keycode
);
669 if ( keycode
== MKBD_IGNORE
) {
670 release_all_keys(mkbd
);
674 if ( keycode
== MKBD_FUNCTION
) {
676 mkbd
->modifiers
|= MODIFIER_FUNCTION
;
678 mkbd
->modifiers
&= ~MODIFIER_FUNCTION
;
682 if ( valid_keycode(keycode
) ) {
684 if ( (mkbd
->modifiers
& MODIFIER_FUNCTION
) && eagletouch_function
[key
])
685 keycode
= eagletouch_function
[key
];
686 release_all
= do_keycode_down( mkbd
, keycode
);
689 release_all
= try_keycode_up( mkbd
, keycode
) +
690 try_keycode_up( mkbd
, eagletouch_function
[key
] );
695 release_all_keys(mkbd
);
699 /***********************************************************************************
700 * Micro Innovations IR keyboard
704 * Key down sends one byte: KEY
705 * Key up sends one byte: KEY | 0x80
706 * Last key up repeats key up
707 ***********************************************************************************/
709 static unsigned char microinnovations_normal
[128] = {
710 0, 16, 0, 44, 0, 0, 0, 30, 0, 17, 0, 45, 0, 0, 0, 31,
711 0, 18, 0, 46, 0, 0, 0, 32, 0, 19, 0, 47, 0, 0, 0, 33,
712 0, 20, 0, 48, 0, 0, 0, 34, 0, 21, 0, 57, 0, 0, 0, 35,
713 0, 22, 36, 49, 57, 0, 0, 0, 0, 23, 37, 50, 128, 0, 0, 0,
714 122, 24, 38, 51, 105, 0, 0, 0, 123, 25, 39, 52, 108, 0, 0, 0,
715 125, 12, 40, 103, 106, 0, 0, 0, 90, 14, 28, 111, 0, 0, 0, 0,
716 0, 0, 0, 0, 0, 42, 56, 0, 0, 15, 0, 0, 0, 29, 69, 0,
717 0, 0, 0, 0, 0, 87, 100, 58, 0, 0, 0, 0, 0, 54, 0, 0, };
719 static unsigned char microinnovations_function
[128] = {
720 0, 59, 0, 117, 0, 0, 0, 92, 0, 60, 0, 126, 0, 0, 0, 93,
721 0, 61, 0, 127, 0, 0, 0, 111, 0, 62, 0, 113, 0, 0, 0, 94,
722 0, 63, 0, 124, 0, 0, 0, 95, 0, 64, 0, 0, 0, 0, 0, 99,
723 0, 65, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0,
724 88, 67, 0, 0, 102, 0, 0, 0, 85, 68, 0, 0, 109, 0, 0, 0,
725 89, 0, 0, 104, 107, 0, 0, 0, 119, 91, 116, 0, 0, 0, 0, 0,
726 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
727 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
729 static unsigned char microinnovations_numlock
[128] = {
730 0, 79, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0,
731 0, 81, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0,
732 0, 76, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0,
733 0, 71, 75, 0, 0, 0, 0, 0, 0, 72, 76, 79, 82, 0, 0, 0,
734 0, 73, 77, 80, 83, 0, 0, 0, 0, 82, 55, 81, 78, 0, 0, 0,
735 0, 98, 0, 74, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
736 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
739 static void h3600_microinnovations_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
741 unsigned char key
= data
& 0x7f;
742 unsigned int key_down
= !(data
& 0x80);
743 unsigned char keycode
= microinnovations_normal
[key
];
746 SFDEBUG(2,"Read 0x%02x\n", data
);
748 if ( keycode
== MKBD_FUNCTION
) {
750 mkbd
->modifiers
|= MODIFIER_FUNCTION
;
752 mkbd
->modifiers
&= ~MODIFIER_FUNCTION
;
756 if ( valid_keycode(keycode
) ) {
758 if ( (mkbd
->modifiers
& MODIFIER_NUMLOCK
) && microinnovations_numlock
[key
])
759 keycode
= microinnovations_numlock
[key
];
760 else if ( (mkbd
->modifiers
& MODIFIER_FUNCTION
) && microinnovations_function
[key
])
761 keycode
= microinnovations_function
[key
];
762 release_all
= do_keycode_down( mkbd
, keycode
);
765 release_all
= try_keycode_up( mkbd
, keycode
) +
766 try_keycode_up( mkbd
, microinnovations_numlock
[key
] ) +
767 try_keycode_up( mkbd
, microinnovations_function
[key
] );
772 release_all_keys(mkbd
);
775 /***********************************************************************************
776 * Grandtec PocketVIK (www.grandtec.com)
780 * This keyboard autorepeats
781 * It does not generate key up
783 * It may have a low power sleep mode that needs to be cycled????
785 * Set 1: ShiftL, ShiftR, CtrlL, AltL, AltR, CtrlR, Fn
788 * Set 1 keys do not generate keystrokes. They set fields in a bit mask.
790 * MASK = 0x80 | (sum of active modifiers)
792 * On keydown, you either get
794 * Case 1 (no bit mask field) KEY
795 * Case 2 (bitmask field) MASK, KEY
796 ***********************************************************************************/
798 static unsigned char pocketvik_normal
[128] = {
799 0, 108, 105, 51, 0, 0, 57, 46, 0, 50, 103, 53, 52, 0, 106, 47,
800 0, 44, 87, 28, 40, 0, 37, 35, 34, 45, 31, 0, 27, 39, 11, 36,
801 21, 33, 32, 30, 16, 26, 25, 23, 22, 20, 19, 18, 17, 15, 13, 58,
802 10, 9, 7, 6, 4, 3, 41, 14, 24, 12, 8, 5, 0, 122, 2, 38,
803 111, 1, 48, 43, 14, 125, 123, 124, 49, 0, 0, 0, 0, 0, 0, 0,
804 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
805 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
808 static unsigned char pocketvik_function
[128] = {
809 0, 109, 102, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 107, 0,
810 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
811 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
812 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0,
813 88, 0, 0, 0, 0, 92, 85, 90, 0, 0, 0, 0, 0, 0, 0, 0,
814 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
815 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
816 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
818 #define POCKETVIK_Fn 0x40
823 } pocketvik_modifiers
[] = {
824 { 0x01, KEY_LEFTSHIFT
},
825 { 0x02, KEY_RIGHTSHIFT
},
826 { 0x04, KEY_LEFTCTRL
},
827 { 0x08, KEY_RIGHTCTRL
},
828 { 0x10, KEY_LEFTALT
},
829 { 0x20, KEY_RIGHTALT
}
832 static void h3600_pocketvik_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
834 unsigned char keycode
;
835 unsigned char modifier_keys
= 0;
838 SFDEBUG(2,"Read 0x%02x\n", data
);
840 switch (mkbd
->state
) {
843 mkbd
->state
= MKBD_BITMASK
;
849 modifier_keys
= mkbd
->last
;
850 mkbd
->state
= MKBD_READ
;
854 keycode
= (modifier_keys
& POCKETVIK_Fn
) ? pocketvik_function
[data
] : pocketvik_normal
[data
];
856 if ( valid_keycode(keycode
) ) {
857 for ( i
= 0 ; i
< ARRAY_SIZE(pocketvik_modifiers
) ; i
++ )
858 if ( pocketvik_modifiers
[i
].mask
& modifier_keys
)
859 do_keycode_down( mkbd
, pocketvik_modifiers
[i
].key
);
861 do_keycode_down( mkbd
, keycode
);
862 do_keycode_up( mkbd
, keycode
);
864 for ( i
= 0 ; i
< ARRAY_SIZE(pocketvik_modifiers
) ; i
++ )
865 if ( pocketvik_modifiers
[i
].mask
& modifier_keys
)
866 do_keycode_up( mkbd
, pocketvik_modifiers
[i
].key
);
870 /***********************************************************************************
875 * This keyboard autorepeats
876 * It does not generate key up for most keys
878 * Set 1: ShiftL, ShiftR, Ctrl, Alt, Fn
883 * Set 1 KEY | 0x80 KEY
884 * Set 2 KEY | 0x80, KEY <none>
886 * If you press two keys from Set 1 you get the following:
888 * Press Key #1 KEY1_DOWN
889 * Press Key #2 KEY1_UP
890 * Release Key #1 KEY2_DOWN
891 * Release Key #2 KEY2_UP
892 ***********************************************************************************/
894 static unsigned char flexis_fx100_normal
[128] = {
895 30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 1, 48, 16, 17, 18, 19,
896 21, 20, 2, 3, 4, 5, 7, 6, 13, 10, 8, 12, 9, 11, 27, 24,
897 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,
898 15, 57, 41, 14, 0, 0, 0, 56, 54, 58, 128, 29, 42, 87, 0, 0,
899 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
900 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
901 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
902 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 105, 106, 108, 103, 0, };
904 static unsigned char flexis_fx100_function
[128] = {
905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
906 0, 0, 123, 88, 85, 89, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0,
907 0, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0,
908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 107, 109, 104, 0, };
914 static void h3600_flexis_process_char( struct mkbd_data
*mkbd
, unsigned char data
)
916 unsigned char key
= data
& 0x7f;
917 unsigned int key_down
= data
& 0x80;
918 unsigned char keycode
= flexis_fx100_normal
[key
];
921 SFDEBUG(2,"Read 0x%02x\n", data
);
923 if ( keycode
== MKBD_FUNCTION
) {
925 mkbd
->modifiers
|= MODIFIER_FUNCTION
;
927 mkbd
->modifiers
&= ~MODIFIER_FUNCTION
;
931 if ( valid_keycode(keycode
) ) {
933 if ( (mkbd
->modifiers
& MODIFIER_FUNCTION
) && flexis_fx100_function
[key
])
934 keycode
= flexis_fx100_function
[key
];
935 release_all
= do_keycode_down( mkbd
, keycode
);
938 release_all
= try_keycode_up( mkbd
, keycode
) +
939 try_keycode_up( mkbd
, flexis_fx100_function
[key
] );
944 release_all_keys(mkbd
);
947 /***********************************************************************************/
949 static struct microkbd_dev keyboards
[] = {
950 { "HP/Compaq Micro Keyboard", "compaq",
951 h3600_compaq_process_char
, 4800, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
952 { "RipTide SnapNType", "snapntype",
953 h3600_snapntype_process_char
, 2400, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
954 { "iConcepts Portable Keyboard", "iconcepts",
955 h3600_iconcepts_process_char
, 9600, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
956 { "HP/Compaq Foldable Keyboard", "foldable",
957 h3600_foldable_process_char
, 4800, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
958 { "Micro Innovations IR Keyboard", "microinnovations",
959 h3600_microinnovations_process_char
, 9600, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_2
},
960 { "Eagle-Touch Portable PDA Keyboard", "eagletouch",
961 h3600_eagletouch_process_char
, 9600, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
962 { "GrandTec PocketVIK", "pocketvik",
963 h3600_pocketvik_process_char
, 57600, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
964 { "Flexis FX100", "flexis",
965 h3600_flexis_process_char
, 9600, UTCR0_8BitData
| UTCR0_1StpBit
, &g_uart_3
},
968 #define NUM_KEYBOARDS ARRAY_SIZE(keyboards)
971 /***********************************************************************************/
972 /* Basic driver code */
973 /***********************************************************************************/
975 static ssize_t
h3600_microkbd_read(struct file
*filp
, char *buf
, size_t count
, loff_t
*f_pos
)
979 current
->state
= TASK_INTERRUPTIBLE
;
980 while (!signal_pending(current
))
982 current
->state
= TASK_RUNNING
;
986 static struct mkbd_data g_keyboard
;
988 static void h3600_microkbd_ledfunc(unsigned int led
)
990 SFDEBUG(2," led=0x%02x [%s %s %s]\n", led
,
991 (led
& 0x04 ? "CAPS" : "----"),
992 (led
& 0x02 ? "NUML" : "----"),
993 (led
& 0x01 ? "SCRL" : "----"));
995 g_keyboard
.modifiers
|= MODIFIER_NUMLOCK
;
997 g_keyboard
.modifiers
&= ~MODIFIER_NUMLOCK
;
1000 static int h3600_microkbd_open( struct inode
* inode
, struct file
* filp
)
1002 unsigned int minor
= MINOR( inode
->i_rdev
);
1003 struct microkbd_dev
*dev
= keyboards
+ minor
;
1006 SFDEBUG(1," minor=%d\n",minor
);
1008 if ( minor
>= NUM_KEYBOARDS
) {
1009 printk(KERN_ALERT __FUNCTION__
" bad minor=%d\n", minor
);
1013 if ( g_keyboard
.usage_count
!= 0 ) {
1014 printk(KERN_ALERT __FUNCTION__
" keyboard device already open\n");
1018 retval
= request_irq( dev
->uart
->irq
, h3600_microkbd_data_interrupt
,
1019 SA_INTERRUPT
| SA_SAMPLE_RANDOM
,
1020 "h3600_microkbd", (void *) &g_keyboard
);
1021 if ( retval
) return retval
;
1023 memset(&g_keyboard
, 0, sizeof(struct mkbd_data
));
1024 g_keyboard
.dev
= dev
;
1026 dev
->uart
->init( dev
);
1028 filp
->private_data
= &g_keyboard
;
1029 kbd_ledfunc
= h3600_microkbd_ledfunc
;
1030 g_keyboard
.usage_count
++;
1035 static int h3600_microkbd_release(struct inode
* inode
, struct file
* filp
)
1037 struct mkbd_data
*mkbd
= (struct mkbd_data
*) filp
->private_data
;
1041 if ( --mkbd
->usage_count
== 0 ) {
1042 SFDEBUG(1,"Closing down keyboard\n");
1043 release_all_keys(mkbd
);
1044 free_irq(mkbd
->dev
->uart
->irq
, (void *)mkbd
);
1045 mkbd
->dev
->uart
->release( mkbd
->dev
);
1053 struct file_operations microkbd_fops
= {
1054 read
: h3600_microkbd_read
,
1055 open
: h3600_microkbd_open
,
1056 release
: h3600_microkbd_release
,
1059 /***********************************************************************************/
1060 /* Proc filesystem interface */
1061 /***********************************************************************************/
1063 static struct proc_dir_entry
*proc_dir
;
1065 #define PRINT_DATA(x,s) \
1066 p += sprintf (p, "%-20s : %d\n", s, g_statistics.x)
1068 int h3600_microkbd_proc_stats_read(char *page
, char **start
, off_t off
,
1069 int count
, int *eof
, void *data
)
1074 PRINT_DATA(isr
, "Keyboard interrupts");
1075 PRINT_DATA(rx
, "Bytes received");
1076 PRINT_DATA(frame
, "Frame errors");
1077 PRINT_DATA(overrun
, "Overrun errors");
1078 PRINT_DATA(parity
, "Parity errors");
1079 PRINT_DATA(bad_xor
, "Bad XOR");
1080 PRINT_DATA(invalid
, "Invalid keycode");
1081 PRINT_DATA(already_down
, "Key already down");
1082 PRINT_DATA(already_up
, "Key already up");
1083 PRINT_DATA(valid
, "Valid keys");
1084 PRINT_DATA(forced_release
, "Forced release");
1085 p
+= sprintf(p
,"%-20s : %d\n", "Usage count", g_keyboard
.usage_count
);
1086 p
+= sprintf(p
,"\nRegistered keyboards\n");
1087 for ( i
= 0 ; i
< NUM_KEYBOARDS
; i
++ )
1088 p
+= sprintf(p
, " %20s (%d) : %s\n", keyboards
[i
].name
, i
, keyboards
[i
].full_name
);
1090 len
= (p
- page
) - off
;
1094 *eof
= (len
<= count
) ? 1 : 0;
1095 *start
= page
+ off
;
1100 /***********************************************************************************
1102 * TODO: We seem to survive suspend/resume - no doubt due to settings by the serial driver
1103 * We might want to not rely on them.
1105 * TODO: Limit ourselves to a single reader at a time.
1107 * TODO: Have a PROC setting so you don't need a reader to keep alive....
1108 * This is the "I want to be myself" mode of operation.
1109 ***********************************************************************************/
1111 static struct pm_dev
*microkbd_pm
;
1114 static int h3600_microkbd_pm_callback(struct pm_dev
*dev
, pm_request_t rqst
, void *data
)
1116 struct mkbd_data
*mkbd
= (struct mkbd_data
*) dev
->data
;
1117 SFDEBUG(1,"changing to state %d\n", rqst
);
1118 if ( mkbd
->usage_count
> 0 ) {
1121 release_all_keys(mkbd
);
1124 mkbd
->dev
->uart
->init( mkbd
->dev
);
1132 /***********************************************************************************/
1133 /* Initialization code */
1134 /***********************************************************************************/
1136 static int g_microkbd_major
; /* Dynamic major number */
1137 static devfs_handle_t devfs_dir
;
1140 #define H3600_MICROKBD_MODULE_NAME "microkbd"
1141 #define H3600_MICROKBD_PROC_STATS "microkbd"
1143 int __init
h3600_microkbd_init_module( void )
1148 g_microkbd_major
= devfs_register_chrdev(0, H3600_MICROKBD_MODULE_NAME
, µkbd_fops
);
1149 if (g_microkbd_major
< 0) {
1150 printk(KERN_ALERT __FUNCTION__
": can't get major number\n");
1151 return g_microkbd_major
;
1154 devfs_dir
= devfs_mk_dir(NULL
, "microkbd", NULL
);
1155 if ( !devfs_dir
) return -EBUSY
;
1157 for ( i
= 0 ; i
< NUM_KEYBOARDS
; i
++ )
1158 keyboards
[i
].devfs
= devfs_register( devfs_dir
, keyboards
[i
].name
, DEVFS_FL_DEFAULT
,
1159 g_microkbd_major
, i
, S_IFCHR
| S_IRUSR
| S_IWUSR
, µkbd_fops
, NULL
);
1161 /* Register in /proc filesystem */
1162 create_proc_read_entry(H3600_MICROKBD_PROC_STATS
, 0, proc_dir
,
1163 h3600_microkbd_proc_stats_read
, NULL
);
1166 microkbd_pm
= pm_register(PM_SYS_DEV
, PM_SYS_COM
, h3600_microkbd_pm_callback
);
1168 microkbd_pm
->data
= &g_keyboard
;
1173 void __exit
h3600_microkbd_cleanup_module( void )
1178 pm_unregister(microkbd_pm
);
1179 remove_proc_entry(H3600_MICROKBD_PROC_STATS
, proc_dir
);
1181 for ( i
= 0 ; i
< NUM_KEYBOARDS
; i
++ )
1182 devfs_unregister( keyboards
[i
].devfs
);
1184 devfs_unregister( devfs_dir
);
1185 devfs_unregister_chrdev( g_microkbd_major
, H3600_MICROKBD_MODULE_NAME
);
1188 MODULE_DESCRIPTION("Compaq iPAQ microkeyboard driver");
1189 MODULE_LICENSE("Dual BSD/GPL");
1191 module_init(h3600_microkbd_init_module
);
1192 module_exit(h3600_microkbd_cleanup_module
);