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; }
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; }
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); }
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; }
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; }
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; }