/*
 * Copyright (C) 2013 secunet Security Networks AG
 *
 * 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 <stdlib.h>
#include <usb/usb.h>
#include "generic_hub.h"

#include "base/time.h"

enum {
	GenericHub_NoDev = -1,
};

void generic_hub_destroy(UsbDev *const dev)
{
	generic_hub_t *const hub = GEN_HUB(dev);
	if (!hub)
		return;

	// First, detach all devices behind this hub.
	for (int port = 1; port <= hub->num_ports; port++) {
		if (hub->ports[port] >= 0) {
			usb_debug("generic_hub: Detachment at port %d\n", port);
			usb_detach_device(dev->controller, hub->ports[port]);
			hub->ports[port] = GenericHub_NoDev;
		}
	}

	// Disable all ports.
	if (hub->ops->disable_port)
		for (int port = 1; port <= hub->num_ports; port++)
			hub->ops->disable_port(dev, port);

	free(hub->ports);
	free(hub);
}

static int generic_hub_debounce(UsbDev *const dev, const int port)
{
	generic_hub_t *const hub = GEN_HUB(dev);

	const int step_ms = 1; // linux uses 25ms, we're busy anyway.
	const int at_least_ms = 100; // 100ms as in usb20 spec 9.1.2.
	const int timeout_ms = 1500; // linux uses this value.

	int total_ms = 0;
	int stable_ms = 0;
	while (stable_ms < at_least_ms && total_ms < timeout_ms) {
		mdelay(step_ms);

		const int changed = hub->ops->port_status_changed(dev, port);
		const int connected = hub->ops->port_connected(dev, port);
		if (changed < 0 || connected < 0)
			return -1;

		if (!changed && connected) {
			stable_ms += step_ms;
		} else {
			usb_debug("generic_hub: Unstable connection at %d\n",
				  port);
			stable_ms = 0;
		}
		total_ms += step_ms;
	}
	if (total_ms >= timeout_ms)
		usb_debug("generic_hub: Debouncing timed out at %d\n", port);
	return 0; // Ignore timeouts, try to always go on.
}

int generic_hub_wait_for_port(UsbDev *const dev, const int port,
			      const int wait_for,
			      int (*const port_op)(UsbDev *, int),
			      int timeout_steps, const int step_us)
{
	do {
		int state = port_op(dev, port);
		if (state < 0)
			return -1;
		else if (!!state == wait_for)
			return timeout_steps;
		udelay(step_us);
		timeout_steps--;
	} while(timeout_steps);

	return 0;
}

int generic_hub_resetport(UsbDev *const dev, const int port)
{
	generic_hub_t *const hub = GEN_HUB(dev);

	if (hub->ops->start_port_reset(dev, port) < 0)
		return -1;

	// Wait for 10ms. (usb20 spec 11.5.1.5: reset should take 10 to 20ms)
	mdelay(10);

	// Now wait 12ms for the hub to finish the reset.
	const int ret = generic_hub_wait_for_port(
			// Time out after 120 * 100us = 12ms.
			dev, port, 0, hub->ops->port_in_reset, 120, 100);
	if (ret < 0)
		return -1;
	else if (!ret)
		usb_debug("generic_hub: Reset timed out at port %d\n", port);

	return 0; // Ignore timeouts, try to always go on.
}

static int generic_hub_detach_dev(UsbDev *const dev, const int port)
{
	generic_hub_t *const hub = GEN_HUB(dev);

	usb_detach_device(dev->controller, hub->ports[port]);
	hub->ports[port] = GenericHub_NoDev;

	return 0;
}

static int generic_hub_attach_dev(UsbDev *const dev, const int port)
{
	generic_hub_t *const hub = GEN_HUB(dev);

	if (generic_hub_debounce(dev, port) < 0)
		return -1;

	if (hub->ops->reset_port) {
		if (hub->ops->reset_port(dev, port) < 0)
			return -1;
		// After reset the port will be enabled automatically.
		const int ret = generic_hub_wait_for_port(
			// Time out after 1,000 * 10us = 10ms.
			dev, port, 1, hub->ops->port_enabled, 1000, 10);
		if (ret < 0)
			return -1;
		else if (!ret)
			usb_debug("generic_hub: Port %d still "
				  "disabled after 10ms\n", port);
	}

	const UsbSpeed speed = hub->ops->port_speed(dev, port);
	if (speed >= 0) {
		usb_debug("generic_hub: Success at port %d\n", port);
		if (hub->ops->reset_port)
			mdelay(10); // Reset recovery time. (usb20 spec 7.1.7.5)
		hub->ports[port] = usb_attach_device(
				dev->controller, dev->address, port, speed);
	}
	return 0;
}

int generic_hub_scanport(UsbDev *const dev, const int port)
{
	generic_hub_t *const hub = GEN_HUB(dev);

	if (hub->ports[port] >= 0) {
		usb_debug("generic_hub: Detachment at port %d\n", port);

		const int ret = generic_hub_detach_dev(dev, port);
		if (ret < 0)
			return ret;
	}

	if (hub->ops->port_connected(dev, port)) {
		usb_debug("generic_hub: Attachment at port %d\n", port);

		return generic_hub_attach_dev(dev, port);
	}

	return 0;
}

static void generic_hub_poll(UsbDev *const dev)
{
	generic_hub_t *const hub = GEN_HUB(dev);
	if (!hub)
		return;

	if (hub->ops->hub_status_changed &&
			hub->ops->hub_status_changed(dev) != 1)
		return;

	for (int port = 1; port <= hub->num_ports; port++) {
		const int ret = hub->ops->port_status_changed(dev, port);
		if (ret < 0) {
			return;
		} else if (ret == 1) {
			usb_debug("generic_hub: Port change at %d\n", port);
			if (generic_hub_scanport(dev, port) < 0)
				return;
		}
	}
}

int generic_hub_init(UsbDev *const dev, const int num_ports,
		     const GenericHubOps *const ops)
{
	dev->destroy = generic_hub_destroy;
	dev->poll = generic_hub_poll;
	dev->data = malloc(sizeof(generic_hub_t));
	if (!dev->data) {
		usb_debug("generic_hub: ERROR: Out of memory\n");
		return -1;
	}

	generic_hub_t *const hub = GEN_HUB(dev);
	hub->num_ports = num_ports;
	hub->ports = malloc(sizeof(*hub->ports) * (num_ports + 1));
	hub->ops = ops;
	if (!hub->ports) {
		usb_debug("generic_hub: ERROR: Out of memory\n");
		free(dev->data);
		dev->data = NULL;
		return -1;
	}
	for (int port = 1; port <= num_ports; ++port)
		hub->ports[port] = GenericHub_NoDev;

	// Enable all ports.
	if (ops->enable_port) {
		for (int port = 1; port <= num_ports; ++port)
			ops->enable_port(dev, port);
		// Wait once for all ports.
		mdelay(20);
	}

	return 0;
}
