| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- // -----------------------------------------------------------------------------
- // USB Library "usblib"
- // Author: Sychov A.
- // Date: 29/07/2019
- // Version: 1.1
- // -----------------------------------------------------------------------------
- // File: Thread-unsafe internal buffer-object 'USB-transfer'
- // Version: 1.1
- // -----------------------------------------------------------------------------
- #define __USER_USB_HEADER__
- #include <string.h>
- #include "usb/usb_transfers.h"
- //----------------------------------------------------------------------------
- // usb_reset_transfer()
- //
- // Non thread-safe!
- //
- // Resets the specified transfer.
- // Note: the specified end-of-transfer handler isn't called.
- void usb_reset_transfer( sUSBTransfer_t * pUsbTransfer )
- {
- if( NULL != pUsbTransfer )
- {
- pUsbTransfer->pWriteData = pUsbTransfer->pDefaultBuffer;
- pUsbTransfer->pReadData = pUsbTransfer->pDefaultBuffer;
- #if USB_TRANSFER_SUPPORT_FLAGS
- // reset only unlocked flags
- pUsbTransfer->flags = pUsbTransfer->flags & (pUsbTransfer->flagsLock);
- #endif
- }
- }
- //----------------------------------------------------------------------------
- // usb_reset_channel()
- //
- // Non thread-safe!
- //
- // Resets either RX and TX transfers in the channel
- void usb_reset_channel( sUSBEpChannel_t * ch )
- {
- usb_reset_transfer( &ch->RxTransfer );
- usb_reset_transfer( &ch->TxTransfer );
- }
- //----------------------------------------------------------------------------
- // usb_reset_channel_tx()
- //
- // Non thread-safe!
- //
- // Resets the TX-transfer in the channel
- void usb_reset_channel_tx( sUSBEpChannel_t * ch )
- {
- usb_reset_transfer( &ch->TxTransfer );
- }
- //----------------------------------------------------------------------------
- // usb_reset_channel_rx()
- //
- // Non thread-safe!
- //
- // Resets the RX-transfer in the channel
- void usb_reset_channel_rx( sUSBEpChannel_t * ch )
- {
- usb_reset_transfer( &ch->RxTransfer );
- }
- //----------------------------------------------------------------------------
- // usb_create_channel()
- // Creates a bidirectional linear-buffered logical-channel
- // @ch - the channel to construct
- // @pTxBuffer and @txSize - buffer and size of the buffer to Tx operations
- // @pRxBuffer and @rxSize - buffer and size of the buffer to Rx operations
- // @eotTxHandler - the event handler, is called when data run out in Tx Buffer
- // @eotRxHandler - the event handler, is called when data run out in Rx Buffer
- // @chContext - user defined context, will be passed into @eotTxHandler and @eotRxHandler
- // Returns true in case the channel is successfully created
- #if USB_TRANSFER_SUPPORT_EOTH
- bool usb_create_channel( sUSBEpChannel_t * ch,
- void * pTxBuffer, size_t txSize,
- void * pRxBuffer, size_t rxSize,
- fEndOfTransferHandler_t eotTxHandler,
- fEndOfTransferHandler_t eotRxHandler,
- void * channelContext )
- #else
- bool usb_create_channel( sUSBEpChannel_t * ch,
- void * pTxBuffer, size_t txSize,
- void * pRxBuffer, size_t rxSize,
- const void * reserved1,
- const void * reserved2,
- void * channelContext )
- #endif
- {
- #if USB_TRANSFER_SUPPORT_EOTH
- return
- usb_create_transfer( &ch->RxTransfer, pRxBuffer, rxSize, eotRxHandler, channelContext )
- && usb_create_transfer( &ch->TxTransfer, pTxBuffer, txSize, eotTxHandler, channelContext );
- #else
- return
- usb_create_transfer( &ch->RxTransfer, pRxBuffer, rxSize, reserved1, channelContext )
- && usb_create_transfer( &ch->TxTransfer, pTxBuffer, txSize, reserved2, channelContext );
- #endif
- /*
- if( NULL == pTxBuffer || NULL == pRxBuffer ||
- 0 == txSize || 0 == rxSize )
- {
- return false;
- }
- ch->RxTransfer.pDefaultBuffer = (uint8_t*)pTxBuffer;
- ch->RxTransfer.size = txSize;
- ch->RxTransfer.fEndOfTransferHandler = eotRxHandler;
- ch->RxTransfer.ctx = channelContext;
- ch->TxTransfer.pDefaultBuffer = (uint8_t*)pRxBuffer;
- ch->TxTransfer.size = rxSize;
- ch->TxTransfer.fEndOfTransferHandler = eotTxHandler;
- ch->TxTransfer.ctx = channelContext;
- usb_reset_channel( ch );
- return true;
- */
- }
- //----------------------------------------------------------------------------
- // usb_create_transfer()
- // Creates a signle linear-buffered transfer
- // @transf - the transfer to construct
- // @pBuffer and @size - buffer and size of the buffer for transfer operations
- // @eotHandler - the event handler, is called when data run out in the buffer
- // @chContext - user defined context, will be passed into @eotHandler
- // Returns true in case the channel is successfully created
- #if USB_TRANSFER_SUPPORT_EOTH
- bool usb_create_transfer( sUSBTransfer_t * transf,
- void * pBuffer, size_t size,
- fEndOfTransferHandler_t eotHandler,
- void * channelContext )
- #else
- bool usb_create_transfer( sUSBTransfer_t * transf,
- void * pBuffer, size_t size,
- const void * reserved,
- void * channelContext )
- #endif
- {
- if( NULL == pBuffer || 0 == size )
- {
- return false;
- }
- transf->pDefaultBuffer = (uint8_t*)pBuffer;
- transf->size = size;
- #if USB_TRANSFER_SUPPORT_EOTH
- transf->fEndOfTransferHandler = eotHandler;
- #endif
- transf->ctx = channelContext;
- #if USB_TRANSFER_SUPPORT_FLAGS
- transf->flags = 0;
- transf->flagsLock = 0; // no lock by default
- #endif
- usb_reset_transfer( transf );
- return true;
- }
- // usb_push_transfer()
- // Non thread-safe!
- // Writes data into the transfer.
- // @transf - specifies the transfer to operate with
- // @pWriteBuffer - data to be written
- // @pushSize - amount of bytes to write
- // Returns the @pushSize in case all the data has been written into the transfer
- // Otherwise, returns 0. In this case no write operation has been performed.
- // Note: the write operation can be split up to several write operations,
- // until the buffer is full.
- // To prepare the transfer for next portion of data, use usb_reset_transfer()
- size_t usb_push_transfer( sUSBTransfer_t * transf, const void * pWriteBuffer, size_t pushSize )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != pWriteBuffer && 0 != pushSize && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf && NULL != pWriteBuffer && 0 != pushSize )
- #endif
- {
- size_t length = ((ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pDefaultBuffer);
- if( length + pushSize <= transf->size )
- {
- memcpy( transf->pWriteData, pWriteBuffer, pushSize );
- transf->pWriteData += pushSize;
- return pushSize;
- }
- }
- return 0;
- }
- // usb_write_transfer()
- // Non thread-safe!
- // Writes data into the transfer.
- // @transf - specifies the transfer to operate with
- // @pWriteBuffer - data to be written
- // @writeSize - amount of bytes to write
- // Returns amount of bytes written into the transfer
- // In this case no write operation has been performed the function returns 0.
- // Note: the write operation can be split up to several write operations,
- // until the buffer is full.
- // To prepare the transfer for next portion of data, use usb_reset_transfer()
- size_t usb_write_transfer( sUSBTransfer_t * transf, const void * pWriteBuffer, size_t writeSize )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != pWriteBuffer && 0 != writeSize && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf && NULL != pWriteBuffer && 0 != writeSize )
- #endif
- {
- size_t length = ((ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pDefaultBuffer);
- if( length + writeSize > transf->size )
- {
- writeSize = transf->size - length;
- }
- if( writeSize )
- {
- memcpy( transf->pWriteData, pWriteBuffer, writeSize );
- transf->pWriteData += writeSize;
- return writeSize;
- }
- }
- return 0;
- }
- // usb_read_transfer()
- //
- // Non thread-safe!
- //
- // Reads the data from the transfer.
- // @transf - specifies the transfer to operate with
- // @pReadBuffer - the buffer to receive data, can be NULL
- // @readSize - amount of data to copy into the @pReadBuffer, can be 0.
- // @enableEotHandler - enables/disables calling of End-Of-Transfer handler
- // during the call if the transfer is empty.
- // In case, @readSize is equal or greater than amount of data in the transfer,
- // the function reads actual amount of data and returns count of read bytes.
- // Since all data is read from the transfer, the transfer is being reset
- // automatically. If the End-of-transfer handler is specified for this transfer,
- // it will be invoked after the transfer is reset only if @enableEotHandler is
- // true, so the handler can write the next portion of data into the transfer.
- // Otherwise, if @readSize is less than amount of data in the transfer, then
- // only @readSize bytes will be copyied into @pReadBuffer, the rest data are
- // still stored in the transfer-buffer and should be either read by next call,
- // or reset by calling usb_reset_transfer().
- // Note: if the data in transfer is reset by calling usb_reset_transfer(), the
- // End-of-pipe handler is not called.
- // You can call the function with @pReadBuffer = NULL and @readSize = 0, and
- // @enableEotHandler = true to check if the transfer empty and call the End-of-
- // -transfer handler. In this case the function always returns zero.
- // Note: if you specify @pReadBuffer = NULL, you must set @readSize = 0.
- // To determine amount of bytes in the transfer use usb_count_transfer().
- //
- size_t usb_read_transfer( sUSBTransfer_t * transf, void * pReadBuffer, size_t readSize, bool enableEotHandler )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- // retireve the data length in transfer
- size_t length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pReadData;
- // check user params:
- if( NULL != pReadBuffer && 0 != readSize )
- {
- // for the length greater than 0:
- if( length > 0 )
- {
- // user requests the part of all the data:
- if( readSize < length )
- {
- memcpy( pReadBuffer, transf->pReadData, readSize );
- transf->pReadData += readSize;
- return readSize;
- }
- // user request all the data:
- else
- {
- memcpy( pReadBuffer, transf->pReadData, length );
- // reset transfer
- transf->pReadData = transf->pDefaultBuffer;
- transf->pWriteData = transf->pDefaultBuffer;
- // call the handler if allowed and specified:
- #if USB_TRANSFER_SUPPORT_EOTH
- if( enableEotHandler )
- if( NULL != transf->fEndOfTransferHandler )
- {
- size_t rc = transf->fEndOfTransferHandler( transf, transf->ctx );
- (void)rc;
- }
- #endif
- return length;
- }
- }
- }
- else
- {
- // user want to check if the transfer empty and call the handler:
- #if USB_TRANSFER_SUPPORT_EOTH
- // check the length
- if( (length == 0)
- &&
- enableEotHandler
- &&
- (NULL != transf->fEndOfTransferHandler)
- )
- {
- // call the handler
- size_t rc = transf->fEndOfTransferHandler( transf, transf->ctx );
- (void)rc;
- }
- #endif
- return 0; // by design, see description
- }
- }
- return 0;
- }
- // usb_count_transfer():
- //
- // Non thread-safe!
- //
- // Returns amount of data in the transfer.
- // @transf - the transfer to operate with, Non-NULL
- // Returns amount of data to be read.
- size_t usb_count_transfer( sUSBTransfer_t * transf )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- // retireve the data length in transfer
- size_t length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pReadData;
- return length;
- }
- return 0;
- }
- // usb_truncate_transfer()
- //
- // Non thread-safe!
- //
- // Truncates the data into the transfer.
- // @transf - the transfer to operate with, Non-NULL
- // @size - the size limit to apply
- // The function truncates the data in the transfer to the specified @size
- // Returns acutal amount of data in the transfer.
- size_t usb_truncate_transfer( sUSBTransfer_t * transf, size_t size )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- // retireve the data length in transfer
- size_t length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pReadData;
- // truncate only if the transfer contains more data than specified by @size
- if( length > size )
- {
- // cut off extra data
- transf->pWriteData = (uint8_t*)((ptrdiff_t)transf->pReadData + (ptrdiff_t)size);
- // return amount of cut bytes
- return (size);
- }
- return (length);
- }
- return 0;
- }
- #if USB_TRANSFER_SUPPORT_EOTH
- // usb_transfer_override_handler:
- // Replaces the End-of-transfer handler for the specified transfer @transf
- // @transf - the transfer to operate with
- // @handler - new end-of-transfer handler
- // If succeeded, the previous handler pointer is returned by function, and NULL otherwise.
- fEndOfTransferHandler_t usb_transfer_override_handler( sUSBTransfer_t * transf, fEndOfTransferHandler_t handler )
- {
- if( NULL != transf )
- {
- fEndOfTransferHandler_t prevHandler = transf->fEndOfTransferHandler;
- transf->fEndOfTransferHandler = handler;
- return prevHandler;
- }
- return NULL;
- }
- #endif
- // usb_transfer_overridelength()
- //
- // Non thread-safe!
- //
- // Overrides the transfer data length.
- // @transf - the transfer to operate with, Non-NULL
- // @length - new length
- // The function overrides the original transfer data length with the specified @length
- // Returns new length value.
- size_t usb_transfer_overridelength( sUSBTransfer_t * transf, size_t length )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- if( length > transf->size )
- {
- length = transf->size;
- }
- // set the length
- transf->pWriteData = (uint8_t*)((ptrdiff_t)transf->pDefaultBuffer + (ptrdiff_t)length);
-
- return (length);
- }
- return 0;
- }
- // usb_transfer_virtual_read()
- //
- // Non thread-safe!
- //
- // Performs virtual reading from transfer without actual data retrieving from.
- // @transf - the transfer to operate with, Non-NULL
- // @length - the number of bytes for virtual reading
- // The function changes the transfer data length.
- // Returns the number of read bytes
- size_t usb_transfer_virtual_read( sUSBTransfer_t * transf, size_t length )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( (NULL != transf) && (length > 0) && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( (NULL != transf) && (length > 0) )
- #endif
- {
- // retireve the data length in transfer
- size_t stored_length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pReadData;
- if( length > stored_length )
- {
- length = stored_length;
- }
- // perform virtual reading by shifting the pointer @pReadData
- transf->pReadData = (uint8_t*)((ptrdiff_t)transf->pReadData + (ptrdiff_t)length);
-
- return (length);
- }
- return 0;
- }
- // usb_transfer_virtual_write()
- //
- // Non thread-safe!
- //
- // Performs virtual writing to transfer without actual data placing in.
- // @transf - the transfer to operate with, Non-NULL
- // @length - the number of bytes for virtual writing
- // The function changes the transfer data length.
- // Returns the number of written bytes
- size_t usb_transfer_virtual_write( sUSBTransfer_t * transf, size_t length )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( (NULL != transf) && (length > 0) && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( (NULL != transf) && (length > 0) )
- #endif
- {
- // retireve the remaining length in transfer
- size_t remaining_length = transf->size - ((ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pDefaultBuffer);
- if( length > remaining_length )
- {
- length = remaining_length;
- }
- // perform writing reading by shifting the pointer @pWriteData
- transf->pWriteData = (uint8_t*)((ptrdiff_t)transf->pWriteData + (ptrdiff_t)length);
-
- return (length);
- }
- return 0;
- }
- // usb_transfer_compress()
- //
- // Non thread-safe!
- //
- // Optimizes the transfer by size by packing data inside.
- // @transf - the transfer to operate with, Non-NULL
- // The function moves the data from middle of the transfer to the beginning
- // with keeping actual size.
- // Returns the number of bytes optimized
- size_t usb_transfer_compress( sUSBTransfer_t * transf )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- // retireve the data length in transfer
- size_t stored_length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pReadData;
-
- if( stored_length > 0 )
- {
- // move the contents by to the beginning of the transfer (re-use)
- memmove( transf->pDefaultBuffer, transf->pReadData, stored_length );
- transf->pWriteData = (uint8_t*)((ptrdiff_t)transf->pDefaultBuffer + stored_length);
- }
- else
- {
- transf->pWriteData = transf->pDefaultBuffer;
- }
- size_t optimized_length = (ptrdiff_t)transf->pReadData - (ptrdiff_t)transf->pDefaultBuffer;
- transf->pReadData = transf->pDefaultBuffer;
- return optimized_length;
- }
- return 0;
- }
- // usb_size_transfer()
- //
- // Non thread-safe!
- //
- // Returns the transfer absoulte size.
- // @transf - the transfer to operate with, Non-NULL
- // Returns the size in bytes
- size_t usb_size_transfer( sUSBTransfer_t * transf )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- return (transf->size);
- }
- return 0;
- }
- // usb_space_transfer()
- //
- // Non thread-safe!
- //
- // Returns the transfer available space.
- // @transf - the transfer to operate with, Non-NULL
- // Returns amount of free space in the transfer in bytes.
- size_t usb_space_transfer( sUSBTransfer_t * transf )
- {
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- #else
- if( NULL != transf )
- #endif
- {
- // retireve the data length in transfer
- size_t used_length = (ptrdiff_t)transf->pWriteData - (ptrdiff_t)transf->pDefaultBuffer;
-
- return (transf->size - used_length);
- }
- return 0;
- }
- #if USB_TRANSFER_MOVE_SEMANTIC
- // usb_move_transfer()
- //
- // Non thread-safe!
- //
- // Implements a move-semantic on couple of transfer objects
- // @transf_to - the transfer for move to, can not be NULL
- // @transf_from - the transfer for move from, can not be NULL
- // @copyContextValue - copy the context value assotiated with the source tranfer.
- // The source object (@transf_from) must be valid, while it does
- // not matter if the destination object @transf_to is invalid or not.
- // After operation the source object will be destroyed, you must
- // call usb_move_transfer() or usb_create_transfer() function on the source
- // transfer to recover it.
- // Note: user context in the source transfer will not be cleared and it can
- // be used after the function call.
- // Returns the operation result, true if object had been moved
- // successfully, and false otherwise.
- bool usb_move_transfer( sUSBTransfer_t * transf_to, sUSBTransfer_t * transf_from, bool copyContextValue )
- {
- if( NULL != transf_to && NULL != transf_from && NULL != transf_from->pDefaultBuffer && 0 != transf_from->size )
- {
- void * pDestUserContext = transf_to->ctx;
- *transf_to = *transf_from;
- transf_from->pDefaultBuffer = NULL;
- transf_from->pWriteData = NULL;
- transf_from->pReadData = NULL;
- transf_from->size = 0;
- #if USB_TRANSFER_SUPPORT_FLAGS
- // reset only the bits that are reset in @flagsLock
- // If the bit is set in @flagsLock, the corresponding bit will be kept in @flags
- transf_from->flags = transf_from->flags & transf_from->flagsLock;
- #endif
- #if USB_TRANSFER_SUPPORT_EOTH
- transf_from->fEndOfTransferHandler = NULL;
- #endif
- if( !copyContextValue )
- {
- transf_to->ctx = pDestUserContext;
- }
- // keep the source transfer's context unchanged
- (void)transf_from->ctx;
- }
- return false;
- }
- // usb_copy_transfer()
- // Copies the data from one transfer to another
- // The source transfer is not being modified if @keepSource is true.
- // Otherwise, if @keepSource is false, the source transfer will be changed,
- // and the data copied to destination transfer will be removed from the source transfer.
- // @count - specifies amount of data to be copied.
- // If the source transfer contains less bytes that specified in @count, or the
- // destination transfer does not have enough free space, only the minimum between
- // these number of bytes will be copied.
- // Returns: number of copied bytes
- size_t usb_copy_transfer( sUSBTransfer_t * transf_to, sUSBTransfer_t * transf_from, size_t count, bool keepSource )
- {
- if( NULL == transf_to || NULL == transf_from || 0 == count )
- {
- return 0;
- }
- #if USB_TRANSFER_MOVE_SEMANTIC
- if( NULL == transf_to->pDefaultBuffer || 0 == transf_to->size
- || NULL == transf_from->pDefaultBuffer || 0 == transf_from->size )
- {
- return 0;
- }
- #endif
-
- // retireve free space from the destination transfer
- size_t free_space = transf_to->size - ((ptrdiff_t)transf_to->pWriteData - (ptrdiff_t)transf_to->pDefaultBuffer);
-
- // retrieve used length from the source transfer
- size_t used_space = (ptrdiff_t)transf_from->pWriteData - (ptrdiff_t)transf_from->pDefaultBuffer;
- // check the limits: count must be less or equal to MIN( used_space, free_space )
- if( count > free_space ) count = free_space;
- if( count > used_space ) count = used_space;
- memcpy( transf_to->pWriteData, transf_from->pReadData, count );
-
- // perform virtual writing by shifting the pointer @pWriteData
- transf_to->pWriteData = (uint8_t*)((ptrdiff_t)transf_to->pWriteData + (ptrdiff_t)count);
-
- if( !keepSource )
- {
- // perform virtual reading by shifting the pointer @pReadData
- transf_from->pReadData = (uint8_t*)((ptrdiff_t)transf_from->pReadData + (ptrdiff_t)count);
- }
- return count;
- }
- // usb_validate_transfer()
- //
- // Non thread-safe!
- //
- // Validates the transfer parameters. Usefull for checking objects
- // after moving by usb_move_transfer().
- // @transf - the transfer to operate with, Non-NULL
- // Returns true if the specified object is valid, false otherwise.
- bool usb_validate_transfer( sUSBTransfer_t * transf )
- {
- if( NULL != transf && NULL != transf->pDefaultBuffer && 0 != transf->size )
- if( NULL != transf->pWriteData && NULL != transf->pReadData )
- {
- if( ((ptrdiff_t)transf->pDefaultBuffer + transf->size
- >=
- (ptrdiff_t)transf->pWriteData )
- &&
- ((ptrdiff_t)transf->pDefaultBuffer + transf->size
- >=
- (ptrdiff_t)transf->pReadData )
- &&
- ((ptrdiff_t)transf->pReadData <= (ptrdiff_t)transf->pWriteData)
- )
- {
- return true;
- }
- }
- return false;
- }
- #endif
- #if USB_TRANSFER_SUPPORT_FLAGS
- // @usb_transfer_modify_flags
- // Modifies the user-dependent general-purpose flags using specified mask @mask and value @value
- // Returns: true if no error occurred, false otherwise.
- bool usb_transfer_modify_flags( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value )
- {
- if( NULL != transf )
- {
- // Modify only the bits that are not locked by @flagsLock
- transf->flags = ((transf->flags & (~transf->flagsLock)) & (~mask)) | (mask & value) | (transf->flags & transf->flagsLock);
- return true;
- }
- return false;
- }
- // @usb_transfer_modify_flags_locks
- // Modifies the lock mask for user-dependent general-purpose flags using specified mask @mask and value @value
- // Returns: true if no error occurred, false otherwise.
- bool usb_transfer_modify_flags_locks( sUSBTransfer_t * transf, tUSBTransferFlags_t lockMask, tUSBTransferFlags_t lockValue )
- {
- if( NULL != transf )
- {
- transf->flagsLock = (transf->flagsLock & (~lockMask)) | (lockMask & lockValue);
- return true;
- }
- return false;
- }
- // @usb_transfer_check_flags_wo_checking
- //
- static bool usb_transfer_check_flags_wo_checking( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value, eUSBTransferFlagMode_t mode )
- {
- uint32_t value1 = (transf->flags & mask);
- uint32_t value2 = (value & mask);
- if( eUSBTransferFlagMode_Or == mode )
- {
- return (0 != ((~(value1 ^ value2)) & mask));
- }
- else
- {
- return (0 == (value1 ^ value2));
- }
- }
- // @usb_transfer_check_flags
- // Check if the user-dependent general-purpose flags fit to the specified mask @mask and value @value using comparing method @mode.
- // @transf - the transfer object to operate with;
- // @mask - specified mask to check
- // @value - specified value to check
- // @mode - comparing method:
- // - eUSBTransferFlagMode_Or: at least one transfer bit-flag must be equal to the specified value;
- // - eUSBTransferFlagMode_And: all the transfer bit-flag must be equal to the specified value;
- // @pResult = the pointer to receive output result
- // Returns: true if no error occurred, false otherwise.
- bool usb_transfer_check_flags( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value, eUSBTransferFlagMode_t mode, bool * pResult )
- {
- if( (NULL != transf) && (NULL != pResult) )
- {
- *pResult = usb_transfer_check_flags_wo_checking( transf, mask, value, mode );
- return true;
- }
- return false;
- }
- // @usb_transfer_check_flags_fast
- // Check if the user-dependent general-purpose flags fit to the specified mask @mask and value @value using comparing method @mode.
- // @transf - the transfer object to operate with;
- // @mask - specified mask to check
- // @value - specified value to check
- // @mode - comparing method:
- // - eUSBTransferFlagMode_Or: at least one transfer bit-flag must be equal to the specified value;
- // - eUSBTransferFlagMode_And: all the transfer bit-flag must be equal to the specified value;
- // Returns: true if no error occurred and the comparing output is TRUE, false otherwise.
- // Note: you can use this function instead of @usb_transfer_check_flags if you are sure that the @transf pointer is valid.
- bool usb_transfer_check_flags_fast( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value, eUSBTransferFlagMode_t mode )
- {
- if( NULL != transf )
- {
- return usb_transfer_check_flags_wo_checking( transf, mask, value, mode );
- }
- return false;
- }
- #endif
|