コード例 #1
0
ファイル: usb-hub.c プロジェクト: AmesianX/WinQEMU
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;
}
コード例 #2
0
struct usb_device *usb_poll_hub_port( struct rt_urb *p_urb, __u8 hub_port_nr )
{
  struct usb_device *p_new_dev  = NULL;
  portstat_t p_pstat;
  struct rt_urb *p_urb_save     = NULL;
  struct usb_device *p_usbdev_save = NULL;

  if(! p_urb || !p_urb->p_usbdev || !p_urb->p_usbdev->p_hcd){
    if (!p_urb)                           ERR("[ERROR] %s - Invalid URB-Pointer \n", __FUNCTION__);
    if (!p_urb->p_usbdev)                 ERR("[ERROR] %s - Invalid USB-Device-Pointer \n", __FUNCTION__);
    if (!p_urb->p_usbdev->p_hcd)          ERR("[ERROR] %s - Invalid Host-Controller-Pointer \n", __FUNCTION__);
    return NULL;
  }

  if (hub_get_portstat( p_urb, hub_port_nr, &p_pstat)){
    ERR_MSG2(p_urb->p_hcd,p_urb->p_usbdev," %s - Get Portstat for Port[%d] failed \n",__FUNCTION__, hub_port_nr);
    return NULL;
  }

  dump_portstatus( p_urb->p_usbdev, hub_port_nr, &p_pstat);

  if( p_pstat.change.c_port_connection ) {  /* Connection detect */
    if( hub_clear_port_feature( p_urb , hub_port_nr, C_PORT_CONNECTION) ){
      return NULL;
    }
    if( p_pstat.stat.port_connection){

      hub_port_resume( p_urb ,hub_port_nr);
      hub_port_reset( p_urb ,hub_port_nr);
      udelay(10);

      // unregister hub_urb
      p_urb_save    = p_urb;
      p_usbdev_save = p_urb->p_usbdev;
      nrt_usb_unregister_urb(p_urb);

      p_new_dev = nrt_usb_config_dev( p_urb->p_hcd, p_urb->p_usbdev->rh_port, p_pstat.stat.port_lowspeed);

      // re-register hub_urb
      p_urb = p_urb_save;
      p_urb->p_usbdev = p_usbdev_save;
      p_urb->p_hcd = p_usbdev_save->p_hcd;
      nrt_usb_register_urb(p_urb);

      return p_new_dev;

    }

    hub_set_port_feature(   p_urb, hub_port_nr, PORT_SUSPEND );
    hub_clear_port_feature( p_urb, hub_port_nr, PORT_ENABLE  );

  }

  return NULL;
}
コード例 #3
0
int usb_init_hub( struct rt_urb *p_urb )
{
  int i;
  hub_descriptor_t *p_hub_desc = NULL;


  if(!p_urb || ! p_urb->p_usbdev){
    return -1;
  }

  p_hub_desc = kmalloc( sizeof(hub_descriptor_t),GFP_KERNEL);
  if(!p_hub_desc){
    return -ENOMEM;
  }

  alloc_bytes += sizeof(hub_descriptor_t);
  DBG("RT-USBCORE: %d Byte allocated (%s %d Byte)\n", alloc_bytes, "+", sizeof(hub_descriptor_t) );

  memset( p_hub_desc,0,sizeof( hub_descriptor_t ) );
  p_urb->p_usbdev->p_hub_desc = p_hub_desc;

  DBG_MSG2(p_urb->p_hcd,p_urb->p_usbdev," Hub-Descriptor saved @ 0x%p\n",p_hub_desc);
  if( hub_get_descriptor( p_urb, p_hub_desc ) ){
    kfree(p_hub_desc);
    alloc_bytes -= sizeof(hub_descriptor_t);
    DBG("RT-USBCORE: %d Byte allocated (%s %d Byte)\n", alloc_bytes, "-", sizeof(hub_descriptor_t) );

    return -1;
  }

  dump_hub_descriptor( p_urb->p_usbdev );

  for(i=1; i<= p_hub_desc->bNbrPorts; i++) {
    if( hub_set_port_feature( p_urb, i, PORT_POWER) < 0 ){
      continue;
    }
  }

  /* Angabe in 2ms -Intervallen */
  udelay( p_hub_desc->bPwrOn2PwrGood * 2000);

  return(0);
}
コード例 #4
0
int hub_port_reset( struct rt_urb *p_urb, __u16 port_nr)
{
  int tries = 100;
  int us_delay = 10000;
  portstat_t pstat;

  if( hub_set_port_feature( p_urb, port_nr, PORT_RESET) ){
    return -1;
  }

  do{
    udelay(us_delay);
    if( hub_get_portstat( p_urb, port_nr, &pstat) ){
      return -1;
    }
  } while( tries-- && !pstat.change.c_port_reset );

  if(!tries){
    return(-1);
  }

  hub_clear_port_feature( p_urb, port_nr, C_PORT_RESET);
  return 0;
}
コード例 #5
0
ファイル: vsfusbh_HUB.c プロジェクト: hank-fan/vsf
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;
}
コード例 #6
0
ファイル: vsfusbh_HUB.c プロジェクト: hank-fan/vsf
static vsf_err_t hub_init_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);

	vsfurb->sm = &hub->sm;

	// init hub
	err = hub_class_check(hub);
	if (err != VSFERR_NONE)
		return err;

	vsfurb->transfer_buffer = &hub->hub_desc;
	vsfurb->transfer_length = 4;
	err = hub_get_descriptor(hub->usbh, vsfurb);
	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_desc.bDescLength > sizeof(hub->hub_desc))
	{
		return VSFERR_FAIL;
	}

	vsfurb->transfer_buffer = &hub->hub_desc;
	vsfurb->transfer_length = hub->hub_desc.bDescLength;
	err = hub_get_descriptor(hub->usbh, vsfurb);
	if (err != VSFERR_NONE)
		return err;
	vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
	if (vsfurb->status != URB_OK)
		return VSFERR_FAIL;

	hub->dev->maxchild = min(hub->hub_desc.bNbrPorts, USB_MAXCHILDREN);

	vsfurb->transfer_buffer = &hub->hub_status;
	vsfurb->transfer_length = sizeof(hub->hub_status);
	err = hub_get_status(hub->usbh, vsfurb);
	if (err != VSFERR_NONE)
		return err;
	vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
	if (vsfurb->status != URB_OK)
		return VSFERR_FAIL;

	hub->counter = 0;

	do
	{
		hub->counter++;
		hub->vsfurb->transfer_buffer = NULL;
		hub->vsfurb->transfer_length = 0;
		err = hub_set_port_feature(hub->usbh, hub->vsfurb, hub->counter,
				USB_PORT_FEAT_POWER);
		if (err != VSFERR_NONE)
			return err;
		vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);
		if (vsfurb->status != URB_OK)
			return VSFERR_FAIL;
		vsfsm_pt_delay(pt, hub->hub_desc.bPwrOn2PwrGood * 2);
	} while (hub->counter < hub->dev->maxchild);

	vsfsm_pt_end(pt);

	return VSFERR_NONE;
}