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

Commit de9008b9 authored by Aniket Randive's avatar Aniket Randive
Browse files

USB: gadget: support for dynamic read of usb composition



This change is used to pick one of the pid from
command line parameter and boot the gadget as
per the usb composition.

Change-Id: Ia49b8fd8431675a9fcbf7e7818650d9226fe8685
Signed-off-by: default avatarAniket Randive <arandive@codeaurora.org>
parent 834619a5
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -2,21 +2,32 @@ Qualcomm Technologies, Inc's USB Gadget

Required properties:
- compatible: Should be "qcom,usb-gadget".
- qcom,vid: VendorId to be used by composite device.

Required subnode properties:
- qcom,pid: ProductId to be used by composite device.
- qcom,composition: List of configurations where each is separated by '|'.
	And each configuration has comma separated list of functions
	specified as: <f1_name>.<f1_instance_name>,<f2_name>....
- qcom,vid: VendorId to be used by composite device.
- qcom,pid: ProductId to be used by composite device.

Optional properties:
- qcom,default-pid: ProductId to be used by composite device.
- qcom,class: Class of composite device.
- qcom,subclass: SubClass of composite device.
- qcom,protocol: Protocol of composite device.

Examples:
Example:
	usb_gadget {
		compatible = "qcom,usb-gadget";
		qcom,composition = "rndis.rndis|ecm.ecm";
		qcom,vid = <0x05c6>;
		qcom,pid = <0x9057>;

		composition1 {
			qcom,pid = <0x9103>;
			qcom,composition = "diag.diag,ipc.ipc,gsi.rmnet,gsi.rmnet.v2x,ecm.ecm,gsi.dpl";
		};

		composition2 {
			qcom,pid = <0x9105>;
			qcom,composition = "diag.diag,gsi.dpl";
		};
	};
+45 −21
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <linux/property.h>
#include <linux/usb/composite.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/kernel.h>

struct qti_usb_function {
	struct usb_function_instance *fi;
@@ -59,6 +61,10 @@ module_param_string(serialno, serialno_string,
		    sizeof(serialno_string), 0644);
MODULE_PARM_DESC(quirks, "String representing name of manufacturer");

static char usb_pid_string[256];
module_param_string(usb_pid, usb_pid_string, sizeof(usb_pid_string), 0644);
MODULE_PARM_DESC(quirks, "String representing product id");

/* String Table */
static struct usb_string strings_dev[] = {
	[USB_GADGET_MANUFACTURER_IDX].s = manufacturer_string,
@@ -468,20 +474,8 @@ static void qti_gadget_unregister(struct qti_usb_gadget *qg)
static int qti_gadget_get_properties(struct qti_usb_gadget *gadget)
{
	struct device *dev = gadget->dev;
	int ret, val;

	ret = device_property_read_string(dev, "qcom,composition",
				    &gadget->composition_funcs);
	if (ret) {
		dev_err(dev, "USB gadget composition not specified\n");
		return ret;
	}

	/* bail out if ffs is specified and let userspace handle it */
	if (strstr(gadget->composition_funcs, "ffs.")) {
		dev_err(dev, "user should enable ffs\n");
		return -EINVAL;
	}
	struct device_node *child = NULL;
	int ret = 0, val = 0, pid = 0;

	ret = device_property_read_u32(dev, "qcom,vid", &val);
	if (ret) {
@@ -490,13 +484,6 @@ static int qti_gadget_get_properties(struct qti_usb_gadget *gadget)
	}
	gadget->cdev.desc.idVendor = (u16)val;

	ret = device_property_read_u32(dev, "qcom,pid", &val);
	if (ret) {
		dev_err(dev, "USB gadget idProduct not specified\n");
		return ret;
	}
	gadget->cdev.desc.idProduct = (u16)val;

	ret = device_property_read_u32(dev, "qcom,class", &val);
	if (!ret)
		gadget->cdev.desc.bDeviceClass = (u8)val;
@@ -509,6 +496,43 @@ static int qti_gadget_get_properties(struct qti_usb_gadget *gadget)
	if (!ret)
		gadget->cdev.desc.bDeviceProtocol = (u8)val;

	/* Check if pid passed via cmdline which takes precedence */
	if (usb_pid_string != NULL) {
		ret = kstrtoint(usb_pid_string, 16, &val);
		if (ret)
			return ret;
	} else {
		ret = device_property_read_u32(dev, "qcom,default-pid", &val);
		if (ret) {
			dev_dbg(dev, "USB gadget default-pid not specified\n");
			return ret;
		}
	}

	pid = val;

	/* Go through all the child nodes and find matching pid */
	while ((child = of_get_next_child(dev->of_node, child)) != NULL) {
		of_property_read_u32(child, "qcom,pid", &val);
		if (val == pid) {
			of_property_read_string(child, "qcom,composition",
					&gadget->composition_funcs);
			break;
		}
	}

	/* Check if couldn't find a matching composition */
	if (gadget->composition_funcs == NULL)
		return -EINVAL;

	/* bail out if ffs is specified and let userspace handle it */
	if (strstr(gadget->composition_funcs, "ffs.")) {
		dev_err(dev, "user should enable ffs\n");
		return -EINVAL;
	}

	gadget->cdev.desc.idProduct = (u16)pid;

	return 0;
}