Greetings, Dmitry could use some input on this.
On the hp6xx we got 3 external buttons (record / play / rewind), the status of those buttons can be read from PGDR where each bit = one button. Value 0 means pressed key and value 1 means non_pressed. I start out by reversing the bit values, just to get it more logical. When I bootup with this patch applied I get : 1 key is dead (maybe some weird keymap thingi.. probably logical) 2 keys give correct keymap output (B & C) but doesn't turn off when I release key so they keep adding. When I finally press enter and "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb..... cccccccccccccccccccccccccccccccccccc.... : File name too long", the keys are dead. I must be doing something wrong, so appreciate some guru input. Worth knowing is that when I just did a simple "printk(KERN_INFO "you press key X\n"); it works fine, its when I try to merge it with the keyboard that stuff get messed up. Below is the critical section, its set at beginning of keyboard interrupt: + /* grab status byte for external keys */ + new_status = (~(inb(PGDR))); + old_status = jornadakbd->old_status; + + diff = ((new_status) ^ (old_status)); + + if (diff > 0) { + /* Run through all extra keys */ + for (i = 0; i < EXTERN_KEYS; i++) { + scancode = (129 + i); + /* Has this key changed? */ + if (diff & (jornadakbd->status_regs[i])) { + if (new_status & jornadakbd->status_regs[i]) { + /* Key Pressed */ + input_event(input_dev, EV_MSC, MSC_SCAN, scancode); + input_report_key(input_dev, keymap[scancode], 1); + } else { + /* Key Released */ + input_event(input_dev, EV_MSC, MSC_SCAN, scancode); + input_report_key(input_dev, keymap[scancode], 0); + } + } + + } + jornadakbd->old_status = jornadakbd->new_status; + sync_me = 1; + } + Entire patch : -------------- diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index a23633a..6f2ca27 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <asm/hp6xx.h> #include <asm/delay.h> #include <asm/io.h> @@ -59,11 +60,12 @@ static const unsigned short jornada_scancodes[] = { KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_Y, /* 105 -> 112 */ /* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */ KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */ -/* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* **** */ KEY_A, KEY_B, KEY_C, 0, 0, 0, 0, 0, 0, 0, /* 129 -> 136 */ 0, 0, 0, 0, 0 }; -#define JORNADA_SCAN_SIZE 18 +#define JORNADA_SCAN_SIZE 16 /* 128 keys */ +#define EXTERN_KEYS 3 /* record / last / next */ struct jornadakbd { struct input_polled_dev *poll_dev; @@ -71,15 +73,50 @@ struct jornadakbd { unsigned char length; unsigned char old_scan[JORNADA_SCAN_SIZE]; unsigned char new_scan[JORNADA_SCAN_SIZE]; + unsigned char new_status; + unsigned char old_status; + unsigned char status_regs[EXTERN_KEYS]; }; static void jornada_parse_kbd(struct jornadakbd *jornadakbd) { struct input_dev *input_dev = jornadakbd->poll_dev->input; unsigned short *keymap = jornadakbd->keymap; + unsigned char old_status; + unsigned char new_status; unsigned int sync_me = 0; unsigned int i, j; - + unsigned char diff, scancode; + + /* grab status byte for external keys */ + new_status = (~(inb(PGDR))); + old_status = jornadakbd->old_status; + + /* Want to reverse values at same time */ + diff = ((new_status) ^ (old_status)); + + if (diff > 0) { + /* Run through all extra keys */ + for (i = 0; i < EXTERN_KEYS; i++) { + scancode = (129 + i); + /* Has this key changed? */ + if (diff & (jornadakbd->status_regs[i])) { + if (new_status & jornadakbd->status_regs[i]) { + /* Key Pressed */ + input_event(input_dev, EV_MSC, MSC_SCAN, scancode); + input_report_key(input_dev, keymap[scancode], 1); + } else { + /* Key Released */ + input_event(input_dev, EV_MSC, MSC_SCAN, scancode); + input_report_key(input_dev, keymap[scancode], 0); + } + } + + } + jornadakbd->old_status = jornadakbd->new_status; + sync_me = 1; + } + for (i = 0; i < JORNADA_SCAN_SIZE; i++) { unsigned char new = jornadakbd->new_scan[i]; unsigned char old = jornadakbd->old_scan[i]; @@ -91,7 +128,7 @@ static void jornada_parse_kbd(struct jornadakbd *jornadakbd) for (j = 0; j < 8; j++) { unsigned int bit = 1 << j; if (xor & bit) { - unsigned int scancode = (i << 3) + j; + scancode = (i << 3) + j; input_event(input_dev, EV_MSC, MSC_SCAN, scancode); input_report_key(input_dev, @@ -101,7 +138,7 @@ static void jornada_parse_kbd(struct jornadakbd *jornadakbd) } } } - + if (sync_me) input_sync(input_dev); } @@ -165,8 +202,8 @@ static void jornada_scan_keyb(unsigned char *s) ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR); /* Ignore extra keys and events */ - *s++ = ctrl_inb(PGDR); - *s++ = ctrl_inb(PHDR); +// *s++ = ctrl_inb(PGDR); +// *s++ = ctrl_inb(PHDR); } static void jornadakbd680_poll(struct input_polled_dev *dev) @@ -202,6 +239,11 @@ static int __devinit jornada680kbd_probe(struct platform_device *pdev) memcpy(jornadakbd->keymap, jornada_scancodes, sizeof(jornadakbd->keymap)); + jornadakbd->status_regs[0] = 0x08; + jornadakbd->status_regs[1] = 0x10; + jornadakbd->status_regs[2] = 0x20; + jornadakbd->old_status = 0; + poll_dev->private = jornadakbd; poll_dev->poll = jornadakbd680_poll; poll_dev->poll_interval = 50; /* msec */ @@ -216,11 +258,11 @@ static int __devinit jornada680kbd_probe(struct platform_device *pdev) input_dev->dev.parent = &pdev->dev; input_dev->id.bustype = BUS_HOST; - for (i = 0; i < 128; i++) + for (i = 0; i < 136; i++) if (jornadakbd->keymap[i]) __set_bit(jornadakbd->keymap[i], input_dev->keybit); __clear_bit(KEY_RESERVED, input_dev->keybit); - + input_set_capability(input_dev, EV_MSC, MSC_SCAN); error = input_register_polled_device(jornadakbd->poll_dev);
keyb_patch.patch
Description: Binary data