/** * @brief USBH_Connect * USB Connect callback function from the Interrupt. * @param selected device * @retval none */ rt_uint8_t susb_connect (USB_OTG_CORE_HANDLE *pdev) { struct uhost_msg msg; pdev->host.ConnSts = 1; rt_kprintf("susb_connect\n"); if(root_hub.port_status[0] & PORT_CCS) return 0; if(ignore_disconnect == RT_TRUE) return 0; USB_Host.Control.hc_num_out = USBH_Alloc_Channel(&USB_OTG_Core, 0x00); USB_Host.Control.hc_num_in = USBH_Alloc_Channel(&USB_OTG_Core, 0x80); /* Open Control pipes */ USBH_Open_Channel(&USB_OTG_Core, USB_Host.Control.hc_num_in, USB_Host.device_prop.address,USB_Host.device_prop.speed, EP_TYPE_CTRL, USB_Host.Control.ep0size); /* Open Control pipes */ USBH_Open_Channel(&USB_OTG_Core, USB_Host.Control.hc_num_out, USB_Host.device_prop.address, USB_Host.device_prop.speed, EP_TYPE_CTRL, USB_Host.Control.ep0size); root_hub.port_status[0] |= (PORT_CCS | PORT_CCSC); msg.type = USB_MSG_CONNECT_CHANGE; msg.content.uhub = &root_hub; rt_usb_post_event(&msg, sizeof(struct uhost_msg)); return 0; }
/** * @brief USBH_MSC_InterfaceInit * Interface initialization for MSC class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status : Status of class request handled. */ static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, void *phost) { USBH_HOST *pphost = phost; if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == MSC_CLASS) && \ (pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == MSC_PROTOCOL)) { if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0] [0].wMaxPacketSize; } if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; } MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkOutEp); MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkInEp); /* Open the new channels */ USBH_Open_Channel (pdev, MSC_Machine.hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, MSC_Machine.MSBulkOutEpSize); USBH_Open_Channel (pdev, MSC_Machine.hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, MSC_Machine.MSBulkInEpSize); } else { pphost->usr_cb->DeviceNotSupported(); } return USBH_OK ; }
/** * @brief USBH_MSC_InterfaceInit * Interface initialization for MSC class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status : Status of class request handled. */ static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, USBH_DeviceProp_TypeDef *hdev) { if((hdev->Itf_Desc.bInterfaceClass == MSC_CLASS) && \ (hdev->Itf_Desc.bInterfaceProtocol == MSC_PROTOCOL)) { if(hdev->Ep_Desc[0].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (hdev->Ep_Desc[0].bEndpointAddress); MSC_Machine.MSBulkInEpSize = hdev->Ep_Desc[0].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (hdev->Ep_Desc[0].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = hdev->Ep_Desc[0].wMaxPacketSize; } if(hdev->Ep_Desc[1].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (hdev->Ep_Desc[1].bEndpointAddress); MSC_Machine.MSBulkInEpSize = hdev->Ep_Desc[1].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (hdev->Ep_Desc[1].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = hdev->Ep_Desc[1].wMaxPacketSize; } MSC_Machine.hc_num_out = USBH_Alloc_Channel(&USB_OTG_FS_dev, MSC_Machine.MSBulkOutEp); MSC_Machine.hc_num_in = USBH_Alloc_Channel(&USB_OTG_FS_dev, MSC_Machine.MSBulkInEp); /* Open the new channels */ USBH_Open_Channel (pdev, MSC_Machine.hc_num_out, hdev->address, hdev->speed, EP_TYPE_BULK, MSC_Machine.MSBulkOutEpSize); USBH_Open_Channel (pdev, MSC_Machine.hc_num_in, hdev->address, hdev->speed, EP_TYPE_BULK, MSC_Machine.MSBulkInEpSize); } else { USBH_Machine.usr_cb->USBH_USR_DeviceNotSupported(); } return USBH_OK ; }
/** * This function will allocate a pipe for specified endpoint, it will be used to do transfer. * * @param pipe the pointer of pipe handle to be allocated. * @param ifinst the usb interface instance. * @param ep the endpoint descriptor. * @param func_callback callback function to be registed * * @return the error code, RT_EOK on successfully. */ static rt_err_t susb_alloc_pipe(upipe_t* pipe, uifinst_t ifinst, uep_desc_t ep, func_callback callback) { rt_uint32_t channel, speed; rt_uint8_t ep_type; upipe_t p; RT_ASSERT(ep != RT_NULL); p = (upipe_t)rt_malloc(sizeof(struct upipe)); p->ifinst = ifinst; p->callback = callback; p->status = UPIPE_STATUS_OK; rt_memcpy(&p->ep, ep, ep->bLength); speed = HCD_GetCurrentSpeed(&USB_OTG_Core); channel = USBH_Alloc_Channel(&USB_OTG_Core, p->ep.bEndpointAddress); if((ep->bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_BULK) ep_type = EP_TYPE_BULK; else if((ep->bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT) ep_type = EP_TYPE_INTR; else rt_kprintf("unsupported endpoint type\n"); /* Open the new channels */ USBH_Open_Channel(&USB_OTG_Core, channel, ifinst->uinst->address, speed, ep_type, p->ep.wMaxPacketSize); RT_DEBUG_LOG(1, ("susb_alloc_pipe : %d, chanel %d, max packet size %d\n", p->ep.bEndpointAddress, channel, p->ep.wMaxPacketSize)); p->user_data = (void*)channel; *pipe = p; return RT_EOK; }
/** * @brief USBH_HID_InterfaceInit * The function init the HID class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status :Response for USB HID driver intialization */ static USBH_Status USBH_HID_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, void *phost) { uint8_t maxEP; USBH_HOST *pphost = phost; uint8_t num =0; USBH_Status status = USBH_BUSY ; HID_Machine.state = HID_ERROR; //printf("USBH_HID_InterfaceInit\n"); if(pphost->device_prop.Itf_Desc[0].bInterfaceSubClass == HID_BOOT_CODE) { /*Decode Bootclass Protocl: Mouse or Keyboard*/ if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) { HID_Machine.cb = &HID_KEYBRD_cb; } else if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_MOUSE_BOOT_CODE) { HID_Machine.cb = &HID_MOUSE_cb; } //printf("USBH_HID_InterfaceInit %x %x\n", pphost->device_prop.Itf_Desc[0].bInterfaceSubClass, pphost->device_prop.Itf_Desc[0].bInterfaceProtocol); HID_Machine.state = HID_IDLE; HID_Machine.ctl_state = HID_REQ_IDLE; HID_Machine.ep_addr = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress; HID_Machine.length = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; HID_Machine.poll = pphost->device_prop.Ep_Desc[0][0].bInterval ; if (HID_Machine.poll < HID_MIN_POLL) { HID_Machine.poll = HID_MIN_POLL; } /* Check fo available number of endpoints */ /* Find the number of EPs in the Interface Descriptor */ /* Choose the lower number in order not to overrun the buffer allocated */ maxEP = ( (pphost->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? pphost->device_prop.Itf_Desc[0].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS); /* Decode endpoint IN and OUT address from interface descriptor */ for (num=0; num < maxEP; num++) { if(pphost->device_prop.Ep_Desc[0][num].bEndpointAddress & 0x80) { HID_Machine.HIDIntInEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); HID_Machine.hc_num_in =\ USBH_Alloc_Channel(pdev, pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); /* Open channel for IN endpoint */ USBH_Open_Channel (pdev, HID_Machine.hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_INTR, HID_Machine.length); } else { HID_Machine.HIDIntOutEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); HID_Machine.hc_num_out =\ USBH_Alloc_Channel(pdev, pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); /* Open channel for OUT endpoint */ USBH_Open_Channel (pdev, HID_Machine.hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_INTR, HID_Machine.length); } } start_toggle =0; status = USBH_OK; } else { pphost->usr_cb->DeviceNotSupported(); } return status; }
/** * @brief USBH_HID_InterfaceInit * The function init the HID class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status :Response for USB HID driver intialization */ static USBH_Status USBH_HID_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, void *phost) { uint8_t maxEP; USBH_HOST *pphost = phost; HID_Machine_TypeDef *HID_Machine = &HID_Machines[pdev->cfg.coreID]; uint8_t num =0; USBH_Status status = USBH_BUSY ; HID_Machine->state = HID_ERROR; // should always be the case, no need to detect //if (HID_GAMEPAD_cb.Detect(pphost->device_prop.Dev_Desc.idVendor, pphost->device_prop.Dev_Desc.idProduct) || (pphost->device_prop.Itf_Desc[0].bInterfaceSubClass == HID_BOOT_CODE)) { /*Decode Bootclass Protocl: Mouse or Keyboard*/ if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) { HID_Machine->cb = &HID_KEYBRD_cb; } else if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_MOUSE_BOOT_CODE) { HID_Machine->cb = &HID_MOUSE_cb; } else { HID_Machine->cb = &HID_GAMEPAD_cb; } HID_Machine->state = HID_IDLE; HID_Machine->ctl_state = HID_REQ_IDLE; HID_Machine->ep_addr = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress; HID_Machine->length = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; HID_Machine->poll = pphost->device_prop.Ep_Desc[0][0].bInterval ; if (HID_Machine->poll < HID_MIN_POLL) { HID_Machine->poll = HID_MIN_POLL; } /* Check fo available number of endpoints */ /* Find the number of EPs in the Interface Descriptor */ /* Choose the lower number in order not to overrun the buffer allocated */ maxEP = ( (pphost->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? pphost->device_prop.Itf_Desc[0].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS); /* Decode endpoint IN and OUT address from interface descriptor */ for (num=0; num < maxEP; num++) { if(pphost->device_prop.Ep_Desc[0][num].bEndpointAddress & 0x80) { HID_Machine->HIDIntInEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); HID_Machine->hc_num_in =\ USBH_Alloc_Channel(pdev, pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); /* Open channel for IN endpoint */ USBH_Open_Channel (pdev, HID_Machine->hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_INTR, HID_Machine->length); } else { HID_Machine->HIDIntOutEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); HID_Machine->hc_num_out =\ USBH_Alloc_Channel(pdev, pphost->device_prop.Ep_Desc[0][num].bEndpointAddress); /* Open channel for OUT endpoint */ USBH_Open_Channel (pdev, HID_Machine->hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_INTR, HID_Machine->length); } } start_toggles[pdev->cfg.coreID] =0; status = USBH_OK; } /* else { // pphost->usr_cb->DeviceNotSupported(); } */ return status; }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; // if (USB_DEBUG) { // USB_debugEvent(); // xprintf("USBH_Process phost->gState = %d\n", phost->gState); // } /* check for Host port events */ if (((HCD_IsDeviceConnected(pdev) == 0) || (HCD_IsPortEnabled(pdev) == 0)) && (phost->gState != HOST_IDLE)) { if (phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; // if (USB_DEBUG){ // USB_debugEvent(); // } } } switch (phost->gState) { case HOST_IDLE: if (HCD_IsDeviceConnected(pdev)) { phost->gState = HOST_WAIT_PRT_ENABLED; /*wait debounce delay */ USB_OTG_BSP_mDelay(200); // was 100 // if (USB_DEBUG){ // USB_debugEvent(); // } /* Apply a port RESET */ HCD_ResetPort(pdev); /* User RESET callback*/ phost->usr_cb->ResetDevice(); } break; case HOST_WAIT_PRT_ENABLED: if (pdev->host.PortEnabled == 1) { phost->gState = HOST_DEV_ATTACHED; } break; case HOST_DEV_ATTACHED: phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); // if (USB_DEBUG){ // USB_debugEvent(); // } phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); // if (USB_DEBUG){ // USB_debugEvent(); // } /* Open Control pipes */ USBH_Open_Channel(pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); // if (USB_DEBUG){ // USB_debugEvent(); // } /* Open Control pipes */ USBH_Open_Channel(pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); // if (USB_DEBUG){ // USB_debugEvent(); // } break; case HOST_ENUMERATION: /* Check for enumeration status */ if (USBH_HandleEnum(pdev, phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); phost->gState = HOST_USR_INPUT; // if (USB_DEBUG){ // USB_debugEvent(); // } } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if (phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { if ((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } // if (USB_DEBUG){ // USB_debugEvent(); // } } break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ // if (USB_DEBUG){ // USB_debugEvent(); // } status = phost->class_cb->Requests(pdev, phost); if (status == USBH_OK) { phost->gState = HOST_CLASS; // if (USB_DEBUG){ // USB_debugEvent(); // } } else { // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_HandleControl(pdev, phost); break; case HOST_SUSPENDED: break; case HOST_ERROR_STATE: /* Re-Initilaize Host for new Enumeration */ // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED: // if (USB_DEBUG){ // USB_debugEvent(); // } /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected(); /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; /* Re-Initilaize Host for new Enumeration */ HCD_Init(pdev, #ifdef USE_USB_OTG_FS USB_OTG_FS_CORE_ID #else USB_OTG_HS_CORE_ID #endif ); break; default: break; } }
/** * @brief USBH_MSC_InterfaceInit * Interface initialization for MSC class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status : Status of class request handled. */ static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, void *phost) { USBH_HOST *pphost = phost; if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == MSC_CLASS) && \ (pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == MSC_PROTOCOL)) { if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0] [0].wMaxPacketSize; } if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80) { MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; } else { MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; } MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkOutEp); MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkInEp); /* Open the new channels */ USBH_Open_Channel (pdev, MSC_Machine.hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, MSC_Machine.MSBulkOutEpSize); USBH_Open_Channel (pdev, MSC_Machine.hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, MSC_Machine.MSBulkInEpSize); } else { if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_HUB) { LCD_ErrLog("Hub is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_CDCC) { LCD_ErrLog("Communications and CDC Control device is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_HID) { LCD_ErrLog("HID device is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_PRINTER) { LCD_ErrLog("Printer device is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_SMARTCARD) { LCD_ErrLog("Smart Card device is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_VIDEO) { LCD_ErrLog("Video device is not supported.\n"); } else if (pphost->device_prop.Itf_Desc[0].bInterfaceClass == USB_AVD) { LCD_ErrLog("Audio/Video Devices is not supported.\n"); } else { LCD_ErrLog ("The attached device is not supported. \n"); } pphost->usr_cb->DeviceNotSupported(); } return USBH_OK ; }
void USBPT_Work() { if (USBPT_Has_Dev == 0) { if (HCD_IsDeviceConnected(&USB_OTG_Core_host) != 0) { USBPT_printf("USBPT Device Connecting \r\n"); if (USBH_Open_Channel( &USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in), 0x80, USBPT_Dev->device_prop.address, // still 0 at this point USBPT_Dev->device_prop.speed, EP_TYPE_CTRL, USBPT_Dev->Control.ep0size) == HC_OK && USBH_Open_Channel( &USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out), 0x00, USBPT_Dev->device_prop.address, // still 0 at this point USBPT_Dev->device_prop.speed, EP_TYPE_CTRL, USBPT_Dev->Control.ep0size) == HC_OK ) { DCD_DevConnect(&USB_OTG_Core_dev); USBPT_Has_Dev = 1; } else { dbg_printf(DBGMODE_ERR, "USBPT Unable to allocate control EP HC \r\n"); } } else { return; } } else { if (HCD_IsDeviceConnected(&USB_OTG_Core_host) == 0) { USBPT_printf("USBPT Device Disconnecting \r\n"); USBD_DeInit(&USB_OTG_Core_dev); DCD_DevDisconnect(&USB_OTG_Core_dev); USBPT_Has_Dev = 0; for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBH_Free_Channel(&USB_OTG_Core_host, &(USBPTH_Listeners[i].hc)); } USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out)); USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in)); } } for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i]; int8_t hc = USBPTH_Listeners[i].hc; if (hc >= 0) // if listener is actually allocated { USBH_EpDesc_TypeDef* epDesc = pl->epDesc; uint8_t epnum = epDesc->bEndpointAddress; uint8_t epType = 0; USBPT_GeneralInDataLen = epDesc->wMaxPacketSize; // try to send read tokens only on even frames if (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0) continue; dbg_trace(); // attempt to start the read, check the read type first if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; USBH_InterruptReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; USBH_BulkReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; USBH_IsocReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } // now we wait for a reply, or maybe there isn't one USBH_Status status; char sent = 0; delay_1ms_cnt = 100; do { URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc); if (us == URB_DONE) { // data was indeed received // print it to the serial port for monitoring USBPT_printf("USBPT:IN:EP0x%02X:", epnum); for (uint16_t c = 0; c < USBPT_GeneralInDataLen; c++) { USBPT_printf(" 0x%02X", USBPT_GeneralInData[c]); } USBPT_printf("\r\n"); // relay the data to the host DCD_EP_Tx(&USB_OTG_Core_dev, epnum, USBPT_GeneralInData, USBPT_GeneralInDataLen); sent = 1; break; } else if (us == URB_ERROR) { dbg_printf(DBGMODE_ERR, "DataIn Error on EP 0x%02X \r\n", epnum); break; } else if (us == URB_STALL) { dbg_printf(DBGMODE_ERR, "DataIn Stalled EP 0x%02X \r\n", epnum); break; } else if (us == URB_NOTREADY) { // NAK, no data break; } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { dbg_printf(DBGMODE_ERR, "DataIn Read Timed Out EP 0x%02X \r\n", epnum); } } } }
uint8_t USBPTD_DataOut (void *pcore , uint8_t epnum) { USB_OTG_CORE_HANDLE* pcore_ = (USB_OTG_CORE_HANDLE*)pcore; DCD_DEV* pdev = &(pcore_->dev); uint8_t* data; uint16_t wLength; if (epnum == 0x00) { // CTRL REQ wLength = USBPT_CtrlDataLen; data = USBPT_CtrlData; } else { wLength = pdev->out_ep[epnum].xfer_count; data = pdev->out_ep[epnum].xfer_buff; } // print to monitor USBPT_printf("USBPT:OUT:EP0x%02X:", epnum); for (uint16_t i = 0; i < wLength; i++) { USBPT_printf(" 0x%02X", data[i]); } USBPT_printf("\r\n"); if (epnum == 0x00) { // CTRL REQ USBH_Status status; delay_1ms_cnt = 100; // wait for transfer complete do { status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen ); if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } else { status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev); if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut timed out while sending to device, status: 0x%04X \r\n", status); USBD_CtlError(pcore , 0); return USBD_FAIL; } else if (status != USBH_OK) { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut failed to send to device, status: 0x%04X \r\n", status); USBD_CtlError(pcore , 0); return USBD_FAIL; } else { // everything is OK USBD_CtlSendStatus(pcore); return USBD_OK; } } else { wLength = pdev->out_ep[epnum].xfer_count; data = pdev->out_ep[epnum].xfer_buff; // allocate memory needed if (USBPT_GeneralOutData != 0) free(USBPT_GeneralOutData); USBPT_GeneralOutDataLen = wLength; USBPT_GeneralOutData = malloc(wLength); memcpy(USBPT_GeneralOutData, data, USBPT_GeneralOutDataLen); USBH_EpDesc_TypeDef* epDesc = 0; for (uint8_t i = 0; i < USBPTH_OutEPCnt; i++) { // look for appropriate EP if (USBPTH_OutEP[i]->bEndpointAddress == epnum) { epDesc = USBPTH_OutEP[i]; break; } } if (epDesc != 0) // EP found { uint8_t epType = 0; int8_t hc = -1; if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; } // dynamically allocate host channel for use if (USBH_Open_Channel( &USB_OTG_Core_host, &hc, epnum, USBPT_Dev->device_prop.address, USBPT_Dev->device_prop.speed, epType, epDesc->wMaxPacketSize) == HC_OK) { // try to only send on even frame volatile uint32_t syncTries = 0x7FFFFFFF; while (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0 && syncTries--) __NOP(); // send using appropriate method switch (epType) { case EP_TYPE_INTR: USBH_InterruptSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc); break; case EP_TYPE_BULK: USBH_BulkSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc); break; case EP_TYPE_ISOC: USBH_IsocSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc); break; default: break; } // wait until done sending USBH_Status status; delay_1ms_cnt = 100; do { URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc); if (us == URB_DONE) { break; } else if (us == URB_ERROR) { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Error on EP 0x%02X \r\n", epnum); DCD_EP_Stall(pcore, epnum); break; } else if (us == URB_STALL) { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Stalled EP 0x%02X \r\n", epnum); DCD_EP_Stall(pcore, epnum); break; } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Timed Out EP 0x%02X \r\n", epnum); } // free the channel to be used by something else later USBH_Free_Channel(&USB_OTG_Core_host, &hc); } else { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Failed to Alloc HC for EP 0x%02X \r\n", epnum); } } else { dbg_printf(DBGMODE_ERR, "USBPTD_DataOut No Such EP 0x%02X \r\n", epnum); } return USBD_OK; } return USBD_OK; }
uint8_t USBPTD_SetupStage(USB_OTG_CORE_HANDLE* pcore, USB_SETUP_REQ* req) { // store for later use from another function memcpy(USBPT_LastSetupPacket, pcore->dev.setup_packet, 24); // print for monitoring USBPT_printf("\b\r\n USBPT:SETUP:"); for (uint8_t i = 0; i < 8; i++) { USBPT_printf(" 0x%02X", USBPT_LastSetupPacket[i]); } USBPT_printf("\r\n"); // prepare to be sent to the device memcpy(USBPT_Dev->Control.setup.d8, USBPT_LastSetupPacket, 8); // set address must be handled explicitly if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_SET_ADDRESS) { // let the internal code handle it for the device interface USBD_StdDevReq(pcore, req); // pass it to the downstream device USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100); USBD_CtlSendStatus(pcore); // modifiy our host channel to match USBPT_Dev->device_prop.address = (uint8_t)(req->wValue) & 0x7F; USBH_Modify_Channel (&USB_OTG_Core_host, USBPT_Dev->Control.hc_num_in, USBPT_Dev->device_prop.address, 0, 0, 0); USBH_Modify_Channel (&USB_OTG_Core_host, USBPT_Dev->Control.hc_num_out, USBPT_Dev->device_prop.address, 0, 0, 0); // modify all other channels to match for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i]; uint8_t hc = pl->hc; if (hc != 0 && hc != HC_ERROR) // if listener is actually allocated { USBH_EpDesc_TypeDef* epDesc = pl->epDesc; uint8_t epType = 0; if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) { epType = EP_TYPE_CTRL; } USBH_Modify_Channel( &USB_OTG_Core_host, USBPTH_Listeners[i].hc, USBPT_Dev->device_prop.address, USBPT_Dev->device_prop.speed, epType, USBPTH_Listeners[i].epDesc->wMaxPacketSize); } } // note: out direction channels are dynamically allocated only when needed // so we don't need to modify those channel addresses return USBD_OK; } // no data means we can just directly relay the data if (req->wLength == 0) { USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100); USBD_CtlSendStatus(pcore); return USBD_OK; } // there is extra data later USBPT_CtrlDataLen = req->wLength; if (USBPT_CtrlData != 0) free(USBPT_CtrlData); USBPT_CtrlData = malloc(USBPT_CtrlDataLen); USBH_Status status; // wait until previous req is finished delay_1ms_cnt = 100; while (delay_1ms_cnt > 0 && USBPT_Dev->Control.state != CTRL_COMPLETE && USBPT_Dev->Control.state != CTRL_IDLE && USBPT_Dev->Control.state != CTRL_ERROR && USBPT_Dev->Control.state != CTRL_STALLED); { status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev); } // finalize previous ctrl req if (USBPT_Dev->RequestState == CMD_WAIT) { USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, 0 , 0 ); } // prepare new setup USBH_SubmitSetupRequest(USBPT_Dev, USBPT_CtrlData, USBPT_CtrlDataLen); USBPT_Dev->RequestState = CMD_WAIT; USBH_CtlSendSetup (&USB_OTG_Core_host, USBPT_Dev->Control.setup.d8, USBPT_Dev->Control.hc_num_out); USBPT_Dev->Control.state = CTRL_SETUP_WAIT; USBPT_Dev->Control.timer = HCD_GetCurrentFrame(pcore); USBPT_Dev->Control.timeout = 50; if ((req->bmRequest & 0x80) == 0) { // H2D // we need to obtain the data from EP0_RxReady first USBD_CtlPrepareRx (pcore, USBPT_CtrlData, USBPT_CtrlDataLen); return USBD_OK; } else { // D2H // wait for request to finish delay_1ms_cnt = 100; do { status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen ); if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } else { status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev); if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { // timeout dbg_printf(DBGMODE_ERR, "USBPT Setup Timed Out \r\n"); USBD_CtlSendStatus(pcore); // we reply with nothing to simulate a timeout return USBH_OK; } else if (status == USBH_OK) { // all good, send back the data USBD_CtlSendData (pcore, USBPT_CtrlData, USBPT_CtrlDataLen); // handle config descriptors specially, we need to know what channels to open based on endpoints if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_GET_DESCRIPTOR && req->wValue == USB_DESC_CONFIGURATION && req->wLength > USB_CONFIGURATION_DESC_SIZE) { // this is a full length configuration descriptor // we need this info to open as many D2H endpoints to channels USBH_ParseCfgDesc(&USBPT_Dev->device_prop.Cfg_Desc, USBPT_Dev->device_prop.Itf_Desc, USBPT_Dev->device_prop.Ep_Desc, USBPT_CtrlData, USBPT_CtrlDataLen); USBPTH_OutEPCnt = 0; USBPT_GeneralInDataLen = 0; for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++) { for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++) { USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j]; for (uint8_t k = 0; k < USBPTH_MAX_LISTENERS; k++) { if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_D2H && USBPTH_Listeners[k].used == 0) { USBPTH_Listeners[k].epDesc = epDesc; uint8_t epType = 0; if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) { epType = EP_TYPE_CTRL; } USBH_Open_Channel( &USB_OTG_Core_host, &(USBPTH_Listeners[k].hc), epDesc->bEndpointAddress, USBPT_Dev->device_prop.address, USBPT_Dev->device_prop.speed, epType, USBPTH_Listeners[k].epDesc->wMaxPacketSize); if (USBPTH_Listeners[k].hc >= 0) { USBPTH_Listeners[k].used = 1; DCD_EP_Open(&USB_OTG_Core_dev, epDesc->bEndpointAddress, epDesc->wMaxPacketSize, epType); if (epDesc->wMaxPacketSize > USBPT_GeneralInDataMax) { USBPT_GeneralInDataMax = epDesc->wMaxPacketSize; } } } } if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) { USBPTH_OutEPCnt++; } } } if (USBPT_GeneralInData != 0) free(USBPT_GeneralInData); // release memory if previously allocated USBPT_GeneralInData = malloc(USBPT_GeneralInDataMax); // only allocate the memory we need if (USBPTH_OutEP != 0) free(USBPTH_OutEP); // release memory if previously allocated USBPTH_OutEP = malloc(sizeof(USBH_EpDesc_TypeDef*) * USBPTH_OutEPCnt); // only allocate the memory we need uint8_t ec = 0; for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++) { for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++) { USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j]; if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) { // only save the H2D direction endpoints USBPTH_OutEP[ec] = epDesc; ec++; } } } } return USBH_OK; } else { if (status == USBH_STALL || status == USBH_NOT_SUPPORTED) { dbg_printf(DBGMODE_ERR, "USBPT Setup Stalled \r\n"); USBD_CtlError(pcore , req); return USBH_OK; } } return USBD_OK; } dbg_printf(DBGMODE_ERR, "USBPT Setup Unhandled Error \r\n"); USBD_CtlError(pcore , req); return USBD_OK; }
/* * This is broken. We need to enumerate differently. * It causes major problems with several devices if detected in an unexpected order. * * * Oleg - I wouldn't do anything before the newly connected device is considered sane. * i.e.(delays are not indicated for brevity): * 1. reset * 2. GetDevDescr(); * 3a. If ACK, continue with allocating address, addressing, etc. * 3b. Else reset again, count resets, stop at some number (5?). * 4. When max.number of resets is reached, toggle power/fail * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD() * it doesn't need to be reset again * New steps proposal: * 1: get address pool instance. exit on fail * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. * 3: bus reset, 100ms delay * 4: set address * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail * 6: while (configurations) { * for(each configuration) { * for (each driver) { * 6a: Ask device if it likes configuration. Returns 0 on OK. * If successful, the driver configured device. * The driver now owns the endpoints, and takes over managing them. * The following will need codes: * Everything went well, instance consumed, exit with success. * Instance already in use, ignore it, try next driver. * Not a supported device, ignore it, try next driver. * Not a supported configuration for this device, ignore it, try next driver. * Could not configure device, fatal, exit with fail. * } * } * } * 7: for(each driver) { * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID * 8: if we get here, no driver likes the device plugged in, so exit failure. * */ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { //uint8_t bAddress = 0; //printf("Configuring: parent = %i, port = %i\r\n", parent, port); uint8_t devConfigIndex; uint8_t rcode = 0; uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; UsbDevice *p = NULL; EpInfo *oldep_ptr = NULL; EpInfo epInfo; USB_OTG_CORE_HANDLE *pdev = coreConfig; epInfo.epAddr = 0; epInfo.maxPktSize = 8; epInfo.epAttribs = 0; epInfo.bmNakPower = USB_NAK_MAX_POWER; // assume: // HC0 for control - out // HC1 for control - in //uint8_t hcnum = USBH_GetFreeChannel(pdev); //if(hcnum > 1) { // USBH_Free_Channel(pdev, epInfo.hcNumOut); // USBH_Free_Channel(pdev, epInfo.hcNumIn); //} USBH_Free_Channel(pdev, 0); USBH_Free_Channel(pdev, 1); epInfo.hcNumOut = USBH_Alloc_Channel(pdev, 0x00); // ep_addr = 0 epInfo.hcNumIn = USBH_Alloc_Channel(pdev, 0x80); USBH_Open_Channel(pdev, epInfo.hcNumOut, 0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8); USBH_Open_Channel(pdev, epInfo.hcNumIn, 0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8); printf("\nControl Pipe: out = %d (0), in = %d (1)", epInfo.hcNumOut, epInfo.hcNumIn); delay_ms(1000); AddressPool &addrPool = GetAddressPool(); // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); if (!p) { printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; } // Save old pointer to EP_RECORD of address 0 // oldep_ptr = p->epinfo; // Temporary assign new pointer to epInfo to p->epinfo in order to // avoid toggle inconsistence p->epinfo = &epInfo; p->lowspeed = lowspeed; // Get device descriptor rcode = getDevDescr(0, 0, 8, (uint8_t*)buf); // 8 should be enough, sizeof (USB_DEVICE_DESCRIPTOR) printf("\nControl - Got 1st 8 bytes desc"); // Extract Max Packet Size from the device descriptor epInfo.maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; //USB::USBH_Modify_Channel (pdev, epInfo.hcNumOut, 0, 0, 0, 0, epInfo.maxPktSize); //USB::USBH_Modify_Channel (pdev, epInfo.hcNumIn, 0, 0, 0, 0, epInfo.maxPktSize); // Restore p->epinfo // keep CtrlXfer's hcNumOut/In in p->epinfo. p->epinfo = oldep_ptr; if (rcode) { printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); return rcode; } // to-do? // Allocate new address according to device class //bAddress = addrPool.AllocAddress(parent, false, port); //if (!bAddress) // return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; rcode = getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); printf("\nControl - Got 2nd 18 bytes desc."); uint16_t vid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; uint16_t pid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; uint8_t klass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass; // Attempt to configure if VID/PID or device class matches with a driver for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { if (!devConfig[devConfigIndex]) continue; // no driver if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid)) { rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); break; } else if (devConfig[devConfigIndex]->DEVCLASSOK(klass)) { rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); if (!rcode) break; } } if (devConfigIndex < USB_NUMDEVICES) { return rcode; } // blindly attempt to configure for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { if (!devConfig[devConfigIndex]) continue; if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); //printf("ERROR ENUMERATING %2.2x\r\n", rcode); if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { // in case of an error dev_index should be reset to 0 // in order to start from the very beginning the // next time the program gets here //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) // devConfigIndex = 0; return rcode; } } // if we get here that means that the device class is not supported by any of registered classes rcode = DefaultAddressing(parent, port, lowspeed); return rcode; }
/** * @brief CDC_InterfaceInit * The function init the CDC class. * @param pdev: Selected device * @param hdev: Selected device property * @retval USBH_Status :Response for USB CDC driver intialization */ static USBH_Status CDC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, void *phost) { USBH_HOST *pphost = phost; USBH_Status status = USBH_OK ; /* Communication Interface */ if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == COMMUNICATION_DEVICE_CLASS_CODE)&& \ (pphost->device_prop.Itf_Desc[0].bInterfaceSubClass == ABSTRACT_CONTROL_MODEL) && \ (pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == COMMON_AT_COMMAND)) { /*Collect the notification endpoint address and length*/ CDC_Machine.CDC_CommItf.ep_addr = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress; CDC_Machine.CDC_CommItf.length = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) { CDC_Machine.CDC_CommItf.notificationEp =\ (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); } /*Allocate the length for host channel number in*/ CDC_Machine.CDC_CommItf.hc_num_in = USBH_Alloc_Channel(pdev, CDC_Machine.CDC_CommItf.notificationEp ); /* Open channel for IN endpoint */ USBH_Open_Channel (pdev, CDC_Machine.CDC_CommItf.hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_INTR, CDC_Machine.CDC_CommItf.length); } else { pphost->usr_cb->DeviceNotSupported(); } /* Data Interface */ if((pphost->device_prop.Itf_Desc[1].bInterfaceClass == DATA_INTERFACE_CLASS_CODE)&& \ (pphost->device_prop.Itf_Desc[1].bInterfaceSubClass == RESERVED) && \ (pphost->device_prop.Itf_Desc[1].bInterfaceProtocol == NO_CLASS_SPECIFIC_PROTOCOL_CODE)) { /*Collect the class specific endpoint address and length*/ CDC_Machine.CDC_DataItf.ep_addr = pphost->device_prop.Ep_Desc[1][0].bEndpointAddress; CDC_Machine.CDC_DataItf.length = pphost->device_prop.Ep_Desc[1][0].wMaxPacketSize; if(pphost->device_prop.Ep_Desc[1][0].bEndpointAddress & 0x80) { CDC_Machine.CDC_DataItf.cdcInEp = (pphost->device_prop.Ep_Desc[1][0].bEndpointAddress); } else { CDC_Machine.CDC_DataItf.cdcOutEp = (pphost->device_prop.Ep_Desc[1][0].bEndpointAddress); } if(pphost->device_prop.Ep_Desc[1][1].bEndpointAddress & 0x80) { CDC_Machine.CDC_DataItf.cdcInEp = (pphost->device_prop.Ep_Desc[1][1].bEndpointAddress); } else { CDC_Machine.CDC_DataItf.cdcOutEp = (pphost->device_prop.Ep_Desc[1][1].bEndpointAddress); } /*Allocate the length for host channel number out*/ CDC_Machine.CDC_DataItf.hc_num_out = USBH_Alloc_Channel(pdev, CDC_Machine.CDC_DataItf.cdcOutEp); /*Allocate the length for host channel number in*/ CDC_Machine.CDC_DataItf.hc_num_in = USBH_Alloc_Channel(pdev, CDC_Machine.CDC_DataItf.cdcInEp); /* Open channel for OUT endpoint */ USBH_Open_Channel (pdev, CDC_Machine.CDC_DataItf.hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, CDC_Machine.CDC_DataItf.length); /* Open channel for IN endpoint */ USBH_Open_Channel (pdev, CDC_Machine.CDC_DataItf.hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, CDC_Machine.CDC_DataItf.length); /*Initilise the Tx/Rx Params*/ CDC_InitTxRxParam(); /*Initialize the class specific request with "GET_LINE_CODING"*/ CDC_ReqState = CDC_GET_LINE_CODING_RQUEST ; } else { pphost->usr_cb->DeviceNotSupported(); } return status; }
static void _dev_probe_entry(void *parameter) { wifi_usb_adapter_t *adapter = (wifi_usb_adapter_t *)&wifi_usb_adapter; USB_OTG_CORE_HANDLE *pdev = &USB_OTG_Core_dev; USBH_HOST *pphost = &USB_Host; DBGPRINT(WHED_DEBUG_TRACE, "%s: ---->\n", __FUNCTION__); DBGPRINT(WHED_DEBUG_TRACE, "VID:%x, PID:%x.\n",\ pphost->device_prop.Dev_Desc.idVendor, pphost->device_prop.Dev_Desc.idProduct); if (!adapter->device_matched) { DBGPRINT(WHED_DEBUG_ERROR, "Device is not supported.\n"); return; } /* Control channel */ adapter->usb_ctrl_req.ep0size = pphost->Control.ep0size; /* no use */ adapter->usb_ctrl_req.hc_num_in = pphost->Control.hc_num_in; adapter->usb_ctrl_req.hc_num_out = pphost->Control.hc_num_out; DBGPRINT(WHED_DEBUG_TRACE, "Control in pipe - 0x%x\n", adapter->usb_ctrl_req.hc_num_in); DBGPRINT(WHED_DEBUG_TRACE, "Control out pipe - 0x%x\n", adapter->usb_ctrl_req.hc_num_out); /* Data IN channel */ adapter->hc_num_in = USBH_Alloc_Channel(pdev, adapter->bulk_in_ep); USBH_Open_Channel(pdev, adapter->hc_num_in, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, adapter->bulk_in_ep_size); DBGPRINT(WHED_DEBUG_TRACE, "Bulk in pipe - 0x%x\n", adapter->hc_num_in); /* Data OUT channel */ adapter->hc_num_out = USBH_Alloc_Channel(pdev, adapter->bulk_out_ep); USBH_Open_Channel(pdev, adapter->hc_num_out, pphost->device_prop.address, pphost->device_prop.speed, EP_TYPE_BULK, adapter->bulk_out_ep_size); DBGPRINT(WHED_DEBUG_TRACE, "Bulk out pipe - 0x%x\n", adapter->hc_num_out); /* Initialize the usb request state machine. */ adapter->usb_ctrl_req.state = CTRL_IDLE; adapter->usb_tx_req.state = USB_BULK_STATE_IDLE; adapter->usb_rx_req.state = USB_BULK_STATE_IDLE; adapter->usb_ctrl_req.retry = 3; adapter->usb_tx_req.retry = 3; adapter->usb_rx_req.retry = 3; /* Initialize the Wifi module, */ rt2870_probe(adapter, &adapter->pAdapter); /* Inform to the system */ sys_add_event_queue(&p_cms_envar->sys, SYS_MSG_INITED, 0, 0, 0); }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; /* check for Host port events */ if (((HCD_IsDeviceConnected(pdev) == 0)|| (HCD_IsPortEnabled(pdev) == 0))&& (phost->gState != HOST_IDLE)) { if(phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; } } switch (phost->gState) { case HOST_IDLE : if (HCD_IsDeviceConnected(pdev)) { phost->gState = HOST_WAIT_PRT_ENABLED; /*wait denounce delay */ USB_OTG_BSP_mDelay(100); /* Apply a port RESET */ HCD_ResetPort(pdev); /* User RESET callback*/ phost->usr_cb->ResetDevice(); } break; case HOST_WAIT_PRT_ENABLED: if (pdev->host.PortEnabled == 1) { phost->gState = HOST_DEV_ATTACHED; USB_OTG_BSP_mDelay(50); } break; case HOST_DEV_ATTACHED : phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); /* Reset USB Device */ if ( HCD_ResetPort(pdev) == 0) { phost->usr_cb->ResetDevice(); /* Host is Now ready to start the Enumeration */ phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); } break; case HOST_ENUMERATION: /* Check for enumeration status */ if ( USBH_HandleEnum(pdev , phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); #if defined (USB_OTG_FS_LOW_PWR_MGMT_SUPPORT) || defined (USB_OTG_HS_LOW_PWR_MGMT_SUPPORT) phost->gState = HOST_SUSPENDED; #else phost->gState = HOST_USR_INPUT; #endif /* LOW_PWR_MGMT_SUPPORT*/ } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if ( phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { if((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } } break; case HOST_CLASS_REQUEST: /* process class standard control requests state machine */ status = phost->class_cb->Requests(pdev, phost); if(status == USBH_OK) { phost->gState = HOST_CLASS; } else { USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ USBH_HandleControl(pdev, phost); break; #if defined (USB_OTG_FS_LOW_PWR_MGMT_SUPPORT) || defined (USB_OTG_HS_LOW_PWR_MGMT_SUPPORT) case HOST_SUSPENDED: if (USBH_SetDeviceFeature(pdev, phost, FEATURE_SELECTOR_DEVICE, 0)==USBH_OK) { suspend_flag = 1; USB_OTG_BSP_Suspend(pdev); phost->usr_cb->UserInput(); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); /* After wakeup got to HOST_WAKEUP state */ phost->gState = HOST_WAKEUP; } break; case HOST_WAKEUP: /* issue a ClearDeviceFeature request */ if (USBH_ClearDeviceFeature(pdev, phost, FEATURE_SELECTOR_DEVICE, 0)==USBH_OK) { phost->gState = HOST_USR_INPUT; } break; #endif /* USE_HOST_MODE */ case HOST_ERROR_STATE: /* Re-Initialize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED : /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected(); /* Re-Initialize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; /* Re-Initialize Host for new Enumeration */ HCD_Init(pdev, #ifdef USE_USB_OTG_FS USB_OTG_FS_CORE_ID #else USB_OTG_HS_CORE_ID #endif ); break; default : break; } }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; /* check for Host port events */ if ((HCD_IsDeviceConnected(pdev) == 0)&& (phost->gState != HOST_IDLE)) { if(phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; } } switch (phost->gState) { case HOST_IDLE : if (HCD_IsDeviceConnected(pdev)) { phost->gState = HOST_DEV_ATTACHED; USB_OTG_BSP_mDelay(100); } break; case HOST_DEV_ATTACHED : phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); /* Reset USB Device */ if ( HCD_ResetPort(pdev) == 0) { phost->usr_cb->ResetDevice(); /* Wait for USB USBH_ISR_PrtEnDisableChange() Host is Now ready to start the Enumeration */ phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); } break; case HOST_ENUMERATION: /* Check for enumeration status */ if ( USBH_HandleEnum(pdev , phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); phost->gState = HOST_USR_INPUT; } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if ( phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { if((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } } break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ status = phost->class_cb->Requests(pdev, phost); if(status == USBH_OK) { phost->gState = HOST_CLASS; } else { USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ USBH_HandleControl(pdev, phost); break; case HOST_SUSPENDED: break; case HOST_ERROR_STATE: /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED : /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected(); /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; break; default : break; } }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; /* check for Host port events */ if ((HCD_IsDeviceConnected(pdev) == 0)&& (phost->gState != HOST_IDLE)) { printf("check for Host port events\r\n"); if(phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; } } switch (phost->gState) { case HOST_IDLE : if (HCD_IsDeviceConnected(pdev)) { printf("HOST_DEV_ATTACHED is enter\r\n"); phost->gState = HOST_DEV_ATTACHED; USB_OTG_BSP_mDelay(100); } break; case HOST_DEV_ATTACHED : phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); /* Reset USB Device */ if ( HCD_ResetPort(pdev) == 0) { printf("HOST_DEV_ATTACHED state reset device"); phost->usr_cb->ResetDevice(); /* Wait for USB USBH_ISR_PrtEnDisableChange() Host is Now ready to start the Enumeration */ phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); } // printfpdev_reg(pdev); break; case HOST_ENUMERATION: // printfpdev_reg(pdev); // printf(" in HOST_ENUMERATION state\r\n "); /* Check for enumeration status */ if ( USBH_HandleEnum(pdev , phost) == USBH_OK) { printf("HOST_ENUMERATION state enumeration is ok"); /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); phost->gState = HOST_USR_INPUT; } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if ( phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { printf("HOST_USR_INPUT state : user_input is ok\r\n"); if((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } } // printf("GINTSTS :%X\r\n",(pdev->regs.GREGS->GINTSTS)); break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ status = phost->class_cb->Requests(pdev, phost); if(status == USBH_OK) { printf("HOST_CLASS_REQUEST state : contol requests is ok and host class is enter\r\n"); phost->gState = HOST_CLASS; #if 0 // USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFNUM,0X43FD039B); printf("GRXSTSR: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->GRXSTSR)); printf("HNPTXSTS: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS)); printf("HFNUM: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.HREGS->HFNUM)); printf("HNPTXSTS: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS)); printf("DIEPTSIZ: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[8]->DIEPCTL )); printf("DIEPDMA: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[8]->DIEPDMA )); printfpdev_reg(pdev); #endif } else { USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ printf("HOST_CTRL_XFER\r\n"); USBH_HandleControl(pdev, phost); break; case HOST_SUSPENDED: printf("HOST_SUSPENDED\r\n"); break; case HOST_ERROR_STATE: /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED : /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected();//user µ÷ÓÃ /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; // NVIC_SystemReset(); break; default : break; } }