summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSakethram Bommisetti <sakethram.bommisetti@stericsson.com>2011-09-06 19:16:35 +0530
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 16:07:23 +0200
commit66f9d0923890085da40fa908b8619e029fe824af (patch)
tree70ae36a7acdf283fc567131c00ed0af032f8776b
parent6b1cb7c41d42f2dd1089203951c19590f5e89fca (diff)
USB:Composite Driver Patch
Added code for ECM. Mass Storage supports 2 luns by default. ST-Ericsson ID: 259958 Signed-off-by: Sakethram Bommisetti <sakethram.bommisetti@stericsson.com>
-rw-r--r--drivers/usb/gadget/android.c147
1 files changed, 146 insertions, 1 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 8cb5aae5994..15977c311db 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -54,6 +54,7 @@
#define USB_ETH_RNDIS y
#include "f_rndis.c"
#include "rndis.c"
+#include "f_ecm.c"
#include "u_ether.c"
MODULE_AUTHOR("Mike Lockwood");
@@ -336,6 +337,148 @@ static struct android_usb_function ptp_function = {
.bind_config = ptp_function_bind_config,
};
+struct ecm_function_config {
+ u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ char manufacturer[256];;
+};
+static int ecm_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct ecm_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+ return 0;
+}
+
+static void ecm_function_cleanup(struct android_usb_function *f)
+{
+ kfree(f->config);
+ f->config = NULL;
+}
+
+static int ecm_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+{
+ int ret = 0;
+ struct ecm_function_config *ecm = f->config;
+
+ if (!ecm) {
+ pr_err("%s: ecm_pdata\n", __func__);
+ return -1;
+ }
+
+
+ pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
+ ecm->ethaddr[0], ecm->ethaddr[1], ecm->ethaddr[2],
+ ecm->ethaddr[3], ecm->ethaddr[4], ecm->ethaddr[5]);
+
+ ret = gether_setup(c->cdev->gadget, ecm->ethaddr);
+
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
+
+ return ecm_bind_config(c, ecm->ethaddr);
+}
+
+static void ecm_function_unbind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ gether_cleanup();
+}
+
+static ssize_t ecm_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *config = f->config;
+ return sprintf(buf, "%s\n", config->manufacturer);
+}
+
+static ssize_t ecm_manufacturer_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *config = f->config;
+
+ if (size >= sizeof(config->manufacturer))
+ return -EINVAL;
+ if (sscanf(buf, "%s", config->manufacturer) == 1)
+ return size;
+ return -1;
+}
+
+static DEVICE_ATTR(manufactur, S_IRUGO | S_IWUSR, ecm_manufacturer_show,
+ ecm_manufacturer_store);
+
+static ssize_t ecm_ethaddr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *ecm = f->config;
+ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ecm->ethaddr[0], ecm->ethaddr[1], ecm->ethaddr[2],
+ ecm->ethaddr[3], ecm->ethaddr[4], ecm->ethaddr[5]);
+}
+
+static ssize_t ecm_ethaddr_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *ecm = f->config;
+
+ if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (int *)&ecm->ethaddr[0], (int *)&ecm->ethaddr[1],
+ (int *)&ecm->ethaddr[2], (int *)&ecm->ethaddr[3],
+ (int *)&ecm->ethaddr[4], (int *)&ecm->ethaddr[5]) == 6)
+ return size;
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(ethadd, S_IRUGO | S_IWUSR, ecm_ethaddr_show,
+ ecm_ethaddr_store);
+
+static ssize_t ecm_vendorID_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *config = f->config;
+ return sprintf(buf, "%04x\n", config->vendorID);
+}
+
+static ssize_t ecm_vendorID_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct ecm_function_config *config = f->config;
+ int value;
+
+ if (sscanf(buf, "%04x", &value) == 1) {
+ config->vendorID = value;
+ return size;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(vendor, S_IRUGO | S_IWUSR, ecm_vendorID_show,
+ ecm_vendorID_store);
+
+static struct device_attribute *ecm_function_attributes[] = {
+ &dev_attr_ethadd,
+ &dev_attr_vendor,
+ &dev_attr_manufactur,
+ NULL
+};
+
+static struct android_usb_function ecm_function = {
+ .name = "ecm",
+ .init = ecm_function_init,
+ .cleanup = ecm_function_cleanup,
+ .bind_config = ecm_function_bind_config,
+ .unbind_config = ecm_function_unbind_config,
+ .attributes = ecm_function_attributes,
+};
+
struct rndis_function_config {
u8 ethaddr[ETH_ALEN];
@@ -537,8 +680,9 @@ static int mass_storage_function_init(struct android_usb_function *f,
if (!config)
return -ENOMEM;
- config->fsg.nluns = 1;
+ config->fsg.nluns = 2;
config->fsg.luns[0].removable = 1;
+ config->fsg.luns[1].removable = 1;
common = fsg_common_init(NULL, cdev, &config->fsg);
if (IS_ERR(common)) {
@@ -651,6 +795,7 @@ static struct android_usb_function *supported_functions[] = {
&rndis_function,
&mass_storage_function,
&accessory_function,
+ &ecm_function,
NULL
};