Re: usb:gadget:hid:Add BOOT mode support

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

 



On Tue, 26 May 2015, Golmer Palmer wrote:

> Alan Stern <stern@...> writes:
> 
> > > Please, take into account that I mentioned that the ASSUMPTION that 
> > > keyboard and mouse drivers are compatible with BOTH protocols is 
> really 
> > > TRUE.
> > 
> > No, it isn't.  You said "several Keyboard and Mouse implementations
> > using this framework are in fact fully compatible with BOOT mode."  
> > This means that other implementations are _not_ compatible with Boot
> > mode.  The assumption is _sometimes_ true and _sometimes_ false.
> 
> Yes. You're right. And you put the solution in your patch: if the 
> descriptor of the device contains the USB_INTERFACE_SUBCLASS_BOOT then
> this device has implemented the BOOT protocol. If not listed as boot 
> compatible, then no option for working in BOOT mode.
> 
> The assumption about I speak is this: implementations that advertise as
> BOOT compatible AND are using a DIFFERENT implementation for BOOT and 
> REPORT modes are... INEXISTENT. This type of implementations don't 
> exists in the Linux gadget land because with the current driver is 
> impossible to change from REPORT to BOOT (remember that the function 
> Set_Protocol() *always* return ERROR). Then this case can be put 
> out-of-scope. In any case can be possible to modify the code to include
> a define option for enable it. But the current case is that neither 
> implementation with boot=report and boot!=report can work because the 
> lack of Set_Protocol() and Get_protocol().
> So the best, at minimum, is support the most common case (boot=report).
> 
> Personally, I only know a very few devices that supports the report mode
> with expanded functions and supporting also the boot mode. Mainly 
> advanced keyboards (multi-key) that all of them are implemented using 
> custom stacks (not the Linux gadget). So this a very *uncommon* case.

> Correct. When someone needs this in the future a new function for enable
> it should needed in the kernel driver. But for fully support the BOOT 
> mode a simple implementation of the Set_Protocol() and Get_Protocol() 
> are the only requirement.
> 
> So please, can you add also some minimal support inside Set_Protocol()
> to "change" from mode "0" to mode "1" (and viceversa) assuming that both
> modes are equal?

Okay, a revised patch is below.  Let me know how it works out.

> Thank you Alan for your support and comments. I really appreciate them!

You're welcome.

Alan Stern



Index: usb-4.0/drivers/usb/gadget/function/f_hid.c
===================================================================
--- usb-4.0.orig/drivers/usb/gadget/function/f_hid.c
+++ usb-4.0/drivers/usb/gadget/function/f_hid.c
@@ -44,6 +44,7 @@ struct f_hidg {
 	/* configuration */
 	unsigned char			bInterfaceSubClass;
 	unsigned char			bInterfaceProtocol;
+	unsigned char			protocol_is_report;
 	unsigned short			report_desc_length;
 	char				*report_desc;
 	unsigned short			report_length;
@@ -418,7 +419,9 @@ static int hidg_setup(struct usb_functio
 	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
 		  | HID_REQ_GET_PROTOCOL):
 		VDBG(cdev, "get_protocol\n");
-		goto stall;
+		length = min_t(unsigned, length, 1);
+		((u8 *) req->buf)[0] = hidg->protocol_is_report;
+		goto respond;
 		break;
 
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -430,6 +433,17 @@ static int hidg_setup(struct usb_functio
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
 		  | HID_REQ_SET_PROTOCOL):
 		VDBG(cdev, "set_protocol\n");
+		if (value > 1)
+			goto stall;
+		length = 0;
+		/*
+		 * We assume that programs implementing the Boot protocol
+		 * are also compatible with the Report protocol.
+		 */
+		if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
+			hidg->protocol_is_report = value;
+			goto respond;
+		}
 		goto stall;
 		break;
 
@@ -933,6 +947,8 @@ static struct usb_function *hidg_alloc(s
 	hidg->minor = opts->minor;
 	hidg->bInterfaceSubClass = opts->subclass;
 	hidg->bInterfaceProtocol = opts->protocol;
+	hidg->protocol_is_report = (hidg->bInterfaceSubClass !=
+			USB_INTERFACE_SUBCLASS_BOOT);
 	hidg->report_length = opts->report_length;
 	hidg->report_desc_length = opts->report_desc_length;
 	if (opts->report_desc) {

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux