Re: [PATCH 3/8] usb: gadget: OS Feature Descriptors support

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

 



On Tue, May 06 2014, Andrzej Pietrasiewicz wrote:
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>

Acked-by: Michal Nazarewicz <mina86@xxxxxxxxxx>

> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
> index 4e8aaa6..47a6f4e 100644
> --- a/drivers/usb/gadget/composite.c
> +++ b/drivers/usb/gadget/composite.c
> @@ -454,8 +456,46 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
>  
>  	}
>  
> -	/* This is a lookup by config *INDEX* */
>  	w_value &= 0xff;
> +	/*
> +	 * This is a lookup to make non-compliant USB hosts happy.
> +	 *
> +	 * By non-compliant USB hosts I mean those which only ask for
> +	 * configuration @index 0.
> +	 * If one configuration is marked "special" by storing
> +	 * its address in cdev->os_desc_config, we try returning
> +	 * exactly this configuration.
> +	 *
> +	 * Otherwise, regular list lookup is performed.
> +	 *
> +	 * If we are connected to a compliant USB host _and_
> +	 * one configuration is "special" we report it @ index 0,
> +	 * but report remaining configurations as well - with adjusted
> +	 * indices.
> +	 */
> +	c = cdev->os_desc_config;
> +	if (c) {
> +		if (!w_value) {
> +			switch (speed) {
> +			case USB_SPEED_SUPER:
> +				if (!c->superspeed)
> +					goto list_lookup;
> +				break;
> +			case USB_SPEED_HIGH:
> +				if (!c->highspeed)
> +					goto list_lookup;
> +				break;
> +			default:
> +				if (!c->fullspeed)
> +					goto list_lookup;
> +			}
> +
> +			return config_buf(c, speed, cdev->req->buf, type);
> +		}
> +		--w_value; /* account for conf returned @ index 0 */
> +	}

This is non-ideal since the body of the if is repeated twice.  Perhaps
it could be folded into the loop, something like:

	/* This is a lookup by config *INDEX* */
	w_value &= 0xff;

	struct list_head *pos = &cdev->configs;
	c = cdev->os_desc_config;
	if (c) 
		goto check_config;

	while ((pos = pos->next) != &cdev->configs) {
		c = list_entry(pos, typeof(*c), list);

		/* skip OS config which is handled separately */
		if (c == cdev->os_desc_config)
			continue;

check_config:
		/* ignore configs that won't work at this speed */
		switch (speed) {
		case USB_SPEED_SUPER:
			if (!c->superspeed)
				continue;
			break;
		case USB_SPEED_HIGH:
			if (!c->highspeed)
				continue;
			break;
		default:
			if (!c->fullspeed)
				continue;
		}

		if (w_value == 0)
			return config_buf(c, speed, cdev->req->buf, type);
		w_value--;
	}

Not tested.

> +list_lookup:
> +	/* This is a lookup by config *INDEX* */
>  	list_for_each_entry(c, &cdev->configs, list) {
>  		/* ignore configs that won't work at this speed */
>  		switch (speed) {

-- 
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michał “mina86” Nazarewicz    (o o)
ooo +--<mpn@xxxxxxxxxx>--<xmpp:mina86@xxxxxxxxxx>--ooO--(_)--Ooo--

Attachment: signature.asc
Description: PGP signature


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

  Powered by Linux