/** Initialises the USB hardware and sets up the USB stack by installing default callbacks. @return TRUE if initialisation was successful */ BOOL USBInit(void) { // init hardware USBHwInit(); // Manual reset to workaround silicon bug USBHwReset(); // Reset USB address USBHwSetAddress(0); // register device status interrupt handler USBHwRegisterDevIntHandler(HandleUsbDevStatus); // register control transfer handler on EP0 USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer); USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer); // setup control endpoints USBHwEPConfig(0x00, MAX_PACKET_SIZE0); USBHwEPConfig(0x80, MAX_PACKET_SIZE0); // register standard request handler USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData); return TRUE; }
/** Local function to handle a standard device request @param [in] pSetup The setup packet @param [in,out] *piLen Pointer to data length @param [in,out] ppbData Data buffer. @return true if the request was handled successfully */ static bool HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, uint8_t **ppbData) { uint8_t *pbData = *ppbData; switch (pSetup->bRequest) { case REQ_GET_STATUS: // bit 0: self-powered // bit 1: remote wakeup = not supported pbData[0] = 0; pbData[1] = 0; *piLen = 2; break; case REQ_SET_ADDRESS: USBHwSetAddress(pSetup->wValue); break; case REQ_GET_DESCRIPTOR: DBG("D%x", pSetup->wValue); return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); case REQ_GET_CONFIGURATION: // indicate if we are configured pbData[0] = bConfiguration; *piLen = 1; break; case REQ_SET_CONFIGURATION: if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) { DBG("USBSetConfiguration failed!\n"); return false; } // configuration successful, update current configuration bConfiguration = pSetup->wValue & 0xFF; break; case REQ_CLEAR_FEATURE: case REQ_SET_FEATURE: if (pSetup->wValue == FEA_REMOTE_WAKEUP) { // put DEVICE_REMOTE_WAKEUP code here } if (pSetup->wValue == FEA_TEST_MODE) { // put TEST_MODE code here } return false; case REQ_SET_DESCRIPTOR: DBG("Device req %d not implemented\n", pSetup->bRequest); return false; default: DBG("Illegal device req %d\n", pSetup->bRequest); return false; } return true; }
/************************************************************************* HandleStdDeviceReq ================== Local function to handle a standard device request IN pSetup The setup packet IN/OUT *piLen Pointer to data length ppbData Data buffer. Returns TRUE if the request was handled successfully **************************************************************************/ static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) { U8 *pbData = *ppbData; switch (pSetup->bRequest) { case REQ_GET_STATUS: // bit 0: self-powered // bit 1: remote wakeup pbData[0] = 0; // TODO use bmAttributes according to configuration pbData[1] = 0; *piLen = 2; break; case REQ_SET_ADDRESS: USBHwSetAddress(pSetup->wValue); break; case REQ_GET_DESCRIPTOR: DBG("D%x", pSetup->wValue); if (pfnGetDescriptor == NULL) { return FALSE; } return pfnGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); case REQ_GET_CONFIGURATION: // indicate if we are configured pbData[0] = bConfiguration; *piLen = 1; break; case REQ_SET_CONFIGURATION: bConfiguration = pSetup->wValue & 0xFF; // TODO use bConfigurationValue(s) USBHwConfigDevice((pSetup->wValue & 0xFF) != 0); break; case REQ_CLEAR_FEATURE: case REQ_SET_FEATURE: if (pSetup->wValue == FEA_REMOTE_WAKEUP) { // put DEVICE_REMOTE_WAKEUP code here } if (pSetup->wValue == FEA_TEST_MODE) { // put TEST_MODE code here } return FALSE; case REQ_SET_DESCRIPTOR: DBG("Device req %d not implemented\n", pSetup->bRequest); return FALSE; default: DBG("Illegal device req %d\n", pSetup->bRequest); return FALSE; } return TRUE; }