Re: [PATCH] New USB Keyboard interface for KDB
Jay Lan <[email protected]>
| Newsgroups | gmane.linux.kernel.debugging |
|---|---|
| Message-ID | <[email protected]> |
Aaron Young wrote: > This patch implements a new KDB interface for USB keyboards > which fixes the following problems: > > 1. Currently KDB is only "OHCI" type USB aware. If a keyboard is attached > via a USB2.0 hub, the Linux kernel EHCI driver is used instead of OHCI, but > kdb will still attempt to use the OHCI driver poll interface to > read a character from the keyboard - this results in a crash from > within kdb and, hence, kdb is unuseable. > > This patch allows KDB to work with any Host Contoller driver > and call the correct HC driver poll routine (as long as the > HC driver provides a .kdb_poll_char routine via it's > associated hc_driver struct). > If a HC driver is managing a keyboard, but doesn't provide a > valid .kdb_poll_char routine, the keyboard will be ignored by KDB. > > 2. Hotplug - currently, if a USB keyboard is unplugged and plugged back > in, KDB loses track and no longer recognizes the keyboard for use from KDB. > This is because the "kdb_usb_infos" struct was getting zeroed and the > .poll_func field set to NULL on hotunplugs (and not set to something > valid on hotplugs) > > Hotplugged keyboards are now recognized by KDB. > > 3. Currently KDB can only make use of 1 USB type keyboard. This is because > of the single "kdb_usb_infos" structure interface - which can only describe > a single keyboard/urb. > > New code can handle up to 8 attached keyboards - input is multiplexed > from all of them while in kdb. The number of supported USB keyboards can > easily be changed via the KDB_USB_NUM_KEYBOARDS def in appropriate > arch/XXX/kdb//kdba_io.c file. > > > General notes about the new code: > > The new USB interface is composed of two new routines which > HID drivers need to call when configuring USB keyboards: > > kdb_usb_keyboard_attach() - to attach a USB keyboard to KDB > kdb_usb_keyboard_detach() - to detach a USB keyboard from KDB > > These should be called from the hotplug interfaces so that hotplugs/ > unplugs keep KDB up-to-date on what keyboards are on the system. > > Each USB Host Controller driver which could manage keyboards needs > to add a .kdb_poll_char entry to it's associated hc_driver struct and > and, of course, provide the routine to poll a keyboard's URB for characters. > The OHCI implementation is complete and there. UHCI is completely > missing at this point and EHCI is partially there - i.e. EHCI provides > the .kdb_poll_char entry, but the associated routine, ehci_kdb_poll_char() > is not yet implemented (and just returns -1 for now). I plan to work > on the EHCI poll code next. I hope to have a subsequent patch for this > very soon. > > Issues: > > While testing I noticed some issues when using hubs to attach > USB keyboards. When multiple keyboards are attached via a USB1.1 > hub, only one of the keyboards is operational from kdb - not sure > why. It's probably a shortcoming of the OHCI poll character code. > Also, it appears hotplug of USB1.1 hubs doesn't work right in Linux > and the HID hotplug interfaces are not called for the attached keyboards. > Hotplug does work correctly with USB2.0 hubs however. > > When keyboard(s) are attached directly to USB ports (with no hubs), I > could find no issues - hotplug/unplug, mulitplexing all appear to work > properly. > > Testing: > > These changes have only been tested on a ia64 machine containing > OHCI/EHCI style USB controllers. Additional testing on other archs > and USB configs by others would be appreciated. > > > Patch is against 2.6.23-rc8 (should be applied after kdb-4.4-2.6.23-*.1 patch set) Well, actually i generated this patch for you against linux-2.6.23 and the 2.6.23 version of kdb patchset. I did basic testing on ia64, x86_64, and i386, but i did not have equipments to test new feature of USB keyboards/mice though. Thanks, - jay > > Signed-off-by: Aaron Young ([email protected]) > > --- > > diff -pNaru linux.orig/arch/i386/kdb/kdba_io.c linux/arch/i386/kdb/kdba_io.c > --- linux.orig/arch/i386/kdb/kdba_io.c 2007-11-09 11:37:45.000000000 -0800 > +++ linux/arch/i386/kdb/kdba_io.c 2007-11-08 14:26:07.710994431 -0800 > @@ -29,9 +29,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + rc = 0; /* success */ > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + break; > + } > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > - > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > - case 0x2: > - case 0x20: /* Shift */ > - return shift_map[keycode]; > - case 0x1: > - case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > - case 0x4: > - case 0x40: /* Alt */ > - break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > - switch(keycode) > - { > - case 0x1C: /* Enter */ > - return 13; > - > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > - } > - } > - } > - return -1; > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > + > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > + case 0x2: > + case 0x20: /* Shift */ > + return shift_map[keycode]; > + case 0x1: > + case 0x10: /* Ctrl */ > + return ctrl_map[keycode]; > + case 0x4: > + case 0x40: /* Alt */ > + break; > + } > + } else if (keycode) { /* If only one key pressed */ > + switch(keycode) > + { > + case 0x1C: /* Enter */ > + return 13; > + > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > + } > + } > + } > + > + /* no chars were returned from any of the USB keyboards */ > + > + return -1; > } > #endif /* CONFIG_KDB_USB */ > > diff -pNaru linux.orig/arch/ia64/kdb/kdba_io.c linux/arch/ia64/kdb/kdba_io.c > --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-09 11:37:47.000000000 -0800 > +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-08 14:31:06.500022083 -0800 > @@ -39,9 +39,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -62,39 +63,122 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if (!kdb_usb_infos.poll_func || !kdb_usb_infos.urb || !kdb_usb_infos.buffer) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + rc = 0; /* success */ > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > + > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > case 0x2: > case 0x20: /* Shift */ > return shift_map[keycode]; > @@ -104,34 +188,35 @@ static int get_usb_char(void) > case 0x4: > case 0x40: /* Alt */ > break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > + } > + } else if (keycode) { /* If only one key pressed */ > switch(keycode) > { > - case 0x1C: /* Enter */ > - return 13; > + case 0x1C: /* Enter */ > + return 13; > > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > } > } > } > + > + /* no chars were returned from any of the USB keyboards */ > + > return -1; > } > #endif /* CONFIG_KDB_USB */ > diff -pNaru linux.orig/arch/x86_64/kdb/kdba_io.c linux/arch/x86_64/kdb/kdba_io.c > --- linux.orig/arch/x86_64/kdb/kdba_io.c 2007-11-09 11:37:46.000000000 -0800 > +++ linux/arch/x86_64/kdb/kdba_io.c 2007-11-08 14:28:31.507644333 -0800 > @@ -29,9 +29,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + rc = 0; /* success */ > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + break; > + } > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > - > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > - case 0x2: > - case 0x20: /* Shift */ > - return shift_map[keycode]; > - case 0x1: > - case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > - case 0x4: > - case 0x40: /* Alt */ > - break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > - switch(keycode) > - { > - case 0x1C: /* Enter */ > - return 13; > - > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > - } > - } > - } > - return -1; > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > + > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > + case 0x2: > + case 0x20: /* Shift */ > + return shift_map[keycode]; > + case 0x1: > + case 0x10: /* Ctrl */ > + return ctrl_map[keycode]; > + case 0x4: > + case 0x40: /* Alt */ > + break; > + } > + } else if (keycode) { /* If only one key pressed */ > + switch(keycode) > + { > + case 0x1C: /* Enter */ > + return 13; > + > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > + } > + } > + } > + > + /* no chars were returned from any of the USB keyboards */ > + > + return -1; > } > #endif /* CONFIG_KDB_USB */ > > diff -pNaru linux.orig/drivers/hid/usbhid/hid-core.c linux/drivers/hid/usbhid/hid-core.c > --- linux.orig/drivers/hid/usbhid/hid-core.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/hid/usbhid/hid-core.c 2007-11-08 14:04:41.124958377 -0800 > @@ -900,9 +900,12 @@ static void hid_disconnect(struct usb_in > usbhid = hid->driver_data; > > #ifdef CONFIG_KDB_USB > - /* Unlink the KDB USB struct */ > - if (usbhid->urbin == kdb_usb_infos.urb) > - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); > + /* > + * If the URB was for a Keyboard, detach it from kdb. > + * If the URB was for another type of device, just > + * allow kdb_usb_keyboard_detach() to silently fail. > + */ > + kdb_usb_keyboard_detach(usbhid->urbin); > #endif > > spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ > @@ -991,15 +994,20 @@ static int hid_probe(struct usb_interfac > printk(": USB HID v%x.%02x %s [%s] on %s\n", > hid->version >> 8, hid->version & 0xff, c, hid->name, path); > > -#ifdef CONFIG_KDB_USB > - /* Initialization of the KDB structure */ > +#ifdef CONFIG_KDB_USB > + /* Attach USB keyboards to kdb */ > if (!strcmp(c, "Keyboard")) { > + int ret; > struct usbhid_device *usbhid = hid->driver_data; > - kdb_usb_infos.urb = usbhid->urbin; > - kdb_usb_infos.buffer = usbhid->inbuf; > - kdb_usb_infos.reset_timer = NULL; > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + > + if (ret == -1) > + printk(": FAILED to register keyboard (%s) " > + "with KDB\n", path); > } > -#endif > +#endif /* CONFIG_KDB_USB */ > > return 0; > } > diff -pNaru linux.orig/drivers/hid/usbhid/usbkbd.c linux/drivers/hid/usbhid/usbkbd.c > --- linux.orig/drivers/hid/usbhid/usbkbd.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/hid/usbhid/usbkbd.c 2007-11-08 14:04:41.148957819 -0800 > @@ -292,12 +292,15 @@ static int usb_kbd_probe(struct usb_inte > kbd->new, (maxp > 8 ? 8 : maxp), > usb_kbd_irq, kbd, endpoint->bInterval); > > -#ifdef CONFIG_KDB_USB > - /* Init the KDB structure */ > - kdb_usb_infos.urb = kbd->irq; > - kdb_usb_infos.buffer = kbd->new; > - kdb_usb_infos.reset_timer = NULL; > -#endif > +#ifdef CONFIG_KDB_USB > + /* Attach keyboard to kdb */ > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + > + kdb_usb_keyboard_attach(kbd->irq, kbd->new, > + usb_hcd_get_kdb_poll_func(dev)); > + > +#endif /* CONFIG_KDB_USB */ > + > kbd->irq->transfer_dma = kbd->new_dma; > kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > > @@ -334,12 +337,11 @@ static void usb_kbd_disconnect(struct us > struct usb_kbd *kbd = usb_get_intfdata (intf); > > usb_set_intfdata(intf, NULL); > + if (kbd) { > #ifdef CONFIG_KDB_USB > - /* Unlink the KDB USB struct */ > - if (kbd && kbd->irq == kdb_usb_infos.urb) > - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); > + /* Detach the keyboard from kdb */ > + kdb_usb_keyboard_detach(kbd->irq); > #endif /* CONFIG_KDB_USB */ > - if (kbd) { > usb_kill_urb(kbd->irq); > input_unregister_device(kbd->dev); > usb_kbd_free_mem(interface_to_usbdev(intf), kbd); > diff -pNaru linux.orig/drivers/usb/core/hcd.c linux/drivers/usb/core/hcd.c > --- linux.orig/drivers/usb/core/hcd.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/core/hcd.c 2007-11-08 14:04:42.228932671 -0800 > @@ -1718,6 +1718,20 @@ usb_hcd_platform_shutdown(struct platfor > } > EXPORT_SYMBOL (usb_hcd_platform_shutdown); > > +#ifdef CONFIG_KDB_USB > +void * > +usb_hcd_get_kdb_poll_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_poll_char); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > +#endif /* CONFIG_KDB_USB */ > + > /*-------------------------------------------------------------------------*/ > > #if defined(CONFIG_USB_MON) > diff -pNaru linux.orig/drivers/usb/core/hcd.h linux/drivers/usb/core/hcd.h > --- linux.orig/drivers/usb/core/hcd.h 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/core/hcd.h 2007-11-08 14:04:42.248932205 -0800 > @@ -202,6 +202,10 @@ struct hc_driver { > int (*start_port_reset)(struct usb_hcd *, unsigned port_num); > void (*hub_irq_enable)(struct usb_hcd *); > /* Needed only if port-change IRQs are level-triggered */ > +#ifdef CONFIG_KDB_USB > + /* KDB poll function for this HC */ > + int (*kdb_poll_char)(struct urb *urb); > +#endif /* CONFIG_KDB_USB */ > }; > > extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); > diff -pNaru linux.orig/drivers/usb/host/ehci-hcd.c linux/drivers/usb/host/ehci-hcd.c > --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-08 14:04:42.272931646 -0800 > @@ -916,6 +916,17 @@ static int ehci_get_frame (struct usb_hc > ehci->periodic_size; > } > > +#ifdef CONFIG_KDB_USB > + > +int > +ehci_kdb_poll_char(struct urb *urb) > +{ > + /* routine not yet implemented */ > + return -1; > +} > + > +#endif /* CONFIG_KDB_USB */ > + > /*-------------------------------------------------------------------------*/ > > #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC > diff -pNaru linux.orig/drivers/usb/host/ehci-pci.c linux/drivers/usb/host/ehci-pci.c > --- linux.orig/drivers/usb/host/ehci-pci.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/host/ehci-pci.c 2007-11-08 14:04:42.292931181 -0800 > @@ -22,6 +22,10 @@ > #error "This file is PCI bus glue. CONFIG_PCI must be defined." > #endif > > +#ifdef CONFIG_KDB_USB > +#include <linux/kdb.h> > +#endif > + > /*-------------------------------------------------------------------------*/ > > /* called after powerup, by probe or system-pm "wakeup" */ > @@ -367,6 +371,10 @@ static const struct hc_driver ehci_pci_h > .hub_control = ehci_hub_control, > .bus_suspend = ehci_bus_suspend, > .bus_resume = ehci_bus_resume, > + > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = ehci_kdb_poll_char, > +#endif > }; > > /*-------------------------------------------------------------------------*/ > diff -pNaru linux.orig/drivers/usb/host/ohci-hcd.c linux/drivers/usb/host/ohci-hcd.c > --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-08 14:04:41.244955583 -0800 > @@ -851,20 +851,14 @@ static void ohci_quirk_nec_worker(struct > > #ifdef CONFIG_KDB_USB > > -static void > -ohci_kdb_poll (void * __ohci, struct urb *urb) > +int > +ohci_kdb_poll_char(struct urb *urb) > { > struct ohci_hcd *ohci; > struct ohci_regs * regs; > > - /* > - * NOTE - we use the ohci_hcd from the urb rather than the > - * __ohci parameter (which is NULL anyway). This ensures > - * that we will process the proper controller for the urb. > - */ > - > - if (!urb) /* can happen if no keyboard attached */ > - return; > + if (!urb) /* should not happen */ > + return -1; > > ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); > regs = ohci->regs; > @@ -873,23 +867,27 @@ ohci_kdb_poll (void * __ohci, struct urb > if (urb->status != -EINPROGRESS) { > > if (usb_submit_urb (urb, GFP_ATOMIC)) > - return; > + return -1; > > /* make sure the HC registers are set correctly */ > - writel (OHCI_INTR_WDH, ®s->intrenable); > - writel (OHCI_INTR_WDH, ®s->intrstatus); > - writel (OHCI_INTR_MIE, ®s->intrenable); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); > + ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); > > // flush those pci writes > - (void) readl (&ohci->regs->control); > + (void) ohci_readl (ohci, &ohci->regs->control); > } > > if (ohci->hcca->done_head) { > dl_done_list_kdb (ohci, urb); > - writel (OHCI_INTR_WDH, ®s->intrstatus); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); > // flush the pci write > - (void) readl (&ohci->regs->control); > + (void) ohci_readl (ohci, &ohci->regs->control); > + > + return 0; > } > + > + return -1; > } > > #endif /* CONFIG_KDB_USB */ > diff -pNaru linux.orig/drivers/usb/host/ohci-pci.c linux/drivers/usb/host/ohci-pci.c > --- linux.orig/drivers/usb/host/ohci-pci.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/usb/host/ohci-pci.c 2007-11-08 14:04:41.268955024 -0800 > @@ -18,7 +18,7 @@ > #error "This file is PCI bus glue. CONFIG_PCI must be defined." > #endif > > -#ifdef CONFIG_KDB_USB > +#ifdef CONFIG_KDB_USB > #include <linux/kdb.h> > #endif > > @@ -219,12 +219,7 @@ static int __devinit ohci_pci_start (str > ohci_err (ohci, "can't start\n"); > ohci_stop (hcd); > } > -#ifdef CONFIG_KDB_USB > - if (ret >= 0) { > - kdb_usb_infos.poll_func = ohci_kdb_poll; > - kdb_usb_infos.uhci = NULL; /* not used */ > - } > -#endif > + > return ret; > } > > @@ -363,6 +358,9 @@ static const struct hc_driver ohci_pci_h > .bus_resume = ohci_bus_resume, > #endif > .start_port_reset = ohci_start_port_reset, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = ohci_kdb_poll_char, > +#endif > }; > > /*-------------------------------------------------------------------------*/ > diff -pNaru linux.orig/include/linux/kdb.h linux/include/linux/kdb.h > --- linux.orig/include/linux/kdb.h 2007-11-09 11:37:44.000000000 -0800 > +++ linux/include/linux/kdb.h 2007-11-08 14:04:41.420951485 -0800 > @@ -140,16 +140,12 @@ extern void smp_kdb_stop(void); > #endif /* CONFIG_SMP */ > > #ifdef CONFIG_KDB_USB > + > #include <linux/usb.h> > > -struct kdb_usb_exchange { > - void *uhci; /* pointer to the UHCI structure */ > - struct urb *urb; /* pointer to the URB */ > - unsigned char *buffer; /* pointer to buffer */ > - void (*poll_func)(void *, struct urb *); /* pointer to the polling function */ > - void (*reset_timer)(void); /* pointer to the reset timer function */ > -}; > -extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */ > +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > +extern int kdb_usb_keyboard_detach(struct urb *urb); > + > #endif /* CONFIG_KDB_USB */ > > static inline > diff -pNaru linux.orig/include/linux/kdbprivate.h linux/include/linux/kdbprivate.h > --- linux.orig/include/linux/kdbprivate.h 2007-11-09 11:37:44.000000000 -0800 > +++ linux/include/linux/kdbprivate.h 2007-11-08 14:04:41.460950554 -0800 > @@ -482,4 +482,15 @@ extern char kdb_prompt_str[]; > > #define KDB_WORD_SIZE ((int)sizeof(kdb_machreg_t)) > > +#ifdef CONFIG_KDB_USB > +#include <linux/usb.h> > + > +struct kdb_usb_kbd_info { > + struct urb *urb; /* pointer to the URB */ > + unsigned char *buffer; /* pointer to the kbd char buffer */ > + int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ > + int caps_lock; /* state of the caps lock for this keyboard */ > +}; > +#endif /* CONFIG_KDB_USB */ > + > #endif /* !_KDBPRIVATE_H */ > > --- > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.