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

Commit 823c7ed0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: f_gsi: Allow user to specify MAC address for RNDIS/ECM"

parents ce3f22ec c6585c88
Loading
Loading
Loading
Loading
+96 −8
Original line number Diff line number Diff line
@@ -2938,6 +2938,26 @@ static void ipa_ready_callback(void *user_data)
	wake_up_interruptible(&gsi->d_port.wait_for_ipa_ready);
}

static void gsi_get_ether_addr(const char *str, u8 *dev_addr)
{
	if (str) {
		unsigned int i;

		for (i = 0; i < ETH_ALEN; i++) {
			unsigned char num;

			if ((*str == '.') || (*str == ':'))
				str++;
			num = hex_to_bin(*str++) << 4;
			num |= hex_to_bin(*str++);
			dev_addr[i] = num;
		}
		if (is_valid_ether_addr(dev_addr))
			return;
	}
	random_ether_addr(dev_addr);
}

static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
@@ -3012,8 +3032,12 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		rndis_set_param_medium(gsi->params, RNDIS_MEDIUM_802_3, 0);

		/* export host's Ethernet address in CDC format */
		random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
		random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
		gsi_get_ether_addr(gsi->dev_addr,
				   gsi->d_port.ipa_init_params.device_ethaddr);

		gsi_get_ether_addr(gsi->host_addr,
				   gsi->d_port.ipa_init_params.host_ethaddr);

		log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
				gsi->d_port.ipa_init_params.host_ethaddr,
				gsi->d_port.ipa_init_params.device_ethaddr);
@@ -3217,8 +3241,12 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.notify_buf_len = GSI_CTRL_NOTIFY_BUFF_LEN;

		/* export host's Ethernet address in CDC format */
		random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
		random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
		gsi_get_ether_addr(gsi->dev_addr,
				   gsi->d_port.ipa_init_params.device_ethaddr);

		gsi_get_ether_addr(gsi->host_addr,
				   gsi->d_port.ipa_init_params.host_ethaddr);

		log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
				gsi->d_port.ipa_init_params.host_ethaddr,
				gsi->d_port.ipa_init_params.device_ethaddr);
@@ -3657,9 +3685,53 @@ static ssize_t gsi_rndis_class_id_store(struct config_item *item,
}
CONFIGFS_ATTR(gsi_, rndis_class_id);

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

	return scnprintf(page, PAGE_SIZE, "%s\n", gsi->host_addr);
}

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

	if (len > GSI_MAX_MAC_ADDR_LEN)
		return -EINVAL;

	strlcpy(gsi->host_addr, page, GSI_MAX_MAC_ADDR_LEN);

	return len;
}
CONFIGFS_ATTR(gsi_, host_addr);

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

	return scnprintf(page, PAGE_SIZE, "%s\n", gsi->dev_addr);
}

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

	if (len > GSI_MAX_MAC_ADDR_LEN)
		return -EINVAL;

	strlcpy(gsi->dev_addr, page, GSI_MAX_MAC_ADDR_LEN);

	return len;
}
CONFIGFS_ATTR(gsi_, dev_addr);

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

@@ -3669,6 +3741,18 @@ static struct config_item_type gsi_func_rndis_type = {
	.ct_owner	= THIS_MODULE,
};

static struct configfs_attribute *gsi_ecm_attrs[] = {
	&gsi_attr_host_addr,
	&gsi_attr_dev_addr,
	NULL,
};

static struct config_item_type gsi_func_ecm_type = {
	.ct_item_ops	= &gsi_item_ops,
	.ct_attrs	= gsi_ecm_attrs,
	.ct_owner	= THIS_MODULE,
};

static void gsi_inst_clean(struct gsi_opts *opts)
{
	if (opts->gsi->c_port.cdev.dev) {
@@ -3721,6 +3805,10 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
		config_group_init_type_name(&opts->func_inst.group,
						fi->group.cg_item.ci_name,
						&gsi_func_rndis_type);
	if (prot_id == IPA_USB_ECM)
		config_group_init_type_name(&opts->func_inst.group,
						fi->group.cg_item.ci_name,
						&gsi_func_ecm_type);

	gsi = gsi_function_init(prot_id);
	if (IS_ERR(gsi))
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#define GSI_CTRL_NAME_LEN (sizeof(GSI_MBIM_CTRL_NAME)+2)
#define GSI_MAX_CTRL_PKT_SIZE 8192
#define GSI_CTRL_DTR (1 << 0)
#define GSI_MAX_MAC_ADDR_LEN 18

#define GSI_NUM_IN_RNDIS_BUFFERS 50
#define GSI_NUM_IN_RMNET_BUFFERS 50
@@ -267,6 +268,8 @@ struct f_gsi {
	u32 vendorID;
	u8 ethaddr[ETH_ADDR_STR_LEN];
	const char *manufacturer;
	char host_addr[GSI_MAX_MAC_ADDR_LEN];
	char dev_addr[GSI_MAX_MAC_ADDR_LEN];
	struct rndis_params *params;
	atomic_t connected;
	bool data_interface_up;