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

Commit 1b1d3969 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: Select RNDIS over ethernet as default class"

parents bd31130c b3ab2100
Loading
Loading
Loading
Loading
+124 −0
Original line number Original line Diff line number Diff line
@@ -2507,6 +2507,10 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
	struct f_gsi *gsi = func_to_gsi(f);
	struct f_gsi *gsi = func_to_gsi(f);
	struct rndis_params *params;
	struct rndis_params *params;
	int status;
	int status;
	__u8  class;
	__u8  subclass;
	__u8  proto;



	if (gsi->prot_id == IPA_USB_RMNET ||
	if (gsi->prot_id == IPA_USB_RMNET ||
		gsi->prot_id == IPA_USB_DIAG)
		gsi->prot_id == IPA_USB_DIAG)
@@ -2588,6 +2592,85 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
					DEFAULT_PKT_ALIGNMENT_FACTOR);
					DEFAULT_PKT_ALIGNMENT_FACTOR);
		rndis_set_pkt_alignment_factor(gsi->params,
		rndis_set_pkt_alignment_factor(gsi->params,
					DEFAULT_PKT_ALIGNMENT_FACTOR);
					DEFAULT_PKT_ALIGNMENT_FACTOR);

		/* Windows7/Windows10 automatically loads RNDIS drivers for
		 * class drivers which represents MISC_ACTIVE_SYNC,
		 * MISC_RNDIS_OVER_ETHERNET & WIRELESS_CONTROLLER_REMOTE_NDIS.
		 * All the codes listed below are from
		 * http://www.usb.org/developers/defined_class and its unknown
		 * why windows loads rndis class driver for some of them.
		 * Note that, Windows loads NDIS6 stack automatically for
		 * MISC_RNDIS_OVER_ETHERNET. Windows loads NDIS5 stack for
		 * MISC_ACTIVE_SYNC and WIRELESS_CONTROLLER_REMOTE_NDIS.
		 * For other class codes, NDIS stack can be selected using
		 * customized INF file but that defeats the purpose as its
		 * expected to load drivers automatically for known class
		 * drivers published by usbif.
		 * Linux rndis host driver supports MISC_ACTIVE_SYNC and
		 * WIRELESS_CONTROLLER_REMOTE_NDIS as of now.
		 * Default to rndis over ethernet which loads NDIS6 drivers
		 * for windows7/windows10 to avoid data stall issues
		 */
		if (gsi->rndis_id == RNDIS_ID_UNKNOWN)
			gsi->rndis_id = MISC_RNDIS_OVER_ETHERNET;

		switch (gsi->rndis_id) {
		default:
			/* fall throug */
		case WIRELESS_CONTROLLER_REMOTE_NDIS:
			class = USB_CLASS_WIRELESS_CONTROLLER;
			subclass = 0x01;
			proto = 0x03;
			break;
		case MISC_ACTIVE_SYNC:
			class = USB_CLASS_MISC;
			subclass = 0x01;
			proto = 0x01;
			break;
		case MISC_RNDIS_OVER_ETHERNET:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x01;
			break;
		case MISC_RNDIS_OVER_WIFI:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x02;
			break;
		case MISC_RNDIS_OVER_WIMAX:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x03;
			break;
		case MISC_RNDIS_OVER_WWAN:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x04;
			break;
		case MISC_RNDIS_FOR_IPV4:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x05;
			break;
		case MISC_RNDIS_FOR_IPV6:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x06;
			break;
		case MISC_RNDIS_FOR_GPRS:
			class = USB_CLASS_MISC;
			subclass = 0x04;
			proto = 0x07;
			break;
		}

		info.iad_desc->bFunctionClass = class;
		info.iad_desc->bFunctionSubClass = subclass;
		info.iad_desc->bFunctionProtocol = proto;
		info.ctrl_desc->bInterfaceClass = class;
		info.ctrl_desc->bInterfaceSubClass = subclass;
		info.ctrl_desc->bInterfaceProtocol = proto;

		break;
		break;
	case IPA_USB_MBIM:
	case IPA_USB_MBIM:
		info.string_defs = mbim_gsi_string_defs;
		info.string_defs = mbim_gsi_string_defs;
