Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80e9be60 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: core: Update config summary descriptor handling



USB 3.2 Specification updated configuration summary descriptor
different from drafted version. This descriptor is needed per
function. Descriptor provides list of configuration indices
that include that function. Use bcdVersion to handle spec
compliant descriptor and select device preferred config supporting
BADD3 or lower revision.

Change-Id: I7cf28eaf61ca91496be84d90ad00704fe4acb149
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent 314af848
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1025,7 +1025,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
				(struct usb_ptm_cap_descriptor *)buffer;
			break;
		case USB_CAP_TYPE_CONFIG_SUMMARY:
			/* one such desc per configuration */
			/* one such desc per function */
			if (!dev->bos->num_config_summary_desc)
				dev->bos->config_summary =
				(struct usb_config_summary_descriptor *)buffer;
+21 −18
Original line number Diff line number Diff line
@@ -44,30 +44,33 @@ static int is_activesync(struct usb_interface_descriptor *desc)
		&& desc->bInterfaceProtocol == 1;
}

static int usb_audio_max_rev_config(struct usb_host_bos *bos)
static int get_usb_audio_config(struct usb_host_bos *bos)
{
	int desc_cnt, func_cnt, numfunc;
	int num_cfg_desc;
	unsigned int desc_cnt, num_cfg_desc, len = 0;
	unsigned char *buffer;
	struct usb_config_summary_descriptor *conf_summary;

	if (!bos || !bos->config_summary)
		goto done;

	conf_summary = bos->config_summary;
	num_cfg_desc = bos->num_config_summary_desc;

	conf_summary = bos->config_summary;
	buffer = (unsigned char *)conf_summary;
	for (desc_cnt = 0; desc_cnt < num_cfg_desc; desc_cnt++) {
		numfunc = conf_summary->bNumFunctions;
		for (func_cnt = 0; func_cnt < numfunc; func_cnt++) {
			/* look for BADD 3.0 */
			if (conf_summary->cs_info[func_cnt].bClass ==
				USB_CLASS_AUDIO &&
				conf_summary->cs_info[func_cnt].bProtocol ==
				UAC_VERSION_3 &&
				conf_summary->cs_info[func_cnt].bSubClass !=
				FULL_ADC_PROFILE)
				return conf_summary->bConfigurationValue;
		}
		conf_summary =
			(struct usb_config_summary_descriptor *)(buffer + len);

		len += conf_summary->bLength;

		if (conf_summary->bcdVersion != USB_CONFIG_SUMMARY_DESC_REV ||
				conf_summary->bClass != USB_CLASS_AUDIO)
			continue;

		/* look for 1st config summary without UAC3 full ADC profile */
		if (conf_summary->bProtocol < UAC_VERSION_3 ||
				(conf_summary->bProtocol == UAC_VERSION_3 &&
				 conf_summary->bSubClass != FULL_ADC_PROFILE))
			return conf_summary->bConfigurationIndex[0];
	}

done:
@@ -176,8 +179,8 @@ int usb_choose_configuration(struct usb_device *udev)
			insufficient_power, plural(insufficient_power));

	if (best) {
		/* choose usb audio class preferred config if available */
		i = usb_audio_max_rev_config(udev->bos);
		/* choose device preferred config */
		i = get_usb_audio_config(udev->bos);
		if (i < 0)
			i = best->desc.bConfigurationValue;
		dev_dbg(&udev->dev,
+7 −11
Original line number Diff line number Diff line
@@ -1083,22 +1083,18 @@ struct usb_ptm_cap_descriptor {
 * which Configuration to use to obtain the desired functionality.
 */
#define USB_CAP_TYPE_CONFIG_SUMMARY	0x10

struct function_class_info {
	__u8 bClass;
	__u8 bSubClass;
	__u8 bProtocol;
};
#define USB_CONFIG_SUMMARY_DESC_REV	0x100

struct usb_config_summary_descriptor {
	__u8 bLength;
	__u8 bDescriptorType;
	__u8 bDevCapabilityType;
	__u16 bcdVersion;
	__u8 bConfigurationValue;
	__u8 bMaxPower;
	__u8 bNumFunctions;
	struct function_class_info cs_info[];
	__u8 bClass;
	__u8 bSubClass;
	__u8 bProtocol;
	__u8 bConfigurationCount;
	__u8 bConfigurationIndex[];
} __attribute__((packed));

/*-------------------------------------------------------------------------*/