Merge "usb: f_gsi: Send zero length packet for MBIM/GPS on cable connect"

This commit is contained in:
qctecmdr 2020-12-10 16:11:03 -08:00 committed by Gerrit - the friendly Code Review server
commit aa860b5b17
3 changed files with 134 additions and 7 deletions

View File

@ -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;

View File

@ -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

View File

@ -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
};