Beispiel #1
0
//*****************************************************************************
//
//! Writes data to a ring buffer.
//!
//! \param psUSBRingBuf points to the ring buffer to be written to.
//! \param pui8Data points to the data to be written.
//! \param ui32Length is the number of bytes to be written.
//!
//! This function write a sequence of bytes into a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
USBRingBufWrite(tUSBRingBufObject *psUSBRingBuf, const uint8_t *pui8Data,
                uint32_t ui32Length)
{
    uint32_t ui32Temp;

    //
    // Check the arguments.
    //
    ASSERT(psUSBRingBuf != NULL);
    ASSERT(pui8Data != NULL);
    ASSERT(ui32Length != 0);

    //
    // Verify that space is available in the buffer.
    //
    ASSERT(ui32Length <= USBRingBufFree(psUSBRingBuf));

    //
    // Write the data into the ring buffer.
    //
    for(ui32Temp = 0; ui32Temp < ui32Length; ui32Temp++)
    {
        USBRingBufWriteOne(psUSBRingBuf, pui8Data[ui32Temp]);
    }
}
Beispiel #2
0
//*****************************************************************************
//
//! Writes data to a ring buffer.
//!
//! \param ptUSBRingBuf points to the ring buffer to be written to.
//! \param pucData points to the data to be written.
//! \param ulLength is the number of bytes to be written.
//!
//! This function write a sequence of bytes into a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
USBRingBufWrite(tUSBRingBufObject *ptUSBRingBuf, const unsigned char *pucData,
                unsigned long ulLength)
{
    unsigned long ulTemp;

    //
    // Check the arguments.
    //
    ASSERT(ptUSBRingBuf != NULL);
    ASSERT(pucData != NULL);
    ASSERT(ulLength != 0);

    //
    // Verify that space is available in the buffer.
    //
    ASSERT(ulLength <= USBRingBufFree(ptUSBRingBuf));

    //
    // Write the data into the ring buffer.
    //
    for(ulTemp = 0; ulTemp < ulLength; ulTemp++)
    {
        USBRingBufWriteOne(ptUSBRingBuf, pucData[ulTemp]);
    }
}
Beispiel #3
0
//*****************************************************************************
//
//! Writes a block of data to the transmit buffer and queues it for
//! transmission to the USB controller.
//!
//! \param psBuffer points to the pointer instance into which data is to be
//! written.
//! \param pucData points to the first byte of data which is to be written.
//! \param ulLength is the number of bytes of data to write to the buffer.
//!
//! This function copies the supplied data into the transmit buffer.  The
//! transmit buffer data will be packetized according to the constraints
//! imposed by the lower layer in use and sent to the USB controller as soon as
//! possible.  Once a packet is transmitted and acknowledged, a
//! \b USB_EVENT_TX_COMPLETE event will be sent to the application callback
//! indicating the number of bytes that have been sent from the buffer.
//!
//! Attempts to send more data than there is space for in the transmit buffer
//! will result in fewer bytes than expected being written.  The value returned
//! by the function indicates the actual number of bytes copied to the buffer.
//!
//! \return Returns the number of bytes actually written.
//
//*****************************************************************************
unsigned long
USBBufferWrite(const tUSBBuffer *psBuffer, const unsigned char *pucData,
               unsigned long ulLength)
{
    unsigned long ulSpace;
    tUSBBufferVars *psVars;

    //
    // Check parameter validity.
    //
    ASSERT(psBuffer && pucData);
    ASSERT(psBuffer->bTransmitBuffer == true);

    //
    // Get our workspace variables.
    //
    psVars = psBuffer->pvWorkspace;

    //
    // How much space is left in the buffer?
    //
    ulSpace = USBRingBufFree(&psVars->sRingBuf);

    //
    // How many bytes will we write?
    //
    ulLength = (ulLength > ulSpace) ? ulSpace : ulLength;

    //
    // Write the data to the buffer.
    //
    if(ulLength)
    {
        USBRingBufWrite(&psVars->sRingBuf, pucData, ulLength);
    }

    //
    // Try to transmit the next packet to the host.
    //
    ScheduleNextTransmission(psBuffer);

    //
    // Tell the caller how many bytes we wrote to the buffer.
    //
    return(ulLength);
}
Beispiel #4
0
//*****************************************************************************
//
//! Writes a block of data to the transmit buffer and queues it for
//! transmission to the USB controller.
//!
//! \param psBuffer points to the pointer instance into which data is to be
//! written.
//! \param pui8Data points to the first byte of data which is to be written.
//! \param ui32Length is the number of bytes of data to write to the buffer.
//!
//! This function copies the supplied data into the transmit buffer.  The
//! transmit buffer data will be packetized according to the constraints
//! imposed by the lower layer in use and sent to the USB controller as soon as
//! possible.  Once a packet is transmitted and acknowledged, a
//! \b USB_EVENT_TX_COMPLETE event will be sent to the application callback
//! indicating the number of bytes that have been sent from the buffer.
//!
//! Attempts to send more data than there is space for in the transmit buffer
//! will result in fewer bytes than expected being written.  The value returned
//! by the function indicates the actual number of bytes copied to the buffer.
//!
//! \return Returns the number of bytes actually written.
//
//*****************************************************************************
uint32_t
USBBufferWrite(const tUSBBuffer *psBuffer, const uint8_t *pui8Data,
               uint32_t ui32Length)
{
    uint32_t ui32Space;
    tUSBBufferVars *psPrivate;

    //
    // Check parameter validity.
    //
    ASSERT(psBuffer && pui8Data);
    ASSERT(psBuffer->bTransmitBuffer == true);

    //
    // Create a writable pointer to the private data.
    //
    psPrivate = &((tUSBBuffer *)psBuffer)->sPrivateData;

    //
    // How much space is left in the buffer?
    //
    ui32Space = USBRingBufFree(&psPrivate->sRingBuf);

    //
    // How many bytes will we write?
    //
    ui32Length = (ui32Length > ui32Space) ? ui32Space : ui32Length;

    //
    // Write the data to the buffer.
    //
    if(ui32Length)
    {
        USBRingBufWrite(&psPrivate->sRingBuf, pui8Data, ui32Length);
    }

    //
    // Try to transmit the next packet to the host.
    //
    ScheduleNextTransmission((tUSBBuffer *)psBuffer);

    //
    // Tell the caller how many bytes we wrote to the buffer.
    //
    return(ui32Length);
}
Beispiel #5
0
//*****************************************************************************
//
//! Returns the number of free bytes in the buffer.
//!
//! \param psBuffer is the pointer to the buffer instance which is to be
//! queried.
//!
//! This function returns the number of free bytes in the buffer.  For a
//! transmit buffer, this indicates the maximum number of bytes that can be
//! passed on a call to USBBufferWrite() and accepted for transmission.  For a
//! receive buffer, it indicates the number of bytes that can be read from the
//! USB controller before the buffer will be full.
//!
//! \return Returns the number of free bytes in the buffer.
//
//*****************************************************************************
unsigned long
USBBufferSpaceAvailable(const tUSBBuffer *psBuffer)
{
    tUSBBufferVars *psVars;

    //
    // Check parameter validity.
    //
    ASSERT(psBuffer);

    //
    // Get our workspace variables.
    //
    psVars = psBuffer->pvWorkspace;

    //
    // Return the amount of space available in the buffer.
    //
    return(USBRingBufFree(&psVars->sRingBuf));
}
Beispiel #6
0
//*****************************************************************************
//
//! Returns the number of free bytes in the buffer.
//!
//! \param psBuffer is the pointer to the buffer instance which is to be
//! queried.
//!
//! This function returns the number of free bytes in the buffer.  For a
//! transmit buffer, this indicates the maximum number of bytes that can be
//! passed on a call to USBBufferWrite() and accepted for transmission.  For a
//! receive buffer, it indicates the number of bytes that can be read from the
//! USB controller before the buffer will be full.
//!
//! \return Returns the number of free bytes in the buffer.
//
//*****************************************************************************
uint32_t
USBBufferSpaceAvailable(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 space available in the buffer.
    //
    return(USBRingBufFree(&psPrivate->sRingBuf));
}
Beispiel #7
0
//*****************************************************************************
//
//! Writes a single byte of data to a ring buffer.
//!
//! \param ptUSBRingBuf points to the ring buffer to be written to.
//! \param ucData is the byte to be written.
//!
//! This function writes a single byte of data into a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
USBRingBufWriteOne(tUSBRingBufObject *ptUSBRingBuf, unsigned char ucData)
{
    //
    // Check the arguments.
    //
    ASSERT(ptUSBRingBuf != NULL);

    //
    // Verify that space is available in the buffer.
    //
    ASSERT(USBRingBufFree(ptUSBRingBuf) != 0);

    //
    // Write the data byte.
    //
    ptUSBRingBuf->pucBuf[ptUSBRingBuf->ulWriteIndex] = ucData;

    //
    // Increment the write index.
    //
    UpdateIndexAtomic(&ptUSBRingBuf->ulWriteIndex, 1, ptUSBRingBuf->ulSize);
}
Beispiel #8
0
//*****************************************************************************
//
//! Writes a single byte of data to a ring buffer.
//!
//! \param psUSBRingBuf points to the ring buffer to be written to.
//! \param ui8Data is the byte to be written.
//!
//! This function writes a single byte of data into a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
USBRingBufWriteOne(tUSBRingBufObject *psUSBRingBuf, uint8_t ui8Data)
{
    //
    // Check the arguments.
    //
    ASSERT(psUSBRingBuf != NULL);

    //
    // Verify that space is available in the buffer.
    //
    ASSERT(USBRingBufFree(psUSBRingBuf) != 0);

    //
    // Write the data byte.
    //
    psUSBRingBuf->pui8Buf[psUSBRingBuf->ui32WriteIndex] = ui8Data;

    //
    // Increment the write index.
    //
    UpdateIndexAtomic(&psUSBRingBuf->ui32WriteIndex, 1,
                      psUSBRingBuf->ui32Size);
}
Beispiel #9
0
//*****************************************************************************
//
//! Adds bytes to the ring buffer by advancing the write index.
//!
//! \param psUSBRingBuf points to the ring buffer to which bytes have been
//! added.
//! \param ui32NumBytes is the number of bytes added to the buffer.
//!
//! This function should be used by clients who wish to add data to the buffer
//! directly rather than via calls to USBRingBufWrite() or
//! USBRingBufWriteOne().  It advances the write index by a given number of
//! bytes.
//!
//! \note It is considered an error if the \e ui32NumBytes parameter is larger
//! than the amount of free space in the buffer and a debug build of this
//! function will fail (ASSERT) if this condition is detected.  In a release
//! build, the buffer read pointer will be advanced if too much data is written
//! but this will, of course, result in some of the oldest data in the buffer
//! being discarded and also, depending upon how data is being read from
//! the buffer, may result in a race condition which could corrupt the read
//! pointer.
//!
//! \return None.
//
//*****************************************************************************
void
USBRingBufAdvanceWrite(tUSBRingBufObject *psUSBRingBuf, uint32_t ui32NumBytes)
{
    uint32_t ui32Count;

    //
    // Check the arguments.
    //
    ASSERT(psUSBRingBuf != NULL);

    //
    // Make sure we were not asked to add a silly number of bytes.
    //
    ASSERT(ui32NumBytes <= psUSBRingBuf->ui32Size);

    //
    // Determine how much free space we currently think the buffer has.
    //
    ui32Count = USBRingBufFree(psUSBRingBuf);

    //
    // Check that the client has not added more data to the buffer than there
    // is space for.  In this case, corruption may have occurred since the
    // buffer may have been read under interrupt context while the writer was
    // busy trashing the area around the read pointer.
    //
    ASSERT(ui32Count >= ui32NumBytes);

    //
    // Update the write pointer.
    //
    psUSBRingBuf->ui32WriteIndex += ui32NumBytes;

    //
    // Check and correct for wrap.
    //
    if(psUSBRingBuf->ui32WriteIndex >= psUSBRingBuf->ui32Size)
    {
        psUSBRingBuf->ui32WriteIndex -= psUSBRingBuf->ui32Size;
    }

    //
    // Did the client add more bytes than the buffer had free space for?  This
    // should be considered a bug since, unless this function is called in
    // the same context as the code which is reading from the buffer, writing
    // over the earliest data can cause corrupted data to be read.  The
    // ASSERT above catches this in debug builds but, in release builds, we
    // go ahead and try to fix up the read pointer appropriately.
    //
    if(ui32Count < ui32NumBytes)
    {
        //
        // Yes - we need to advance the read pointer to ahead of the write
        // pointer to discard some of the oldest data.
        //
        psUSBRingBuf->ui32ReadIndex = psUSBRingBuf->ui32WriteIndex + 1;

        //
        // Correct for buffer wrap if necessary.
        //
        if(psUSBRingBuf->ui32ReadIndex >= psUSBRingBuf->ui32Size)
        {
            psUSBRingBuf->ui32ReadIndex -= psUSBRingBuf->ui32Size;
        }
    }

}
Beispiel #10
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);
}