/*
 * This file is part of the libpayload project.
 *
 * Copyright (C) 2008-2010 coresystems GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

//#define USB_DEBUG

#include <libpayload-config.h>
#include <usb/usb.h>

hci_t *usb_hcs = 0;

hci_t *
new_controller (void)
{
	hci_t *controller = malloc (sizeof (hci_t));

	if (controller) {
		/* atomic */
		controller->next = usb_hcs;
		usb_hcs = controller;
		/* atomic end */
	}

	return controller;
}

void
detach_controller (hci_t *controller)
{
	if (controller == NULL)
		return;
	if (usb_hcs == controller) {
		usb_hcs = controller->next;
	} else {
		hci_t *it = usb_hcs;
		while (it != NULL) {
			if (it->next == controller) {
				it->next = controller->next;
				return;
			}
			it = it->next;
		}
	}
}

/**
 * Shut down all controllers
 */
int
usb_exit (void)
{
	while (usb_hcs != NULL) {
		usb_hcs->shutdown(usb_hcs);
	}
	return 0;
}

/**
 * Polls all hubs on all USB controllers, to find out about device changes
 */
void
usb_poll (void)
{
	if (usb_hcs == 0)
		return;
	hci_t *controller = usb_hcs;
	while (controller != NULL) {
		int i;
		for (i = 0; i < 128; i++) {
			if (controller->devices[i] != 0) {
				controller->devices[i]->poll (controller->devices[i]);
			}
		}
		controller = controller->next;
	}
}

void
init_device_entry (hci_t *controller, int i)
{
	if (controller->devices[i] != 0)
		usb_debug("warning: device %d reassigned?\n", i);
	controller->devices[i] = malloc(sizeof(usbdev_t));
	controller->devices[i]->controller = controller;
	controller->devices[i]->address = -1;
	controller->devices[i]->hub = -1;
	controller->devices[i]->port = -1;
	controller->devices[i]->init = usb_nop_init;
	controller->devices[i]->init (controller->devices[i]);
}

void
set_feature (usbdev_t *dev, int endp, int feature, int rtype)
{
	dev_req_t dr;

	dr.bmRequestType = rtype;
	dr.data_dir = host_to_device;
	dr.bRequest = SET_FEATURE;
	dr.wValue = feature;
	dr.wIndex = endp;
	dr.wLength = 0;
	dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
}

void
get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
{
	dev_req_t dr;

	dr.bmRequestType = rtype;
	dr.data_dir = device_to_host;
	dr.bRequest = GET_STATUS;
	dr.wValue = 0;
	dr.wIndex = intf;
	dr.wLength = len;
	dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
}

u8 *
get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType,
		int descIdx, int langID)
{
	u8 buf[8];
	u8 *result;
	dev_req_t dr;
	int size;

	dr.bmRequestType = bmRequestType;
	dr.data_dir = device_to_host;	// always like this for descriptors
	dr.bRequest = GET_DESCRIPTOR;
	dr.wValue = (descType << 8) | descIdx;
	dr.wIndex = langID;
	dr.wLength = 8;
	if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf) < 0) {
		usb_debug ("getting descriptor size (type %x) failed\n",
			descType);
	}

	if (descType == 1) {
		device_descriptor_t *dd = (device_descriptor_t *) buf;
		usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0);
		if (dd->bMaxPacketSize0 != 0)
			dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
	}

	/* special case for configuration descriptors: they carry all their
	   subsequent descriptors with them, and keep the entire size at a
	   different location */
	size = buf[0];
	if (buf[1] == 2) {
		int realsize = ((unsigned short *) (buf + 2))[0];
		size = realsize;
	}
	result = malloc (size);
	memset (result, 0, size);
	dr.wLength = size;
	if (dev->controller->
	    control (dev, IN, sizeof (dr), &dr, size, result) < 0) {
		usb_debug ("getting descriptor (type %x, size %x) failed\n",
			descType, size);
	}

	return result;
}

