usb: gadget: Add network gadget driver for dun and rmnet
This gadget driver works as independent data and control pass
through between modem device connected over USB or HSIC
and host/laptop.This driver communicates with modem device
using network bridge host driver.
Change-Id: Iaffdeaa6b5dbd601b73cba721a8f062d69912908
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Jack Pham <jackp@codeaurora.org>
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 7cd0288..de8c8ed 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -76,6 +76,7 @@
static unsigned int no_tty_ports;
static unsigned int no_sdio_ports;
static unsigned int no_smd_ports;
+static unsigned int no_hsic_sports;
static unsigned int nr_ports;
static struct port_info {
@@ -254,9 +255,13 @@
static int gport_setup(struct usb_configuration *c)
{
int ret = 0;
+ int port_idx;
+ int i;
- pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
- __func__, no_tty_ports, no_sdio_ports, nr_ports);
+ pr_debug("%s: no_tty_ports: %u no_sdio_ports: %u"
+ " no_smd_ports: %u no_hsic_sports: %u nr_ports: %u\n",
+ __func__, no_tty_ports, no_sdio_ports, no_smd_ports,
+ no_hsic_sports, nr_ports);
if (no_tty_ports)
ret = gserial_setup(c->cdev->gadget, no_tty_ports);
@@ -264,15 +269,34 @@
ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
if (no_smd_ports)
ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
+ if (no_hsic_sports) {
+ port_idx = ghsic_data_setup(no_hsic_sports, USB_GADGET_SERIAL);
+ if (port_idx < 0)
+ return port_idx;
+ for (i = 0; i < nr_ports; i++) {
+ if (gserial_ports[i].transport ==
+ USB_GADGET_XPORT_HSIC) {
+ gserial_ports[i].client_port_num = port_idx;
+ port_idx++;
+ }
+ }
+
+ /*clinet port num is same for data setup and ctrl setup*/
+ ret = ghsic_ctrl_setup(no_hsic_sports, USB_GADGET_SERIAL);
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
return ret;
}
static int gport_connect(struct f_gser *gser)
{
- unsigned port_num;
+ unsigned port_num;
+ int ret;
- pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
+ pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n",
__func__, xport_to_str(gser->transport),
gser, &gser->port, gser->port_num);
@@ -288,6 +312,21 @@
case USB_GADGET_XPORT_SMD:
gsmd_connect(&gser->port, port_num);
break;
+ case USB_GADGET_XPORT_HSIC:
+ ret = ghsic_ctrl_connect(&gser->port, port_num);
+ if (ret) {
+ pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ ret = ghsic_data_connect(&gser->port, port_num);
+ if (ret) {
+ pr_err("%s: ghsic_data_connect failed: err:%d\n",
+ __func__, ret);
+ ghsic_ctrl_disconnect(&gser->port, port_num);
+ return ret;
+ }
+ break;
default:
pr_err("%s: Un-supported transport: %s\n", __func__,
xport_to_str(gser->transport));
@@ -301,7 +340,7 @@
{
unsigned port_num;
- pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
+ pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n",
__func__, xport_to_str(gser->transport),
gser, &gser->port, gser->port_num);
@@ -317,6 +356,10 @@
case USB_GADGET_XPORT_SMD:
gsmd_disconnect(&gser->port, port_num);
break;
+ case USB_GADGET_XPORT_HSIC:
+ ghsic_ctrl_disconnect(&gser->port, port_num);
+ ghsic_data_disconnect(&gser->port, port_num);
+ break;
default:
pr_err("%s: Un-supported transport:%s\n", __func__,
xport_to_str(gser->transport));
@@ -865,7 +908,7 @@
transport = str_to_xport(name);
pr_debug("%s, port:%d, transport:%s\n", __func__,
- port_num, xport_to_str(transport));
+ port_num, xport_to_str(transport));
gserial_ports[port_num].transport = transport;
gserial_ports[port_num].port_num = port_num;
@@ -883,6 +926,10 @@
gserial_ports[port_num].client_port_num = no_smd_ports;
no_smd_ports++;
break;
+ case USB_GADGET_XPORT_HSIC:
+ /*client port number will be updated in gport_setup*/
+ no_hsic_sports++;
+ break;
default:
pr_err("%s: Un-supported transport transport: %u\n",
__func__, gserial_ports[port_num].transport);