Esempio n. 1
0
static int hub_check_port(struct usb_dev *dev, int port)
{
	struct usb_hub_ps ps;
	uint32_t time;

	if (!hub_get_port_status(dev, port, &ps, sizeof(ps)))
		return false;
	dprintf("Port Status %04X Port Change %04X\n",
		le16_to_cpu(ps.wPortStatus),
		le16_to_cpu(ps.wPortChange));

	if (!(le16_to_cpu(ps.wPortStatus) & HUB_PS_POWER)) {
		hub_set_port_feature(dev, port, HUB_PF_POWER);
		SLOF_msleep(100);
		time = SLOF_GetTimer() + USB_TIMEOUT;
		while (time > SLOF_GetTimer()) {
			cpu_relax();
			hub_get_port_status(dev, port, &ps, sizeof(ps));
			if (le16_to_cpu(ps.wPortStatus) & HUB_PS_CONNECTION) {
				dprintf("power on Port Status %04X Port Change %04X\n",
					le16_to_cpu(ps.wPortStatus),
					le16_to_cpu(ps.wPortChange));
				break;
			}
		}
	}

	if (le16_to_cpu(ps.wPortStatus) & HUB_PS_CONNECTION) {
		hub_set_port_feature(dev, port, HUB_PF_RESET);
		SLOF_msleep(100);
		time = SLOF_GetTimer() + USB_TIMEOUT;
		while (time > SLOF_GetTimer()) {
			cpu_relax();
			hub_get_port_status(dev, port, &ps, sizeof(ps));
			if (!(le16_to_cpu(ps.wPortStatus) & HUB_PS_RESET)) {
				dprintf("reset Port Status %04X Port Change %04X\n",
					le16_to_cpu(ps.wPortStatus),
					le16_to_cpu(ps.wPortChange));
				return true;
			}
		}
	}
	return false;
}
Esempio n. 2
0
static vsf_err_t hub_reset_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
	struct vsfusbh_hub_t *hub = (struct vsfusbh_hub_t *)pt->user_data;
	struct vsfusbh_urb_t *vsfurb = hub->vsfurb;
	vsf_err_t err;

	vsfsm_pt_begin(pt);

	hub->retry = 0;

	do
	{
		/* send command to reset port */
		vsfurb->transfer_buffer = NULL;
		vsfurb->transfer_length = 0;
		err = hub_set_port_feature(hub->usbh, vsfurb, hub->counter,
				USB_PORT_FEAT_RESET);
		if (err != VSFERR_NONE)
			return err;
		vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
		if (vsfurb->status != URB_OK)
			return VSFERR_FAIL;

		/* delay 100ms after port reset*/
		vsfsm_pt_delay(pt, 100);

		// clear reset
		vsfurb->transfer_buffer = NULL;
		vsfurb->transfer_length = 0;
		err = hub_clear_port_feature(hub->usbh, vsfurb,
				hub->counter, USB_PORT_FEAT_C_RESET);
		if (err != VSFERR_NONE)
			return err;
		vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
		if (vsfurb->status != URB_OK)
			return VSFERR_FAIL;

		/* delay 100ms after port reset*/
		vsfsm_pt_delay(pt, 50);

		/* get port status for check */
		vsfurb->transfer_buffer = &hub->hub_portsts;
		vsfurb->transfer_length = sizeof(hub->hub_portsts);
		err = hub_get_port_status(hub->usbh, vsfurb, hub->counter);
		if (err != VSFERR_NONE)
			return err;
		vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
		if (vsfurb->status != URB_OK)
			return VSFERR_FAIL;

		/* check port status after reset */
		if (hub->hub_portsts.wPortStatus & USB_PORT_STAT_ENABLE)
		{
			return VSFERR_NONE;
		}
		else
		{
			/* delay 200ms for next reset*/
			vsfsm_pt_delay(pt, 200);
		}

	} while (hub->retry++ <= 3);

	vsfsm_pt_end(pt);
	return VSFERR_FAIL;
}
Esempio n. 3
0
static vsf_err_t hub_scan_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
	vsf_err_t err;
	struct vsfusbh_hub_t *hub = (struct vsfusbh_hub_t *)pt->user_data;
	struct vsfusbh_urb_t *vsfurb = hub->vsfurb;

	vsfsm_pt_begin(pt);

	do
	{
		hub->counter = 1;
		do
		{
			// get port status
			vsfurb->transfer_buffer = &hub->hub_portsts;
			vsfurb->transfer_length = sizeof(hub->hub_portsts);
			err = hub_get_port_status(hub->usbh, vsfurb, hub->counter);
			if (err != VSFERR_NONE)
				return err;
			vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
			if (vsfurb->status != URB_OK)
				return VSFERR_FAIL;

			if (hub->hub_portsts.wPortChange & USB_PORT_STAT_C_CONNECTION)
			{
				// try to connect
				vsfsm_pt_wfpt(pt, &hub->drv_connect_pt);
			}
			else if (hub->hub_portsts.wPortChange & USB_PORT_STAT_C_ENABLE)
			{
				vsfurb->transfer_buffer = NULL;
				vsfurb->transfer_length = 0;
				err = hub_clear_port_feature(hub->usbh, vsfurb,
						hub->counter, USB_PORT_FEAT_C_ENABLE);
				if (err != VSFERR_NONE)
					return err;
				vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
				if (vsfurb->status != URB_OK)
					return VSFERR_FAIL;

				hub->hub_portsts.wPortChange &= ~USB_PORT_STAT_C_ENABLE;
			}

			if (hub->hub_portsts.wPortChange & USB_PORT_STAT_C_SUSPEND)
			{
				vsfurb->transfer_buffer = NULL;
				vsfurb->transfer_length = 0;
				err = hub_clear_port_feature(hub->usbh, vsfurb,
						hub->counter, USB_PORT_FEAT_C_SUSPEND);
				if (err != VSFERR_NONE)
					return err;
				vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
				if (vsfurb->status != URB_OK)
					return VSFERR_FAIL;

				hub->hub_portsts.wPortChange &= ~USB_PORT_STAT_C_SUSPEND;
			}
			if (hub->hub_portsts.wPortChange & USB_PORT_STAT_C_OVERCURRENT)
			{
				vsfurb->transfer_buffer = NULL;
				vsfurb->transfer_length = 0;
				err = hub_clear_port_feature(hub->usbh, vsfurb,
						hub->counter, USB_PORT_FEAT_C_OVER_CURRENT);
				if (err != VSFERR_NONE)
					return err;
				vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
				if (vsfurb->status != URB_OK)
					return VSFERR_FAIL;

				hub->hub_portsts.wPortChange &= ~USB_PORT_FEAT_C_OVER_CURRENT;

				// TODO : power every port
			}
			if (hub->hub_portsts.wPortChange & USB_PORT_STAT_C_RESET)
			{
				vsfurb->transfer_buffer = NULL;
				vsfurb->transfer_length = 0;
				err = hub_clear_port_feature(hub->usbh, vsfurb,
						hub->counter, USB_PORT_FEAT_C_RESET);
				if (err != VSFERR_NONE)
					return err;
				vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
				if (vsfurb->status != URB_OK)
					return VSFERR_FAIL;

				hub->hub_portsts.wPortChange &= ~USB_PORT_FEAT_C_RESET;
			}
		} while (hub->counter++ < hub->dev->maxchild);

		// TODO : poll hub status

		vsfsm_pt_delay(pt, 500);
	} while (1);
	vsfsm_pt_end(pt);

	return VSFERR_NONE;
}