/* * Returns how many bytes are in the buffer are received and ready to be read. */ BYTE USBHID_bytesInUSBBuffer (BYTE intfNum) { BYTE bTmp1 = 0; BYTE bTmp2; BYTE edbIndex; WORD state; edbIndex = stUsbHandle[intfNum].edb_Index; //interrupts disable state = usbDisableOutEndpointInterrupt(edbIndex); if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ //if suspended or not enumerated - report 0 bytes available usbRestoreOutEndpointInterrupt(state); return (0); } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //If a RX operation is underway, part of data may //was read of the OEP buffer bTmp1 = HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp; if (*HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & EPBCNT_NAK){ //the next buffer has a valid data packet bTmp2 = *(HidReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 + 1); //holds how many valid bytes in the EP buffer if (bTmp2 > (*HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & 0x7F) - 2){ //check if all data received correctly bTmp1 += (*HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & 0x7F) - 2; } else { bTmp1 += bTmp2; } } } else { if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet bTmp2 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & 0x7F; bTmp1 = *((BYTE*)stUsbHandle[intfNum].oep_X_Buffer + 1); if (bTmp2 - 2 < bTmp1){ //check if the count (second byte) is valid bTmp1 = bTmp2 - 2; } } if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){ //this buffer has a valid data packet bTmp2 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & 0x7F; if (bTmp2 - 2 > *((BYTE*)stUsbHandle[intfNum].oep_Y_Buffer + 1)){ //check if the count (second byte) is valid bTmp1 += *((BYTE*)stUsbHandle[intfNum].oep_Y_Buffer + 1); } else { bTmp1 += bTmp2 - 2; } } } //interrupts enable usbRestoreOutEndpointInterrupt(state); return (bTmp1); }
/* * Aborts an active receive operation on interface intfNum. * Returns the number of bytes that were received and transferred * to the data location established for this receive operation. */ uint8_t USBPHDC_abortReceive (uint16_t* size, uint8_t intfNum) { uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableOutEndpointInterrupt(edbIndex); *size = 0; //set received bytes count to 0 //is receive operation underway? if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){ //how many bytes are already received? *size = PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = 0; } //restore interrupt status usbRestoreOutEndpointInterrupt(state); return (USB_SUCCEED); }
/* * Aborts an active receive operation on interface intfNum. * Returns the number of bytes that were received and transferred * to the data location established for this receive operation. */ BYTE USBCDC_abortReceive (WORD* size, BYTE intfNum) { //interrupts disable BYTE edbIndex; WORD state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableOutEndpointInterrupt(edbIndex); *size = 0; //set received bytes count to 0 //is receive operation underway? if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){ //how many bytes are already received? *size = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = 0; } //restore interrupt status usbRestoreOutEndpointInterrupt(state); return (kUSB_succeed); }
/* * This function indicates the status of the itnerface intfNum. * If a send operation is active for this interface, * the function also returns the number of bytes that have been transmitted to the host. * If a receiver operation is active for this interface, the function also returns * the number of bytes that have been received from the host and are waiting at the assigned address. * * returns kUSBPHDC_waitingForSend (indicates that a call to USBPHDC_SendData() * has been made, for which data transfer has not been completed) * * returns kUSBPHDC_waitingForReceive (indicates that a receive operation * has been initiated, but not all data has yet been received) * * returns kUSBPHDC_dataWaiting (indicates that data has been received * from the host, waiting in the USB receive buffers) */ uint8_t USBPHDC_intfStatus (uint8_t intfNum, uint16_t* bytesSent, uint16_t* bytesReceived) { uint8_t ret = 0; uint16_t stateIn, stateOut; uint8_t edbIndex; *bytesSent = 0; *bytesReceived = 0; edbIndex = stUsbHandle[intfNum].edb_Index; stateIn = usbDisableInEndpointInterrupt(edbIndex); stateOut = usbDisableOutEndpointInterrupt(edbIndex); //Is send operation underway? if (PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSendLeft != 0){ ret |= kUSBPHDC_waitingForSend; *bytesSent = PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSend - PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)]. nPHDCBytesToSendLeft; } //Is receive operation underway? if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ ret |= kUSBPHDC_waitingForReceive; *bytesReceived = PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; } else { //receive operation not started //do not access USB memory if suspended (PLL off). It may produce //BUS_ERROR if (!bFunctionSuspended){ if ((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK) | //any of buffers has a valid data packet (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK)){ ret |= kUSBPHDC_dataWaiting; } } } if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ //if suspended or not enumerated - report no other tasks pending ret = kUSBPHDC_busNotAvailable; } //restore interrupt status usbRestoreInEndpointInterrupt(stateIn); usbRestoreOutEndpointInterrupt(stateOut); __no_operation(); return (ret); }
/* * This function rejects payload data that has been received from the host. */ BYTE USBHID_rejectData (BYTE intfNum) { WORD state; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableOutEndpointInterrupt(edbIndex); //interrupts disable //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if (bFunctionSuspended){ usbRestoreOutEndpointInterrupt(state); return (kUSBHID_busNotAvailable); } //Is receive operation underway? //- do not flush buffers if any operation still active. if (!HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){ BYTE tmp1 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK; BYTE tmp2 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK; if (tmp1 ^ tmp2){ //switch current buffer if any and only ONE of the //buffers is full //switch current buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY + 1) & 0x01; } tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX = 0; //flush buffer X tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY = 0; //flush buffer Y HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; //indicates that no more data available in the EP } usbRestoreOutEndpointInterrupt(state); return (kUSB_succeed); }
uint8_t USBCDC_getInterfaceStatus (uint8_t intfNum, uint16_t* bytesSent, uint16_t* bytesReceived) { uint8_t ret = 0; uint16_t stateIn, stateOut; uint8_t edbIndex; *bytesSent = 0; *bytesReceived = 0; edbIndex = stUsbHandle[intfNum].edb_Index; stateIn = usbDisableInEndpointInterrupt(edbIndex); stateOut = usbDisableOutEndpointInterrupt(edbIndex); //Is send operation underway? if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft != 0){ ret |= USBCDC_WAITING_FOR_SEND; *bytesSent = CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend - CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft; } //Is receive operation underway? if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ ret |= USBCDC_WAITING_FOR_RECEIVE; *bytesReceived = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - CdcReadCtrl[INTFNUM_OFFSET(intfNum)]. nBytesToReceiveLeft; } else { //receive operation not started //do not access USB memory if suspended (PLL off). //It may produce BUS_ERROR if (!bFunctionSuspended){ if ((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK) | //any of buffers has a valid data packet (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK)){ ret |= USBCDC_DATA_WAITING; } } } if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ //if suspended or not enumerated - report no other tasks pending ret = USBCDC_BUS_NOT_AVAILABLE; } //restore interrupt status usbRestoreInEndpointInterrupt(stateIn); usbRestoreOutEndpointInterrupt(stateOut); __no_operation(); return (ret); }
uint8_t USBCDC_rejectData (uint8_t intfNum) { uint8_t edbIndex; uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if (bFunctionSuspended){ usbRestoreOutEndpointInterrupt(state); return (USBCDC_BUS_NOT_AVAILABLE); } //Is receive operation underway? //- do not flush buffers if any operation still active. if (!CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer){ uint8_t tmp1 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK; uint8_t tmp2 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK; if (tmp1 ^ tmp2){ //switch current buffer if any and only ONE of buffers //is full //switch current buffer CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY + 1) & 0x01; } tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX = 0; //flush buffer X tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY = 0; //flush buffer Y CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; //indicates that no more data available in the EP } usbRestoreOutEndpointInterrupt(state); return (USB_SUCCEED); }
/* * Returns how many bytes are in the buffer are received and ready to be read. */ uint8_t USBPHDC_bytesInUSBBuffer (uint8_t intfNum) { uint8_t bTmp1 = 0; uint16_t state; uint8_t edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ usbRestoreOutEndpointInterrupt(state); //if suspended or not enumerated - report 0 bytes available return (0); } if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //If a RX operation is underway, part of data may was read of the //OEP buffer bTmp1 = PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp; if (*PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & EPBCNT_NAK){ //the next buffer has a valid data packet bTmp1 += *PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 & 0x7F; } } else { if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet bTmp1 = tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & 0x7F; } if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){ //this buffer has a valid data packet bTmp1 += tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & 0x7F; } } usbRestoreOutEndpointInterrupt(state); return (bTmp1); }
/* * Receives data over interface intfNum, of size size, into memory starting at address data. * Returns: * kUSBPHDC_receiveStarted if the receiving process started. * kUSBPHDC_receiveCompleted all requested date are received. * kUSBPHDC_receiveInProgress previous receive opereation is in progress. The requested receive operation can be not started. * kUSBPHDC_generalError error occurred. */ uint8_t USBPHDC_receiveData (uint8_t* data, uint16_t size, uint8_t intfNum) { uint8_t nTmp1; uint8_t edbIndex; uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; if ((size == 0) || //read size is 0 (data == NULL)){ return (kUSBPHDC_generalError); } state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ //data can not be read because of USB suspended usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_busNotAvailable); } if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ //receive process already started usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_intfBusyError); } PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive = size; //bytes to receive PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = size; //left bytes to receive PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = data; //set user receive buffer //read rest of data from buffer, if any4 if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //copy data from pEP-endpoint into User's buffer PHDCCopyUsbToBuff(PHDCReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & USB_RECEIVED_COMPLETED_EVENT){ USBPHDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_receiveCompleted); //receive completed } //check other EP buffer for data - exchange pCT1 with pCT2 if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 == &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX){ PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer; } else { PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer; } nTmp1 = *PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; //try read data from second buffer if (nTmp1 & EPBCNT_NAK){ //if the second buffer has received data? nTmp1 = nTmp1 & 0x7f; //clear NAK bit PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer PHDCCopyUsbToBuff(PHDCReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); } if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & USB_RECEIVED_COMPLETED_EVENT){ USBPHDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_receiveCompleted); //receive completed } } //read rest of data from buffer, if any //read 'fresh' data, if available nTmp1 = 0; if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ //this is current buffer if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet //this is the active EP buffer //pEP1 PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; //second EP buffer PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; nTmp1 = 1; //indicate that data is available } } else { //Y_BUFFER if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){ //this is the active EP buffer PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (uint8_t*)stUsbHandle[intfNum].oep_Y_Buffer; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; //second EP buffer PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (uint8_t*)stUsbHandle[intfNum].oep_X_Buffer; PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; nTmp1 = 1; //indicate that data is available } } if (nTmp1){ //how many byte we can get from one endpoint buffer nTmp1 = *PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; while (nTmp1 == 0) { nTmp1 = *PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; } if (nTmp1 & EPBCNT_NAK){ nTmp1 = nTmp1 & 0x7f; //clear NAK bit PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer PHDCCopyUsbToBuff(PHDCReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); nTmp1 = *PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; //try read data from second buffer if ((PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft > 0) && //do we have more data to send? (nTmp1 & EPBCNT_NAK)){ //if the second buffer has received data? nTmp1 = nTmp1 & 0x7f; //clear NAK bit PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer PHDCCopyUsbToBuff(PHDCReadCtrl[INTFNUM_OFFSET( intfNum)].pEP2, PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2, intfNum); PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; } } } if (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & USB_RECEIVED_COMPLETED_EVENT){ USBPHDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_receiveCompleted); } //interrupts enable usbRestoreOutEndpointInterrupt(state); return (kUSBPHDC_receiveStarted); }
uint8_t USBMSC_pollCommand () { uint16_t state; uint8_t edbIndex; uint8_t * pCT1; uint8_t * pCT2; edbIndex = stUsbHandle[MSC0_INTFNUM].edb_Index; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; //check if currently transmitting data.. if (MscReadControl.bReadProcessing == TRUE){ state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts if ((MscReadControl.dwBytesToSendLeft == 0) && (MscReadControl.lbaCount == 0)){ //data is no more processing - clear flags.. MscReadControl.bReadProcessing = FALSE; usbRestoreOutEndpointInterrupt(state); } else { if (!(tInputEndPointDescriptorBlock[edbIndex].bEPCNF & EPCNF_STALL)){ //if it is not stalled - contiune communication USBIEPIFG |= 1 << (edbIndex + 1); //trigger IN interrupt to finish data tranmition } usbRestoreOutEndpointInterrupt(state); return (USBMSC_PROCESS_BUFFER); } } if (MscState.isMSCConfigured == FALSE){ return (USBMSC_OK_TO_SLEEP); } if (!MscState.bMscSendCsw){ if (MscState.bMscCbwReceived){ if (Scsi_Verify_CBW() == SUCCESS){ //Successful reception of CBW //Parse the CBW opcode and invoke the right command handler function Scsi_Cmd_Parser(MSC0_INTFNUM); MscState.bMscSendCsw = TRUE; } MscState.bMscCbwReceived = FALSE; //CBW is performed! } else { return (USBMSC_OK_TO_SLEEP); } //check if any of out pipes has pending data and trigger interrupt if ((MscWriteControl.pCT1 != NULL) && ((*MscWriteControl.pCT1 & EPBCNT_NAK ) || (*MscWriteControl.pCT2 & EPBCNT_NAK ))){ USBOEPIFG |= 1 << (edbIndex + 1); //trigger OUT interrupt again return (USBMSC_PROCESS_BUFFER); //do not asleep, as data is coming in //and follow up data perform will be required. } } if (MscState.bMscSendCsw){ if (MscState.bMcsCommandSupported == TRUE){ //watiting till transport is finished! if ((MscWriteControl.bWriteProcessing == FALSE) && (MscReadControl.bReadProcessing == FALSE) && (MscReadControl.lbaCount == 0)){ //Send CSW if (MscState.stallAtEndofTx == TRUE) { if ((*pCT1 & EPBCNT_NAK) && (*pCT2 & EPBCNT_NAK)) { MscState.stallAtEndofTx = FALSE; usbStallInEndpoint(MSC0_INTFNUM); } } else if (SUCCESS == Scsi_Send_CSW(MSC0_INTFNUM)){ MscState.bMscSendCsw = FALSE; return (USBMSC_OK_TO_SLEEP); } } else { MSCFromHostToBuffer(); } } } return (USBMSC_PROCESS_BUFFER); //When MscState.bMcsCommandSupported = FALSE, bReadProcessing became true, and //bWriteProcessing = true. }
/* * Receives data over interface intfNum, of size size, into memory starting at address data. * Returns: * kUSBHID_receiveStarted if the receiving process started. * kUSBHID_receiveCompleted all requested date are received. * kUSBHID_receiveInProgress previous receive opereation is in progress. The requested receive operation can be not started. * kUSBHID_generalError error occurred. */ BYTE USBHID_receiveData (BYTE* data, WORD size, BYTE intfNum) { BYTE nTmp1; WORD state; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if ((size == 0) || //read size is 0 (data == NULL)){ return (kUSBHID_generalError); } state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts //do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ usbRestoreOutEndpointInterrupt(state); return (kUSBHID_busNotAvailable); } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ //receive process already started usbRestoreOutEndpointInterrupt(state); return (kUSBHID_receiveInProgress); } HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive = size; //bytes to receive HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = size; //left bytes to receive HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = data; //set user receive buffer //read rest of data from buffer, if any if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //copy data from pEP-endpoint into User's buffer HidCopyUsbToBuff(HidReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1,intfNum); if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending USBHID_handleReceiveCompleted(intfNum); //call event handler in interrupt context usbRestoreOutEndpointInterrupt(state); return (kUSBHID_receiveCompleted); //receive completed } //check other EP buffer for data - exchange pCT1 with pCT2 if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 == &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX){ HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; } else { HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; } nTmp1 = *HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; //try read data from second buffer if (nTmp1 & EPBCNT_NAK){ //if the second buffer has received data? nTmp1 = nTmp1 & 0x7f; //clear NAK bit HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = *(HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos + 1); //holds how many valid bytes in the EP buffer if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > nTmp1 - 2){ HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1 - 2; } HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos += 2; //here starts user data HidCopyUsbToBuff(HidReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1,intfNum); } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ USBHID_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBHID_receiveCompleted); //receive completed } } //read rest of data from buffer, if any //read 'fresh' data, if available nTmp1 = 0; if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ //this is current buffer if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & EPBCNT_NAK){ //this buffer has a valid data packet //this is the active EP buffer //pEP1 HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; //second EP buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; nTmp1 = 1; //indicate that data is available } } else { //Y_BUFFER if (tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY & EPBCNT_NAK){ //this is the active EP buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; //second EP buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; nTmp1 = 1; //indicate that data is available } } if (nTmp1){ //how many byte we can get from one endpoint buffer nTmp1 = *HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; if (nTmp1 & EPBCNT_NAK){ nTmp1 = nTmp1 & 0x7f; //clear NAK bit HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = *(HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos + 1); //holds how many valid bytes in the EP buffer if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > nTmp1 - 2){ HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1 - 2; } HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos += 2; //here starts user data HidCopyUsbToBuff(HidReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1,intfNum); nTmp1 = *HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; //try read data from second buffer if ((HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft > 0) && //do we have more data to receive? (nTmp1 & EPBCNT_NAK)){ //if the second buffer has received data? nTmp1 = nTmp1 & 0x7f; //clear NAK bit HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = *(HidReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 + 1); //holds how many valid bytes in the EP buffer if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > nTmp1 - 2){ HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1 - 2; } HidReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 += 2; //here starts user data HidCopyUsbToBuff(HidReadCtrl[INTFNUM_OFFSET( intfNum)].pEP2, HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2,intfNum); HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; } } } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ USBHID_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBHID_receiveCompleted); } //interrupts enable usbRestoreOutEndpointInterrupt(state); return (kUSBHID_receiveStarted); }