📄 usb.c
字号:
if (UDCCS0 & UDC_UDCCS0_SST) { REG_SET(®isters->UDCCS0, UDC_UDCCS0_SST); } /* decode token */ ixUSBEP0TokenDecode(device); if (ep0Control->currentToken == SETUP_TOKEN) /* SETUP active */ { UINT32 offset = 0; /* setup packet offset */ controlWriteError = FALSE; /* reset control write error flag on SETUP token */ /* debug */ IX_USB_TRACE("::> SETUP\n", 0, 0, 0, 0, 0, 0); /* increment SETUP counter */ context->counters.setup++; if (ep0Control->state != IDLE) { if (ep0Control->transferType == CONTROL_READ) { crFailed++; IX_USB_VERBOSE_WARN_TRACE("USB: SETUP token prematurely ended Control Read transaction\n", 0, 0, 0, 0, 0, 0); } else if (ep0Control->transferType == CONTROL_WRITE) { cwFailed++; IX_USB_VERBOSE_WARN_TRACE("USB: SETUP token prematurely ended Control Write transaction\n", 0, 0, 0, 0, 0, 0); } else if (ep0Control->transferType == CONTROL_NO_DATA) { cnFailed++; IX_USB_VERBOSE_WARN_TRACE("USB: SETUP token prematurely ended Control No Data transaction\n", 0, 0, 0, 0, 0, 0); } else { IX_USB_VERBOSE_WARN_TRACE("USB: SETUP token in an *******>INVALID<******** transaction\n", 0, 0, 0, 0, 0, 0); } /* SETUP occurred in the middle of another transaction, reset endpoint */ ixUSBEP0StateReset(device); ixUSBEndpointClear(device, ENDPOINT_0); } IX_USB_VERBOSE4_TRACE("USB: control packet: ", 0, 0, 0, 0, 0, 0); /* read packet */ /* tm - workaround for 0x81 sillicon bug (SA = 1, OPR = 1, RNE = 0) */ if ((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) == 0) { /* ignore RNE, forcibly read 8 bytes */ for (offset = 0 ; offset < SETUP_PACKET_SIZE ; offset++) { ep0Control->setupBuffer[offset] = DREG_GET(®isters->UDDR0); if (offset == 0 && (REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE)) { IX_USB_TRACE("USB: Oops, RNE came back up.\n", 0, 0, 0, 0, 0, 0); } } } else { while (((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) != 0) /* receive FIFO not empty */ && (offset < SETUP_PACKET_SIZE)) /* copy maximum 8 bytes */ { ep0Control->setupBuffer[offset] = DREG_GET(®isters->UDDR0); IX_USB_VERBOSE4_TRACE("0x%02x ", (unsigned char) ep0Control->setupBuffer[offset], 0, 0, 0, 0, 0); offset++; } } /* we should exactly 8 bytes in the FIFO; if we have more then the incoming OUT token has rewritten the FIFO with a payload and we have to discard the setup */ if ((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) != 0) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "USB: Control write error, there's still data in the EP0 FIFO:", 0, 0, 0, 0, 0, 0); /* drain and discard FIFO */ while((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) != 0) { unsigned char extraData = (unsigned char) DREG_GET(®isters->UDDR0); ixOsalLog(IX_OSAL_LOG_LVL_WARNING, IX_OSAL_LOG_DEV_STDOUT, "0x%02x", extraData, 0, 0, 0, 0, 0); } /* indicate the error condition further in this transaction */ controlWriteError = TRUE; } /* a valid setup packet has exactly 8 bytes */ if (offset != SETUP_PACKET_SIZE) { IX_USB_VERBOSE_WARN_TRACE("Warning, did not read a full setup packet (8 expected, %d read)\n", offset, 0, 0, 0, 0, 0); /* mangled packet, clear OPR and SA, set IPR in case host follows with IN token - tm */ REG_SET(®isters->UDCCS0, (UDC_UDCCS0_OPR | UDC_UDCCS0_SA | UDC_UDCCS0_IPR)); ixUSBEP0StateReset(device); ixUSBEndpointClear(device, ENDPOINT_0); ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
return; } if (controlWriteError) { /* we'll discard all incoming payload within this transaction */ ep0Control->expected = 0; /* erase junk setup buffer to known values */ ep0Control->setupBuffer[0] = (unsigned char) 0xff; ep0Control->setupBuffer[1] = (unsigned char) 0xff; ep0Control->setupBuffer[2] = (unsigned char) 0xff; ep0Control->setupBuffer[3] = (unsigned char) 0xff; ep0Control->setupBuffer[4] = (unsigned char) 0xff; ep0Control->setupBuffer[5] = (unsigned char) 0xff; ep0Control->setupBuffer[6] = (unsigned char) 0xff; ep0Control->setupBuffer[7] = (unsigned char) 0xff; } else { /* decode the transfer type and direction from packet */ ixUSBEP0SetupPacketDecode(device); } IX_USB_VERBOSE4_TRACE("Read SETUP packet, %d bytes\n", offset, 0, 0, 0, 0, 0); /* show control stats */ IX_USB_TRACE("USB: Control read (%d/%d/%d)\n", crInitiated, crCompleted, crFailed, 0, 0, 0); IX_USB_TRACE("USB: Control write (%d/%d/%d)\n", cwInitiated, cwCompleted, cwFailed, 0, 0, 0); IX_USB_TRACE("USB: Control nodata (%d/%d)\n", cnInitiated, cnFailed, 0, 0, 0, 0); /* reset transfer counter for data stage */ ep0Control->transferred = 0; epData->transferAllowed = FALSE; ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
/* dispatch setup buffer */ if (context->eventProcessor.setupCallback != NULL) { IX_USB_TRACE("USB: Callback on 8 bytes SETUP packet\n", 0, 0, 0, 0, 0, 0); context->eventProcessor.setupCallback(device, ep0Control->setupBuffer); } ixOsalMutexLock(&usbBufferSubmitMutex[0], IX_OSAL_WAIT_FOREVER); /* clear OPR and SA */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_OPR ); REG_SET(®isters->UDCCS0, UDC_UDCCS0_SA ); /* allow premature STATUS USB_IN on Control Write */ if (ep0Control->transferType == CONTROL_WRITE) { /* set IPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_IPR); } epData->transferAllowed = TRUE; ixUSBEP0RequestSend(device); } else if (ep0Control->currentToken == OUT_TOKEN) /* USB_OUT token received */ { /* debug */ IX_USB_TRACE("::> OUT\n", 0, 0, 0, 0, 0, 0); /* debug sanity check */ if (ep0Control->transferType == CONTROL_READ && ep0Control->state != END_IN_XFER && ep0Control->state != ACTIVE_IN) { /* state machine in invalid mode */ IX_USB_TRACE("USB: internal error in state machine (current: %d)\n", ep0Control->state, 0, 0, 0, 0, 0); } if (ep0Control->state == END_IN_XFER) { /* consume token and set state machine to IDLE */ ixUSBEP0SendCleanup(device); IX_USB_VERBOSE5_TRACE("::> UDCCS0 is 0x%02X on EXIT\n", UDCCS0, 0, 0, 0, 0, 0); /* clear OPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_OPR); ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
crCompleted++; ixUSBDataSendAllow(device); return; } else if (ep0Control->state == ACTIVE_IN) { /* premature STATUS, host won't accept more data */ if (ep0Control->transferred == ep0Control->expected) { /* transfer was completed but no 0-length packet was sent */ ixUSBEP0SendCleanup(device); crCompleted++; } else { /* ERROR, STATUS stage entered before transfer completion */ ixUSBEP0StateReset(device); ixUSBEndpointClear(device, ENDPOINT_0); crFailed++; } /* clear OPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_OPR); UDCCS0 = REG_GET(®isters->UDCCS0); IX_USB_VERBOSE5_TRACE("::> UDCCS0 is 0x%02X on EXIT\n", UDCCS0, 0, 0, 0, 0, 0); ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
return; } else if (ep0Control->state == IDLE) /* First USB_OUT packet */ { ep0Control->state = ACTIVE_OUT; IX_USB_VERBOSE5_TRACE("::> Beginning OUT transaction, %d bytes expected\n", ep0Control->expected, 0, 0, 0, 0, 0); /* alloc recv buffer */ epData->currentBuffer = ixUSBBufferAlloc(ep0Control->expected); } IX_USB_VERBOSE5_TRACE("::> Reading FIFO at offset %d\n", epData->currentOffset, 0, 0, 0, 0, 0); if (controlWriteError) { /* invalid transaction, drain FIFO and discard data */ while ((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) != 0) { *((unsigned char *)(IX_USB_MBLK_DATA(epData->currentBuffer) + epData->currentOffset)) = DREG_GET(®isters->UDDR0); epData->currentOffset++; } } else { /* read FIFO until RNE == 0, appending to recv buffer */ while ((REG_GET(®isters->UDCCS0) & UDC_UDCCS0_RNE) != 0 /* receive FIFO not empty */ && epData->currentOffset < ep0Control->expected) /* stop when all expected data was received */ { *((unsigned char *)(IX_USB_MBLK_DATA(epData->currentBuffer) + epData->currentOffset)) = DREG_GET(®isters->UDDR0); epData->currentOffset++; ep0Control->transferred++; } } IX_USB_TRACE("USB: => Read %d bytes so far in this control write, %d expected\n", ep0Control->transferred, ep0Control->expected, 0, 0, 0, 0); /* check for end of transfer */ if (ep0Control->transferred == ep0Control->expected) { ep0Control->state = END_OUT_XFER; } /* allow USB_IN STATUS - set IPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_IPR); /* clear OPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_OPR); /* Check for end of transfer and ship data *before* status stage WHY: Might miss the status stage which is signalled by an IN token */ if (ep0Control->transferred == ep0Control->expected) { ixUSBEP0DataDeliver(device); } } else if (ep0Control->currentToken == IN_TOKEN) /* USB_IN token */ { /* debug */ if (controlWriteError) { IX_USB_TRACE("::> IN\n", 0, 0, 0, 0, 0, 0); } if (ep0Control->state == ACTIVE_OUT) { /* Premature USB_IN stage */; ixUSBEP0StateReset(device); ixUSBEndpointClear(device, ENDPOINT_0); crFailed ++; ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
return; } else if (ep0Control->state == END_OUT_XFER) { ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
cwCompleted++; /* Control Write ended, deliver data */ /* ixUSBEP0DataDeliver(device); */ return; } /* unlock FIFO for next packet */ epData->transferAllowed = TRUE; ixUSBEP0RequestSend(device); /* send data, if available */ } else { IX_USB_VERBOSE4_TRACE("::> UNKNOWN TOKEN", 0, 0, 0, 0, 0, 0); } ixOsalMutexUnlock(&usbBufferSubmitMutex[0]);
}/** * @fn PRIVATE void ixUSBEP0TokenDecode(USBDevice *device) * * @brief Decode the received USB token * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Decodes the USB token received on endpoint 0 based on the * state of the <b>SA</b> (Setup Active) and <b>OPR</b> (USB_OUT Packet Ready) * bits of <b>UDCCS0</b> (endpoint 0 control/status register).<br> * The decoded value is placed in the <i>ep0ControlData.currentToken</i> * field, component of <i>device->deviceContext</i>. * * @internal */PRIVATE void ixUSBEP0TokenDecode(USBDevice *device){ EP0ControlData *ep0Data = EP0CONTROL(device); UDCRegisters *registers = REGISTERS(device); UINT32 UDCCS0 = REG_GET(®isters->UDCCS0); BOOL SA = UDCCS0 & UDC_UDCCS0_SA; BOOL OPR = UDCCS0 & UDC_UDCCS0_OPR; IX_USB_VERBOSE5_TRACE("::> Decode UDCCS0 is 0x%02X\n", UDCCS0, 0, 0, 0, 0, 0); if (SA && OPR) { ep0Data->currentToken = SETUP_TOKEN; } else if (OPR) /* || RNE is a hack */ { ep0Data->currentToken = OUT_TOKEN; } else { ep0Data->currentToken = IN_TOKEN; }}/** * @fn PRIVATE void ixUSBEP0SetupPacketDecode(USBDevice *device) * * @brief Decode the received USB SETUP packet * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Decodes the 8-byte SETUP packet received on endpoint 0, extracting * the expected transfer type and length for the data stage of the * ongoing control transaction.<br> * Populates the <i>expected</i> and <i>transferType</i> fields of * the device->deviceContext.ep0ControlData structure. * * @internal */PRIVATE void ixUSBEP0SetupPacketDecode(USBDevice *device){ EP0ControlData *ep0Data = EP0CONTROL(device); USBSetupPacket *controlPacket; controlPacket = (USBSetupPacket *) ep0Data->setupBuffer; IX_USB_VERBOSE4_TRACE("SETUP packet:\n[%02x %02x %02x %02x", ep0Data->setupBuffer[0], ep0Data->setupBuffer[1], ep0Data->setupBuffer[2], ep0Data->setupBuffer[3], 0, 0); IX_USB_VERBOSE4_TRACE(" %02x %02x %02x %02x]\n", ep0Data->setupBuffer[4], ep0Data->setupBuffer[5], ep0Data->setupBuffer[6], ep0Data->setupBuffer[7], 0, 0); SWAP_USB_WORD(&controlPacket->wIndex); SWAP_USB_WORD(&controlPacket->wLength); SWAP_USB_WORD(&controlPacket->wValue); /* debug */ IX_USB_VERBOSE4_TRACE("SETUP packet decoding:\n bmRequestType 0x%02X, bRequest %02X, wValue %04X, wIndex %04X, wLength %04X\n", controlPacket->bmRequestType, controlPacket->bRequest, controlPacket->wValue, controlPacket->wIndex, controlPacket->wLength, 0); /* get expected transfer length */ ep0Data->expected = controlPacket->wLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -