Loading drivers/usb/gadget/function/f_gsi.c +43 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) */ Loading Loading @@ -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); Loading Loading @@ -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. Loading Loading @@ -2849,9 +2864,11 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) 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: Loading Loading @@ -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); Loading @@ -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__); Loading @@ -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" : Loading Loading @@ -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; Loading drivers/usb/gadget/function/f_gsi.h +90 −1 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; } Loading Loading @@ -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 include/linux/ipa_usb.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/usb/gadget/function/f_gsi.c +43 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) */ Loading Loading @@ -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); Loading Loading @@ -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. Loading Loading @@ -2849,9 +2864,11 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) 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: Loading Loading @@ -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); Loading @@ -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__); Loading @@ -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" : Loading Loading @@ -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; Loading
drivers/usb/gadget/function/f_gsi.h +90 −1 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; } Loading Loading @@ -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
include/linux/ipa_usb.h +1 −0 Original line number Diff line number Diff line Loading @@ -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