void
set_configuration (usbdev_t *dev)
{
	dev_req_t dr;

	dr.bmRequestType = 0;
	dr.bRequest = SET_CONFIGURATION;
	dr.wValue = dev->configuration[5];
	dr.wIndex = 0;
	dr.wLength = 0;
	dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
}

int
clear_feature (usbdev_t *dev, int endp, int feature, int rtype)
{
	dev_req_t dr;

	dr.bmRequestType = rtype;
	dr.data_dir = host_to_device;
	dr.bRequest = CLEAR_FEATURE;
	dr.wValue = feature;
	dr.wIndex = endp;
	dr.wLength = 0;
	return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0;
}

int
clear_stall (endpoint_t *ep)
{
	usbdev_t *dev = ep->dev;
	int endp = ep->endpoint;
	int rtype = gen_bmRequestType (host_to_device, standard_type,
					endp ? endp_recp : dev_recp);

	int ret = clear_feature (dev, endp, ENDPOINT_HALT, rtype);
	ep->toggle = 0;
	return ret;
}

/* returns free address or -1 */
static int
get_free_address (hci_t *controller)
{
	int i;
	for (i = 1; i < 128; i++) {
		if (controller->devices[i] == 0)
			return i;
	}
	usb_debug ("no free address found\n");
	return -1;		// no free address
}

int
generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr)
{
	int adr = get_free_address (controller);	// address to set
	dev_req_t dr;

	memset (&dr, 0, sizeof (dr));
	dr.data_dir = host_to_device;
	dr.req_type = standard_type;
	dr.req_recp = dev_recp;
	dr.bRequest = SET_ADDRESS;
	dr.wValue = adr;
	dr.wIndex = 0;
	dr.wLength = 0;

	init_device_entry(controller, adr);
	usbdev_t *dev = controller->devices[adr];
	// dummy values for registering the address
	dev->address = 0;
	dev->hub = hubaddr;
	dev->port = hubport;
	dev->speed = speed;
	dev->endpoints[0].dev = dev;
	dev->endpoints[0].endpoint = 0;
	dev->endpoints[0].maxpacketsize = 8;
	dev->endpoints[0].toggle = 0;
	dev->endpoints[0].direction = SETUP;
	mdelay (50);
	if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0) {
		usb_debug ("set_address failed\n");
		return -1;
	}
	mdelay (50);

	return adr;
}

/* Normalize bInterval to log2 of microframes */
static int
usb_decode_interval(const int speed, const endpoint_type type, const unsigned char bInterval)
{
#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1)
	switch (speed) {
	case LOW_SPEED:
		switch (type) {
		case ISOCHRONOUS: case INTERRUPT:
			return LOG2(bInterval) + 3;
		default:
			return 0;
		}
	case FULL_SPEED:
		switch (type) {
		case ISOCHRONOUS:
			return (bInterval - 1) + 3;
		case INTERRUPT:
			return LOG2(bInterval) + 3;
		default:
			return 0;
		}
	case HIGH_SPEED:
		switch (type) {
		case ISOCHRONOUS: case INTERRUPT:
			return bInterval - 1;
		default:
			return LOG2(bInterval);
		}
	case SUPER_SPEED:
		switch (type) {
		case ISOCHRONOUS: case INTERRUPT:
			return bInterval - 1;
		default:
			return 0;
		}
	default:
		return 0;
	}
#undef LOG2
}

