/** Local function to handle a request by calling one of the installed request handlers. In case of data going from host to device, the data is at *ppbData. In case of data going from device to host, the handler can either choose to write its data at *ppbData or update the data pointer. @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 handles successfully */ static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) { TFnHandleRequest *pfnHandler; int iType; if( pSetup->bRequest == 0x55 && pSetup->wValue == 0x0000 && *piLen == 128 ) { const U8 midi_indicator[128] = { 0xD1,0x0F,0xED,0x54,0xCF,0xC5,0xFB,0xB8,0x97,0x52,0x38,0x91,0x38,0x91,0x0E,0x7D, 0x0F,0xED,0x38,0x93,0x01,0x91,0x0E,0x91,0x00,0xC1,0x1F,0x02,0x0E,0x91,0xF7,0x04, 0x10,0x40,0x00,0x6E,0x10,0x6E,0xE7,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x55,0x46,0x1F, 0x00,0xD8,0x48,0x40,0x37,0x6A,0xF7,0x6A,0x00,0x30,0x00,0x00,0xC7,0x06,0x2E,0x73, 0x4A,0x2C,0x13,0x7B,0xE9,0x7F,0x32,0x00,0x2A,0x28,0x0D,0x9B,0xFE,0x0B,0x21,0xEF, 0x42,0x2A,0x2F,0x73,0xB5,0xB8,0xDA,0x76,0xE6,0x79,0xBF,0x0F,0xEB,0x79,0x3E,0x0B}; *ppbData = (U8 *)midi_indicator; return TRUE; } iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); pfnHandler = apfnReqHandlers[iType]; if (pfnHandler == NULL) { DBG("No handler for reqtype %d\n", iType); return FALSE; } return pfnHandler(pSetup, piLen, ppbData); }
/** Local function to handle a request by calling one of the installed request handlers. In case of data going from host to device, the data is at *ppbData. In case of data going from device to host, the handler can either choose to write its data at *ppbData or update the data pointer. @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 handles successfully */ static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) { TFnHandleRequest *pfnHandler; int iType; iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); pfnHandler = apfnReqHandlers[iType]; if (pfnHandler == NULL) { DBG("No handler for reqtype %d\n", iType); return FALSE; } return pfnHandler(pSetup, piLen, ppbData); }
/** Local function to handle a request by calling one of the installed request handlers. In case of data going from host to device, the data is at *ppbData. In case of data going from device to host, the handler can either choose to write its data at *ppbData or update the data pointer. @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 handles successfully */ static bool _HandleRequest(TSetupPacket *pSetup, int *piLen, uint8_t **ppbData) { TFnHandleRequest *pfnHandler; int iType; iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); pfnHandler = apfnReqHandlers[iType]; if (pfnHandler == NULL) { DBG(UART0,"No handler for reqtype %d\n", iType); return false; } return pfnHandler(pSetup, piLen, ppbData); }
/** Local function to handle a request by calling one of the installed request handlers. In case of data going from host to device, the data is at *ppbData. In case of data going from device to host, the handler can either choose to write its data at *ppbData or update the data pointer. @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 handles successfully */ static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) { TFnHandleRequest *pfnHandler; int iType; iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); if(iType == REQTYPE_TYPE_VENDOR) { BOOL fFilterStatus = FALSE; if(USBFilterOsVendorMessage(pSetup, &fFilterStatus, piLen, ppbData)) { return fFilterStatus; } } pfnHandler = apfnReqHandlers[iType]; if (pfnHandler == NULL) { DBG("No handler for reqtype %d\n", iType); return FALSE; } return pfnHandler(pSetup, piLen, ppbData); }
/** * Handles IN/OUT transfers on EP0 * * @param [in] bEP Endpoint address * @param [in] bEPStat Endpoint status */ void USBHandleControlTransfer(U8 bEP, U8 bEPStat) { int iChunk, iType; if (bEP == 0x00) { // OUT transfer if (bEPStat & EP_STATUS_SETUP) { // setup packet, reset request message state machine USBHwEPRead(0x00, (U8 *)&Setup, sizeof(Setup)); DBG("S%x", Setup.bRequest); // defaults for data pointer and residue iType = REQTYPE_GET_TYPE(Setup.bmRequestType); pbData = apbDataStore[iType]; iResidue = Setup.wLength; iLen = Setup.wLength; if ((Setup.wLength == 0) || (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) { // ask installed handler to process request if (!_HandleRequest(&Setup, &iLen, &pbData)) { DBG("_HandleRequest1 failed\n"); StallControlPipe(bEPStat); return; } // send smallest of requested and offered length iResidue = MIN(iLen, Setup.wLength); // send first part (possibly a zero-length status message) DataIn(); } } else { if (iResidue > 0) { // store data iChunk = USBHwEPRead(0x00, pbData, iResidue); if (iChunk < 0) { StallControlPipe(bEPStat); return; } pbData += iChunk; iResidue -= iChunk; if (iResidue == 0) { // received all, send data to handler iType = REQTYPE_GET_TYPE(Setup.bmRequestType); pbData = apbDataStore[iType]; if (!_HandleRequest(&Setup, &iLen, &pbData)) { DBG("_HandleRequest2 failed\n"); StallControlPipe(bEPStat); return; } // send status to host DataIn(); } } else { // absorb zero-length status message iChunk = USBHwEPRead(0x00, NULL, 0); DBG(iChunk > 0 ? "?" : ""); } } } else if (bEP == 0x80) { // IN transfer // send more data if available (possibly a 0-length packet) DataIn(); } else { ASSERT(FALSE); } }
void USBCTRL::EPIntHandler(USBHW *u, uint8_t bEP, uint8_t bEPStatus) { iprintf("E0x%02X:0x%02X\t", bEP, bEPStatus); if (bEP == 0x00) { if (bEPStatus & EP_STATUS_SETUP) { // defaults for data pointer and residue HwEPRead(bEP, (uint8_t *) &Setup, sizeof(Setup)); uint8_t iType = REQTYPE_GET_TYPE(Setup.bmRequestType); pbData = &apbDataStore[iType][0]; iResidue = Setup.wLength; iLen = Setup.wLength; if ((Setup.wLength == 0) || (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) { switch(REQTYPE_GET_TYPE(Setup.bmRequestType)) { case REQTYPE_TYPE_STANDARD: { // iprintf("STDREQ:%02X,%02X,%04X,%04X,%04x\n", Setup.bmRequestType, Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wLength); uint8_t r = 0; switch (REQTYPE_GET_RECIP(Setup.bmRequestType)) { case REQTYPE_RECIP_DEVICE: { iprintf("StdDevReq:Rq=%02x,wV=%02x,wI=%02x,wL=%02x\n", Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wLength); r = HandleStdDeviceReq(&Setup, &iLen, &pbData); iprintf("Reply:%d bytes, max this packet: %d\n", iLen, Setup.wLength); break; } case REQTYPE_RECIP_INTERFACE: { iprintf("StdIntReq:Rq=%02x,wV=%02x,wI=%02x,wL=%02x\n", Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wLength); r = HandleStdInterfaceReq(&Setup, &iLen, &pbData); break; } case REQTYPE_RECIP_ENDPOINT: { iprintf("StdEPReq:Rq=%02x,wV=%02x,wI=%02x,wL=%02x\n", Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wLength); r = HandleStdEndPointReq(&Setup, &iLen, &pbData); break; } case REQTYPE_RECIP_OTHER: { iprintf("StdReq?:RqType=%02x;Rq=%02x,wV=%02x,wI=%02x,wL=%02x\n", Setup.bmRequestType, Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wLength); break; } } if (!r) { iprintf("STALL!\n"); HwEPStall(0x80, TRUE); return; } iResidue = iLen; if (iResidue > Setup.wLength) iResidue = Setup.wLength; DataIn(); return; }; } } iprintf("Unknown Setup ReqType %d - ignored\n", Setup.bmRequestType); iprintf("bRequest: %d (0x%02X), wValue: %d, wIndex: %d (0x%X), wLength: %d\n", Setup.bRequest, Setup.bRequest, Setup.wValue, Setup.wIndex, Setup.wIndex, Setup.wLength); iprintf("Dir: %s, ", (REQTYPE_GET_DIR(Setup.bmRequestType)?"Device->Host":"Host->Device")); if (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_DEVICE) { iResidue = Setup.wLength; } else { iResidue = 0; } switch (REQTYPE_GET_TYPE(Setup.bmRequestType)) { case REQTYPE_TYPE_STANDARD: iprintf("Type: Standard, "); break; case REQTYPE_TYPE_CLASS: iprintf("Type: Class , "); break; case REQTYPE_TYPE_VENDOR: iprintf("Type: Vendor , "); break; default: iprintf("Type: Reserved, "); break; } switch (REQTYPE_GET_RECIP(Setup.bmRequestType)) { case 0: iprintf("Recip: Device\n"); break; case 1: iprintf("Recip: Interface 0x%X\n", Setup.wIndex); break; case 2: iprintf("Recip: Endpoint 0x%X\n", Setup.wIndex); break; case 3: iprintf("Recip: Other\n"); break; default: iprintf("Recip: unknown\n"); break; } // if (REQTYPE_GET_TYPE(Setup.bmRequestType) == REQTYPE_TYPE_CLASS) { // // find interface // int i; // for (i = 0; descriptors[i] != ((usbdesc_base *) 0); i++) { // if ((descriptors[i]->bDescType == DT_INTERFACE) && (REQTYPE_GET_RECIP(Setup.bmRequestType) == REQTYPE_RECIP_INTERFACE)) { // usbdesc_interface *inf = (usbdesc_interface *) descriptors[i]; // if (inf->bInterfaceNumber == Setup.wIndex) { // iprintf("Firing Interface's setup handler: %p\n", inf->setupReceiver); // if (inf->setupReceiver) { // inf->setupReceiver->SetupHandler(u, bEP, &Setup); // break; // } // } // } // if ((descriptors[i]->bDescType == DT_ENDPOINT) && (REQTYPE_GET_RECIP(Setup.bmRequestType) == REQTYPE_RECIP_ENDPOINT)) { // usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i]; // if (ep->bEndpointAddress == bEP) { // iprintf("Firing Endpoint's setup handler: %p\n", ep->setupReceiver); // if (ep->setupReceiver) // ep->setupReceiver->SetupHandler(u, bEP, &Setup); // } // } // } // } } else { int iChunk; if (iResidue > 0) { // store data iChunk = HwEPRead(0x00, pbData, iResidue); iprintf("G:%db\n", iChunk); if (iChunk < 0) { HwEPStall(0x80, TRUE); return; } pbData += iChunk; iResidue -= iChunk; if (iResidue == 0) { // received all, send data to handler uint8_t iType = REQTYPE_GET_TYPE(Setup.bmRequestType); pbData = apbDataStore[iType]; iprintf("HANDLE 0x%02X with %db\n", iType, iLen); // if (!_HandleRequest(&Setup, &iLen, &pbData)) { // DBG("_HandleRequest2 failed\n"); // StallControlPipe(bEPStat); // return; // } // send status to host DataIn(); } } else { // absorb zero-length status message iChunk = HwEPRead(0x00, NULL, 0); iprintf("g%db\n", iChunk); // acknowledge HwEPWrite(0x80, 0, 0); // DBG(iChunk > 0 ? "?" : ""); } } if (REQTYPE_GET_TYPE(Setup.bmRequestType) == REQTYPE_TYPE_CLASS) { if ((iResidue == Setup.wLength) || (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) { // find interface int i; for (i = 0; descriptors[i] != ((usbdesc_base *) 0); i++) { if ((descriptors[i]->bDescType == DT_INTERFACE) && (REQTYPE_GET_RECIP(Setup.bmRequestType) == REQTYPE_RECIP_INTERFACE)) { usbdesc_interface *inf = (usbdesc_interface *) descriptors[i]; if (inf->bInterfaceNumber == Setup.wIndex) { iprintf("Firing Interface's setup handler: %p\n", inf->setupReceiver); if (inf->setupReceiver) { inf->setupReceiver->SetupHandler(u, bEP, &Setup); break; } } } if ((descriptors[i]->bDescType == DT_ENDPOINT) && (REQTYPE_GET_RECIP(Setup.bmRequestType) == REQTYPE_RECIP_ENDPOINT)) { usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i]; if (ep->bEndpointAddress == bEP) { iprintf("Firing Endpoint's setup handler: %p\n", ep->setupReceiver); if (ep->setupReceiver) ep->setupReceiver->SetupHandler(u, bEP, &Setup); } } } } } } else if (bEP == 0x80) { DataIn(); } else { int i; usbdesc_base *descriptor; for (i = 0; i < 32; i++) { descriptor = descriptors[i]; if (descriptor->bDescType == DT_ENDPOINT) { usbdesc_endpoint *endpoint = (usbdesc_endpoint *) descriptor; if (endpoint->bEndpointAddress == bEP) { endpoint->callbackReceiver->EPIntHandler(u, bEP, bEPStatus); } } } } }