| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098 |
- //*****************************************************************************
- //
- // usbbuffer.c - USB buffer object.
- //
- // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Texas Instruments (TI) is supplying this software for use solely and
- // exclusively on TI's microcontroller products. The software is owned by
- // TI and/or its suppliers, and is protected under applicable copyright
- // laws. You may not combine this software with "viral" open-source
- // software in order to form a larger program.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
- // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
- // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
- // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
- // DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of AM1808 Sitaraware USB Library and reused from revision 6288
- // of the Stellaris USB Library.
- //
- //*****************************************************************************
- #include "hw_types.h"
- #include "debug.h"
- #include "usblib.h"
- #include "usblibpriv.h"
- //*****************************************************************************
- //
- //! \addtogroup usblib_buffer_api
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- // USB instance Object
- //
- //*****************************************************************************
- extern tUSBInstanceObject g_USBInstance[];
- //*****************************************************************************
- //
- // Workspace variables required by each buffer instance. This structure is
- // overlaid on the pvWorkspace memory provided in the tUSBBuffer structure
- // passed to USBBufferInit().
- //
- //*****************************************************************************
- typedef struct
- {
- tUSBRingBufObject sRingBuf;
- }
- tUSBBufferVars;
- //*****************************************************************************
- //
- // 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 int 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 int
- HandleRxAvailable(tUSBBuffer *psBuffer, unsigned int ulSize,
- unsigned char *pucData)
- {
- tUSBBufferVars *psVars;
- unsigned int 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);
- }
- //*****************************************************************************
- //
- // 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 int
- HandleDataRemaining(tUSBBuffer *psBuffer)
- {
- unsigned int 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);
- }
- //*****************************************************************************
- //
- // Handles USB_EVENT_TX_COMPLETE for a transmit buffer.
- //
- // \param psBuffer points to the buffer which is receiving the event.
- // \param ulSize is the number of bytes that have been transmitted and
- // acknowledged.
- //
- // This function informs us that data written to the lower layer from a
- // transmit buffer has been successfully transmitted. We use this to update
- // the buffer read pointer and attempt to schedule the next transmission if
- // data remains in the buffer.
- //
- // \return Returns the number of bytes remaining to be processed.
- //
- //*****************************************************************************
- static unsigned int
- HandleTxComplete(tUSBBuffer *psBuffer, unsigned int ulSize)
- {
- tUSBBufferVars *psVars;
- //
- // Get a pointer to our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // Update the transmit buffer read pointer to remove the data that has
- // now been transmitted.
- //
- USBRingBufAdvanceRead(&psVars->sRingBuf, ulSize);
- //
- // Try to schedule the next packet transmission if data remains to be
- // sent.
- //
- ScheduleNextTransmission(psBuffer);
- //
- // The return code from this event is ignored.
- //
- return(0);
- }
- //*****************************************************************************
- //
- // Handles USB_EVENT_REQUEST_BUFFER for a receive buffer.
- //
- // \param psBuffer points to the buffer which is receiving the event.
- // \param ulSize is the size of the buffer requested.
- // \param ppucBuffer is a pointer which is to be written with a pointer to
- // the returned buffer.
- //
- // This function is called by a low level driver that wishes to receive data
- // automatically and write it directly to a memory buffer, either using
- // software or DMA prior to issuing USB_EVENT_RX_AVAILABLE. The event is sent
- // in advance of receiving data to provide storage for whatever is received
- // next.
- //
- // If we have a contiguous block of space in the buffer of at least ulSize
- // bytes immediately in front of the current write pointer, we pass this back
- // otherwise we send NULL indicating that the next packet should be notified
- // using a standard USB_EVENT_RX_AVAILABLE event without being received
- // automatically. Note that the USB_EVENT_REQUEST_BUFFER protocol allows us to
- // return less than \e ulSize bytes if we know how much data is expected next
- // but this is not possible here since the USBBuffer knows nothing about the
- // protocol whose data it is handling.
- //
- // \return Returns the number of bytes remaining to be processed.
- //
- //*****************************************************************************
- static unsigned int
- HandleRequestBuffer(tUSBBuffer *psBuffer, unsigned int ulSize,
- unsigned char **ppucBuffer)
- {
- tUSBBufferVars *psVars;
- unsigned int ulSpace;
- //
- // Get a pointer to our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // How much contiguous space do we have available?
- //
- ulSpace = USBRingBufContigFree(&psVars->sRingBuf);
- //
- // Is there enough space available to satisfy the request?
- //
- if(ulSpace >= ulSize)
- {
- //
- // Yes - return the current write pointer
- //
- *ppucBuffer = psVars->sRingBuf.pucBuf + psVars->sRingBuf.ulWriteIndex;
- return(ulSize);
- }
- else
- {
- //
- // We do not have enough contiguous space following the current write
- // pointer to satisfy the request so do not provide a buffer.
- //
- *ppucBuffer = (unsigned char *)0;
- return(0);
- }
- }
- //*****************************************************************************
- //
- //! Initializes a USB buffer object to be used with a given USB controller and
- //! device or host class driver.
- //!
- //! \param psBuffer points to a structure containing information on the buffer
- //! memory to be used and the underlying device or host class driver whose data
- //! is to be buffered. This structure must remain accessible for as int as
- //! the buffer is in use.
- //!
- //! This function is used to initialize a USB buffer object and insert it
- //! into the function and callback interfaces between an underlying driver
- //! and the application. The caller supplies information on both the RAM
- //! to be used to buffer data, the type of buffer to be created (transmit or
- //! receive) and the functions to be called in the lower layer to transfer
- //! data to or from the USB controller.
- //!
- //! \return Returns the original buffer structure pointer if successful or
- //! NULL if an error is detected.
- //
- //*****************************************************************************
- const tUSBBuffer *
- USBBufferInit(const tUSBBuffer *psBuffer)
- {
- tUSBBufferVars *psVars;
- //
- // Check parameter validity.
- //
- ASSERT(psBuffer && psBuffer->pvWorkspace && psBuffer->pcBuffer &&
- psBuffer->ulBufferSize && psBuffer->pfnAvailable &&
- psBuffer->pfnTransfer && psBuffer->pfnCallback);
- //
- // Get a pointer to the buffer workspace and inttialize the variables it
- // contains.
- //
- psVars = psBuffer->pvWorkspace;
- USBRingBufInit(&psVars->sRingBuf, psBuffer->pcBuffer,
- psBuffer->ulBufferSize);
- //
- // If all is well, return the same pointer we were originally passed.
- //
- return(psBuffer);
- }
- //*****************************************************************************
- //
- //! Returns the current ring buffer indices for this USB buffer.
- //!
- //! \param psBuffer is the pointer to the buffer instance whose information
- //! is being queried.
- //! \param psRingBuf is a pointer to storage that will be written with the
- //! current ring buffer control structure for this USB buffer.
- //!
- //! This function is provided to aid a client wishing to write data directly
- //! into the USB buffer rather than using the USBBufferWrite() function. This
- //! may be necessary to control when the USBBuffer starts transmission of a
- //! large block of data, for example.
- //!
- //! A transmit buffer will immediately send a new packet on any call to
- //! USBBufferWrite() if the underlying layer indicates that a transmission can
- //! be started. In some cases this is not desirable and a client may wish to
- //! wishes to write more data to the buffer in advance of starting transmission
- //! to the lower layer. In such cases, this function may be called to retrieve
- //! the current ring buffer indices and the buffer accessed directly. Once the
- //! client has written all data it wishes to send, it should call function
- //! USBBufferDataWritten() to indicate that transmission may begin.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBBufferInfoGet(const tUSBBuffer *psBuffer, tUSBRingBufObject *psRingBuf)
- {
- tUSBBufferVars *psVars;
- //
- // Check parameter validity.
- //
- ASSERT(psBuffer && psRingBuf);
- //
- // Get our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // Copy the current ring buffer settings to the clients storage.
- //
- *psRingBuf = psVars->sRingBuf;
- }
- //*****************************************************************************
- //
- //! Indicates that a client has written data directly into the buffer and
- //! wishes to start transmission.
- //!
- //! \param psBuffer is the pointer to the buffer instance into which data has
- //! been written.
- //! \param ulLength is the number of bytes of data that the client has written.
- //!
- //! This function updates the USB buffer write pointer and starts transmission
- //! of the data in the buffer assuming the lower layer is ready to receive a
- //! new packet. The function is provided to aid a client wishing to write
- //! data directly into the USB buffer rather than using the USBBufferWrite()
- //! function. This may be necessary to control when the USB buffer starts
- //! transmission of a large block of data, for example.
- //!
- //! A transmit buffer will immediately send a new packet on any call to
- //! USBBufferWrite() if the underlying layer indicates that a transmission can
- //! be started. In some cases this is not desirable and a client may wish to
- //! write more data to the buffer in advance of starting transmission
- //! to the lower layer. In such cases, USBBufferInfoGet() may be called to
- //! retrieve the current ring buffer indices and the buffer accessed directly.
- //! Once the client has written all data it wishes to send (taking care to
- //! handle the ring buffer wrap), it should call this function to indicate that
- //! transmission may begin.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBBufferDataWritten(const tUSBBuffer *psBuffer, unsigned int ulLength)
- {
- tUSBBufferVars *psVars;
- //
- // Check parameter validity.
- //
- ASSERT(psBuffer);
- //
- // Get our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // Advance the ring buffer write pointer to include the newly written
- // data.
- //
- if(ulLength)
- {
- USBRingBufAdvanceWrite(&psVars->sRingBuf, ulLength);
- }
- //
- // Try to schedule a new packet transmission.
- //
- ScheduleNextTransmission(psBuffer);
- }
- //*****************************************************************************
- //
- //! Indicates that a client has read data directly out of the buffer.
- //!
- //! \param psBuffer is the pointer to the buffer instance from which data has
- //! been read.
- //! \param ulLength is the number of bytes of data that the client has read.
- //!
- //! This function updates the USB buffer read pointer to remove data that
- //! the client has read directly rather than via a call to USBBufferRead().
- //! The function is provided to aid a client wishing to minimize data copying.
- //! To read directly from the buffer, a client must call USBBufferInfoGet() to
- //! retrieve the current buffer indices. With this information, the data
- //! following the current read index can be read. Once the client has
- //! processed much data as it needs, USBBufferDataRemoved() must be called to
- //! advance the read pointer past the data that has been read and free up that
- //! section of the buffer. The client must take care to correctly handle the
- //! wrap point if accessing the buffer directly.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBBufferDataRemoved(const tUSBBuffer *psBuffer, unsigned int ulLength)
- {
- tUSBBufferVars *psVars;
- //
- // Check parameter validity.
- //
- ASSERT(psBuffer);
- //
- // Get our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // Advance the ring buffer write pointer to include the newly written
- // data.
- //
- if(ulLength)
- {
- USBRingBufAdvanceRead(&psVars->sRingBuf, ulLength);
- }
- }
- //*****************************************************************************
- //
- //! Sets the callback pointer supplied to clients of this buffer.
- //!
- //! \param psBuffer is the pointer to the buffer instance whose callback data
- //! is to be changed.
- //! \param pvCBData is the pointer the client wishes to receive on all future
- //! callbacks from this buffer.
- //!
- //! This function sets the callback pointer which this buffer will supply
- //! to clients as the \e pvCBData parameter in all future calls to the
- //! event callback.
- //!
- //! \note If this function is to be used, the application must ensure that the
- //! tUSBBuffer structure used to describe this buffer is held in RAM rather
- //! than flash. The \e pvCBData value passed is written directly into this
- //! structure.
- //!
- //! \return Returns the previous callback pointer set for the buffer.
- //
- //*****************************************************************************
- void *
- USBBufferCallbackDataSet(tUSBBuffer *psBuffer, void *pvCBData)
- {
- void *pvOldData;
- //
- // Keep a copy of the old callback data.
- //
- pvOldData = psBuffer->pvCBData;
- //
- // Replace the callback data with the new value.
- //
- psBuffer->pvCBData = pvCBData;
- //
- // Give the caller the old value back.
- //
- return(pvOldData);
- }
- //*****************************************************************************
- //
- //! 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 int
- USBBufferWrite(const tUSBBuffer *psBuffer, const unsigned char *pucData,
- unsigned int ulLength)
- {
- unsigned int 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);
- }
- //*****************************************************************************
- //
- //! Flushes a USB buffer, discarding any data that it contains.
- //!
- //! \param psBuffer is the pointer to the buffer instance which is to be
- //! flushed.
- //!
- //! This function discards all data currently in the supplied buffer without
- //! processing (transmitting it via the USB controller or passing it to the
- //! client depending upon the buffer mode).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBBufferFlush(const tUSBBuffer *psBuffer)
- {
- tUSBBufferVars *psVars;
- //
- // Check parameter validity.
- //
- ASSERT(psBuffer);
- //
- // Get our workspace variables.
- //
- psVars = psBuffer->pvWorkspace;
- //
- // Flush the ring buffer.
- //
- USBRingBufFlush(&psVars->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 int
- USBBufferRead(const tUSBBuffer *psBuffer, unsigned char *pucData,
- unsigned int ulLength)
- {
- tUSBBufferVars *psVars;
- unsigned int 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);
- }
- //*****************************************************************************
- //
- //! 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 int
- 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 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 int
- 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));
- }
- //*****************************************************************************
- //
- //! Called by the USB buffer to notify the client of asynchronous events.
- //!
- //! \param pvCBData is the client-supplied callback pointer associated with
- //! this buffer instance.
- //! \param ulEvent is the identifier of the event being sent. This will be
- //! a general event identifier of the form USBD_EVENT_xxxx or a device
- //! class-dependent event of the form USBD_CDC_EVENT_xxx or
- //! USBD_HID_EVENT_xxx.
- //! \param ulMsgValue is an event-specific parameter value.
- //! \param pvMsgData is an event-specific data pointer.
- //!
- //! This function is the USB buffer event handler that applications should
- //! register with the USB device class driver as the callback for the channel
- //! which is to be buffered using this buffer.
- //!
- //! \note This function will never be called by an application. It is the
- //! handler that allows the USB buffer to be inserted above the device class
- //! driver or host pipe driver and below the application to offer buffering
- //! support.
- //!
- //! \return The return value is dependent upon the event being processed.
- //
- //*****************************************************************************
- unsigned int
- USBBufferEventCallback(void *pvCBData, unsigned int ulEvent,
- unsigned int ulMsgValue, void *pvMsgData)
- {
- tUSBBuffer *psBuffer;
- //
- // Get our instance data pointers from the callback data.
- //
- psBuffer = (tUSBBuffer *)pvCBData;
- ASSERT(psBuffer);
- //
- // Which event have we been sent?
- //
- switch(ulEvent)
- {
- //
- // Data is available from the lower layer.
- //
- case USB_EVENT_RX_AVAILABLE:
- {
- //
- // This event is only relevant to us if we are a receive buffer.
- //
- if(!psBuffer->bTransmitBuffer)
- {
- return(HandleRxAvailable(psBuffer, ulMsgValue, pvMsgData));
- }
- break;
- }
- //
- // We are being asked how much data remains to be processed.
- //
- case USB_EVENT_DATA_REMAINING:
- {
- return(HandleDataRemaining(psBuffer));
- }
- //
- // A previous transmission has completed.
- //
- case USB_EVENT_TX_COMPLETE:
- {
- //
- // This event is only relevant to us if we are a transmit buffer.
- //
- if(psBuffer->bTransmitBuffer)
- {
- //
- // Handle the message then drop out of the switch so that the
- // event is echoed to the layer above.
- //
- HandleTxComplete(psBuffer, ulMsgValue);
- }
- break;
- }
- //
- // We are being asked to provide a buffer into which the next packet
- // can be received.
- //
- case USB_EVENT_REQUEST_BUFFER:
- {
- //
- // This event is only relevant to us if we are a receive buffer.
- //
- if(!psBuffer->bTransmitBuffer)
- {
- return(HandleRequestBuffer(psBuffer, ulMsgValue, pvMsgData));
- }
- break;
- }
- //
- // All other events are merely passed through to the client.
- //
- default:
- {
- break;
- }
- }
- //
- // If we drop out of the switch, we need to pass the event on to the client
- // unmodified and return the relevant return code back to the lower layer.
- //
- return(psBuffer->pfnCallback(psBuffer->pvCBData, ulEvent, ulMsgValue,
- pvMsgData));
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|