static int
set_address (hci_t *controller, int speed, int hubport, int hubaddr)
{
	int adr = controller->set_address(controller, speed, hubport, hubaddr);
	if (adr < 0 || !controller->devices[adr]) {
		usb_debug ("set_address failed\n");
		return -1;
	}
	configuration_descriptor_t *cd;
	device_descriptor_t *dd;

	usbdev_t *dev = controller->devices[adr];
	dev->address = adr;
	dev->hub = hubaddr;
	dev->port = hubport;
	dev->speed = speed;
	dev->descriptor = get_descriptor (dev, gen_bmRequestType
		(device_to_host, standard_type, dev_recp), 1, 0, 0);
	dd = (device_descriptor_t *) dev->descriptor;

	usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x)",
		 dd->idVendor, dd->idProduct,
		 dd->bcdUSB >> 8, dd->bcdUSB & 0xff);
	dev->quirks = usb_quirk_check(dd->idVendor, dd->idProduct);

	usb_debug ("\ndevice has %x configurations\n", dd->bNumConfigurations);
	if (dd->bNumConfigurations == 0) {
		/* device isn't usable */
		usb_debug ("... no usable configuration!\n");
		dev->address = 0;
		return -1;
	}

	dev->configuration = get_descriptor (dev, gen_bmRequestType
		(device_to_host, standard_type, dev_recp), 2, 0, 0);
	cd = (configuration_descriptor_t *) dev->configuration;
	interface_descriptor_t *interface =
		(interface_descriptor_t *) (((char *) cd) + cd->bLength);
	{
		int i;
		int num = cd->bNumInterfaces;
		interface_descriptor_t *current = interface;
		usb_debug ("device has %x interfaces\n", num);
		if (num > 1) {
			int interfaces = usb_interface_check(dd->idVendor, dd->idProduct);
			if (interfaces) {
				/* Well known device, don't warn */
				num = interfaces;
			} else {

				usb_debug ("\nNOTICE: This driver defaults to using the first interface.\n"
					"This might be the wrong choice and lead to limited functionality\n"
					"of the device. Please report such a case to coreboot@coreboot.org\n"
					"as you might be the first.\n");
				/* we limit to the first interface, as there was no need to
				 * implement something else for the time being. If you need
				 * it, see the SetInterface and GetInterface functions in
				 * the USB specification, and adapt appropriately.
				 */
				num = (num > 1) ? 1 : num;
			}
		}
		for (i = 0; i < num; i++) {
			int j;
			usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n",
					current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol);
			endpoint_descriptor_t *endp =
				(endpoint_descriptor_t *) (((char *) current)
							   + current->bLength);
			/* Skip any non-endpoint descriptor */
			if (endp->bDescriptorType != 0x05)
				endp = (endpoint_descriptor_t *)(((char *)endp) + ((char *)endp)[0]);

			memset (dev->endpoints, 0, sizeof (dev->endpoints));
			dev->num_endp = 1;	// 0 always exists
			dev->endpoints[0].dev = dev;
			dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
			dev->endpoints[0].direction = SETUP;
			dev->endpoints[0].type = CONTROL;
			dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval);
			for (j = 1; j <= current->bNumEndpoints; j++) {
#ifdef USB_DEBUG
				static const char *transfertypes[4] = {
					"control", "isochronous", "bulk", "interrupt"
				};
				usb_debug ("   #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", endp->wMaxPacketSize, transfertypes[endp->bmAttributes]);
#endif
				endpoint_t *ep =
					&dev->endpoints[dev->num_endp++];
				ep->dev = dev;
				ep->endpoint = endp->bEndpointAddress;
				ep->toggle = 0;
				ep->maxpacketsize = endp->wMaxPacketSize;
				ep->direction =
					((endp->bEndpointAddress & 0x80) ==
					 0) ? OUT : IN;
				ep->type = endp->bmAttributes;
				ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval);
				endp = (endpoint_descriptor_t
					*) (((char *) endp) + endp->bLength);
			}
			current = (interface_descriptor_t *) endp;
		}
	}

	if (controller->finish_device_config &&
			controller->finish_device_config(dev))
		return adr; /* Device isn't configured correctly,
			       only control transfers may work. */

	set_configuration(dev);

	int class = dd->bDeviceClass;
	if (class == 0)
		class = interface->bInterfaceClass;

	enum {
		audio_device      = 0x01,
		comm_device       = 0x02,
		hid_device        = 0x03,
		physical_device   = 0x05,
		imaging_device    = 0x06,
		printer_device    = 0x07,
		msc_device        = 0x08,
		hub_device        = 0x09,
		cdc_device        = 0x0a,
		ccid_device       = 0x0b,
		security_device   = 0x0d,
		video_device      = 0x0e,
		healthcare_device = 0x0f,
		diagnostic_device = 0xdc,
		wireless_device   = 0xe0,
		misc_device       = 0xef,
	};
	usb_debug(", class: ");
	switch (class) {
	case audio_device:
		usb_debug("audio\n");
		break;
	case comm_device:
		usb_debug("communication\n");
		break;
	case hid_device:
		usb_debug ("HID\n");
#ifdef CONFIG_LP_USB_HID
		controller->devices[adr]->init = usb_hid_init;
		return adr;
#else
		usb_debug ("NOTICE: USB HID support not compiled in\n");
#endif
		break;
	case physical_device:
		usb_debug("physical\n");
		break;
	case imaging_device:
		usb_debug("camera\n");
		break;
	case printer_device:
		usb_debug("printer\n");
		break;
	case msc_device:
		usb_debug ("MSC\n");
#ifdef CONFIG_LP_USB_MSC
		controller->devices[adr]->init = usb_msc_init;
		return adr;
#else
		usb_debug ("NOTICE: USB MSC support not compiled in\n");
#endif
		break;
	case hub_device:
		usb_debug ("hub\n");
#ifdef CONFIG_LP_USB_HUB
		controller->devices[adr]->init = usb_hub_init;
		return adr;
#else
		usb_debug ("NOTICE: USB hub support not compiled in.\n");
#endif
		break;
	case cdc_device:
		usb_debug("CDC\n");
		break;
	case ccid_device:
		usb_debug("smartcard / CCID\n");
		break;
	case security_device:
		usb_debug("content security\n");
		break;
	case video_device:
		usb_debug("video\n");
		break;
	case healthcare_device:
		usb_debug("healthcare\n");
		break;
	case diagnostic_device:
		usb_debug("diagnostic\n");
		break;
	case wireless_device:
		usb_debug("wireless\n");
		break;
	default:
		usb_debug("unsupported class %x\n", class);
		break;
	}
	controller->devices[adr]->init = usb_generic_init;
	return adr;
}

