//***************************************************************************** // //! Reads a single byte of data from a ring buffer. //! //! \param psUSBRingBuf points to the ring buffer to be written to. //! //! This function reads a single byte of data from a ring buffer. //! //! \return The byte read from the ring buffer. // //***************************************************************************** uint8_t USBRingBufReadOne(tUSBRingBufObject *psUSBRingBuf) { uint8_t ui8Temp; // // Check the arguments. // ASSERT(psUSBRingBuf != NULL); // // Verify that space is available in the buffer. // ASSERT(USBRingBufUsed(psUSBRingBuf) != 0); // // Write the data byte. // ui8Temp = psUSBRingBuf->pui8Buf[psUSBRingBuf->ui32ReadIndex]; // // Increment the read index. // UpdateIndexAtomic(&psUSBRingBuf->ui32ReadIndex, 1, psUSBRingBuf->ui32Size); // // Return the character read. // return(ui8Temp); }
//***************************************************************************** // //! Reads data from a ring buffer. //! //! \param psUSBRingBuf points to the ring buffer to be read from. //! \param pui8Data points to where the data should be stored. //! \param ui32Length is the number of bytes to be read. //! //! This function reads a sequence of bytes from a ring buffer. //! //! \return None. // //***************************************************************************** void USBRingBufRead(tUSBRingBufObject *psUSBRingBuf, uint8_t *pui8Data, uint32_t ui32Length) { uint32_t ui32Temp; // // Check the arguments. // ASSERT(psUSBRingBuf != NULL); ASSERT(pui8Data != NULL); ASSERT(ui32Length != 0); // // Verify that data is available in the buffer. // ASSERT(ui32Length <= USBRingBufUsed(psUSBRingBuf)); // // Read the data from the ring buffer. // for(ui32Temp = 0; ui32Temp < ui32Length; ui32Temp++) { pui8Data[ui32Temp] = USBRingBufReadOne(psUSBRingBuf); } }
//***************************************************************************** // //! Reads data from a ring buffer. //! //! \param ptUSBRingBuf points to the ring buffer to be read from. //! \param pucData points to where the data should be stored. //! \param ulLength is the number of bytes to be read. //! //! This function reads a sequence of bytes from a ring buffer. //! //! \return None. // //***************************************************************************** void USBRingBufRead(tUSBRingBufObject *ptUSBRingBuf, unsigned char *pucData, unsigned long ulLength) { unsigned long ulTemp; // // Check the arguments. // ASSERT(ptUSBRingBuf != NULL); ASSERT(pucData != NULL); ASSERT(ulLength != 0); // // Verify that data is available in the buffer. // ASSERT(ulLength <= USBRingBufUsed(ptUSBRingBuf)); // // Read the data from the ring buffer. // for(ulTemp = 0; ulTemp < ulLength; ulTemp++) { pucData[ulTemp] = USBRingBufReadOne(ptUSBRingBuf); } }
//***************************************************************************** // // Handles USB_EVENT_DATA_REMAINING for a receive buffer. // // \param psBuffer points to the buffer which is receiving the event. // // This function determines the total number of bytes of data that remain // unprocessed in the client and buffer and reports this back to the caller. // // \return Returns the number of bytes remaining to be processed. // //***************************************************************************** static unsigned long HandleDataRemaining(tUSBBuffer *psBuffer) { unsigned long ulBufData, ulClientData; tUSBBufferVars *psVars; // // Get a pointer to our workspace variables. // psVars = psBuffer->pvWorkspace; // // How much data does the client currently have buffered? // ulClientData = psBuffer->pfnCallback(psBuffer->pvCBData, USB_EVENT_DATA_REMAINING, 0, (void *)0); // // How much data do we have in the buffer? // ulBufData = USBRingBufUsed(&psVars->sRingBuf); // // Return the total number of bytes of unprocessed data to the lower layer. // return(ulBufData + ulClientData); }
//***************************************************************************** // //! Reads a single byte of data from a ring buffer. //! //! \param ptUSBRingBuf points to the ring buffer to be written to. //! //! This function reads a single byte of data from a ring buffer. //! //! \return The byte read from the ring buffer. // //***************************************************************************** unsigned char USBRingBufReadOne(tUSBRingBufObject *ptUSBRingBuf) { unsigned char ucTemp; // // Check the arguments. // ASSERT(ptUSBRingBuf != NULL); // // Verify that space is available in the buffer. // ASSERT(USBRingBufUsed(ptUSBRingBuf) != 0); // // Write the data byte. // ucTemp = ptUSBRingBuf->pucBuf[ptUSBRingBuf->ulReadIndex]; // // Increment the read index. // UpdateIndexAtomic(&ptUSBRingBuf->ulReadIndex, 1, ptUSBRingBuf->ulSize); // // Return the character read. // return(ucTemp); }
//***************************************************************************** // //! Returns number of bytes available in a ring buffer. //! //! \param psUSBRingBuf is the ring buffer object to check. //! //! This function returns the number of bytes available in the ring buffer. //! //! \return Returns the number of bytes available in the ring buffer. // //***************************************************************************** uint32_t USBRingBufFree(tUSBRingBufObject *psUSBRingBuf) { // // Check the arguments. // ASSERT(psUSBRingBuf != NULL); // // Return the number of bytes available in the ring buffer. // return((psUSBRingBuf->ui32Size - 1) - USBRingBufUsed(psUSBRingBuf)); }
//***************************************************************************** // //! Returns the number of bytes of data available in the buffer. //! //! \param psBuffer is the pointer to the buffer instance which is to be //! queried. //! //! This function may be used to determine the number of bytes of data in a //! buffer. For a receive buffer, this indicates the number of bytes that the //! client can read from the buffer using USBBufferRead(). For a transmit //! buffer, this indicates the amount of data that remains to be sent to the //! USB controller. //! //! \return Returns the number of bytes of data in the buffer. // //***************************************************************************** unsigned long USBBufferDataAvailable(const tUSBBuffer *psBuffer) { tUSBBufferVars *psVars; // // Check parameter validity. // ASSERT(psBuffer); // // Get our workspace variables. // psVars = psBuffer->pvWorkspace; // // Return the amount of data in the buffer. // return(USBRingBufUsed(&psVars->sRingBuf)); }
//***************************************************************************** // //! Returns the number of bytes of data available in the buffer. //! //! \param psBuffer is the pointer to the buffer instance which is to be //! queried. //! //! This function may be used to determine the number of bytes of data in a //! buffer. For a receive buffer, this indicates the number of bytes that the //! client can read from the buffer using USBBufferRead(). For a transmit //! buffer, this indicates the amount of data that remains to be sent to the //! USB controller. //! //! \return Returns the number of bytes of data in the buffer. // //***************************************************************************** uint32_t USBBufferDataAvailable(const tUSBBuffer *psBuffer) { tUSBBufferVars *psPrivate; // // Check parameter validity. // ASSERT(psBuffer); // // Create a writable pointer to the private data. // psPrivate = &((tUSBBuffer *)psBuffer)->sPrivateData; // // Return the amount of data in the buffer. // return(USBRingBufUsed(&psPrivate->sRingBuf)); }
//***************************************************************************** // //! Reads a block of data from a USB receive buffer into storage supplied by //! the caller. //! //! \param psBuffer is the pointer to the buffer instance from which data is //! to be read. //! \param pucData points to a buffer into which the received data will be //! written. //! \param ulLength is the size of the buffer pointed to by pucData. //! //! This function reads up to ulLength bytes of data received from the USB //! host into the supplied application buffer. If the receive buffer //! contains fewer than \e ulLength bytes of data, the data that is present //! will be copied and the return code will indicate the actual number of bytes //! copied to \e pucData. //! //! \return Returns the number of bytes of data read. // //***************************************************************************** unsigned long USBBufferRead(const tUSBBuffer *psBuffer, unsigned char *pucData, unsigned long ulLength) { tUSBBufferVars *psVars; unsigned long ulAvail, ulRead; // // Check parameter validity. // ASSERT(psBuffer && pucData && ulLength); // // Get our workspace variables. // psVars = psBuffer->pvWorkspace; // // How much data is in the buffer? // ulAvail = USBRingBufUsed(&psVars->sRingBuf); // // Determine how many bytes we can actually read. // ulRead = (ulAvail < ulLength) ? ulAvail : ulLength; // // Read the data from the buffer assuming there is some to read. // if(ulRead) { USBRingBufRead(&psVars->sRingBuf, pucData, ulRead); } // // Tell the caller how many bytes we wrote to their buffer. // return(ulRead); }
//***************************************************************************** // //! Reads a block of data from a USB receive buffer into storage supplied by //! the caller. //! //! \param psBuffer is the pointer to the buffer instance from which data is //! to be read. //! \param pui8Data points to a buffer into which the received data will be //! written. //! \param ui32Length is the size of the buffer pointed to by pui8Data. //! //! This function reads up to \e ui32Length bytes of data received from the USB //! host into the supplied application buffer. If the receive buffer //! contains fewer than \e ui32Length bytes of data, the data that is present //! will be copied and the return code will indicate the actual number of bytes //! copied to \e pui8Data. //! //! \return Returns the number of bytes of data read. // //***************************************************************************** uint32_t USBBufferRead(const tUSBBuffer *psBuffer, uint8_t *pui8Data, uint32_t ui32Length) { uint32_t ui32Avail, ui32Read; tUSBBufferVars *psPrivate; // // Check parameter validity. // ASSERT(psBuffer && pui8Data && ui32Length); // // Create a writable pointer to the private data. // psPrivate = &((tUSBBuffer *)psBuffer)->sPrivateData; // // How much data is in the buffer? // ui32Avail = USBRingBufUsed(&psPrivate->sRingBuf); // // Determine how many bytes we can actually read. // ui32Read = (ui32Avail < ui32Length) ? ui32Avail : ui32Length; // // Read the data from the buffer assuming there is some to read. // if(ui32Read) { USBRingBufRead(&psPrivate->sRingBuf, pui8Data, ui32Read); } // // Tell the caller how many bytes we wrote to their buffer. // return(ui32Read); }
//***************************************************************************** // // Handles USB_EVENT_DATA_REMAINING for a receive buffer. // // \param psBuffer points to the buffer which is receiving the event. // // This function determines the total number of bytes of data that remain // unprocessed in the client and buffer and reports this back to the caller. // // \return Returns the number of bytes remaining to be processed. // //***************************************************************************** static uint32_t HandleDataRemaining(tUSBBuffer *psBuffer) { uint32_t ui32BufData, ui32ClientData; // // How much data does the client currently have buffered? // ui32ClientData = psBuffer->pfnCallback(psBuffer->pvCBData, USB_EVENT_DATA_REMAINING, 0, (void *)0); // // How much data do we have in the buffer? // ui32BufData = USBRingBufUsed(&psBuffer->sPrivateData.sRingBuf); // // Return the total number of bytes of unprocessed data to the lower layer. // return(ui32BufData + ui32ClientData); }
//***************************************************************************** // //! Removes bytes from the ring buffer by advancing the read index. //! //! \param psUSBRingBuf points to the ring buffer from which bytes are to be //! removed. //! \param ui32NumBytes is the number of bytes to be removed from the buffer. //! //! This function advances the ring buffer read index by a given number of //! bytes, removing that number of bytes of data from the buffer. If //! \e ui32NumBytes is larger than the number of bytes currently in the buffer, //! the buffer is emptied. //! //! \return None. // //***************************************************************************** void USBRingBufAdvanceRead(tUSBRingBufObject *psUSBRingBuf, uint32_t ui32NumBytes) { uint32_t ui32Count; // // Check the arguments. // ASSERT(psUSBRingBuf != NULL); // // Make sure that we are not being asked to remove more data than is // there to be removed. // ui32Count = USBRingBufUsed(psUSBRingBuf); ui32Count = (ui32Count < ui32NumBytes) ? ui32Count : ui32NumBytes; // // Advance the buffer read index by the required number of bytes. // UpdateIndexAtomic(&psUSBRingBuf->ui32ReadIndex, ui32Count, psUSBRingBuf->ui32Size); }
//***************************************************************************** // //! Removes bytes from the ring buffer by advancing the read index. //! //! \param ptUSBRingBuf points to the ring buffer from which bytes are to be //! removed. //! \param ulNumBytes is the number of bytes to be removed from the buffer. //! //! This function advances the ring buffer read index by a given number of //! bytes, removing that number of bytes of data from the buffer. If \e //! ulNumBytes is larger than the number of bytes currently in the buffer, the //! buffer is emptied. //! //! \return None. // //***************************************************************************** void USBRingBufAdvanceRead(tUSBRingBufObject *ptUSBRingBuf, unsigned long ulNumBytes) { unsigned long ulCount; // // Check the arguments. // ASSERT(ptUSBRingBuf != NULL); // // Make sure that we are not being asked to remove more data than is // there to be removed. // ulCount = USBRingBufUsed(ptUSBRingBuf); ulCount = (ulCount < ulNumBytes) ? ulCount : ulNumBytes; // // Advance the buffer read index by the required number of bytes. // UpdateIndexAtomic(&ptUSBRingBuf->ulReadIndex, ulCount, ptUSBRingBuf->ulSize); }
//***************************************************************************** // // Schedule the next packet transmission to the host if data remains to be // sent. // // \param psBuffer points to the buffer from which a packet transmission is // to be scheduled. // // This function checks to determine whether the lower layer is capable of // accepting a new packet for transmission and, if so, schedules the next // packet transmission if data remains in the buffer. // // \return None. // //***************************************************************************** static void ScheduleNextTransmission(const tUSBBuffer *psBuffer) { tUSBBufferVars *psVars; unsigned long ulPacket, ulSpace, ulTotal; // // Get a pointer to our workspace variables. // psVars = psBuffer->pvWorkspace; // // Ask the lower layer if it has space to accept another packet of data. // ulPacket = psBuffer->pfnAvailable(psBuffer->pvHandle); // // If we were returned something other than zero, we can write that number // of bytes to the lower layer. // if(ulPacket) { // // How much contiguous data do we have in the buffer? // ulSpace = USBRingBufContigUsed(&psVars->sRingBuf); // // How much total data do we have in the buffer? // ulTotal = USBRingBufUsed(&psVars->sRingBuf); // // Write the contiguous bytes to the lower layer assuming there is // something to send. // if(ulSpace) { // // Determine the maximum sized block we can send in this transfer. // ulSpace = (ulSpace < ulPacket) ? ulSpace : ulPacket; // // Call the lower layer to send the new packet. If the current // data spans the buffer wrap, tell the lower layer that it can // expect a second call to fill the whole packet before it // transmits it. // psBuffer->pfnTransfer(psBuffer->pvHandle, (psVars->sRingBuf.pucBuf + psVars->sRingBuf.ulReadIndex), ulSpace, (((ulSpace < ulPacket) && (ulSpace < ulTotal)) ? false : true)); // // Do we need to send a second part to fill out the packet? This // will occur if the current packet spans the buffer wrap. // if((ulSpace < ulPacket) && (ulSpace < ulTotal)) { // // The packet straddled the wrap. How much space remains in // the packet? // ulPacket -= ulSpace; // // How much data can we actually send? // ulSpace = ulTotal - ulSpace; ulSpace = (ulSpace > ulPacket) ? ulPacket : ulSpace; psBuffer->pfnTransfer(psBuffer->pvHandle, psVars->sRingBuf.pucBuf, ulSpace, true); } } // // Don't update the ring buffer read index yet. We do this once we are // sure the packet was correctly transmitted. // } }
//***************************************************************************** // // Handles USB_EVENT_RX_AVAILABLE for a receive buffer. // // \param psBuffer points to the buffer which is receiving the event. // \param ulSize is the size reported in the event. // \param pucData is the pointer provided in the event. // // This function is responsible for reading data from the lower layer into // the buffer or, if we had previously passed a section of the buffer to the // lower layer for it to write into directly, updating the buffer write pointer // to add the new data to the buffer. // // If the pointer provided is NULL, we call the low level pfnTransfer function // to get the new data. If the pointer is not NULL and not within the existing // ring buffer, we copy the data directly from the pointer to the buffer and // return the number of bytes read. // // \return Returns the number of bytes read from the lower layer. // //***************************************************************************** static unsigned long HandleRxAvailable(tUSBBuffer *psBuffer, unsigned long ulSize, unsigned char *pucData) { tUSBBufferVars *psVars; unsigned long ulAvail, ulRead, ulPacket, ulRetCount; // // Get a pointer to our workspace variables. // psVars = psBuffer->pvWorkspace; // // Has the data already been read into memory? // if(pucData) { // // Yes - is it already in our ring buffer? // if((pucData >= psBuffer->pcBuffer) && (pucData < psBuffer->pcBuffer + psBuffer->ulBufferSize)) { // // The data is already in our ring buffer so merely update the // write pointer to add the new data. // USBRingBufAdvanceWrite(&psVars->sRingBuf, ulSize); // // In this case, we pass back 0 to indicate that the lower layer // doesn't need to make any buffer pointer updates. // ulRetCount = 0; } else { // // The data is not within our buffer so we need to copy it into // the buffer. // // How much space does the buffer have available? // ulAvail = USBRingBufFree(&psVars->sRingBuf); // // How much should we copy? // ulRead = (ulAvail < ulSize) ? ulAvail : ulSize; // // Copy the data into the buffer. // USBRingBufWrite(&psVars->sRingBuf, pucData, ulRead); // // We need to return the number of bytes we read in this case // since the buffer supplied to us was owned by the lower layer and // it may need to update its read pointer. // ulRetCount = ulRead; } } else { // // We were passed a NULL pointer so the low level driver has not read // the data into memory yet. We need to call the transfer function to // get the packet. // // How big is the packet that we need to receive? // ulPacket = psBuffer->pfnAvailable(psBuffer->pvHandle); // // How much contiguous space do we have in the buffer? // ulAvail = USBRingBufContigFree(&psVars->sRingBuf); // // Get as much of the packet as we can in the available space. // ulRead = psBuffer->pfnTransfer(psBuffer->pvHandle, (psVars->sRingBuf.pucBuf + psVars->sRingBuf.ulWriteIndex), ulAvail, true); // // Advance the ring buffer write pointer to add our new data. // if(ulRead) { USBRingBufAdvanceWrite(&psVars->sRingBuf, ulRead); } // // Did we get the whole packet? // if(ulRead < ulPacket) { // // No - how much space do we have in the buffer? // ulAvail = USBRingBufContigFree(&psVars->sRingBuf); // // If there is any space left, read as much of the remainder of // the packet as we can. // if(ulAvail) { ulPacket = psBuffer->pfnTransfer(psBuffer->pvHandle, (psVars->sRingBuf.pucBuf + psVars->sRingBuf.ulWriteIndex), ulAvail, true); // // Update the write pointer after we read more data into the // buffer. // if(ulPacket) { USBRingBufAdvanceWrite(&psVars->sRingBuf, ulPacket); } } } // // We need to return 0 in this case to indicate that the lower layer // need not perform any buffer maintenance as a result of the callback. // ulRetCount = 0; } // // How much data do we have in the buffer? // ulAvail = USBRingBufUsed(&psVars->sRingBuf); // // Pass the event on to the client with the current read pointer and // available data size. The client is expected to understand the ring // structure and be able to deal with wrap if it wants to read the data // directly from the buffer. // ulRead = psBuffer->pfnCallback(psBuffer->pvCBData, USB_EVENT_RX_AVAILABLE, ulAvail, (psVars->sRingBuf.pucBuf + psVars->sRingBuf.ulReadIndex)); // // If the client read anything from the buffer, update the read pointer. // USBRingBufAdvanceRead(&psVars->sRingBuf, ulRead); // // Return the correct value to the low level driver. // return(ulRetCount); }
//***************************************************************************** // // Schedule the next packet transmission to the host if data remains to be // sent. // // \param psBuffer points to the buffer from which a packet transmission is // to be scheduled. // // This function checks to determine whether the lower layer is capable of // accepting a new packet for transmission and, if so, schedules the next // packet transmission if data remains in the buffer. // // \return None. // //***************************************************************************** static void ScheduleNextTransmission(tUSBBuffer *psBuffer) { uint32_t ui32Packet, ui32Space, ui32Total, ui32Sent; // // Ask the lower layer if it has space to accept another packet of data. // ui32Packet = psBuffer->pfnAvailable(psBuffer->pvHandle); // // If we were returned something other than zero, we can write that number // of bytes to the lower layer. // if(ui32Packet) { // // How much contiguous data do we have in the buffer? // ui32Space = USBRingBufContigUsed(&psBuffer->sPrivateData.sRingBuf); // // How much total data do we have in the buffer? // ui32Total = USBRingBufUsed(&psBuffer->sPrivateData.sRingBuf); // // How much data will we be sending as a result of this call? // ui32Sent = (ui32Packet < ui32Total) ? ui32Packet : ui32Total; // // Write the contiguous bytes to the lower layer assuming there is // something to send. // if(ui32Space) { // // There is data available to send. Update our state to indicate // the amount we will be sending in this packet. // psBuffer->sPrivateData.ui32LastSent = ui32Sent; // // Determine the maximum sized block we can send in this transfer. // ui32Space = (ui32Space < ui32Packet) ? ui32Space : ui32Packet; // // Call the lower layer to send the new packet. If the current // data spans the buffer wrap, tell the lower layer that it can // expect a second call to fill the whole packet before it // transmits it. // psBuffer->pfnTransfer(psBuffer->pvHandle, (psBuffer->sPrivateData.sRingBuf.pui8Buf + psBuffer->sPrivateData.sRingBuf.ui32ReadIndex), ui32Space, (((ui32Space < ui32Packet) && (ui32Space < ui32Total)) ? false : true)); // // Do we need to send a second part to fill out the packet? This // will occur if the current packet spans the buffer wrap. // if((ui32Space < ui32Packet) && (ui32Space < ui32Total)) { // // The packet straddled the wrap. How much space remains in // the packet? // ui32Packet -= ui32Space; // // How much data can we actually send? // ui32Space = ui32Total - ui32Space; ui32Space = (ui32Space > ui32Packet) ? ui32Packet : ui32Space; psBuffer->pfnTransfer(psBuffer->pvHandle, psBuffer->sPrivateData.sRingBuf.pui8Buf, ui32Space, true); } } else { // // There is no data to send. Did we last send a full packet? // if(psBuffer->sPrivateData.ui32LastSent == ui32Packet) { // // Yes - if necessary, send a zero-length packet back to the // host to complete the last transaction. // if(psBuffer->sPrivateData.ui32Flags & USB_BUFFER_FLAG_SEND_ZLP) { psBuffer->sPrivateData.ui32LastSent = 0; psBuffer->pfnTransfer(psBuffer->pvHandle, psBuffer->sPrivateData.sRingBuf.pui8Buf, 0, true); } } } // // Don't update the ring buffer read index yet. We do this once we are // sure the packet was correctly transmitted. // } }