@@ -3086,6 +3169,43 @@ static struct config_item_type gsi_func_type = {
	.ct_owner	= THIS_MODULE,
	.ct_owner	= THIS_MODULE,
};
};


static ssize_t gsi_rndis_class_id_show(struct config_item *item, char *page)
{
	struct f_gsi *gsi = to_gsi_opts(item)->gsi;

	return snprintf(page, PAGE_SIZE, "%d\n", gsi->rndis_id);
}

static ssize_t gsi_rndis_class_id_store(struct config_item *item,
			const char *page, size_t len)
{
	struct f_gsi *gsi = to_gsi_opts(item)->gsi;
	u8 id;

	if (kstrtou8(page, 0, &id))
		return -EINVAL;

	if (id > RNDIS_ID_UNKNOWN && id < RNDIS_ID_MAX)
		gsi->rndis_id = id;
	else
		return -EINVAL;

	return len;
}
CONFIGFS_ATTR(gsi_, rndis_class_id);

static struct configfs_attribute *gsi_rndis_attrs[] = {
	&gsi_attr_info,
	&gsi_attr_rndis_class_id,
	NULL,
};

static struct config_item_type gsi_func_rndis_type = {
	.ct_item_ops	= &gsi_item_ops,
	.ct_attrs	= gsi_rndis_attrs,
	.ct_owner	= THIS_MODULE,
};

static void gsi_inst_clean(struct gsi_opts *opts)
static void gsi_inst_clean(struct gsi_opts *opts)
{
{
	if (opts->gsi->c_port.ctrl_device.fops)
	if (opts->gsi->c_port.ctrl_device.fops)
@@ -3127,6 +3247,10 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
	}
	}
	mutex_unlock(&inst_status[prot_id].gsi_lock);
	mutex_unlock(&inst_status[prot_id].gsi_lock);


	if (prot_id == IPA_USB_RNDIS)
		config_group_init_type_name(&opts->func_inst.group, "",
					    &gsi_func_rndis_type);

	gsi = gsi_function_init(prot_id);
	gsi = gsi_function_init(prot_id);
	if (IS_ERR(gsi))
	if (IS_ERR(gsi))
		return PTR_ERR(gsi);
		return PTR_ERR(gsi);
+15 −0
Original line number Original line Diff line number Diff line
@@ -122,6 +122,20 @@ enum gsi_ctrl_notify_state {
	GSI_CTRL_NOTIFY_RESPONSE_AVAILABLE,
	GSI_CTRL_NOTIFY_RESPONSE_AVAILABLE,
};
};


enum rndis_class_id {
	RNDIS_ID_UNKNOWN,
	WIRELESS_CONTROLLER_REMOTE_NDIS,
	MISC_ACTIVE_SYNC,
	MISC_RNDIS_OVER_ETHERNET,
	MISC_RNDIS_OVER_WIFI,
	MISC_RNDIS_OVER_WIMAX,
	MISC_RNDIS_OVER_WWAN,
	MISC_RNDIS_FOR_IPV4,
	MISC_RNDIS_FOR_IPV6,
	MISC_RNDIS_FOR_GPRS,
	RNDIS_ID_MAX,
};

#define MAXQUEUELEN 128
#define MAXQUEUELEN 128
struct event_queue {
struct event_queue {
	u8 event[MAXQUEUELEN];
	u8 event[MAXQUEUELEN];
@@ -258,6 +272,7 @@ struct f_gsi {
	struct rndis_params *params;
	struct rndis_params *params;
	atomic_t connected;
	atomic_t connected;
	bool data_interface_up;
	bool data_interface_up;
	enum rndis_class_id rndis_id;


	const struct usb_endpoint_descriptor *in_ep_desc_backup;
	const struct usb_endpoint_descriptor *in_ep_desc_backup;
	const struct usb_endpoint_descriptor *out_ep_desc_backup;
	const struct usb_endpoint_descriptor *out_ep_desc_backup;