Loading drivers/usb/core/config.c +9 −0 Original line number Diff line number Diff line Loading @@ -981,6 +981,15 @@ int usb_get_bos_descriptor(struct usb_device *dev) case USB_PTM_CAP_TYPE: dev->bos->ptm_cap = (struct usb_ptm_cap_descriptor *)buffer; 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: break; } Loading drivers/usb/core/generic.c +34 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/audio.h> #include <linux/usb/audio-v3.h> #include "usb.h" static inline const char *plural(int n) Loading @@ -40,6 +42,34 @@ static int is_activesync(struct usb_interface_descriptor *desc) && 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++) { /* honor device preferred config */ if (conf_summary->cs_info[func_cnt].bClass == USB_CLASS_AUDIO && conf_summary->cs_info[func_cnt].bSubClass != FULL_ADC_3_0) return conf_summary->bConfigurationValue; } } done: return -EINVAL; } int usb_choose_configuration(struct usb_device *udev) { int i; Loading Loading @@ -130,7 +160,6 @@ int usb_choose_configuration(struct usb_device *udev) best = c; break; } /* If all the remaining configs are vendor-specific, * choose the first one. */ else if (!best) Loading @@ -143,6 +172,9 @@ 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); if (i < 0) i = best->desc.bConfigurationValue; dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n", Loading include/linux/usb.h +2 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,8 @@ struct usb_host_bos { struct usb_ssp_cap_descriptor *ssp_cap; struct usb_ss_container_id_descriptor *ss_id; struct usb_ptm_cap_descriptor *ptm_cap; struct usb_config_summary_descriptor *config_summary; unsigned int num_config_summary_desc; }; int __usb_get_extra_descriptor(char *buffer, unsigned size, Loading include/linux/usb/audio-v3.h +2 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ #define CLUSTER_ID_MONO 0x0001 #define CLUSTER_ID_STEREO 0x0002 #define FULL_ADC_PROFILE 0x01 /* A.2 audio function subclass codes */ #define FULL_ADC_3_0 0x01 /* BADD Profile IDs */ #define PROF_GENERIC_IO 0x20 Loading include/uapi/linux/usb/ch9.h +24 −0 Original line number Diff line number Diff line Loading @@ -1051,6 +1051,30 @@ struct usb_ptm_cap_descriptor { */ #define USB_DT_USB_SSP_CAP_SIZE(ssac) (16 + ssac * 4) /* * 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)); /*-------------------------------------------------------------------------*/ /* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with Loading Loading
drivers/usb/core/config.c +9 −0 Original line number Diff line number Diff line Loading @@ -981,6 +981,15 @@ int usb_get_bos_descriptor(struct usb_device *dev) case USB_PTM_CAP_TYPE: dev->bos->ptm_cap = (struct usb_ptm_cap_descriptor *)buffer; 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: break; } Loading
drivers/usb/core/generic.c +34 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/audio.h> #include <linux/usb/audio-v3.h> #include "usb.h" static inline const char *plural(int n) Loading @@ -40,6 +42,34 @@ static int is_activesync(struct usb_interface_descriptor *desc) && 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++) { /* honor device preferred config */ if (conf_summary->cs_info[func_cnt].bClass == USB_CLASS_AUDIO && conf_summary->cs_info[func_cnt].bSubClass != FULL_ADC_3_0) return conf_summary->bConfigurationValue; } } done: return -EINVAL; } int usb_choose_configuration(struct usb_device *udev) { int i; Loading Loading @@ -130,7 +160,6 @@ int usb_choose_configuration(struct usb_device *udev) best = c; break; } /* If all the remaining configs are vendor-specific, * choose the first one. */ else if (!best) Loading @@ -143,6 +172,9 @@ 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); if (i < 0) i = best->desc.bConfigurationValue; dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n", Loading
include/linux/usb.h +2 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,8 @@ struct usb_host_bos { struct usb_ssp_cap_descriptor *ssp_cap; struct usb_ss_container_id_descriptor *ss_id; struct usb_ptm_cap_descriptor *ptm_cap; struct usb_config_summary_descriptor *config_summary; unsigned int num_config_summary_desc; }; int __usb_get_extra_descriptor(char *buffer, unsigned size, Loading
include/linux/usb/audio-v3.h +2 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ #define CLUSTER_ID_MONO 0x0001 #define CLUSTER_ID_STEREO 0x0002 #define FULL_ADC_PROFILE 0x01 /* A.2 audio function subclass codes */ #define FULL_ADC_3_0 0x01 /* BADD Profile IDs */ #define PROF_GENERIC_IO 0x20 Loading
include/uapi/linux/usb/ch9.h +24 −0 Original line number Diff line number Diff line Loading @@ -1051,6 +1051,30 @@ struct usb_ptm_cap_descriptor { */ #define USB_DT_USB_SSP_CAP_SIZE(ssac) (16 + ssac * 4) /* * 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)); /*-------------------------------------------------------------------------*/ /* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with Loading