usb: gadget: Implement ECM over IPA
Add bam transport parameter for u_bam_data interface to
support two types of data transfer - over bam2bam and over ipa.
Add required calls for ecm_ipa driver which will handle the
transfer of data over IPA.
Change-Id: I3fd73b159676f5475c527bf52208533e65dddb1d
Signed-off-by: Anna Perel <aperel@codeaurora.org>
Signed-off-by: Amit Blay <ablay@codeaurora.org>
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 8e25780..9dd9c40 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -76,10 +76,10 @@
#define USB_ETH_RNDIS y
#include "f_rndis.c"
#include "rndis.c"
+#include "f_qc_ecm.c"
#include "u_bam_data.c"
#include "f_mbim.c"
#include "f_ecm.c"
-#include "f_qc_ecm.c"
#include "f_qc_rndis.c"
#include "u_ether.c"
#include "u_qc_ether.c"
@@ -655,6 +655,9 @@
.attributes = rmnet_function_attributes,
};
+/* ecm transport string */
+static char ecm_transports[MAX_XPORT_STR_LEN];
+
struct ecm_function_config {
u8 ethaddr[ETH_ALEN];
};
@@ -678,6 +681,7 @@
struct usb_configuration *c)
{
int ret;
+ char *trans;
struct ecm_function_config *ecm = f->config;
if (!ecm) {
@@ -689,19 +693,28 @@
ecm->ethaddr[0], ecm->ethaddr[1], ecm->ethaddr[2],
ecm->ethaddr[3], ecm->ethaddr[4], ecm->ethaddr[5]);
- ret = gether_qc_setup_name(c->cdev->gadget, ecm->ethaddr, "ecm");
- if (ret) {
- pr_err("%s: gether_setup failed\n", __func__);
- return ret;
+ pr_debug("%s: ecm_transport is %s", __func__, ecm_transports);
+
+ trans = strim(ecm_transports);
+ if (strcmp("BAM2BAM_IPA", trans)) {
+ ret = gether_qc_setup_name(c->cdev->gadget,
+ ecm->ethaddr, "ecm");
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
}
- return ecm_qc_bind_config(c, ecm->ethaddr);
+ return ecm_qc_bind_config(c, ecm->ethaddr, trans);
}
static void ecm_qc_function_unbind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
- gether_qc_cleanup_name("ecm0");
+ char *trans = strim(ecm_transports);
+
+ if (strcmp("BAM2BAM_IPA", trans))
+ gether_qc_cleanup_name("ecm0");
}
static ssize_t ecm_ethaddr_show(struct device *dev,
@@ -731,7 +744,24 @@
static DEVICE_ATTR(ecm_ethaddr, S_IRUGO | S_IWUSR, ecm_ethaddr_show,
ecm_ethaddr_store);
+static ssize_t ecm_transports_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ecm_transports);
+}
+
+static ssize_t ecm_transports_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ strlcpy(ecm_transports, buf, sizeof(ecm_transports));
+ return size;
+}
+
+static DEVICE_ATTR(ecm_transports, S_IRUGO | S_IWUSR, ecm_transports_show,
+ ecm_transports_store);
+
static struct device_attribute *ecm_function_attributes[] = {
+ &dev_attr_ecm_transports,
&dev_attr_ecm_ethaddr,
NULL
};
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index ff0bdaf..a32dd15 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -665,7 +665,8 @@
pr_info("dev:%p portno:%d\n", dev, dev->port_num);
- ret = bam_data_connect(&dev->bam_port, dev->port_num, dev->port_num);
+ ret = bam_data_connect(&dev->bam_port, dev->port_num,
+ USB_GADGET_XPORT_BAM2BAM, dev->port_num, USB_FUNC_MBIM);
if (ret) {
pr_err("bam_data_setup failed: err:%d\n",
ret);
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 88d19f5..559fd04 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2003-2005,2008 David Brownell
* Copyright (C) 2008 Nokia Corporation
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,11 @@
/* #define VERBOSE_DEBUG */
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -29,6 +34,9 @@
#include "u_ether.h"
#include "u_qc_ether.h"
+#include "u_bam_data.h"
+#include <mach/ecm_ipa.h>
+
/*
* This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
@@ -58,9 +66,9 @@
};
struct f_ecm_qc {
- struct qc_gether port;
+ struct qc_gether port;
u8 ctrl_id, data_id;
-
+ enum transport_type xport;
char ethaddr[14];
struct usb_ep *notify;
@@ -69,6 +77,16 @@
bool is_open;
};
+struct f_ecm_qc_ipa_params {
+ u8 dev_mac[ETH_ALEN];
+ u8 host_mac[ETH_ALEN];
+ ecm_ipa_callback ipa_rx_cb;
+ ecm_ipa_callback ipa_tx_cb;
+ void *ipa_priv;
+};
+
+static struct f_ecm_qc_ipa_params ipa_params;
+
static inline struct f_ecm_qc *func_to_ecm_qc(struct usb_function *f)
{
return container_of(f, struct f_ecm_qc, port.func);
@@ -288,51 +306,6 @@
static struct data_port ecm_qc_bam_port;
-static int ecm_qc_bam_setup(void)
-{
- int ret;
-
- ret = bam_data_setup(ECM_QC_NO_PORTS);
- if (ret) {
- pr_err("bam_data_setup failed err: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
-{
- int ret;
-
- ecm_qc_bam_port.cdev = dev->port.func.config->cdev;
- ecm_qc_bam_port.in = dev->port.in_ep;
- ecm_qc_bam_port.out = dev->port.out_ep;
-
- /* currently we use the first connection */
- ret = bam_data_connect(&ecm_qc_bam_port, 0, 0);
- if (ret) {
- pr_err("bam_data_connect failed: err:%d\n",
- ret);
- return ret;
- } else {
- pr_info("ecm bam connected\n");
- }
-
- return 0;
-}
-
-static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
-{
- pr_debug("dev:%p. %s Disconnect BAM.\n", dev, __func__);
-
- bam_data_disconnect(&ecm_qc_bam_port, 0);
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
static void ecm_qc_do_notify(struct f_ecm_qc *ecm)
{
struct usb_request *req = ecm->notify_req;
@@ -401,6 +374,73 @@
ecm_qc_do_notify(ecm);
}
+static int ecm_qc_bam_setup(void)
+{
+ int ret;
+
+ ret = bam_data_setup(ECM_QC_NO_PORTS);
+ if (ret) {
+ pr_err("bam_data_setup failed err: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
+{
+ int ret;
+
+ ecm_qc_bam_port.cdev = dev->port.func.config->cdev;
+ ecm_qc_bam_port.in = dev->port.in_ep;
+ ecm_qc_bam_port.out = dev->port.out_ep;
+
+ /* currently we use the first connection */
+ ret = bam_data_connect(&ecm_qc_bam_port, 0, dev->xport,
+ 0, USB_FUNC_ECM);
+ if (ret) {
+ pr_err("bam_data_connect failed: err:%d\n", ret);
+ return ret;
+ } else {
+ pr_debug("ecm bam connected\n");
+ }
+
+ dev->is_open = true;
+ ecm_qc_notify(dev);
+
+ return 0;
+}
+
+static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
+{
+ pr_debug("dev:%p. Disconnect BAM.\n", dev);
+
+ bam_data_disconnect(&ecm_qc_bam_port, 0);
+
+ ecm_ipa_cleanup(ipa_params.ipa_priv);
+
+ return 0;
+}
+
+void *ecm_qc_get_ipa_rx_cb(void)
+{
+ return ipa_params.ipa_rx_cb;
+}
+
+void *ecm_qc_get_ipa_tx_cb(void)
+{
+ return ipa_params.ipa_tx_cb;
+}
+
+void *ecm_qc_get_ipa_priv(void)
+{
+ return ipa_params.ipa_priv;
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
static void ecm_qc_notify_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_ecm_qc *ecm = req->context;
@@ -524,7 +564,8 @@
* we can disconnect the port from the network layer.
*/
ecm_qc_bam_disconnect(ecm);
- gether_qc_disconnect_name(&ecm->port, "ecm0");
+ if (ecm->xport != USB_GADGET_XPORT_BAM2BAM_IPA)
+ gether_qc_disconnect_name(&ecm->port, "ecm0");
}
if (!ecm->port.in_ep->desc ||
@@ -553,9 +594,12 @@
);
ecm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ecm\n");
- net = gether_qc_connect_name(&ecm->port, "ecm0");
- if (IS_ERR(net))
- return PTR_ERR(net);
+ if (ecm->xport != USB_GADGET_XPORT_BAM2BAM_IPA) {
+ net = gether_qc_connect_name(&ecm->port,
+ "ecm0");
+ if (IS_ERR(net))
+ return PTR_ERR(net);
+ }
if (ecm_qc_bam_connect(ecm))
goto fail;
@@ -597,7 +641,8 @@
if (ecm->port.in_ep->driver_data) {
ecm_qc_bam_disconnect(ecm);
- gether_qc_disconnect_name(&ecm->port, "ecm0");
+ if (ecm->xport != USB_GADGET_XPORT_BAM2BAM_IPA)
+ gether_qc_disconnect_name(&ecm->port, "ecm0");
}
if (ecm->notify->driver_data) {
@@ -662,6 +707,7 @@
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
+
ecm->ctrl_id = status;
ecm_qc_control_intf.bInterfaceNumber = status;
@@ -670,6 +716,7 @@
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
+
ecm->data_id = status;
ecm_qc_data_nop_intf.bInterfaceNumber = status;
@@ -797,6 +844,7 @@
* @c: the configuration to support the network link
* @ethaddr: a buffer in which the ethernet address of the host side
* side of the link was recorded
+ * @xport_name: data path transport type name ("BAM2BAM" or "BAM2BAM_IPA")
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
@@ -805,7 +853,8 @@
* for calling @gether_cleanup() before module unload.
*/
int
-ecm_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+ecm_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ char *xport_name)
{
struct f_ecm_qc *ecm;
int status;
@@ -819,6 +868,8 @@
return status;
}
+ pr_debug("data transport type is %s", xport_name);
+
/* maybe allocate device-global string IDs */
if (ecm_qc_string_defs[0].id == 0) {
@@ -849,11 +900,23 @@
if (!ecm)
return -ENOMEM;
+ ecm->xport = str_to_xport(xport_name);
+ pr_debug("set xport = %d", ecm->xport);
+
/* export host's Ethernet address in CDC format */
- snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
+ if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ gether_qc_get_macs(ipa_params.dev_mac, ipa_params.host_mac);
+ snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
+ "%02X%02X%02X%02X%02X%02X",
+ ipa_params.host_mac[0], ipa_params.host_mac[1],
+ ipa_params.host_mac[2], ipa_params.host_mac[3],
+ ipa_params.host_mac[4], ipa_params.host_mac[5]);
+ } else
+ snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
"%02X%02X%02X%02X%02X%02X",
ethaddr[0], ethaddr[1], ethaddr[2],
ethaddr[3], ethaddr[4], ethaddr[5]);
+
ecm_qc_string_defs[1].s = ecm->ethaddr;
ecm->port.cdc_filter = DEFAULT_FILTER;
@@ -870,8 +933,31 @@
status = usb_add_function(c, &ecm->port.func);
if (status) {
+ pr_err("failed to add function");
+ ecm_qc_string_defs[1].s = NULL;
+ kfree(ecm);
+ return status;
+ }
+
+ if (ecm->xport != USB_GADGET_XPORT_BAM2BAM_IPA)
+ return status;
+
+ status = ecm_ipa_init(&ipa_params.ipa_rx_cb, &ipa_params.ipa_tx_cb,
+ &ipa_params.ipa_priv);
+ if (status) {
+ pr_err("failed to initialize ECM IPA Driver");
+ ecm_qc_string_defs[1].s = NULL;
+ kfree(ecm);
+ return status;
+ }
+
+ status = ecm_ipa_configure(ipa_params.host_mac, ipa_params.dev_mac,
+ ipa_params.ipa_priv);
+ if (status) {
+ pr_err("failed to configure ECM IPA Driver");
ecm_qc_string_defs[1].s = NULL;
kfree(ecm);
}
+
return status;
}
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index 128b6d1..51d7bc1 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -6,7 +6,7 @@
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz (mina86@mina86.com)
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -427,7 +427,8 @@
dev->bam_port.out = dev->port.out_ep;
/* currently we use the first connection */
- ret = bam_data_connect(&dev->bam_port, 0, 0);
+ ret = bam_data_connect(&dev->bam_port, 0, USB_GADGET_XPORT_BAM2BAM,
+ 0, USB_FUNC_RNDIS);
if (ret) {
pr_err("bam_data_connect failed: err:%d\n",
ret);
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 70c71d4..8df06a4 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,9 +22,10 @@
#include <linux/usb/gadget.h>
#include <mach/bam_dmux.h>
-#include <mach/usb_gadget_xport.h>
#include <mach/usb_bam.h>
+#include "u_bam_data.h"
+
#define BAM2BAM_DATA_N_PORTS 1
static struct workqueue_struct *bam_data_wq;
@@ -34,12 +35,6 @@
#define SPS_PARAMS_TBE BIT(6)
#define MSM_VENDOR_ID BIT(16)
-struct data_port {
- struct usb_composite_dev *cdev;
- struct usb_ep *in;
- struct usb_ep *out;
-};
-
struct bam_data_ch_info {
unsigned long flags;
unsigned id;
@@ -53,6 +48,10 @@
u32 src_pipe_idx;
u32 dst_pipe_idx;
u8 connection_idx;
+
+ enum function_type func_type;
+ enum transport_type trans;
+ struct usb_bam_connect_ipa_params ipa_params;
};
struct bam_data_port {
@@ -175,6 +174,22 @@
return 0;
}
+static void bam2bam_data_disconnect_work(struct work_struct *w)
+{
+ struct bam_data_port *port =
+ container_of(w, struct bam_data_port, disconnect_w);
+ struct bam_data_ch_info *d = &port->data_ch;
+ int ret;
+
+ if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ if (d->func_type == USB_FUNC_ECM)
+ ecm_ipa_disconnect(d->ipa_params.priv);
+ ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
+ if (ret)
+ pr_err("usb_bam_disconnect_ipa failed: err:%d\n", ret);
+ }
+}
+
static void bam2bam_data_connect_work(struct work_struct *w)
{
struct bam_data_port *port = container_of(w, struct bam_data_port,
@@ -185,14 +200,49 @@
pr_debug("%s: Connect workqueue started", __func__);
- ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
- &d->dst_pipe_idx);
- d->src_pipe_idx = 11;
- d->dst_pipe_idx = 10;
+ if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ d->ipa_params.client = IPA_CLIENT_USB_CONS;
+ d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
+ if (d->func_type == USB_FUNC_ECM) {
+ d->ipa_params.notify = ecm_qc_get_ipa_tx_cb();
+ d->ipa_params.priv = ecm_qc_get_ipa_priv();
+ }
+ ret = usb_bam_connect_ipa(&d->ipa_params);
+ if (ret) {
+ pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
- if (ret) {
- pr_err("usb_bam_connect failed: err:%d\n", ret);
- return;
+ d->ipa_params.client = IPA_CLIENT_USB_PROD;
+ d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
+ if (d->func_type == USB_FUNC_ECM) {
+ d->ipa_params.notify = ecm_qc_get_ipa_rx_cb();
+ d->ipa_params.priv = ecm_qc_get_ipa_priv();
+ }
+ ret = usb_bam_connect_ipa(&d->ipa_params);
+ if (ret) {
+ pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
+ if (d->func_type == USB_FUNC_ECM) {
+ ret = ecm_ipa_connect(d->ipa_params.cons_clnt_hdl,
+ d->ipa_params.prod_clnt_hdl,
+ d->ipa_params.priv);
+ if (ret) {
+ pr_err("%s: failed to connect IPA: err:%d\n",
+ __func__, ret);
+ return;
+ }
+ }
+ } else { /* transport type is USB_GADGET_XPORT_BAM2BAM */
+ ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
+ &d->dst_pipe_idx);
+ if (ret) {
+ pr_err("usb_bam_connect failed: err:%d\n", ret);
+ return;
+ }
}
if (!port->port_usb) {
@@ -230,15 +280,17 @@
bam_data_start_endless_rx(port);
bam_data_start_endless_tx(port);
- /* Register for peer reset callback */
- usb_bam_register_peer_reset_cb(d->connection_idx,
+ /* Register for peer reset callback if USB_GADGET_XPORT_BAM2BAM */
+ if (d->trans != USB_GADGET_XPORT_BAM2BAM_IPA) {
+ usb_bam_register_peer_reset_cb(d->connection_idx,
bam_data_peer_reset_cb, port);
- ret = usb_bam_client_ready(true);
- if (ret) {
- pr_err("%s: usb_bam_client_ready failed: err:%d\n",
+ ret = usb_bam_client_ready(true);
+ if (ret) {
+ pr_err("%s: usb_bam_client_ready failed: err:%d\n",
__func__, ret);
- return;
+ return;
+ }
}
pr_debug("%s: Connect workqueue done", __func__);
@@ -262,6 +314,7 @@
port->port_num = portno;
INIT_WORK(&port->connect_w, bam2bam_data_connect_work);
+ INIT_WORK(&port->disconnect_w, bam2bam_data_disconnect_work);
/* data ch */
d = &port->data_ch;
@@ -276,6 +329,7 @@
void bam_data_disconnect(struct data_port *gr, u8 port_num)
{
struct bam_data_port *port;
+ struct bam_data_ch_info *d;
pr_debug("dev:%p port#%d\n", gr, port_num);
@@ -285,7 +339,7 @@
}
if (!gr) {
- pr_err("mbim data port is null\n");
+ pr_err("data port is null\n");
return;
}
@@ -303,12 +357,19 @@
port->port_usb = 0;
}
- if (usb_bam_client_ready(false))
- pr_err("%s: usb_bam_client_ready failed\n", __func__);
+ d = &port->data_ch;
+ if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+ queue_work(gbam_wq, &port->disconnect_w);
+ else {
+ if (usb_bam_client_ready(false)) {
+ pr_err("%s: usb_bam_client_ready failed\n",
+ __func__);
+ }
+ }
}
int bam_data_connect(struct data_port *gr, u8 port_num,
- u8 connection_idx)
+ enum transport_type trans, u8 connection_idx, enum function_type func)
{
struct bam_data_port *port;
struct bam_data_ch_info *d;
@@ -322,7 +383,7 @@
}
if (!gr) {
- pr_err("mbim data port is null\n");
+ pr_err("data port is null\n");
return -ENODEV;
}
@@ -349,6 +410,16 @@
d->connection_idx = connection_idx;
+ d->trans = trans;
+
+ if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ d->ipa_params.src_pipe = &(d->src_pipe_idx);
+ d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
+ d->ipa_params.idx = connection_idx;
+ }
+
+ d->func_type = func;
+
queue_work(bam_data_wq, &port->connect_w);
return 0;
diff --git a/drivers/usb/gadget/u_bam_data.h b/drivers/usb/gadget/u_bam_data.h
new file mode 100644
index 0000000..71a01b9
--- /dev/null
+++ b/drivers/usb/gadget/u_bam_data.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __U_BAM_DATA_H
+#define __U_BAM_DATA_H
+
+#include <mach/usb_gadget_xport.h>
+
+enum function_type {
+ USB_FUNC_ECM,
+ USB_FUNC_MBIM,
+ USB_FUNC_RNDIS,
+};
+
+struct data_port {
+ struct usb_composite_dev *cdev;
+ struct usb_ep *in;
+ struct usb_ep *out;
+};
+
+void bam_data_disconnect(struct data_port *gr, u8 port_num);
+
+int bam_data_connect(struct data_port *gr, u8 port_num,
+ enum transport_type trans, u8 connection_idx, enum function_type func);
+
+int bam_data_setup(unsigned int no_bam2bam_port);
+
+void bam_data_suspend(u8 port_num);
+
+void bam_data_resume(u8 port_num);
+
+#endif /* __U_BAM_DATA_H */
diff --git a/drivers/usb/gadget/u_qc_ether.c b/drivers/usb/gadget/u_qc_ether.c
index ce0a12e..e10ec25 100644
--- a/drivers/usb/gadget/u_qc_ether.c
+++ b/drivers/usb/gadget/u_qc_ether.c
@@ -4,7 +4,7 @@
* Copyright (C) 2003-2005,2008 David Brownell
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
* Copyright (C) 2008 Nokia Corporation
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -62,7 +62,7 @@
* or updating its backlink port_usb->ioport
*/
spinlock_t lock;
- struct qc_gether *port_usb;
+ struct qc_gether *port_usb;
struct net_device *net;
struct usb_gadget *gadget;
@@ -235,6 +235,14 @@
.name = "gadget",
};
+void gether_qc_get_macs(u8 dev_mac[ETH_ALEN], u8 host_mac[ETH_ALEN])
+{
+ if (get_qc_ether_addr(qc_dev_addr, dev_mac))
+ pr_debug("using random dev_mac ethernet address\n");
+ if (get_qc_ether_addr(qc_host_addr, host_mac))
+ pr_debug("using random host_mac ethernet address\n");
+}
+
/**
* gether_qc_setup - initialize one ethernet-over-usb link
* @g: gadget to associated with these links
@@ -320,6 +328,7 @@
/**
* gether_qc_cleanup_name - remove Ethernet-over-USB device
+ * @netname: name for network device (for example, "usb")
* Context: may sleep
*
* This is called to free all resources allocated by @gether_qc_setup().
@@ -343,6 +352,7 @@
* is active
* @link: the USB link, set up with endpoints, descriptors matching
* current device speed, and any framing wrapper(s) set up.
+ * @netname: name for network device (for example, "usb")
* Context: irqs blocked
*
* This is called to let the network layer know the connection
@@ -391,6 +401,7 @@
* gether_qc_disconnect_name - notify network layer that USB
* link is inactive
* @link: the USB link, on which gether_connect() was called
+ * @netname: name for network device (for example, "usb")
* Context: irqs blocked
*
* This is called to let the network layer know the connection
diff --git a/drivers/usb/gadget/u_qc_ether.h b/drivers/usb/gadget/u_qc_ether.h
index 29193e0..25562da 100644
--- a/drivers/usb/gadget/u_qc_ether.h
+++ b/drivers/usb/gadget/u_qc_ether.h
@@ -4,7 +4,7 @@
* Copyright (C) 2003-2005,2008 David Brownell
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
* Copyright (C) 2008 Nokia Corporation
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -49,7 +49,7 @@
struct usb_function func;
/* updated by gether_{connect,disconnect} */
- struct eth_qc_dev *ioport;
+ struct eth_qc_dev *ioport;
/* endpoints handle full and/or high speeds */
struct usb_ep *in_ep;
@@ -61,10 +61,7 @@
/* hooks for added framing, as needed for RNDIS and EEM. */
u32 header_len;
- /* NCM requires fixed size bundles */
- bool is_fixed;
- u32 fixed_out_len;
- u32 fixed_in_len;
+
struct sk_buff *(*wrap)(struct qc_gether *port,
struct sk_buff *skb);
int (*unwrap)(struct qc_gether *port,
@@ -89,10 +86,14 @@
void gether_qc_disconnect_name(struct qc_gether *link, const char *netname);
/* each configuration may bind one instance of an ethernet link */
-int ecm_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int ecm_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ char *xport_name);
int
rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer,
u8 maxPktPerXfer);
+
+void gether_qc_get_macs(u8 dev_mac[ETH_ALEN], u8 host_mac[ETH_ALEN]);
+
#endif /* __U_QC_ETHER_H */