Merge "usb: f_gsi: Send zero length packet for MBIM/GPS on cable connect"
This commit is contained in:
commit
aa860b5b17
@ -19,7 +19,7 @@ static struct gsi_inst_status {
|
||||
struct gsi_opts *opts;
|
||||
} inst_status[IPA_USB_MAX_TETH_PROT_SIZE];
|
||||
|
||||
#define MAX_CDEV_INSTANCES 3
|
||||
#define MAX_CDEV_INSTANCES 4
|
||||
|
||||
static int major;
|
||||
static struct class *gsi_class;
|
||||
@ -1533,6 +1533,7 @@ static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
|
||||
atomic_set(&c_port->ctrl_online, 1);
|
||||
break;
|
||||
case QTI_CTRL_GET_LINE_STATE:
|
||||
case GSI_MBIM_GPS_USB_STATUS:
|
||||
val = atomic_read(&gsi->connected);
|
||||
if (gsi->prot_id == IPA_USB_RMNET)
|
||||
val = gsi->rmnet_dtr_status;
|
||||
@ -1742,6 +1743,8 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
|
||||
strlcat(gsi->c_port.name, GSI_MBIM_CTRL_NAME, sz);
|
||||
else if (gsi->prot_id == IPA_USB_DIAG)
|
||||
strlcat(gsi->c_port.name, GSI_DPL_CTRL_NAME, sz);
|
||||
else if (gsi->prot_id == IPA_USB_GPS)
|
||||
strlcat(gsi->c_port.name, GSI_GPS_CTRL_NAME, sz);
|
||||
else
|
||||
ctrl_dev_create = false;
|
||||
|
||||
@ -2497,7 +2500,9 @@ static int gsi_set_alt(struct usb_function *f, unsigned int intf,
|
||||
atomic_set(&gsi->connected, 1);
|
||||
|
||||
/* send 0 len pkt to qti to notify state change */
|
||||
if (gsi->prot_id == IPA_USB_DIAG)
|
||||
if (gsi->prot_id == IPA_USB_DIAG ||
|
||||
gsi->prot_id == IPA_USB_GPS ||
|
||||
gsi->prot_id == IPA_USB_MBIM)
|
||||
gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
|
||||
|
||||
return ret;
|
||||
@ -2529,7 +2534,7 @@ static void gsi_disable(struct usb_function *f)
|
||||
}
|
||||
|
||||
gsi_ctrl_clear_cpkt_queues(gsi, false);
|
||||
/* send 0 len pkt to qti/qbi to notify state change */
|
||||
/* send 0 len pkt to qti/qbi/gps to notify state change */
|
||||
gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
|
||||
gsi->c_port.notify_req_queued = false;
|
||||
/* Disable Data Path - only if it was initialized already (alt=1) */
|
||||
@ -2559,6 +2564,11 @@ static void gsi_suspend(struct usb_function *f)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gsi->data_interface_up) {
|
||||
log_event_dbg("%s: suspend done\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
block_db = true;
|
||||
usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db,
|
||||
GSI_EP_OP_SET_CLR_BLOCK_DBL);
|
||||
@ -2588,6 +2598,11 @@ static void gsi_resume(struct usb_function *f)
|
||||
/* Check any pending cpkt, and queue immediately on resume */
|
||||
gsi_ctrl_send_notification(gsi);
|
||||
|
||||
if (!gsi->data_interface_up) {
|
||||
log_event_dbg("%s: resume done\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux host does not send RNDIS_MSG_INIT or non-zero
|
||||
* RNDIS_MESSAGE_PACKET_FILTER after performing bus resume.
|
||||
@ -2849,9 +2864,11 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = gsi->data_id = usb_interface_id(c, f);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
if (gsi->prot_id != IPA_USB_GPS) {
|
||||
status = gsi->data_id = usb_interface_id(c, f);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (gsi->prot_id) {
|
||||
case IPA_USB_RNDIS:
|
||||
@ -3137,6 +3154,18 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
info.in_req_num_buf = GSI_NUM_IN_BUFFERS;
|
||||
info.notify_buf_len = sizeof(struct usb_cdc_notification);
|
||||
break;
|
||||
case IPA_USB_GPS:
|
||||
info.string_defs = gps_string_defs;
|
||||
info.ctrl_str_idx = 0;
|
||||
info.ctrl_desc = &gps_interface_desc;
|
||||
info.fs_notify_desc = &gps_fs_notify_desc;
|
||||
info.hs_notify_desc = &gps_hs_notify_desc;
|
||||
info.ss_notify_desc = &gps_ss_notify_desc;
|
||||
info.fs_desc_hdr = gps_fs_function;
|
||||
info.hs_desc_hdr = gps_hs_function;
|
||||
info.ss_desc_hdr = gps_ss_function;
|
||||
info.notify_buf_len = sizeof(struct usb_cdc_notification);
|
||||
break;
|
||||
default:
|
||||
log_event_err("%s: Invalid prot id %d", __func__,
|
||||
gsi->prot_id);
|
||||
@ -3147,6 +3176,9 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
if (status)
|
||||
goto dereg_rndis;
|
||||
|
||||
if (gsi->prot_id == IPA_USB_GPS)
|
||||
goto skip_ipa_init;
|
||||
|
||||
status = ipa_register_ipa_ready_cb(ipa_ready_callback, gsi);
|
||||
if (!status) {
|
||||
log_event_info("%s: ipa is not ready", __func__);
|
||||
@ -3172,6 +3204,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
|
||||
gsi->d_port.sm_state = STATE_INITIALIZED;
|
||||
|
||||
skip_ipa_init:
|
||||
DBG(cdev, "%s: %s speed IN/%s OUT/%s NOTIFY/%s\n",
|
||||
f->name,
|
||||
gadget_is_superspeed(c->cdev->gadget) ? "super" :
|
||||
@ -3265,6 +3298,10 @@ static int gsi_bind_config(struct f_gsi *gsi)
|
||||
gsi->function.name = "dpl";
|
||||
gsi->function.strings = qdss_gsi_strings;
|
||||
break;
|
||||
case IPA_USB_GPS:
|
||||
gsi->function.name = "gps";
|
||||
gsi->function.strings = gps_strings;
|
||||
break;
|
||||
default:
|
||||
log_event_err("%s: invalid prot id %d", __func__, prot_id);
|
||||
return -EINVAL;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
|
||||
#define GSI_MBIM_CTRL_NAME "android_mbim"
|
||||
#define GSI_DPL_CTRL_NAME "dpl_ctrl"
|
||||
#define GSI_GPS_CTRL_NAME "gps"
|
||||
#define GSI_CTRL_NAME_LEN (sizeof(GSI_MBIM_CTRL_NAME)+2)
|
||||
#define GSI_MAX_CTRL_PKT_SIZE 8192
|
||||
#define GSI_CTRL_DTR (1 << 0)
|
||||
@ -331,7 +332,8 @@ static enum ipa_usb_teth_prot name_to_prot_id(const char *name)
|
||||
return IPA_USB_MBIM;
|
||||
if (!strncasecmp(name, "dpl", strlen("dpl")))
|
||||
return IPA_USB_DIAG;
|
||||
|
||||
if (!strncasecmp(name, "gps", strlen("gps")))
|
||||
return IPA_USB_GPS;
|
||||
error:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1430,4 +1432,91 @@ static struct usb_gadget_strings *qdss_gsi_strings[] = {
|
||||
&qdss_gsi_string_table,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* gps device descriptor */
|
||||
static struct usb_interface_descriptor gps_interface_desc = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
|
||||
.bInterfaceSubClass = USB_CLASS_VENDOR_SPEC,
|
||||
.bInterfaceProtocol = USB_CLASS_VENDOR_SPEC,
|
||||
/* .iInterface = DYNAMIC */
|
||||
};
|
||||
|
||||
/* Full speed support */
|
||||
static struct usb_endpoint_descriptor gps_fs_notify_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(MAX_NOTIFY_SIZE),
|
||||
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *gps_fs_function[] = {
|
||||
(struct usb_descriptor_header *) &gps_interface_desc,
|
||||
(struct usb_descriptor_header *) &gps_fs_notify_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* High speed support */
|
||||
static struct usb_endpoint_descriptor gps_hs_notify_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(MAX_NOTIFY_SIZE),
|
||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *gps_hs_function[] = {
|
||||
(struct usb_descriptor_header *) &gps_interface_desc,
|
||||
(struct usb_descriptor_header *) &gps_hs_notify_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Super speed support */
|
||||
static struct usb_endpoint_descriptor gps_ss_notify_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(MAX_NOTIFY_SIZE),
|
||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||
};
|
||||
|
||||
static struct usb_ss_ep_comp_descriptor gps_ss_notify_comp_desc = {
|
||||
.bLength = sizeof(gps_ss_notify_comp_desc),
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
/* the following 3 values can be tweaked if necessary */
|
||||
/* .bMaxBurst = 0, */
|
||||
/* .bmAttributes = 0, */
|
||||
.wBytesPerInterval = cpu_to_le16(MAX_NOTIFY_SIZE),
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *gps_ss_function[] = {
|
||||
(struct usb_descriptor_header *) &gps_interface_desc,
|
||||
(struct usb_descriptor_header *) &gps_ss_notify_desc,
|
||||
(struct usb_descriptor_header *) &gps_ss_notify_comp_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* String descriptors */
|
||||
|
||||
static struct usb_string gps_string_defs[] = {
|
||||
[0].s = "GPS",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings gps_string_table = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = gps_string_defs,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *gps_strings[] = {
|
||||
&gps_string_table,
|
||||
NULL,
|
||||
};
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@ enum ipa_usb_teth_prot {
|
||||
IPA_USB_MBIM = 3,
|
||||
IPA_USB_DIAG = 4,
|
||||
IPA_USB_RMNET_CV2X = 5,
|
||||
IPA_USB_GPS = 6,
|
||||
IPA_USB_MAX_TETH_PROT_SIZE
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user