Merge "usb: core: Add support to handle multi config audio device"
This commit is contained in:
commit
6c27d8d8b7
4 changed files with 69 additions and 2 deletions
|
@ -949,6 +949,14 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
||||||
dev->bos->ss_id =
|
dev->bos->ss_id =
|
||||||
(struct usb_ss_container_id_descriptor *)buffer;
|
(struct usb_ss_container_id_descriptor *)buffer;
|
||||||
break;
|
break;
|
||||||
|
case USB_CAP_TYPE_CONFIG_SUMMARY:
|
||||||
|
/* one such desc per configuration */
|
||||||
|
if (!dev->bos->num_config_summary_desc)
|
||||||
|
dev->bos->config_summary =
|
||||||
|
(struct usb_config_summary_descriptor *)buffer;
|
||||||
|
|
||||||
|
dev->bos->num_config_summary_desc++;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/usb/hcd.h>
|
#include <linux/usb/hcd.h>
|
||||||
|
#include <linux/usb/audio.h>
|
||||||
|
#include <linux/usb/audio-v3.h>
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
static inline const char *plural(int n)
|
static inline const char *plural(int n)
|
||||||
|
@ -40,6 +42,36 @@ static int is_activesync(struct usb_interface_descriptor *desc)
|
||||||
&& desc->bInterfaceProtocol == 1;
|
&& desc->bInterfaceProtocol == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usb_audio_max_rev_config(struct usb_host_bos *bos)
|
||||||
|
{
|
||||||
|
int desc_cnt, func_cnt, numfunc;
|
||||||
|
int num_cfg_desc;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
int usb_choose_configuration(struct usb_device *udev)
|
int usb_choose_configuration(struct usb_device *udev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -130,7 +162,6 @@ int usb_choose_configuration(struct usb_device *udev)
|
||||||
best = c;
|
best = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If all the remaining configs are vendor-specific,
|
/* If all the remaining configs are vendor-specific,
|
||||||
* choose the first one. */
|
* choose the first one. */
|
||||||
else if (!best)
|
else if (!best)
|
||||||
|
@ -143,7 +174,10 @@ int usb_choose_configuration(struct usb_device *udev)
|
||||||
insufficient_power, plural(insufficient_power));
|
insufficient_power, plural(insufficient_power));
|
||||||
|
|
||||||
if (best) {
|
if (best) {
|
||||||
i = best->desc.bConfigurationValue;
|
/* choose usb audio class preferred config if available */
|
||||||
|
i = usb_audio_max_rev_config(udev->bos);
|
||||||
|
if (i < 0)
|
||||||
|
i = best->desc.bConfigurationValue;
|
||||||
dev_dbg(&udev->dev,
|
dev_dbg(&udev->dev,
|
||||||
"configuration #%d chosen from %d choice%s\n",
|
"configuration #%d chosen from %d choice%s\n",
|
||||||
i, num_configs, plural(num_configs));
|
i, num_configs, plural(num_configs));
|
||||||
|
|
|
@ -330,6 +330,8 @@ struct usb_host_bos {
|
||||||
struct usb_ss_cap_descriptor *ss_cap;
|
struct usb_ss_cap_descriptor *ss_cap;
|
||||||
struct usb_ssp_cap_descriptor *ssp_cap;
|
struct usb_ssp_cap_descriptor *ssp_cap;
|
||||||
struct usb_ss_container_id_descriptor *ss_id;
|
struct usb_ss_container_id_descriptor *ss_id;
|
||||||
|
struct usb_config_summary_descriptor *config_summary;
|
||||||
|
unsigned int num_config_summary_desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
int __usb_get_extra_descriptor(char *buffer, unsigned size,
|
int __usb_get_extra_descriptor(char *buffer, unsigned size,
|
||||||
|
|
|
@ -894,6 +894,29 @@ struct usb_ssp_cap_descriptor {
|
||||||
#define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */
|
#define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration Summary descriptors: Defines a list of functions in the
|
||||||
|
* configuration. This descriptor may be used by Host software to decide
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue