/* * This is our function to emulate USBH_SendCtrlMsg() but give us enough * access to make aborts/resets work */ static int usb_stor_control_msg(UMAS_DATA_T *umas, uint32_t pipe, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, void *data, uint16_t size) { URB_T *urb = umas->current_urb; int status; volatile int t0; DEV_REQ_T dr; /* fill in the structure */ dr.requesttype = requesttype; dr.request = request; dr.value = value; dr.index = index; dr.length = size; /* fill the URB */ FILL_CONTROL_URB(urb, umas->pusb_dev, pipe, (uint8_t *)&dr, data, size, usb_stor_blocking_completion, NULL); urb->actual_length = 0; urb->error_count = 0; urb->transfer_flags = USB_ASYNC_UNLINK; _UmasUrbComplete = 0; /* submit the URB */ status = USBH_SubmitUrb(urb); if(status) return status; /* wait for the completion of the URB */ #if 1 for(t0 = 0; t0 < 0x8000000; t0++) { if(is_urb_completed()) break; } if(t0 >= 0x8000000) #else t0 = umas_get_ticks(); while(umas_get_ticks() - t0 < 300) { if(is_urb_completed()) break; } if(umas_get_ticks() - t0 >= 300) #endif { UMAS_DEBUG("usb_stor_control_msg time-out failed!\n"); return USB_ERR_TIMEOUT; } /* return the actual length of the data transferred if no error*/ status = urb->status; if(status >= 0) status = urb->actual_length; return status; }
/* * This is our function to emulate usb_bulk_msg() but give us enough * access to make aborts/resets work */ static int usb_stor_bulk_msg(UMAS_DATA_T *umas, void *data, int pipe, uint32_t len, uint32_t *act_len) { URB_T *urb = umas->current_urb; volatile int t0; int status; /* fill the URB */ FILL_BULK_URB(urb, umas->pusb_dev, pipe, data, len, usb_stor_blocking_completion, NULL); urb->actual_length = 0; urb->error_count = 0; urb->transfer_flags = USB_ASYNC_UNLINK; _UmasUrbComplete = 0; /* submit the URB */ status = USBH_SubmitUrb(urb); if(status) return status; #if 1 for(t0 = 0; t0 < 0x1000000; t0++) { if(is_urb_completed()) break; } if(t0 >= 0x8000000) #else t0 = umas_get_ticks(); while(umas_get_ticks() - t0 < 500) { if(is_urb_completed()) break; } if(umas_get_ticks() - t0 >= 500) #endif { UMAS_DEBUG("usb_stor_bulk_msg time-out failed!\n"); return USB_ERR_TIMEOUT; } /* return the actual length of the data transferred */ *act_len = urb->actual_length; return urb->status; }
static int usb_hub_configure(USB_HUB_T *hub, EP_INFO_T *ep_info) { USB_DEV_T *dev = hub->dev; USB_HUB_STATUS_T hubstatus; uint32_t pipe; int maxp, ret; USB_info("[HUB] Enter usb_hub_configure()... hub:%d\n", hub->dev->devnum); /* Request the entire hub descriptor. */ ret = usb_get_hub_descriptor(dev, &hub->descriptor, sizeof(USB_HUB_DESC_T)); /* <hub->descriptor> is large enough for a hub with 127 ports; * the hub can/will return fewer bytes here. */ if(ret < 0) { USB_error("Erro - Unable to get hub descriptor (err = %d)\n", ret); return ret; } dev->maxchild = hub->descriptor.bNbrPorts; #ifdef USB_VERBOSE_DEBUG USB_info("%d port%s detected\n", hub->descriptor.bNbrPorts, (hub->descriptor.bNbrPorts == 1) ? "" : "s"); /* D2: Identifying a Compound Device */ if(hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND) { USB_info("part of a compound device\n"); } else { USB_info("standalone hub\n"); } /* D1..D0: Logical Power Switching Mode */ switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: USB_info("ganged power switching\n"); break; case 0x01: USB_info("individual port power switching\n"); break; case 0x02: case 0x03: USB_info("unknown reserved power switching mode\n"); break; } /* D4..D3: Over-current Protection Mode */ switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: USB_info("global over-current protection\n"); break; case 0x08: USB_info("individual port over-current protection\n"); break; case 0x10: case 0x18: USB_info("no over-current protection\n"); break; } switch(dev->descriptor.bDeviceProtocol) { case 0: break; case 1: USB_debug("Single TT, "); break; case 2: USB_debug("TT per port, "); break; default: USB_debug("Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol); break; } USB_info("power on to power good time: %dms\n", hub->descriptor.bPwrOn2PwrGood * 2); USB_info("hub controller current requirement: %dmA\n", hub->descriptor.bHubContrCurrent); #endif ret = usb_get_hub_status(dev, &hubstatus); if(ret < 0) { USB_error("Unable to get hub %d status (err = %d)\n", hub->dev->devnum, ret); return ret; } hubstatus.wHubStatus = USB_SWAP16(hubstatus.wHubStatus); #ifdef USB_VERBOSE_DEBUG /* Hub status bit 0, Local Power Source */ if(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) { USB_info("local power source is lost (inactive)\n"); } else { USB_info("local power source is good\n"); } /* Hub status bit 1, Over-current Indicator */ if(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) { USB_info("!! over-current\n"); } else { USB_info("No over-current.\n"); } #endif /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(dev, ep_info->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if(maxp > sizeof(hub->buffer)) maxp = sizeof(hub->buffer); hub->urb = USBH_AllocUrb(); if(!hub->urb) { USB_error("Error - couldn't allocate interrupt urb"); return USB_ERR_NOMEM; } #if 1 /* YCHuang 2012.06.01 */ if(ep_info->bInterval < 16) ep_info->bInterval = 16; #endif FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub, ep_info->bInterval); ret = USBH_SubmitUrb(hub->urb); if(ret) { USB_error("Error - USBH_SubmitUrb failed (%d)", ret); USBH_FreeUrb(hub->urb); return ret; } if(g_ohci_bus.root_hub != hub->dev) usb_hub_power_on(hub); return 0; }