Beispiel #1
0
//*****************************************************************************
//
//! 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);
}
Beispiel #2
0
//*****************************************************************************
//
//! 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);
    }
}
Beispiel #3
0
//*****************************************************************************
//
//! 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);
    }
}
Beispiel #4
0
//*****************************************************************************
//
// 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);
}
Beispiel #5
0
//*****************************************************************************
//
//! 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);
}
Beispiel #6
0
//*****************************************************************************
//
//! 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));
}
Beispiel #7
0
//*****************************************************************************
//
//! 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));
}
Beispiel #8
0
//*****************************************************************************
//
//! 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));
}
Beispiel #9
0
//*****************************************************************************
//
//! 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);
}
Beispiel #10
0
//*****************************************************************************
//
//! 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);
}
Beispiel #11
0
//*****************************************************************************
//
// 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);
}
Beispiel #12
0
//*****************************************************************************
//
//! 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);
}
Beispiel #13
0
//*****************************************************************************
//
//! 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);
}
Beispiel #14
0
//*****************************************************************************
//
// 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.
        //
    }
}
Beispiel #15
0
//*****************************************************************************
//
// 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);
}
Beispiel #16
0
//*****************************************************************************
//
// 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.
        //
    }
}