/* This function indicates the status of the interface 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 kUSBHID_waitingForSend (indicates that a call to USBHID_SendData() has been made, for which data transfer has not been completed) returns kUSBHID_waitingForReceive (indicates that a receive operation has been initiated, but not all data has yet been received) returns kUSBHID_dataWaiting (indicates that data has been received from the host, waiting in the USB receive buffers) */ BYTE USBHID_intfStatus(BYTE intfNum, WORD* bytesSent, WORD* bytesReceived) { BYTE ret = 0; unsigned short bGIE; BYTE edbIndex; *bytesSent = 0; *bytesReceived = 0; edbIndex = stUsbHandle[intfNum].edb_Index; bGIE = (__get_SR_register() &GIE); //save interrupt status __disable_interrupt(); //disable interrupts - atomic operation // Is send operation underway? if (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft != 0) { ret |= kUSBHID_waitingForSend; *bytesSent = HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend - HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft; } //Is receive operation underway? if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL) { ret |= kUSBHID_waitingForReceive; *bytesReceived = HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; } else // not receive operation 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 |= kUSBHID_dataWaiting; } } } if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { // if suspended or not enumerated - report no other tasks pending ret = kUSBHID_busNotAvailable; } //restore interrupt status __bis_SR_register(bGIE); //restore interrupt status return ret; }
/* Aborts an active send operation on interface intfNum. Returns the number of bytes that were sent prior to the abort, in size. */ BYTE USBHID_abortSend(WORD* size, BYTE intfNum) { unsigned short bGIE; bGIE = (__get_SR_register() &GIE); //save interrupt status __disable_interrupt(); //disable interrupts - atomic operation *size = (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend - HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft); HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend = 0; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft = 0; __bis_SR_register(bGIE); //restore interrupt status return kUSB_succeed; }
/* * Aborts an active send operation on interface intfNum. * Returns the number of bytes that were sent prior to the abort, in size. */ uint8_t USBPHDC_abortSend (uint16_t* size, uint8_t intfNum) { uint8_t edbIndex; uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableInEndpointInterrupt(edbIndex); *size = (PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSend - PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSendLeft); PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSend = 0; PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSendLeft = 0; usbRestoreInEndpointInterrupt(state); return (USB_SUCCEED); }
/* * Aborts an active send operation on interface intfNum. * Returns the number of bytes that were sent prior to the abort, in size. */ BYTE USBPHDC_abortSend (WORD* size, BYTE intfNum) { BYTE edbIndex; WORD state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableInEndpointInterrupt(edbIndex); *size = (PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSend - PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSendLeft); PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSend = 0; PHDCWriteCtrl[INTFNUM_OFFSET(intfNum)].nPHDCBytesToSendLeft = 0; usbRestoreInEndpointInterrupt(state); return (kUSB_succeed); }
/* Sends data over interface intfNum, of size size and starting at address data. Returns: kUSBHID_sendStarted kUSBHID_sendComplete kUSBHID_intBusyError */ BYTE USBHID_sendData(const BYTE* data, WORD size, BYTE intfNum) { unsigned short bGIE; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if (size == 0) { return kUSBHID_generalError; } bGIE = (__get_SR_register() &GIE); //save interrupt status // atomic operation - disable interrupts __disable_interrupt(); // Disable global 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 __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_busNotAvailable; } if (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft != 0) { // the USB still sends previous data, we have to wait __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_intfBusyError; } //This function generate the USB interrupt. The data will be sent out from interrupt HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend = size; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft = size; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend = data; //trigger Endpoint Interrupt - to start send operation USBIEPIFG |= 1<<(edbIndex+1); //IEPIFGx; __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_sendStarted; }
/* * Aborts an active send operation on interface intfNum. * Returns the number of bytes that were sent prior to the abort, in size. */ BYTE USBCDC_abortSend (WORD* size, BYTE intfNum) { BYTE edbIndex; WORD state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableInEndpointInterrupt(edbIndex); //disable interrupts - atomic operation *size = (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend - CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft); CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = 0; CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft = 0; usbRestoreInEndpointInterrupt(state); return (kUSB_succeed); }
//this function is used only by USB interrupt. //It fills user receiving buffer with received data BOOL CdcToBufferFromHost_Bridge (BYTE intfNum) { BYTE *pEP1, *pCT1; BYTE nTmp1; BYTE bWakeUp = FALSE; //per default we do not wake up after interrupt BYTE i; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; //No data to receive... if (!((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX & 0x80))){ return (bWakeUp); } if (CdcBridgeCtrl.ctsState == 0) { return (bWakeUp); } //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; __no_operation(); __no_operation(); //how many byte we can get from endpoint buffer nTmp1 = *pCT1; if (nTmp1 & EPBCNT_NAK){ nTmp1 = nTmp1 & 0x7f; //clear NAK bit CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer if (nTmp1 > 0) { //Start DMA if (nTmp1 > 5 ) { //Start DMA while (!(*CdcBridgeCtrl.uartIFG & UCTXIFG)); *CdcBridgeCtrl.uartTx = *pEP1; *CdcBridgeCtrl.usbToUartDmaChSz = nTmp1 - 1; // Block size *CdcBridgeCtrl.usbToUartDmaChCtl = DMADT_0 + DMASRCINCR_3 + DMASBDB + DMAEN + DMAIE;// Rpt, inc src, enable } else { for (i = 0; i < nTmp1; i++) { while (!(*CdcBridgeCtrl.uartIFG & UCTXIFG)); // USCI_A0 TX buffer ready? *CdcBridgeCtrl.uartTx = *pEP1++; // TX -> RXed character } *pCT1 = 0x00; } } else { *pCT1 = 0x00; } } return (bWakeUp); }
uint8_t USBCDC_abortSend (uint16_t* size, uint8_t intfNum) { uint8_t edbIndex; uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; state = usbDisableInEndpointInterrupt(edbIndex); //disable interrupts - atomic operation *size = (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend - CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft); CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = 0; CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft = 0; usbRestoreInEndpointInterrupt(state); return (USB_SUCCEED); }
/* * Sends data over interface intfNum, of size size and starting at address data. * Returns: kUSBHID_sendStarted * kUSBHID_sendComplete * kUSBHID_intBusyError */ BYTE USBHID_sendData (const BYTE* data, WORD size, BYTE intfNum) { WORD state; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if (size == 0){ return (kUSBHID_generalError); } state = usbDisableInEndpointInterrupt(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 usbRestoreInEndpointInterrupt(state); return (kUSBHID_busNotAvailable); } if (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft != 0){ //the USB still sends previous data, we have to wait usbRestoreInEndpointInterrupt(state); return (kUSBHID_intfBusyError); } //This function generate the USB interrupt. The data will be sent out from interrupt HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend = size; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft = size; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend = data; //trigger Endpoint Interrupt - to start send operation USBIEPIFG |= 1 << (edbIndex + 1); //IEPIFGx; usbRestoreInEndpointInterrupt(state); return (kUSBHID_sendStarted); }
/* * 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); }
/* * 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); }
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); }
uint8_t USBCDC_sendData (const uint8_t* data, uint16_t size, uint8_t intfNum) { uint8_t edbIndex; uint16_t state; edbIndex = stUsbHandle[intfNum].edb_Index; if (size == 0){ return (USBCDC_GENERAL_ERROR); } state = usbDisableInEndpointInterrupt(edbIndex); //do not access USB memory if suspended (PLL uce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)){ //data can not be read because of USB suspended usbRestoreInEndpointInterrupt(state); //restore interrupt status return (USBCDC_BUS_NOT_AVAILABLE); } if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft != 0){ //the USB still sends previous data, we have to wait usbRestoreInEndpointInterrupt(state); //restore interrupt status return (USBCDC_INTERFACE_BUSY_ERROR); } //This function generate the USB interrupt. The data will be sent out from interrupt CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSend = size; CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft = size; CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].pUsbBufferToSend = data; //trigger Endpoint Interrupt - to start send operation USBIEPIFG |= 1 << (edbIndex + 1); //IEPIFGx; usbRestoreInEndpointInterrupt(state); return (USBCDC_SEND_STARTED); }
/* * 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); }
/* Sends a pre-built report reportData to the host. Returns: kUSBHID_sendComplete kUSBHID_intfBusyError kUSBCDC_busNotAvailable */ BYTE USBHID_sendReport(const BYTE * reportData, BYTE intfNum) { BYTE byte_count; BYTE * pEP1; BYTE * pCT1; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { return kUSBHID_busNotAvailable; } if (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER) { //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].iep_X_Buffer; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; } else { //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].iep_Y_Buffer; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; } byte_count = USBHID_REPORT_LENGTH; // we support only one length of report if(*pCT1 & EPBCNT_NAK) // if this EP is empty { USB_TX_memcpy(pEP1, reportData, byte_count); // copy data into IEP X or Y buffer *pCT1 = byte_count; // Set counter for usb In-Transaction HidWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY+1)&0x01; //switch buffer return kUSBHID_sendComplete; } return kUSBHID_intfBusyError; }
/* This function rejects payload data that has been received from the host. */ BYTE USBHID_rejectData(BYTE intfNum) { unsigned short bGIE; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; bGIE = (__get_SR_register() &GIE); //save interrupt status //interrupts disable __disable_interrupt(); // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if (bFunctionSuspended) { __bis_SR_register(bGIE); //restore interrupt status 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 } __bis_SR_register(bGIE); //restore interrupt status return kUSB_succeed; }
/* * 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); }
/* * 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); }
/* * 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); }
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); }
//this function is used only by USB interrupt BOOL CdcToHostFromBuffer_Bridge (BYTE intfNum) { BYTE byte_count, nTmp2; BYTE * pCT1; BYTE bWakeUp = FALSE; //TRUE for wake up after interrupt BYTE edbIndex; if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft == 0){ return (bWakeUp); } edbIndex = stUsbHandle[intfNum].edb_Index; //this is the active EP buffer pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; if (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; } else { pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; } //how many byte we can send over one endpoint buffer byte_count = (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft > EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl[ INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft; nTmp2 = *pCT1; CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY + 1) & 0x01; if (nTmp2 & EPBCNT_NAK){ //copy data into IEP3 X or Y buffer *pCT1 = byte_count; //Set counter for usb In-Transaction CdcWriteCtrl[INTFNUM_OFFSET(intfNum)].nCdcBytesToSendLeft -= byte_count; } return (bWakeUp); }
/* 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 USBHID_abortReceive(WORD* size, BYTE intfNum) { unsigned short bGIE; bGIE = (__get_SR_register() &GIE); //save interrupt status __disable_interrupt(); //disable interrupts - atomic operation *size = 0; //set received bytes count to 0 //is receive operation underway? if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer) { //how many bytes are already received? *size = HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive - HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = 0; } //restore interrupt status __bis_SR_register(bGIE); //restore interrupt status return kUSB_succeed; }
/* 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; unsigned short bGIE; bGIE = (__get_SR_register() &GIE); //save interrupt status edbIndex = stUsbHandle[intfNum].edb_Index; //interrupts disable __disable_interrupt(); if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { // if suspended or not enumerated - report 0 bytes available __bis_SR_register(bGIE); //restore interrupt status 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 __bis_SR_register(bGIE); //restore interrupt status return bTmp1; }
// helper for USB interrupt handler BOOL HidIsReceiveInProgress(BYTE intfNum) { return (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL); }
//this function is used only by USB interrupt. //It fills user receiving buffer with received data BOOL HidToBufferFromHost(BYTE intfNum) { BYTE * pEP1; BYTE nTmp1; BYTE bWakeUp = FALSE; // per default we do not wake up after interrupt BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0) // do we have somtething to receive? { HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; // no more receiving pending return bWakeUp; } // No data to receive... if (!((tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX | tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY) & 0x80)) { return bWakeUp; } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER) //X is current buffer { //this is the active EP buffer pEP1 = (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; } else { //this is the active EP buffer pEP1 = (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; } // 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 = *(pEP1+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; } pEP1 += 2; // here starts user data HidCopyUsbToBuff(pEP1, 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 send? (nTmp1 & EPBCNT_NAK)) // if the second buffer has received data? { nTmp1 = nTmp1 &0x7f; // clear NAK bit HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = *(pEP1+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) { bWakeUp = USBHID_handleReceiveCompleted(intfNum); } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp) // Is not read data still available in the EP? { if (wUsbEventMask & kUSB_dataReceivedEvent) { bWakeUp = USBHID_handleDataReceived(intfNum); } } } return bWakeUp; }
/* 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; unsigned short bGIE; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if ((size == 0) || // read size is 0 (data == NULL)) { return kUSBHID_generalError; } bGIE = (__get_SR_register() &GIE); //save interrupt status // atomic operation - disable interrupts __disable_interrupt(); // Disable global interrupts // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_busNotAvailable; } if (HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL) // receive process already started { __bis_SR_register(bGIE); //restore interrupt status 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 __bis_SR_register(bGIE); //restore interrupt status 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 USBHID_handleReceiveCompleted(intfNum); // call event handler in interrupt context __bis_SR_register(bGIE); //restore interrupt status 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 USBHID_handleReceiveCompleted(intfNum); // call event handler in interrupt context __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_receiveCompleted; } //interrupts enable __bis_SR_register(bGIE); //restore interrupt status return kUSBHID_receiveStarted; }
// This function copies data from OUT endpoint into user's buffer // Arguments: // pEP - pointer to EP to copy from // pCT - pointer to pCT control reg // VOID HidCopyUsbToBuff(BYTE* pEP, BYTE* pCT,BYTE intfNum) { BYTE nCount; // how many byte we can get from one endpoint buffer nCount = (HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft > HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp) ? HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp : HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft; USB_RX_memcpy(HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer, pEP, nCount); // copy data from OEPx X or Y buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft -= nCount; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer += nCount; // move buffer pointer // to read rest of data next time from this place if (nCount == HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp) // all bytes are copied from receive buffer? { //switch current buffer HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY+1) &0x01; HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; //clear NAK, EP ready to receive data *pCT = 0; } else { HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp -= nCount; HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = pEP + nCount; } }
//this function is used only by USB interrupt BOOL HidToHostFromBuffer(BYTE intfNum) { BYTE byte_count, nTmp2; BYTE * pEP1; BYTE * pEP2; BYTE * pCT1; BYTE * pCT2; BYTE bWakeUp = FALSE; // per default we do not wake up after interrupt BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; if (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft == 0) // do we have somtething to send? { HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSend = 0; //call event callback function if (wUsbEventMask & kUSB_sendCompletedEvent) { bWakeUp = USBHID_handleSendCompleted(intfNum); } return bWakeUp; } if(!(tInputEndPointDescriptorBlock[edbIndex].bEPCNF & EPCNF_TOGGLE)) { //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].iep_X_Buffer; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; //second EP buffer pEP2 = (BYTE*)stUsbHandle[intfNum].iep_Y_Buffer; pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; } else { //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].iep_Y_Buffer; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; //second EP buffer pEP2 = (BYTE*)stUsbHandle[intfNum].iep_X_Buffer; pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; } // how many byte we can send over one endpoint buffer // 2 bytes a reserved: [0] - HID Report Descriptor, [1] - count of valid bytes byte_count = (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft > EP_MAX_PACKET_SIZE-2) ? EP_MAX_PACKET_SIZE-2 : HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft; nTmp2 = *pCT1; if(nTmp2 & EPBCNT_NAK) { USB_TX_memcpy(pEP1+2, HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend, byte_count); // copy data into IEP3 X or Y buffer pEP1[0] = 0x3F; // set HID report descriptor: 0x3F pEP1[1] = byte_count; // set HID report descriptor // 64 bytes will be send: we use only one HID report descriptor *pCT1 = 0x40; // Set counter for usb In-Transaction HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft -= byte_count; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend += byte_count; // move buffer pointer //try to send data over second buffer nTmp2 = *pCT2; if ((HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft > 0) && // do we have more data to send? (nTmp2 & EPBCNT_NAK)) // if the second buffer is free? { // how many byte we can send over one endpoint buffer byte_count = (HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft > EP_MAX_PACKET_SIZE-2) ? EP_MAX_PACKET_SIZE-2 : HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft; USB_TX_memcpy(pEP2+2, HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend, byte_count); // copy data into IEP3 X or Y buffer pEP2[0] = 0x3F; // set HID report descriptor: 0x3F pEP2[1] = byte_count; // set byte count of valid data // 64 bytes will be send: we use only one HID report descriptor *pCT2 = 0x40; // Set counter for usb In-Transaction HidWriteCtrl[INTFNUM_OFFSET(intfNum)].nHidBytesToSendLeft -= byte_count; HidWriteCtrl[INTFNUM_OFFSET(intfNum)].pHidBufferToSend += byte_count; // move buffer pointer } } return bWakeUp; }
/* Receives report reportData from the host. Return: kUSBHID_receiveCompleted kUSBHID_generalError kUSBCDC_busNotAvailable */ BYTE USBHID_receiveReport(BYTE * reportData, BYTE intfNum) { BYTE ret = kUSBHID_generalError; BYTE nTmp1 = 0; BYTE edbIndex; edbIndex = stUsbHandle[intfNum].edb_Index; // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { return kUSBHID_busNotAvailable; } 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 = nTmp1; // holds how many valid bytes in the EP buffer USB_RX_memcpy(reportData, HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos, nTmp1); //memcpy(reportData, HidReadCtrl.pEP1, nTmp1); HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY = (HidReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY+1) &0x01; HidReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = 0; *HidReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = 0; // clear NAK, EP ready to receive data ret = kUSBHID_receiveCompleted; } } return ret; }
//helper for USB interrupt handler int16_t PHDCIsReceiveInProgress (uint8_t intfNum) { return (PHDCReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL); }