//this function is used only by USB interrupt. //It fills user receiving buffer with received data BOOL CdcToBufferFromHost (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 (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //do we have somtething to receive? CdcReadCtrl[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 (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].bCurrentBufferXY == X_BUFFER){ //X is current buffer //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; //second EP buffer CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; } else { //this is the active EP buffer pEP1 = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; //second EP buffer CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; } //how many byte we can get from one endpoint buffer nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].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 CopyUsbToBuff(pEP1, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; //try read data from second buffer if ((CdcReadCtrl[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 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET( intfNum)].pEP2, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2, intfNum); CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; } } if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ bWakeUp |= USBCDC_handleReceiveCompleted(intfNum); } if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp){ //Is not read data still available in the EP? if (wUsbEventMask & kUSB_dataReceivedEvent){ bWakeUp |= USBCDC_handleDataReceived(intfNum); } } } return (bWakeUp); }
//this function is used only by USB interrupt. //It fills user receiving buffer with received data BOOL CdcToBufferFromHost() { BYTE * pEP1; BYTE nTmp1; BYTE bWakeUp = FALSE; // per default we do not wake up after interrupt if (CdcReadCtrl.nBytesToReceiveLeft == 0) // do we have somtething to receive? { CdcReadCtrl.pUserBuffer = NULL; // no more receiving pending return bWakeUp; } // No data to receive... if (!((tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX | tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY) & 0x80)) { return bWakeUp; } if (CdcReadCtrl.bCurrentBufferXY == X_BUFFER) //X is current buffer { //this is the active EP buffer pEP1 = (BYTE*)OEP3_X_BUFFER_ADDRESS; CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX; //second EP buffer CdcReadCtrl.pEP2 = (BYTE*)OEP3_Y_BUFFER_ADDRESS; CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY; } else { //this is the active EP buffer pEP1 = (BYTE*)OEP3_Y_BUFFER_ADDRESS; CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY; //second EP buffer CdcReadCtrl.pEP2 = (BYTE*)OEP3_X_BUFFER_ADDRESS; CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX; } // how many byte we can get from one endpoint buffer nTmp1 = *CdcReadCtrl.pCT1; while(nTmp1 == 0) { nTmp1 = *CdcReadCtrl.pCT1; } if(nTmp1 & EPBCNT_NAK) { nTmp1 = nTmp1 &0x7f; // clear NAK bit CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer CopyUsbToBuff(pEP1, CdcReadCtrl.pCT1); nTmp1 = *CdcReadCtrl.pCT2; //try read data from second buffer if ((CdcReadCtrl.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 CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl.pEP2, CdcReadCtrl.pCT2); CdcReadCtrl.pCT1 = CdcReadCtrl.pCT2; } } if (CdcReadCtrl.nBytesToReceiveLeft == 0) // the Receive opereation is completed { CdcReadCtrl.pUserBuffer = NULL; // no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent) { bWakeUp = USBCDC_handleReceiveCompleted(1); } if (CdcReadCtrl.nBytesInEp) // Is not read data still available in the EP? { if (wUsbEventMask & kUSB_dataReceivedEvent) { bWakeUp = USBCDC_handleDataReceived(1); } } } return bWakeUp; }
/* * Receives data over interface intfNum, of size size, into memory starting at address data. * Returns: * kUSBCDC_receiveStarted if the receiving process started. * kUSBCDC_receiveCompleted all requested date are received. * kUSBCDC_receiveInProgress previous receive opereation is in progress. The requested receive operation can be not started. * kUSBCDC_generalError error occurred. */ BYTE USBCDC_receiveData (BYTE* data, WORD size, BYTE intfNum) { BYTE nTmp1; BYTE edbIndex; WORD state; edbIndex = stUsbHandle[intfNum].edb_Index; if ((size == 0) || //read size is 0 (data == NULL)){ return (kUSBCDC_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 (kUSBCDC_busNotAvailable); } if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer != NULL){ //receive process already started usbRestoreOutEndpointInterrupt(state); return (kUSBCDC_intfBusyError); } CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceive = size; //bytes to receive CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft = size; //left bytes to receive CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = data; //set user receive buffer //read rest of data from buffer, if any if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp > 0){ //copy data from pEP-endpoint into User's buffer CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, CdcReadCtrl[INTFNUM_OFFSET( intfNum) ].pCT1, intfNum); if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBCDC_receiveCompleted); //receive completed } //check other EP buffer for data - exchange pCT1 with pCT2 if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 == &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX){ CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; } else { CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; } nTmp1 = *CdcReadCtrl[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 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); } if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBCDC_receiveCompleted); //receive completed } } //read rest of data from buffer, if any //read 'fresh' data, if available nTmp1 = 0; if (CdcReadCtrl[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 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTX; //second EP buffer CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; CdcReadCtrl[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 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCurrentEpPos = (BYTE*)stUsbHandle[intfNum].oep_Y_Buffer; CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = &tOutputEndPointDescriptorBlock[edbIndex].bEPBCTY; //second EP buffer CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pEP2 = (BYTE*)stUsbHandle[intfNum].oep_X_Buffer; CdcReadCtrl[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 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1; while (nTmp1 == 0) { nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].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 CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET( intfNum)].pCurrentEpPos, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1, intfNum); nTmp1 = *CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; //try read data from second buffer if ((CdcReadCtrl[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 CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesInEp = nTmp1; //holds how many valid bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl[INTFNUM_OFFSET( intfNum)].pEP2, CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2, intfNum); CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT1 = CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pCT2; } } } if (CdcReadCtrl[INTFNUM_OFFSET(intfNum)].nBytesToReceiveLeft == 0){ //the Receive opereation is completed CdcReadCtrl[INTFNUM_OFFSET(intfNum)].pUserBuffer = NULL; //no more receiving pending if (wUsbEventMask & kUSB_receiveCompletedEvent){ USBCDC_handleReceiveCompleted(intfNum); //call event handler in interrupt context } usbRestoreOutEndpointInterrupt(state); return (kUSBCDC_receiveCompleted); } //interrupts enable usbRestoreOutEndpointInterrupt(state); return (kUSBCDC_receiveStarted); }
/* Receives data over interface intfNum, of size size, into memory starting at address data. Returns: kUSBCDC_receiveStarted if the receiving process started. kUSBCDC_receiveCompleted all requested date are received. kUSBCDC_receiveInProgress previous receive opereation is in progress. The requested receive operation can be not started. kUSBCDC_generalError error occurred. */ BYTE USBCDC_receiveData(BYTE* data, WORD size, BYTE intfNum) { BYTE nTmp1; if (CdcReadCtrl.pUserBuffer != NULL) // receive process already started { return kUSBCDC_intfBusyError; } if ((size == 0) || // read size is 0 (data == NULL)) { return kUSBCDC_generalError; } // 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 return kUSBCDC_busNotAvailable; } __disable_interrupt(); //interrupts disable CdcReadCtrl.nBytesToReceive = size; // bytes to receive CdcReadCtrl.nBytesToReceiveLeft = size; // left bytes to receive CdcReadCtrl.pUserBuffer = data; // set user receive buffer //read rest of data from buffer, if any if (CdcReadCtrl.nBytesInEp > 0) { // copy data from pEP-endpoint into User's buffer CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1); if (CdcReadCtrl.nBytesToReceiveLeft == 0) // the Receive opereation is completed { CdcReadCtrl.pUserBuffer = NULL; // no more receiving pending USBCDC_handleReceiveCompleted(1); // call event handler in interrupt context __enable_interrupt(); // interrupts enable return kUSBCDC_receiveCompleted; // receive completed } // check other EP buffer for data - exchange pCT1 with pCT2 if (CdcReadCtrl.pCT1 == &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX) { CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY; CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_Y_BUFFER_ADDRESS; } else { CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX; CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_X_BUFFER_ADDRESS; } nTmp1 = *CdcReadCtrl.pCT1; //try read data from second buffer if (nTmp1 & EPBCNT_NAK) // if the second buffer has received data? { nTmp1 = nTmp1 &0x7f; // clear NAK bit CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1); } if (CdcReadCtrl.nBytesToReceiveLeft == 0) // the Receive opereation is completed { CdcReadCtrl.pUserBuffer = NULL; // no more receiving pending __enable_interrupt(); // interrupts enable return kUSBCDC_receiveCompleted; // receive completed } } //read rest of data from buffer, if any //read 'fresh' data, if available nTmp1 = 0; if (CdcReadCtrl.bCurrentBufferXY == X_BUFFER) //this is current buffer { if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK) //this buffer has a valid data packet { //this is the active EP buffer //pEP1 CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_X_BUFFER_ADDRESS; CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX; //second EP buffer CdcReadCtrl.pEP2 = (BYTE*)OEP3_Y_BUFFER_ADDRESS; CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY; nTmp1 = 1; //indicate that data is available } } else // Y_BUFFER if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK) { //this is the active EP buffer CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_Y_BUFFER_ADDRESS; CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY; //second EP buffer CdcReadCtrl.pEP2 = (BYTE*)OEP3_X_BUFFER_ADDRESS; CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX; nTmp1 = 1; //indicate that data is available } if (nTmp1) { // how many byte we can get from one endpoint buffer nTmp1 = *CdcReadCtrl.pCT1; while(nTmp1 == 0) { nTmp1 = *CdcReadCtrl.pCT1; } if(nTmp1 & EPBCNT_NAK) { nTmp1 = nTmp1 &0x7f; // clear NAK bit CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1); nTmp1 = *CdcReadCtrl.pCT2; //try read data from second buffer if ((CdcReadCtrl.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 CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer CopyUsbToBuff(CdcReadCtrl.pEP2, CdcReadCtrl.pCT2); CdcReadCtrl.pCT1 = CdcReadCtrl.pCT2; } } } if (CdcReadCtrl.nBytesToReceiveLeft == 0) // the Receive opereation is completed { CdcReadCtrl.pUserBuffer = NULL; // no more receiving pending USBCDC_handleReceiveCompleted(1); // call event handler in interrupt context __enable_interrupt(); // interrupts enable return kUSBCDC_receiveCompleted; } //interrupts enable __enable_interrupt(); return kUSBCDC_receiveStarted; }