[PATCH] Add support for USB Keyboard attached to UHCI

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]




 Also, should kdb_uhci_keyboard_chech_uhci_qh() be
 kdb_uhci_keyboard_check_uhci_qh()?


> 
> 
> 
>  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.
> 

---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]

Add to Google Powered by Linux