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

Commit 075105b0 authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa Committed by Mayank Rana
Browse files

usb: gadget: CCID: Add support for SuperSpeed enumeration



Currently CCID function supports only upto HighSpeed
enumeration. Add descriptors for SuperSpeed mode
and bind them to enable SuperSpeed enumeration of
USB CCID function.

Change-Id: I1908a9aa2daec7d1d361cb996e82cd1a0700f7cc
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent 003ee1e0
Loading
Loading
Loading
Loading
+86 −20
Original line number Diff line number Diff line
@@ -206,6 +206,71 @@ static struct usb_descriptor_header *ccid_hs_descs[] = {
	NULL,
};

/* Super speed support: */
static struct usb_endpoint_descriptor ccid_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(CCID_NOTIFY_MAXPACKET),
	.bInterval =		CCID_NOTIFY_INTERVAL + 4,
};

static struct usb_ss_ep_comp_descriptor ccid_ss_notify_comp_desc = {
	.bLength =		sizeof(ccid_ss_notify_comp_desc),
	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,

	/* the following 2 values can be tweaked if necessary */
	/* .bMaxBurst =		0, */
	/* .bmAttributes =	0, */
};

static struct usb_endpoint_descriptor ccid_ss_in_desc = {
	.bLength =		USB_DT_ENDPOINT_SIZE,
	.bDescriptorType =	USB_DT_ENDPOINT,
	.bEndpointAddress =	USB_DIR_IN,
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	cpu_to_le16(1024),
};

static struct usb_ss_ep_comp_descriptor ccid_ss_in_comp_desc = {
	.bLength =		sizeof(ccid_ss_in_comp_desc),
	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,

	/* the following 2 values can be tweaked if necessary */
	/* .bMaxBurst =		0, */
	/* .bmAttributes =	0, */
};

static struct usb_endpoint_descriptor ccid_ss_out_desc = {
	.bLength =		USB_DT_ENDPOINT_SIZE,
	.bDescriptorType =	USB_DT_ENDPOINT,
	.bEndpointAddress =	USB_DIR_OUT,
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	cpu_to_le16(1024),
};

static struct usb_ss_ep_comp_descriptor ccid_ss_out_comp_desc = {
	.bLength =		sizeof(ccid_ss_out_comp_desc),
	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,

	/* the following 2 values can be tweaked if necessary */
	/* .bMaxBurst =		0, */
	/* .bmAttributes =	0, */
};

static struct usb_descriptor_header *ccid_ss_descs[] = {
	(struct usb_descriptor_header *) &ccid_interface_desc,
	(struct usb_descriptor_header *) &ccid_class_desc,
	(struct usb_descriptor_header *) &ccid_ss_notify_desc,
	(struct usb_descriptor_header *) &ccid_ss_notify_comp_desc,
	(struct usb_descriptor_header *) &ccid_ss_in_desc,
	(struct usb_descriptor_header *) &ccid_ss_in_comp_desc,
	(struct usb_descriptor_header *) &ccid_ss_out_desc,
	(struct usb_descriptor_header *) &ccid_ss_out_comp_desc,
	NULL,
};

static inline struct f_ccid *func_to_ccid(struct usb_function *f)
{
	return container_of(f, struct f_ccid, function);
@@ -503,10 +568,7 @@ ccid_function_set_alt(struct usb_function *f, unsigned int intf,
static void ccid_function_unbind(struct usb_configuration *c,
					struct usb_function *f)
{
	if (gadget_is_dualspeed(c->cdev->gadget))
		usb_free_descriptors(f->hs_descriptors);
	usb_free_descriptors(f->fs_descriptors);

	usb_free_all_descriptors(f);
}

static int ccid_function_bind(struct usb_configuration *c,
@@ -551,23 +613,26 @@ static int ccid_function_bind(struct usb_configuration *c,
	ccid_dev->out = ep;
	ep->driver_data = cdev;

	f->fs_descriptors = usb_copy_descriptors(ccid_fs_descs);
	if (!f->fs_descriptors)
		goto ep_auto_out_fail;

	if (gadget_is_dualspeed(cdev->gadget)) {
		ccid_hs_in_desc.bEndpointAddress =
				ccid_fs_in_desc.bEndpointAddress;
		ccid_hs_out_desc.bEndpointAddress =
				ccid_fs_out_desc.bEndpointAddress;
	/*
	 * support all relevant hardware speeds... we expect that when
	 * hardware is dual speed, all bulk-capable endpoints work at
	 * both speeds
	 */
	ccid_hs_in_desc.bEndpointAddress = ccid_fs_in_desc.bEndpointAddress;
	ccid_hs_out_desc.bEndpointAddress = ccid_fs_out_desc.bEndpointAddress;
	ccid_hs_notify_desc.bEndpointAddress =
					ccid_fs_notify_desc.bEndpointAddress;

		/* copy descriptors, and track endpoint copies */
		f->hs_descriptors = usb_copy_descriptors(ccid_hs_descs);
		if (!f->hs_descriptors)

	ccid_ss_in_desc.bEndpointAddress = ccid_fs_in_desc.bEndpointAddress;
	ccid_ss_out_desc.bEndpointAddress = ccid_fs_out_desc.bEndpointAddress;
	ccid_ss_notify_desc.bEndpointAddress =
					ccid_fs_notify_desc.bEndpointAddress;

	ret = usb_assign_descriptors(f, ccid_fs_descs, ccid_hs_descs,
						ccid_ss_descs, NULL);
	if (ret)
		goto ep_auto_out_fail;
	}

	pr_debug("%s: CCID %s Speed, IN:%s OUT:%s\n", __func__,
			gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
@@ -972,6 +1037,7 @@ static int ccid_bind_config(struct f_ccid *ccid_dev)
	ccid_dev->function.name = FUNCTION_NAME;
	ccid_dev->function.fs_descriptors = ccid_fs_descs;
	ccid_dev->function.hs_descriptors = ccid_hs_descs;
	ccid_dev->function.ss_descriptors = ccid_ss_descs;
	ccid_dev->function.bind = ccid_function_bind;
	ccid_dev->function.unbind = ccid_function_unbind;
	ccid_dev->function.set_alt = ccid_function_set_alt;