Looking better! More comments: 1. I don't understand the need for the call to kdb_uhci_keyboard_clear(). It's only called if kdb_usb_keyboard_attach() fails and in that case we didn't add the urb to kdb_usb_kbds[]. So, I don't see the need to clear it out of kdb_usb_kbds[]... (I'm probably missing something here). 2. I probably would have made kdb_uhci_submit_urb() return the newly created kdb_urb (extra arg) on success and not call kdb_usb_keyboard_attach() directly from within. Then you can just make a single call to kdb_usb_keyboard_attach() for all three cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not a *BIG* deal... 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise it will result in compile errors on ia64. i.e. kdb_usb_keyboard_attach() will have a number of args mismatch and all the routines you added to kdba_io_32.c and kdba_io_64.c will not be there. 4. You have the comment "/* found a free array index */" in several of the new kdba_io*.c routines when it really means you found a "match". 5. I just submitted another patch on Wed (Nov. 28th). That will conflict with this one again. Sorry - should be my last patch. Does hotplug/hotunplug of the keyboards work? Does it correctly remove the KDB URBs on hotunplug? Thanks, -Aaron > > On Mon, 26 Nov 2007 13:39:41 -0800 (PST) > Aaron Young <ayoung at cthulhu.engr.sgi.com> wrote: > > > > > > > Konstantin, some comments: > > > > 1. You added some USB specific code to kdba_io_32.c, namely > > kdb_usb_fill_int_urb(), kdb_uhci_submit_urb(). > > > > Would it be better to put this USB code into the kernel uhci > > files (uhci-q.c, uhci-hcd.c or whatever) so kdb can remain unaware > > of USB specifics? > > Also, I think if you did it this way, then it would remove the need > > for the new interface routine kdb_usb_uhci_keyboard_attach(). You > > should be able to just call kdb_usb_keyboard_attach() after you > > create and submit the new URB from hid_probe(). Just add > > a new parameter to kdb_usb_keyboard_attach() for the > > complete_func and pass NULL for it for OHCI and EHCI. > > > > The USB infastructure is constantly being rewritten and > > structures/parameters changing around, so it would be best to keep > > those details over in the kernel and not in kdb IMO. > > > - Got rid from kdb_usb_uhci_keyboard_attach() > - Added "poll_func" argument to kdb_usb_keyboard_attach() > - Moved kdb_usb_fill_int_urb() and kdb_uhci_submit_urb() to hid-core.c. That fixes compilation errors (problem reported by jidong xiao) when USB subsystem is compiled as kernel module. > > > 2. What is the limiting factor preventing multiple keyboards? Is it > > the use of the globals kdb_uhci_hid_qh and kdb_hid_event? Can this > > be fixed somehow? Can they be put into the per device > > kdb_usb_kbd_info struct maybe? > > > - Moved kdb_uhci_hid_qh and hid_event to kdb_usb_kbd_info. Now multiple UHCI keyboards are supported. > > > 4. I think you'll need to add your new interfaces to kdba_io_64.c > > and arch/ia64/kdb/kdba_io.c. Otherwise, the USB modules will > > encounter link/build errors when they can't find > > kdb_usb_uhci_keyboard_attach() (and the other globals and such) on > > those builds/systems. It would be nice to have UHCI support on those > > archs too. > > > - Added x86_64 part. > > > 5. I already submitted another patch for EHCI support which will > > conflict with this one (kdba_io_32.c). Can you add your patch on > > top of that one? > - Done. > > > > > > > -Aaron > > > > Patch against kernel 2.6.24-rc2. Was tested on i386 kernel with 2 UHCI keyboards. > > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > @@ -25,6 +25,18 @@ > * games with the FSBR code to make sure we get the correct order in all > * the cases. I don't think it's worth the effort > */ > +#ifdef CONFIG_KDB_USB > +/* KDB HID QH, managed by KDB code */ > +extern int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh); > +extern int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); > +extern struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); > +extern int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); > +extern int kdb_uhci_keyboard_get_hid_event(struct urb *urb); > +extern int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); > +extern int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh); > +#endif > + > + > static void uhci_set_next_interrupt(struct uhci_hcd *uhci) > { > if (uhci->is_stopped) > @@ -292,6 +304,58 @@ static struct uhci_qh *uhci_alloc_qh(str > return qh; > } > > +#ifdef CONFIG_KDB_USB > +/* > + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv > + */ > +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, > + struct usb_device *udev, struct usb_host_endpoint *hep) > +{ > + dma_addr_t dma_handle; > + struct uhci_qh *qh; > + > + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); > + if (!qh) > + return NULL; > + > + memset(qh, 0, sizeof(*qh)); > + qh->dma_handle = dma_handle; > + > + qh->element = UHCI_PTR_TERM; > + qh->link = UHCI_PTR_TERM; > + > + INIT_LIST_HEAD(&qh->queue); > + INIT_LIST_HEAD(&qh->node); > + > + if (udev) { /* Normal QH */ > + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > + if (qh->type != USB_ENDPOINT_XFER_ISOC) { > + qh->dummy_td = uhci_alloc_td(uhci); > + if (!qh->dummy_td) { > + dma_pool_free(uhci->qh_pool, qh, dma_handle); > + return NULL; > + } > + } > + qh->state = QH_STATE_IDLE; > + qh->hep = hep; > + qh->udev = udev; > + > + if (qh->type == USB_ENDPOINT_XFER_INT || > + qh->type == USB_ENDPOINT_XFER_ISOC) > + qh->load = usb_calc_bus_time(udev->speed, > + usb_endpoint_dir_in(&hep->desc), > + qh->type == USB_ENDPOINT_XFER_ISOC, > + le16_to_cpu(hep->desc.wMaxPacketSize)) > + / 1000 + 1; > + > + } else { /* Skeleton QH */ > + qh->state = QH_STATE_ACTIVE; > + qh->type = -1; > + } > + return qh; > +} > +#endif > + > static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) > { > WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); > @@ -1399,6 +1463,20 @@ static int uhci_urb_enqueue(struct usb_h > if (!urbp) > goto done; > > +#ifdef CONFIG_KDB_USB > + /* Always allocate new QH for KDB URB. > + * KDB HQ will be managed by KDB poll code not by > + * UHCI HCD Driver. > + */ > + if (kdb_uhci_keyboard_urb(urb) != -1){ > + /* KDB urb will be enqued only once */ > + kdb_uhci_keyboard_set_qh(urb, NULL); > + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); > + if (!qh) > + goto err_no_qh; > + kdb_uhci_keyboard_set_qh(urb, qh); > + } else > +#endif > if (urb->ep->hcpriv) > qh = urb->ep->hcpriv; > else { > @@ -1648,6 +1726,13 @@ static int uhci_advance_check(struct uhc > int ret = 1; > unsigned status; > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1){ > + ret = 0; > + goto done; > + } > +#endif > if (qh->type == USB_ENDPOINT_XFER_ISOC) > goto done; > > @@ -1740,6 +1825,11 @@ rescan: > uhci->next_qh = list_entry(qh->node.next, > struct uhci_qh, node); > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1) > + continue; > +#endif > if (uhci_advance_check(uhci, qh)) { > uhci_scan_qh(uhci, qh); > if (qh->state == QH_STATE_ACTIVE) { > @@ -1766,3 +1856,76 @@ rescan: > else > uhci_set_next_interrupt(uhci); > } > + > +#ifdef CONFIG_KDB_USB > +/* > + * Activate KDB UHCI QH, called by KDB poll code. > + */ > +static void kdb_activate_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp; > + struct uhci_td *td; > + __le32 status, token; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + > + list_for_each_entry(td, &urbp->td_list, list){ > + status = td->status; > + token = td->token; > + barrier(); > + /* Clear Status and ActLen */ > + status &= cpu_to_le32(0xff000000); > + /* Make TD Active */ > + status |= cpu_to_le32(TD_CTRL_ACTIVE); > + /* Clear TD Interrupt */ > + status &= cpu_to_le32(~TD_CTRL_IOC); > + /* Toggle Data Sycronization Bit */ > + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) > + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); > + else > + token |= cpu_to_le32(TD_TOKEN_TOGGLE); > + > + td->token = token; > + td->status = status; > + barrier(); > + } > + /* Activate KDB UHCI Keyboard HID QH */ > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + qh->element = LINK_TO_TD(td); > + barrier(); > +} > + > +/* > + * Called when KDB finishes process key press/release event. > + */ > +static void > +kdb_uhci_urb_complete (struct urb *urb) > +{ > + if (!kdb_uhci_keyboard_get_hid_event(urb)) > + return; > + > + /* Activate KDB TD */ > + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > + kdb_uhci_keyboard_set_hid_event(urb, 0); > +} > + > +/* > + * Check if state of KDB URB changed (key was pressed/released). > + */ > +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp = NULL; > + struct uhci_td *td; > + unsigned status; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + status = td_status(td); > + if (!(status & TD_CTRL_ACTIVE)){ > + /* We're okay, the queue has advanced */ > + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); > + return 0; > + } > + return -1; > +} > +#endif > Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c > +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > @@ -969,6 +969,86 @@ static void hid_disconnect(struct usb_in > hid_free_device(hid); > } > > +#ifdef CONFIG_KDB_USB > +/* Only 1 UHCI Keyboard supported */ > +static inline void kdb_usb_fill_int_urb (struct urb *urb, > + struct usb_device *dev, > + unsigned int pipe, > + void *transfer_buffer, > + int buffer_length, > + usb_complete_t complete_fn, > + void *context, > + int interval) > +{ > + urb->dev = dev; > + urb->pipe = pipe; > + urb->transfer_buffer = transfer_buffer; > + urb->transfer_buffer_length = buffer_length; > + urb->complete = complete_fn; > + urb->context = context; > + urb->interval = interval; > + urb->start_frame = -1; > +} > + > +static int kdb_uhci_submit_urb(struct usb_interface *intf, unsigned int usbhid_bufsize, struct urb *hid_inurb) > +{ > + struct urb *kdb_urb = NULL; > + unsigned char *kdb_buffer; > + dma_addr_t uhci_inbuf_dma; > + int ret = -1; > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + > + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, > + usbhid_bufsize, GFP_ATOMIC, > + &uhci_inbuf_dma))) > + goto out; > + > + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) > + goto out; > + > + kdb_usb_fill_int_urb(kdb_urb, > + hid_inurb->dev, > + hid_inurb->pipe, > + kdb_buffer, > + hid_inurb->transfer_buffer_length, > + hid_inurb->complete, > + hid_inurb->context, > + hid_inurb->interval > + ); > + > + (kdb_urb)->transfer_dma = uhci_inbuf_dma; > + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > + > + ret = kdb_usb_keyboard_attach(kdb_urb, kdb_buffer, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > + > + if (ret){ > + kdb_uhci_keyboard_clear(kdb_urb); > + goto out; > + } > + > + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)) > + goto out; > + > + ret = 0; > + return ret; > +out: > + /* Some Error Cleanup */ > + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); > + if (kdb_buffer) > + usb_buffer_free(hid_inurb->dev, > + usbhid_bufsize, kdb_buffer, > + uhci_inbuf_dma); > + > + if (kdb_urb) > + usb_free_urb(kdb_urb); > + > + return ret; > +} > +#endif > + > static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) > { > struct hid_device *hid; > @@ -1045,8 +1125,15 @@ static int hid_probe(struct usb_interfac > int ret; > struct usbhid_device *usbhid = hid->driver_data; > 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))); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + extern int usb_hcd_check_uhci(struct usb_device *udev); > + > + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) > + ret = kdb_uhci_submit_urb(intf, usbhid->bufsize, usbhid->urbin); > + else > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > > if (ret == -1) > printk(": FAILED to register keyboard (%s) " > Index: linux-2.6.24-rc2/include/linux/kdb.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdb.h > +++ linux-2.6.24-rc2/include/linux/kdb.h > @@ -143,9 +143,17 @@ extern void smp_kdb_stop(void); > > #include <linux/usb.h> > > -extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > +extern int kdb_uhci_keyboard_urb(struct urb *urb); > +extern int kdb_uhci_keyboard_clear(struct urb *urb); > +extern int kdb_usb_keyboard_alloc(void); > + > +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func, void *compl_func); > extern int kdb_usb_keyboard_detach(struct urb *urb); > > +extern int > +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, > + void *poll_func, void *compl_func); > + > #endif /* CONFIG_KDB_USB */ > > static inline > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > @@ -50,6 +50,10 @@ > #include "uhci-hcd.h" > #include "pci-quirks.h" > > +#ifdef CONFIG_KDB_USB > +#include <linux/kdb.h> > +#endif > + > /* > * Version Information > */ > @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h > return IRQ_HANDLED; > } > > +#ifdef CONFIG_KDB_USB > +static int > +uhci_kdb_poll_char(struct urb *urb) > +{ > + if (!urb) /* can happen if no keyboard attached */ > + return -1; > + > + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > +} > +#endif > + > /* > * Store the current frame number in uhci->frame_number if the controller > * is runnning. Expand from 11 bits (of which we use only 10) to a > @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive > > .hub_status_data = uhci_hub_status_data, > .hub_control = uhci_hub_control, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = uhci_kdb_poll_char, > + .kdb_completion = kdb_uhci_urb_complete, > +#endif > }; > > static const struct pci_device_id uhci_pci_ids[] = { { > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > +/* Check if URB is managed by KDB code */ > +int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > + > +/* Check if UHCI QH is managed by KDB code */ > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > + > +/* Clear keyboar entry */ > +int kdb_uhci_keyboard_clear(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].urb_complete = NULL; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > + > +/* Set UHCI QH using URB pointer */ > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].qh = qh; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > + > +/* Get UHCI QH using URB pointer */ > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].qh; > + } > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > + > +/* Set UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > + > +/* Get UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > + > +/* Set UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + return i; > + } > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > + > +/* Get UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > + > /* > * kdb_usb_keyboard_attach() > * Attach a USB keyboard to kdb. > */ > int > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > + void *poll_func, void *compl_func) > { > int i; > int rc = -1; > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > kdb_usb_kbds[i].urb = urb; > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = compl_func; > > rc = 0; /* success */ > > @@ -142,6 +277,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > if (kdb_no_usb) > return -1; > @@ -158,20 +296,27 @@ get_usb_char(void) > 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 */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > - keycode = kdb_usb_kbds[i].buffer[2]; > + keycode = kdb_usb_kbds[i].buffer[max]; > 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]; > @@ -182,10 +327,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -194,31 +341,45 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > - > + ret = 13; > + break; > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret = plain_map[keycode]; > + break; > } > else { > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > } > } > } > + /* Key was pressed, return keycode */ > + break; > } > > - /* no chars were returned from any of the USB keyboards */ > + for(i2=0; i2<8; i2++){ > + if (kdb_usb_kbds[i2].buffer) > + for(j=0; j<8; j++){ > + kdb_usb_kbds[i2].buffer[j] = (char)0; > + } > + } > + > + if (kdb_usb_kbds[i].urb_complete) > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > - return -1; > + return ret; > } > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_64.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > +/* Check if URB is managed by KDB code */ > +int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > + > +/* Check if UHCI QH is managed by KDB code */ > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > + > +/* Clear keyboar entry */ > +int kdb_uhci_keyboard_clear(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].urb_complete = NULL; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > + > +/* Set UHCI QH using URB pointer */ > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].qh = qh; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > + > +/* Get UHCI QH using URB pointer */ > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].qh; > + } > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > + > +/* Set UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > + > +/* Get UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > + > +/* Set UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + return i; > + } > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > + > +/* Get UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > + > /* > * kdb_usb_keyboard_attach() > * Attach a USB keyboard to kdb. > */ > int > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > + void *poll_func, void *compl_func) > { > int i; > int rc = -1; > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > kdb_usb_kbds[i].urb = urb; > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = compl_func; > > rc = 0; /* success */ > > @@ -142,6 +277,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > if (kdb_no_usb) > return -1; > @@ -158,20 +296,27 @@ get_usb_char(void) > 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 */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > - keycode = kdb_usb_kbds[i].buffer[2]; > + keycode = kdb_usb_kbds[i].buffer[max]; > 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]; > @@ -182,10 +327,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -194,31 +341,45 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > - > + ret = 13; > + break; > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret = plain_map[keycode]; > + break; > } > else { > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > } > } > } > + /* Key was pressed, return keycode */ > + break; > } > > - /* no chars were returned from any of the USB keyboards */ > + for(i2=0; i2<8; i2++){ > + if (kdb_usb_kbds[i2].buffer) > + for(j=0; j<8; j++){ > + kdb_usb_kbds[i2].buffer[j] = (char)0; > + } > + } > + > + if (kdb_usb_kbds[i].urb_complete) > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > - return -1; > + return ret; > } > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/include/linux/kdbprivate.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h > +++ linux-2.6.24-rc2/include/linux/kdbprivate.h > @@ -489,7 +489,10 @@ 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 (*urb_complete)(struct urb *urb); /* called when URB int is processed */ > int caps_lock; /* state of the caps lock for this keyboard */ > + struct uhci_qh *qh; > + int kdb_hid_event; > }; > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c > @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev > return NULL; > } > EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > + > +void * > +usb_hcd_get_kdb_completion_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_completion); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); > + > +int > +usb_hcd_check_uhci(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) > + return 1; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); > #endif /* CONFIG_KDB_USB */ > > /*-------------------------------------------------------------------------*/ > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h > @@ -213,6 +213,7 @@ struct hc_driver { > #ifdef CONFIG_KDB_USB > /* KDB poll function for this HC */ > int (*kdb_poll_char)(struct urb *urb); > + void (*kdb_completion)(struct urb *urb); > #endif /* CONFIG_KDB_USB */ > }; > > --------------------------- > 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.