//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; 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; }
//this function is used only by USB interrupt BOOL CdcToHostFromBuffer() { BYTE byte_count, nTmp2; BYTE * pEP1; BYTE * pEP2; BYTE * pCT1; BYTE * pCT2; BYTE bWakeUp = FALSE; //TRUE for wake up after interrupt static BYTE bZeroPacketSent; // = FALSE; if (CdcWriteCtrl.nCdcBytesToSendLeft == 0) // do we have somtething to send? { if (!bZeroPacketSent) // zero packet was not yet sent { bZeroPacketSent = TRUE; CdcWriteCtrl.nCdcBytesToSend = 0; // nothing to send //call event callback function if (wUsbEventMask & kUSB_sendCompletedEvent) { bWakeUp = USBCDC_handleSendCompleted(1); } } // if (!bSentZeroPacket) return bWakeUp; } bZeroPacketSent = FALSE; // zero packet will be not sent: we have data if (CdcWriteCtrl.bCurrentBufferXY == X_BUFFER) { //this is the active EP buffer pEP1 = (BYTE*)IEP3_X_BUFFER_ADDRESS; pCT1 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTX; //second EP buffer pEP2 = (BYTE*)IEP3_Y_BUFFER_ADDRESS; pCT2 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTY; } else { //this is the active EP buffer pEP1 = (BYTE*)IEP3_Y_BUFFER_ADDRESS; pCT1 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTY; //second EP buffer pEP2 = (BYTE*)IEP3_X_BUFFER_ADDRESS; pCT2 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTX; } // how many byte we can send over one endpoint buffer byte_count = (CdcWriteCtrl.nCdcBytesToSendLeft > EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl.nCdcBytesToSendLeft; nTmp2 = *pCT1; if(nTmp2 & EPBCNT_NAK) { USB_TX_memcpy(pEP1, CdcWriteCtrl.pBufferToSend, byte_count); // copy data into IEP3 X or Y buffer *pCT1 = byte_count; // Set counter for usb In-Transaction CdcWriteCtrl.bCurrentBufferXY = (CdcWriteCtrl.bCurrentBufferXY+1)&0x01; //switch buffer CdcWriteCtrl.nCdcBytesToSendLeft -= byte_count; CdcWriteCtrl.pBufferToSend += byte_count; // move buffer pointer //try to send data over second buffer nTmp2 = *pCT2; if ((CdcWriteCtrl.nCdcBytesToSendLeft > 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 = (CdcWriteCtrl.nCdcBytesToSendLeft > EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl.nCdcBytesToSendLeft; USB_TX_memcpy(pEP2, CdcWriteCtrl.pBufferToSend, byte_count); // copy data into IEP3 X or Y buffer *pCT2 = byte_count; // Set counter for usb In-Transaction CdcWriteCtrl.bCurrentBufferXY = (CdcWriteCtrl.bCurrentBufferXY+1)&0x01; //switch buffer CdcWriteCtrl.nCdcBytesToSendLeft -= byte_count; CdcWriteCtrl.pBufferToSend += byte_count; //move buffer pointer } } return bWakeUp; }
/* Reset USB-SIE and global variables. */ BYTE USB_reset() { USBKEYPID = 0x9628; // set KEY and PID to 0x9628 -> access to configuration registers enabled //reset should be on the bus after this! bEnumerationStatus = 0x00; // Device not enumerated yet bFunctionSuspended = FALSE; // Device is not in suspend mode bRemoteWakeup = DISABLE; bConfigurationNumber = 0x00; // device unconfigured bInterfaceNumber = 0x00; // FRSTE Workaround: // Clear FRSTE in the RESRIFG interrupt service routine before re-configuring USB control registers. // Set FRSTE at the beginning of SUSRIFG, SETUP, IEPIFG.EP0 and OEPIFG.EP0 interrupt service routines. USBCTL = 0; // Function Reset Connection disable (FRSTE) wBytesRemainingOnIEP0 = NO_MORE_DATA; wBytesRemainingOnOEP0 = NO_MORE_DATA; bStatusAction = STATUS_ACTION_NOTHING; //The address reset normally will be done automatically during bus function reset USBFUNADR = 0x00; // reset address of USB device (unconfigured) /* Set settings for EP0 */ // NAK both 0 endpoints and enable endpoint 0 interrupt tEndPoint0DescriptorBlock.bIEPBCNT = EPBCNT_NAK; tEndPoint0DescriptorBlock.bOEPBCNT = EPBCNT_NAK; tEndPoint0DescriptorBlock.bIEPCNFG = EPCNF_USBIE | EPCNF_UBME | EPCNF_STALL; // 8 byte data packet tEndPoint0DescriptorBlock.bOEPCNFG = EPCNF_USBIE | EPCNF_UBME | EPCNF_STALL; // 8 byte data packet USBOEPIE = BIT0 | BIT1 | BIT3; // enable EP0, and EP3 output IRQ USBIEPIE = BIT0 | BIT1 | BIT2 | BIT3; // enable EP0, EP1, EP2 and EP3 input IRQ #ifdef _HID_ /* Set settings for IEP1 */ // enable endpoint 1 interrupt, input tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPCNF = EPCNF_USBIE | EPCNF_UBME | EPCNF_DBUF; //double buffering tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBBAX = (BYTE)(((IEP1_X_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBBAY = (BYTE)(((IEP1_Y_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBCTX = EPBCNT_NAK; tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBCTY = EPBCNT_NAK; tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPSIZXY = MAX_PACKET_SIZE; /* Set settings for OEP1 */ // enable endpoint 1 interrupt, output tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPCNF = EPCNF_USBIE | EPCNF_UBME | EPCNF_DBUF ; //double buffering tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBBAX = (BYTE)(((OEP1_X_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBBAY = (BYTE)(((OEP1_Y_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTX = 0x00; tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTY = 0x00; // EPBCT_NAK for one buffer (no double) tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPSIZXY = MAX_PACKET_SIZE; HidResetData(); // reset CDC specific data structures #endif // _HID_ #ifdef _CDC_ /* Set settings for IEP2 */ // enable endpoint 2 interrupt, input tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPCNF = EPCNF_USBIE // use Interrupt for this EP | EPCNF_UBME // enable this EP | EPCNF_DBUF; // use double buffering (X and Y buffers) tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPBBAX = (BYTE)(((IEP2_X_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPBBAY = (BYTE)(((IEP2_Y_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPBCTX = EPBCNT_NAK; // NAK: the buffer has no valid data to send to host tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPBCTY = EPBCNT_NAK; // NAK: the buffer has no valid data to send to host tInputEndPointDescriptorBlock[EDB(CDC_INTEP_ADDR)].bEPSIZXY = MAX_PACKET_SIZE; /* Set settings for IEP3 */ // enable endpoint 3 bulk, input tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPCNF = EPCNF_USBIE // use Interrupt for this EP | EPCNF_UBME // enable this EP | EPCNF_DBUF; // use double buffering (X and Y buffers) tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBBAX = (BYTE)(((IEP3_X_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBBAY = (BYTE)(((IEP3_Y_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTX = EPBCNT_NAK; // NAK: the buffer has no valid data to send to host tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTY = EPBCNT_NAK; // NAK: the buffer has no valid data to send to host tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPSIZXY = MAX_PACKET_SIZE; /* Set settings for OEP3 */ // enable endpoint 3 bulk, output tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPCNF = EPCNF_USBIE // use Interrupt for this EP | EPCNF_UBME // enable this EP | EPCNF_DBUF; // use double buffering (X and Y buffers) tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBBAX = (BYTE)(((OEP3_X_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBBAY = (BYTE)(((OEP3_Y_BUFFER_ADDRESS - START_OF_USB_BUFFER) >> 3) & 0x00ff); tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX = 0x00; tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY = 0x00; tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPSIZXY = MAX_PACKET_SIZE; CdcResetData(); // reset CDC specific data structures #endif // _CDC_ USBCTL |= FEN; // enable function USBIFG = 0; // make sure no interrupts are pending USBIE = SETUPIE | RSTRIE | SUSRIE; // enable USB specific interrupts (setup, reset, suspend) USBKEYPID = 0x9600; // access to configuration registers disabled return kUSB_succeed; }
//this function is used only by USB interrupt BOOL HidToHostFromBuffer() { BYTE byte_count, nTmp2; BYTE * pEP1; BYTE * pEP2; BYTE * pCT1; BYTE * pCT2; BYTE bWakeUp = FALSE; // per default we do not wake up after interrupt if (HidWriteCtrl.nHidBytesToSendLeft == 0) // do we have somtething to send? { HidWriteCtrl.nHidBytesToSend = 0; //call event callback function if (wUsbEventMask & kUSB_sendCompletedEvent) { bWakeUp = USBHID_handleSendCompleted(1); } return bWakeUp; } if(!(tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPCNF & EPCNF_TOGGLE)) { //this is the active EP buffer pEP1 = (BYTE*)IEP1_X_BUFFER_ADDRESS; pCT1 = &tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBCTX; //second EP buffer pEP2 = (BYTE*)IEP1_Y_BUFFER_ADDRESS; pCT2 = &tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBCTY; } else { //this is the active EP buffer pEP1 = (BYTE*)IEP1_Y_BUFFER_ADDRESS; pCT1 = &tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].bEPBCTY; //second EP buffer pEP2 = (BYTE*)IEP1_X_BUFFER_ADDRESS; pCT2 = &tInputEndPointDescriptorBlock[EDB(HID_INEP_ADDR)].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.nHidBytesToSendLeft > EP_MAX_PACKET_SIZE-2) ? EP_MAX_PACKET_SIZE-2 : HidWriteCtrl.nHidBytesToSendLeft; nTmp2 = *pCT1; if(nTmp2 & EPBCNT_NAK) { USB_TX_memcpy(pEP1+2, HidWriteCtrl.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.nHidBytesToSendLeft -= byte_count; HidWriteCtrl.pHidBufferToSend += byte_count; // move buffer pointer //try to send data over second buffer nTmp2 = *pCT2; if ((HidWriteCtrl.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.nHidBytesToSendLeft > EP_MAX_PACKET_SIZE-2) ? EP_MAX_PACKET_SIZE-2 : HidWriteCtrl.nHidBytesToSendLeft; USB_TX_memcpy(pEP2+2, HidWriteCtrl.pHidBufferToSend, byte_count); // copy data into IEP3 X or Y buffer pEP2[0] = 0x3F; // set HID report descriptor: 0x3F pEP2[1] = byte_count; // set HID report descriptor // 64 bytes will be send: we use only one HID report descriptor *pCT2 = 0x40; // Set counter for usb In-Transaction HidWriteCtrl.nHidBytesToSendLeft -= byte_count; HidWriteCtrl.pHidBufferToSend += byte_count; // move buffer pointer } } return bWakeUp; }
/* Receives report reportData from the host. Return: kUSBHID_receiveCompleted kUSBHID_receiveError kUSBCDC_busNotAvailable */ BYTE USBHID_receiveReport(BYTE * reportData, BYTE intfNum) { BYTE ret = kUSBHID_receiveError; BYTE nTmp1 = 0; // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR if ((bFunctionSuspended) || (bEnumerationStatus != ENUMERATION_COMPLETE)) { return kUSBHID_busNotAvailable; } if (HidReadCtrl.bCurrentBufferXY == X_BUFFER) //this is current buffer { if (tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK) //this buffer has a valid data packet { //this is the active EP buffer //pEP1 HidReadCtrl.pCurrentEpPos = (BYTE*)OEP1_X_BUFFER_ADDRESS; HidReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTX; //second EP buffer HidReadCtrl.pEP2 = (BYTE*)OEP1_Y_BUFFER_ADDRESS; HidReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTY; nTmp1 = 1; //indicate that data is available } } else // Y_BUFFER if (tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK) { //this is the active EP buffer HidReadCtrl.pCurrentEpPos = (BYTE*)OEP1_Y_BUFFER_ADDRESS; HidReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTY; //second EP buffer HidReadCtrl.pEP2 = (BYTE*)OEP1_X_BUFFER_ADDRESS; HidReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(HID_OUTEP_ADDR)].bEPBCTX; nTmp1 = 1; //indicate that data is available } if (nTmp1) { // how many byte we can get from one endpoint buffer nTmp1 = *HidReadCtrl.pCT1; if(nTmp1 & EPBCNT_NAK) { nTmp1 = nTmp1 &0x7f; // clear NAK bit HidReadCtrl.nBytesInEp = nTmp1; // holds how many valids bytes in the EP buffer USB_RX_memcpy(reportData, HidReadCtrl.pCurrentEpPos, nTmp1); //memcpy(reportData, HidReadCtrl.pEP1, nTmp1); HidReadCtrl.bCurrentBufferXY = (HidReadCtrl.bCurrentBufferXY+1) &0x01; HidReadCtrl.nBytesInEp = 0; *HidReadCtrl.pCT1 = 0; // clear NAK, EP ready to receive data ret = kUSBHID_receiveCompleted; } } return ret; }