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

Commit 34457785 authored by Hemant Kumar's avatar Hemant Kumar Committed by Mayank Rana
Browse files

usb: gadget: Add support for MBIM OS descriptor handling



In order to support MBIM in a multi-config usb composition
make use of composite gadget driver support for OS descriptor.
This allows Host to identify preferred configuration to choose.
Pass signature field, vendor code, compatibleID and
subCompatibleID from user space. Also remove redundant MBIM OS
descriptor related data structure definition in the driver.

Change-Id: I6fd8b950d53ef700be2d435e5973dd2c74525cd8
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent b8cd1590
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -2954,6 +2954,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;
	struct net_device *net;
	char *name = NULL;
	int status;
@@ -3162,18 +3163,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 USB_PROT_RMNET_IPA:
@@ -3363,6 +3361,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)

dereg_rndis:
	rndis_deregister(gsi->params);
	kfree(f->os_desc_table);
fail:
	return status;
}
@@ -3394,8 +3393,11 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
		rndis_deregister(gsi->params);
	}

	if (gsi->prot_id == USB_PROT_MBIM_IPA)
		mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0;
	if (gsi->prot_id == USB_PROT_MBIM_IPA) {
		kfree(f->os_desc_table);
		f->os_desc_table = NULL;
		f->os_desc_n = 0;
	}

	usb_free_all_descriptors(f);

@@ -3709,6 +3711,8 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
	int name_len, prot_id, ret = 0;
	struct gsi_opts *opts;
	struct f_gsi *gsi;
	struct usb_os_desc *descs[1];
	char *names[1];

	opts = container_of(fi, struct gsi_opts, func_inst);

@@ -3728,6 +3732,16 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
						fi->group.cg_item.ci_name,
						&gsi_func_rndis_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 = opts->gsi = __gsi[prot_id];
	opts->gsi->prot_id = prot_id;
	ret = gsi_function_ctrl_port_init(opts->gsi);
@@ -3764,6 +3778,8 @@ static void gsi_free_inst(struct usb_function_instance *f)
		ida_simple_remove(&gsi_ida, minor);
	}

	if (opts && opts->interf_group)
		kfree(opts->interf_group);
	kfree(opts);
}

+7 −44
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@

#include "u_ether.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"
@@ -312,6 +314,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)
@@ -1063,50 +1070,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;
	__u16	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 */