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, &regs->intrenable);
> -             writel (OHCI_INTR_WDH, &regs->intrstatus);
> -             writel (OHCI_INTR_MIE, &regs->intrenable);
> +             ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
> +             ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrstatus);
> +             ohci_writel (ohci, OHCI_INTR_MIE, &regs->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, &regs->intrstatus);
> +             ohci_writel (ohci, OHCI_INTR_WDH, &regs->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.

Reply via email to