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

Commit 8db32dc1 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 5d0a293d 34457785
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 */