/*
 * Should be called by the hub drivers whenever a physical detach occurs
 * and can be called by usb class drivers if they are unsatisfied with a
 * malfunctioning device.
 */
void
usb_detach_device(hci_t *controller, int devno)
{
	/* check if device exists, as we may have
	   been called yet by the usb class driver */
	if (controller->devices[devno]) {
		controller->devices[devno]->destroy (controller->devices[devno]);
		free(controller->devices[devno]);
		controller->devices[devno] = NULL;
		if (controller->destroy_device)
			controller->destroy_device(controller, devno);
	}
}

int
usb_attach_device(hci_t *controller, int hubaddress, int port, int speed)
{
	static const char* speeds[] = { "full", "low", "high" };
	usb_debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no");
	int newdev = set_address (controller, speed, port, hubaddress);
	if (newdev == -1)
		return -1;
	usbdev_t *newdev_t = controller->devices[newdev];
	// determine responsible driver - current done in set_address
	newdev_t->init (newdev_t);
	/* init() may have called usb_detach_device() yet, so check */
	return controller->devices[newdev] ? newdev : -1;
}

static void
usb_generic_destroy (usbdev_t *dev)
{
	if (usb_generic_remove)
		usb_generic_remove(dev);
}

void
usb_generic_init (usbdev_t *dev)
{
	dev->data = NULL;
	dev->destroy = usb_generic_destroy;

	if (usb_generic_create)
		usb_generic_create(dev);
}
