Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33be9e30 authored by Hemant Kumar's avatar Hemant Kumar Committed by Gerrit - the friendly Code Review server
Browse files

usb: gadget: f_gsi: Add support for gps function driver



gps usb functionality is implemented using qmi packets.
User space entity sends and receives QMI packets using
misc device named /dev/gps.

Change-Id: I73af1caa9b272597909199022739390274a4b034
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarElson Roy Serrao <eserrao@codeaurora.org>
parent d0739752
Loading
Loading
Loading
Loading
+38 −4
Original line number Diff line number Diff line
@@ -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;
@@ -1742,6 +1742,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;

@@ -2559,6 +2561,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 +2595,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 +2861,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:
@@ -3137,6 +3151,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 +3173,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 +3201,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 +3295,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;
+90 −1
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
};