Merge "usb: gadget: Add support for MBIM OS descriptor handling"

This commit is contained in:
qctecmdr 2021-03-01 22:58:14 -08:00 • committed by Gerrit - the friendly Code Review server
commit 749644af9b
2 changed files with 37 additions and 58 deletions

View file

@ -2965,6 +2965,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
struct gsi_function_bind_info info = {0};
struct f_gsi *gsi = func_to_gsi(f);
struct rndis_params *params;
struct gsi_opts *opts;
int status;
__u8 class;
__u8 subclass;
@ -3157,18 +3158,15 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
info.notify_buf_len = sizeof(struct usb_cdc_notification);
mbim_gsi_desc.wMaxSegmentSize = cpu_to_le16(0x800);
/*
* If MBIM is bound in a config other than the first, tell
* Windows about it by returning the num as a string in the
* OS descriptor's subCompatibleID field. Windows only supports
* up to config #4.
*/
if (c->bConfigurationValue >= 2 &&
c->bConfigurationValue <= 4) {
log_event_dbg("MBIM in configuration %d",
c->bConfigurationValue);
mbim_gsi_ext_config_desc.function.subCompatibleID[0] =
c->bConfigurationValue + '0';
if (cdev->use_os_string) {
f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
GFP_KERNEL);
if (!f->os_desc_table)
return -ENOMEM;
opts = container_of(f->fi, struct gsi_opts, func_inst);
f->os_desc_n = 1;
f->os_desc_table[0].os_desc = &opts->os_desc;
f->os_desc_table[0].if_id = gsi->data_id;
}
break;
case IPA_USB_RMNET:
@ -3331,6 +3329,7 @@ skip_ipa_init:
dereg_rndis:
rndis_deregister(gsi->params);
kfree(f->os_desc_table);
fail:
return status;
}
@ -3365,8 +3364,11 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_deregister(gsi->params);
}
if (gsi->prot_id == IPA_USB_MBIM)
mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0;
if (gsi->prot_id == IPA_USB_MBIM) {
kfree(f->os_desc_table);
f->os_desc_table = NULL;
f->os_desc_n = 0;
}
usb_free_all_descriptors(f);
@ -3766,6 +3768,8 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
char gsi_inst_name[MAX_INST_NAME_LEN + sizeof("gsi.") + 1];
void *ipc_log_ctxt;
struct gsi_opts *opts, *opts_prev;
struct usb_os_desc *descs[1];
char *names[1];
opts = container_of(fi, struct gsi_opts, func_inst);
@ -3799,6 +3803,16 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
fi->group.cg_item.ci_name,
&gsi_func_ecm_type);
if (prot_id == IPA_USB_MBIM) {
opts->os_desc.ext_compat_id = opts->ext_compat_id;
INIT_LIST_HEAD(&opts->os_desc.ext_prop);
descs[0] = &opts->os_desc;
names[0] = "MBIM";
opts->interf_group = usb_os_desc_prepare_interf_dir(
&opts->func_inst.group, 1,
descs, names, THIS_MODULE);
}
gsi = gsi_function_init(prot_id);
if (IS_ERR(gsi))
return PTR_ERR(gsi);
@ -3847,6 +3861,8 @@ static void gsi_free_inst(struct usb_function_instance *f)
}
ipc_log_context_destroy(opts->gsi->ipc_log_ctxt);
if (opts && opts->interf_group)
kfree(opts->interf_group);
/* Clear instance status */
gsi_inst_clean(opts);
inst_status[prot_id].inst_exist = false;

View file

@ -21,6 +21,8 @@
#include <linux/ipc_logging.h>
#include <linux/timer.h>
#include "configfs.h"
#define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
#define GSI_MBIM_CTRL_NAME "android_mbim"
#define GSI_DPL_CTRL_NAME "dpl_ctrl"
@ -334,6 +336,11 @@ static inline struct f_gsi *c_port_to_gsi(struct gsi_ctrl_port *d)
struct gsi_opts {
struct usb_function_instance func_inst;
struct f_gsi *gsi;
/* os desc support */
struct config_group *interf_group;
char ext_compat_id[16];
struct usb_os_desc os_desc;
};
static inline struct gsi_opts *to_gsi_opts(struct config_item *item)
@ -1080,50 +1087,6 @@ static struct usb_gadget_strings *mbim_gsi_strings[] = {
NULL,
};
/* Microsoft OS Descriptors */
/*
* We specify our own bMS_VendorCode byte which Windows will use
* as the bRequest value in subsequent device get requests.
*/
#define MBIM_VENDOR_CODE 0xA5
/* Microsoft Extended Configuration Descriptor Header Section */
struct mbim_gsi_ext_config_desc_header {
__le32 dwLength;
__le16 bcdVersion;
__le16 wIndex;
__u8 bCount;
__u8 reserved[7];
};
/* Microsoft Extended Configuration Descriptor Function Section */
struct mbim_gsi_ext_config_desc_function {
__u8 bFirstInterfaceNumber;
__u8 bInterfaceCount;
__u8 compatibleID[8];
__u8 subCompatibleID[8];
__u8 reserved[6];
};
/* Microsoft Extended Configuration Descriptor */
static struct {
struct mbim_gsi_ext_config_desc_header header;
struct mbim_gsi_ext_config_desc_function function;
} mbim_gsi_ext_config_desc = {
.header = {
.dwLength = cpu_to_le32(sizeof(mbim_gsi_ext_config_desc)),
.bcdVersion = cpu_to_le16(0x0100),
.wIndex = cpu_to_le16(4),
.bCount = 1,
},
.function = {
.bFirstInterfaceNumber = 0,
.bInterfaceCount = 1,
.compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
/* .subCompatibleID = DYNAMIC */
},
};
/* ecm device descriptors */
#define ECM_QC_LOG2_STATUS_INTERVAL_MSEC 5
#define ECM_QC_STATUS_BYTECOUNT 16 /* 8 byte header + data */