usb: gadget: support hsic in f_acm
Change-Id: Iae949165668b18879085788da425e80bc40bb7a6
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 7f9b130..9c716d4 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -81,6 +81,7 @@
static unsigned int no_acm_sdio_ports;
static unsigned int no_acm_smd_ports;
static unsigned int nr_acm_ports;
+static unsigned int no_acm_hsic_sports;
static struct acm_port_info {
enum transport_type transport;
@@ -101,6 +102,8 @@
static int acm_port_setup(struct usb_configuration *c)
{
int ret = 0;
+ int port_idx=0;
+ int i=0;
pr_debug("%s: no_acm_tty_ports:%u no_acm_sdio_ports: %u nr_acm_ports:%u\n",
__func__, no_acm_tty_ports, no_acm_sdio_ports,
@@ -112,13 +115,33 @@
ret = gsdio_setup(c->cdev->gadget, no_acm_sdio_ports);
if (no_acm_smd_ports)
ret = gsmd_setup(c->cdev->gadget, no_acm_smd_ports);
+ if (no_acm_hsic_sports) {
+ port_idx = ghsic_data_setup(no_acm_hsic_sports,
+ USB_GADGET_SERIAL);
+ if (port_idx < 0)
+ return port_idx;
+ for (i = 0; i < nr_acm_ports; i++) {
+ if (gacm_ports[i].transport ==
+ USB_GADGET_XPORT_HSIC) {
+ gacm_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_acm_hsic_sports, USB_GADGET_SERIAL);
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
return ret;
}
static int acm_port_connect(struct f_acm *acm)
{
unsigned port_num;
+ int ret=0;
port_num = gacm_ports[acm->port_num].client_port_num;
@@ -137,6 +160,21 @@
case USB_GADGET_XPORT_SMD:
gsmd_connect(&acm->port, port_num);
break;
+ case USB_GADGET_XPORT_HSIC:
+ ret = ghsic_ctrl_connect(&acm->port, port_num);
+ if (ret) {
+ pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ ret = ghsic_data_connect(&acm->port, port_num);
+ if (ret) {
+ pr_err("%s: ghsic_data_connect failed: err:%d\n",
+ __func__, ret);
+ ghsic_ctrl_disconnect(&acm->port, port_num);
+ return ret;
+ }
+ break;
default:
pr_err("%s: Un-supported transport: %s\n", __func__,
xport_to_str(acm->transport));
@@ -166,6 +204,10 @@
case USB_GADGET_XPORT_SMD:
gsmd_disconnect(&acm->port, port_num);
break;
+ case USB_GADGET_XPORT_HSIC:
+ ghsic_ctrl_disconnect(&acm->port, port_num);
+ ghsic_data_disconnect(&acm->port, port_num);
+ break;
default:
pr_err("%s: Un-supported transport:%s\n", __func__,
xport_to_str(acm->transport));
@@ -595,15 +637,17 @@
struct usb_ep *ep = acm->notify;
struct usb_request *req;
struct usb_cdc_notification *notify;
- const unsigned len = sizeof(*notify) + length;
void *buf;
int status;
+ unsigned char noti_buf[GS_NOTIFY_MAXPACKET];
+
+ memset(noti_buf, 0, GS_NOTIFY_MAXPACKET);
req = acm->notify_req;
acm->notify_req = NULL;
acm->pending = false;
- req->length = len;
+ req->length = GS_NOTIFY_MAXPACKET;
notify = req->buf;
buf = notify + 1;
@@ -613,6 +657,8 @@
notify->wValue = cpu_to_le16(value);
notify->wIndex = cpu_to_le16(acm->ctrl_id);
notify->wLength = cpu_to_le16(length);
+ memcpy(noti_buf, data, length);
+ memcpy(buf, noti_buf, GS_NOTIFY_MAXPACKET);
memcpy(buf, data, length);
/* ep_queue() can complete immediately if it fills the fifo... */
@@ -967,6 +1013,10 @@
gacm_ports[port_num].client_port_num = no_acm_smd_ports;
no_acm_smd_ports++;
break;
+ case USB_GADGET_XPORT_HSIC:
+ /*client port number will be updated in acm_port_setup*/
+ no_acm_hsic_sports++;
+ break;
default:
pr_err("%s: Un-supported transport transport: %u\n",
__func__, gacm_ports[port_num].transport);