usb_transfers.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. // -----------------------------------------------------------------------------
  2. // USB Library "usblib"
  3. // Author: Sychov A.
  4. // Date: 29/07/2019
  5. // Version: 1.1
  6. // -----------------------------------------------------------------------------
  7. // File: Thread-unsafe internal buffer-object 'USB-transfer' header
  8. // Version: 1.1
  9. // ------------------------------------------------------------------------------
  10. #ifndef USB_LOGICAL_TRANSFER_H
  11. #define USB_LOGICAL_TRANSFER_H
  12. #include <stddef.h>
  13. #include <stdint.h>
  14. #include <stdbool.h>
  15. // USB_TRANSFER_MOVE_SEMANTIC
  16. // Enables a move semantic on the transfers.
  17. // When enabled, some functions will perfrom additional checking of a transfer parameters.
  18. #define USB_TRANSFER_MOVE_SEMANTIC 1
  19. // USB_TRANSFER_SUPPORT_FLAGS
  20. // Implements user-defined flags support for each transfer
  21. #define USB_TRANSFER_SUPPORT_FLAGS 1
  22. // USB_TRANSFER_SUPPORT_EOTH
  23. // Implements the End-of-transfer-handler support
  24. #define USB_TRANSFER_SUPPORT_EOTH 0
  25. struct sUSBTransfer_t;
  26. // USB Transfers
  27. // Software module implements the logical data unit with separated
  28. // read- and write- methods based on linear buffer.
  29. // fEndOfTransferHandler_t
  30. // End-of-thansfer handler, is called when data in the transfer running out
  31. // @transf - the transfer generated the the handler call
  32. // @ctx - user defined context, the context specified at usb_create_pipe()
  33. // The handler is only called when usb_read_pipe() is performed.
  34. // The value returned by the handler must be amount of bytes loaded into the transfer
  35. typedef size_t ( * fEndOfTransferHandler_t)( struct sUSBTransfer_t * transf, void * ctx );
  36. // @tUSBTransferFlag_t
  37. // User-dependent general-purpose bit flags
  38. typedef uint32_t tUSBTransferFlags_t;
  39. // @tUSBTransferFlagMask_t
  40. // User-dependent lock-mask for general-purpose bit flags
  41. typedef uint32_t tUSBTransferFlagMask_t;
  42. // @eUSBTransferFlagMode_t
  43. // Flags checking mode for @usb_transfer_check_flags()
  44. typedef enum {
  45. eUSBTransferFlagMode_Or, // OR-operation with mask
  46. eUSBTransferFlagMode_And, // AND-operation with mask
  47. }
  48. eUSBTransferFlagMode_t;
  49. // Usb Data Transfer Descriptor
  50. struct sUSBTransfer_t
  51. {
  52. size_t size; // maximum buffer capacity
  53. uint8_t * pDefaultBuffer; // Main data buffer
  54. uint8_t * pWriteData; // current Write-data pointer
  55. uint8_t * pReadData; // current Read-data pointer
  56. #if USB_TRANSFER_SUPPORT_EOTH
  57. // End-of-transfer handler: processes the event when the last byte of pipe transferred
  58. fEndOfTransferHandler_t fEndOfTransferHandler;
  59. #endif
  60. #if USB_TRANSFER_SUPPORT_FLAGS
  61. tUSBTransferFlags_t flags;
  62. tUSBTransferFlagMask_t flagsLock;
  63. #endif
  64. void * ctx; // used-defined context
  65. };
  66. typedef struct sUSBTransfer_t sUSBTransfer_t;
  67. // USB Logical Pipe Descriptor
  68. typedef struct
  69. {
  70. sUSBTransfer_t TxTransfer; // IN: Device->Host pipe
  71. sUSBTransfer_t RxTransfer; // OUT: Host->Device pipe
  72. }
  73. sUSBEpChannel_t;
  74. // usb_reset_transfer()
  75. // Non thread-safe!
  76. // Resets the specified transfer.
  77. // Note: the specified end-of-transfer handler isn't called.
  78. void usb_reset_transfer( sUSBTransfer_t * pUsbTransfer );
  79. // usb_reset_channel()
  80. // Non thread-safe!
  81. // Resets either RX and TX transfers in the channel
  82. void usb_reset_channel( sUSBEpChannel_t * ch );
  83. // usb_reset_channel_tx()
  84. // Non thread-safe!
  85. // Resets the TX-transfer in the channel
  86. void usb_reset_channel_tx( sUSBEpChannel_t * ch );
  87. // usb_reset_channel_rx()
  88. // Non thread-safe!
  89. // Resets the RX-transfer in the channel
  90. void usb_reset_channel_rx( sUSBEpChannel_t * ch );
  91. #if USB_TRANSFER_SUPPORT_EOTH
  92. // usb_create_channel()
  93. // Creates a bidirectional linear-buffered logical-channel
  94. // @ch - the channel to construct
  95. // @pTxBuffer and @txSize - buffer and size of the buffer to Tx operations
  96. // @pRxBuffer and @rxSize - buffer and size of the buffer to Rx operations
  97. // @eotTxHandler - the event handler, is called when data run out in Tx Buffer
  98. // @eotRxHandler - the event handler, is called when data run out in Rx Buffer
  99. // @chContext - user defined context, will be passed into @eotTxHandler and @eotRxHandler
  100. // Returns true in case the channel is successfully created
  101. bool usb_create_channel( sUSBEpChannel_t * ch,
  102. void * pTxBuffer, size_t txSize,
  103. void * pRxBuffer, size_t rxSize,
  104. fEndOfTransferHandler_t eotTxHandler,
  105. fEndOfTransferHandler_t eotRxHandler,
  106. void * channelContext );
  107. #else
  108. bool usb_create_channel( sUSBEpChannel_t * ch,
  109. void * pTxBuffer, size_t txSize,
  110. void * pRxBuffer, size_t rxSize,
  111. const void * reserved1,
  112. const void * reserved2,
  113. void * channelContext );
  114. #endif
  115. // usb_create_transfer()
  116. // Creates a signle linear-buffered transfer
  117. // @transf - the transfer to construct
  118. // @pBuffer and @size - buffer and size of the buffer for transfer operations
  119. // @eotHandler - the event handler, is called when data run out in the buffer
  120. // @chContext - user defined context, will be passed into @eotHandler
  121. // Returns true in case the channel is successfully created
  122. #if USB_TRANSFER_SUPPORT_EOTH
  123. bool usb_create_transfer( sUSBTransfer_t * ch,
  124. void * pBuffer, size_t size,
  125. fEndOfTransferHandler_t eotHandler,
  126. void * channelContext );
  127. #else
  128. bool usb_create_transfer( sUSBTransfer_t * ch,
  129. void * pBuffer, size_t size,
  130. const void * reserved,
  131. void * channelContext );
  132. #endif
  133. // usb_push_transfer()
  134. // Non thread-safe!
  135. // Writes data into the transfer.
  136. // @transf - specifies the transfer to operate with
  137. // @pWriteBuffer - data to be written
  138. // @pushSize - amount of bytes to write
  139. // Returns the @pushSize in case all the data has been written into the transfer
  140. // Otherwise, returns 0. In this case no write operation has been performed.
  141. // Note: the write operation can be split up to several write operations,
  142. // until the buffer is full.
  143. // To prepare the transfer for next portion of data, use usb_reset_transfer()
  144. size_t usb_push_transfer( sUSBTransfer_t * transf, const void * pWriteBuffer, size_t pushSize );
  145. // usb_write_transfer()
  146. // Non thread-safe!
  147. // Writes data into the transfer.
  148. // @transf - specifies the transfer to operate with
  149. // @pWriteBuffer - data to be written
  150. // @writeSize - amount of bytes to write
  151. // Returns amount of bytes written into the transfer
  152. // In this case no write operation has been performed the function returns 0.
  153. // Note: the write operation can be split up to several write operations,
  154. // until the buffer is full.
  155. // To prepare the transfer for next portion of data, use usb_reset_transfer()
  156. size_t usb_write_transfer( sUSBTransfer_t * transf, const void * pWriteBuffer, size_t writeSize );
  157. // usb_read_transfer()
  158. // Non thread-safe!
  159. // Reads the data from the transfer.
  160. // @transf - specifies the transfer to operate with
  161. // @pReadBuffer - the buffer to receive data, can be NULL
  162. // @readSize - amount of data to copy into the @pReadBuffer, can be 0.
  163. // @enableEotHandler - enables/disables calling of End-Of-Transfer handler
  164. // during the call if the transfer is empty.
  165. // In case, @readSize is equal or greater than amount of data in the transfer,
  166. // the function reads actual amount of data and returns count of read bytes.
  167. // Since all data is read from the transfer, the transfer is being reset
  168. // automatically. If the End-of-transfer handler is specified for this transfer,
  169. // it will be invoked after the transfer is reset only if @enableEotHandler is
  170. // true, so the handler can write the next portion of data into the transfer.
  171. // Otherwise, if @readSize is less than amount of data in the transfer, then
  172. // only @readSize bytes will be copyied into @pReadBuffer, the rest data are
  173. // still stored in the transfer-buffer and should be either read by next call,
  174. // or reset by calling usb_reset_transfer().
  175. // Note: if the data in transfer is reset by calling usb_reset_transfer(), the
  176. // End-of-pipe handler is not called.
  177. // You can call the function with @pReadBuffer = NULL and @readSize = 0, and
  178. // @enableEotHandler = true to check if the transfer empty and call the End-of-
  179. // -transfer handler. In this case the function always returns zero.
  180. // Note: if you specify @pReadBuffer = NULL, you must set @readSize = 0.
  181. // To determine amount of bytes in the transfer use usb_count_transfer().
  182. //
  183. size_t usb_read_transfer( sUSBTransfer_t * transf, void * pReadBuffer, size_t readSize, bool enableEotHandler );
  184. // usb_count_transfer():
  185. // Non thread-safe!
  186. // Returns amount of data in the transfer.
  187. // @transf - the transfer to operate with, Non-NULL
  188. // Returns amount of data to be read.
  189. size_t usb_count_transfer( sUSBTransfer_t * transf );
  190. // usb_truncate_transfer()
  191. //
  192. // Non thread-safe!
  193. //
  194. // Truncates the data into the transfer.
  195. // @transf - the transfer to operate with, Non-NULL
  196. // @size - the size limit to apply
  197. // The function truncates the data in the transfer to the specified @size
  198. // Returns amount of data truncated.
  199. size_t usb_truncate_transfer( sUSBTransfer_t * transf, size_t size );
  200. #if USB_TRANSFER_SUPPORT_EOTH
  201. // usb_transfer_override_handler:
  202. // Replaces the End-of-transfer handler for the specified transfer @transf
  203. // @transf - the transfer to operate with
  204. // @handler - new end-of-transfer handler
  205. // If succeeded, the previous handler pointer is returned by function, and NULL otherwise.
  206. fEndOfTransferHandler_t usb_transfer_override_handler( sUSBTransfer_t * transf, fEndOfTransferHandler_t handler );
  207. #endif
  208. // usb_transfer_overridelength()
  209. //
  210. // Non thread-safe!
  211. //
  212. // Overrides the transfer data length.
  213. // @transf - the transfer to operate with, Non-NULL
  214. // @length - new length
  215. // The function overrides the original transfer data length with the specified @length
  216. // Returns new length value.
  217. size_t usb_transfer_overridelength( sUSBTransfer_t * transf, size_t length );
  218. // usb_transfer_virtual_read()
  219. //
  220. // Non thread-safe!
  221. //
  222. // Performs virtual reading from transfer without actual data retrieving from.
  223. // @transf - the transfer to operate with, Non-NULL
  224. // @length - the number of bytes for virtual reading
  225. // The function changes the transfer data length.
  226. // Returns the number of read bytes
  227. size_t usb_transfer_virtual_read( sUSBTransfer_t * transf, size_t length );
  228. // usb_transfer_virtual_write()
  229. //
  230. // Non thread-safe!
  231. //
  232. // Performs virtual writing to transfer without actual data placing in.
  233. // @transf - the transfer to operate with, Non-NULL
  234. // @length - the number of bytes for virtual writing
  235. // The function changes the transfer data length.
  236. // Returns the number of written bytes
  237. size_t usb_transfer_virtual_write( sUSBTransfer_t * transf, size_t length );
  238. // usb_transfer_compress()
  239. //
  240. // Non thread-safe!
  241. //
  242. // Optimizes the transfer by size by packing data inside.
  243. // @transf - the transfer to operate with, Non-NULL
  244. // The function moves the data from middle of the transfer to the beginning
  245. // with keeping actual size.
  246. // Returns new length value.
  247. size_t usb_transfer_compress( sUSBTransfer_t * transf );
  248. // usb_size_transfer()
  249. //
  250. // Non thread-safe!
  251. //
  252. // Returns the transfer absoulte size.
  253. // @transf - the transfer to operate with, Non-NULL
  254. // Returns the size in bytes
  255. size_t usb_size_transfer( sUSBTransfer_t * transf );
  256. // usb_space_transfer()
  257. //
  258. // Non thread-safe!
  259. //
  260. // Returns the transfer available space.
  261. // @transf - the transfer to operate with, Non-NULL
  262. // Returns amount of free space in the transfer in bytes.
  263. size_t usb_space_transfer( sUSBTransfer_t * transf );
  264. // usb_transfer_raw_write()
  265. // Returns raw write-pointer to the transfer storage.
  266. // # Ponetially dangerous function, use usb_space_transfer() before.
  267. static inline void * usb_transfer_raw_write( sUSBTransfer_t * transf )
  268. {
  269. return transf->pWriteData;
  270. }
  271. // usb_transfer_raw_read()
  272. // Returns raw read-pointer to the transfer storage.
  273. // # Ponetially dangerous function, use usb_count_transfer() before.
  274. static inline void * usb_transfer_raw_read( sUSBTransfer_t * transf )
  275. {
  276. return transf->pReadData;
  277. }
  278. #if USB_TRANSFER_MOVE_SEMANTIC
  279. // usb_move_transfer()
  280. //
  281. // Non thread-safe!
  282. //
  283. // Implements a move-semantic on couple of transfer objects
  284. // @transf_to - the transfer for move to, can not be NULL
  285. // @transf_from - the transfer for move from, can not be NULL
  286. // @copyContextValue - copy the context value assotiated with the source tranfer.
  287. // Returns the operation result, true if object had been moved
  288. // successfully, and false otherwise.
  289. // The source object (@transf_from) must be valid, while it does
  290. // not matter if the destination object @transf_to is invalid or not.
  291. bool usb_move_transfer( sUSBTransfer_t * transf_to, sUSBTransfer_t * transf_from, bool copyContextValue );
  292. #endif
  293. // usb_validate_transfer()
  294. //
  295. // Non thread-safe!
  296. //
  297. // Validates the transfer parameters. Usefull for checking objects
  298. // after moving by usb_move_transfer().
  299. // @transf - the transfer to operate with, Non-NULL
  300. // Returns true if the specified object is valid, false otherwise.
  301. bool usb_validate_transfer( sUSBTransfer_t * transf );
  302. // usb_transfer_get_context
  303. //
  304. // Non thread-safe!
  305. //
  306. // Retrieves optional user context value.
  307. // @transf - the transfer to operate with, Non-NULL
  308. // @pCtxStore - the pointer to the variable the function will store
  309. // the context value to, must not be NULL
  310. //
  311. // Returns the context value assotiated with the @transf
  312. // In case of success returns 'true', and returns 'false' otherwise.
  313. static inline bool usb_transfer_get_context( sUSBTransfer_t * transf, void ** pCtxStore )
  314. {
  315. if( NULL != transf && NULL != pCtxStore )
  316. {
  317. *pCtxStore = transf->ctx;
  318. return true;
  319. }
  320. return false;
  321. }
  322. // usb_transfer_set_context
  323. //
  324. // Non thread-safe!
  325. //
  326. // Assotiate optional user context value with the transfer.
  327. // @transf - the transfer to operate with, Non-NULL
  328. // @pCtx - user-dependent context value to be assotiated with the transfer, can be NULL
  329. //
  330. // Returns the context value assotiated with the @transf
  331. // In case of success returns 'true', and returns 'false' otherwise.
  332. static inline bool usb_transfer_set_context( sUSBTransfer_t * transf, void * pCtx )
  333. {
  334. if( NULL != transf )
  335. {
  336. transf->ctx = pCtx;
  337. return true;
  338. }
  339. return false;
  340. }
  341. // usb_copy_transfer()
  342. // Copies the data from one transfer to another
  343. // The source transfer is not being modified if @keepSource is true.
  344. // Otherwise, if @keepSource is false, the source transfer will be changed,
  345. // and the data copied to destination transfer will be removed from the source transfer.
  346. // @count - specifies amount of data to be copied.
  347. // If the source transfer contains less bytes that specified in @count, or the
  348. // destination transfer does not have enough free space, only the minimum between
  349. // these number of bytes will be copied.
  350. // Returns: number of copied bytes
  351. size_t usb_copy_transfer( sUSBTransfer_t * transf_to, sUSBTransfer_t * transf_from, size_t count, bool keepSource );
  352. #if USB_TRANSFER_SUPPORT_FLAGS
  353. // @usb_transfer_check_flags
  354. // Check if the user-dependent general-purpose flags fit to the specified mask @mask and value @value using comparing method @mode.
  355. // @transf - the transfer object to operate with;
  356. // @mask - specified mask to check
  357. // @value - specified value to check
  358. // @mode - comparing method:
  359. // - eUSBTransferFlagMode_Or: at least one transfer bit-flag must be equal to the specified value;
  360. // - eUSBTransferFlagMode_And: all the transfer bit-flag must be equal to the specified value;
  361. // @pResult = the pointer to receive output result
  362. // Returns: true if no error occurred, false otherwise.
  363. bool usb_transfer_check_flags( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value, eUSBTransferFlagMode_t mode, bool * pResult );
  364. // @usb_transfer_check_flags_fast
  365. // Check if the user-dependent general-purpose flags fit to the specified mask @mask and value @value using comparing method @mode.
  366. // @transf - the transfer object to operate with;
  367. // @mask - specified mask to check
  368. // @value - specified value to check
  369. // @mode - comparing method:
  370. // - eUSBTransferFlagMode_Or: at least one transfer bit-flag must be equal to the specified value;
  371. // - eUSBTransferFlagMode_And: all the transfer bit-flag must be equal to the specified value;
  372. // Returns: true if no error occurred and the comparing output is TRUE, false otherwise.
  373. // Note: you can use this function instead of @usb_transfer_check_flags if you are sure that the @transf pointer is valid.
  374. bool usb_transfer_check_flags_fast( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value, eUSBTransferFlagMode_t mode );
  375. // @usb_transfer_modify_flags
  376. // Modifies the user-dependent general-purpose flags using specified mask @mask and value @value
  377. // Returns: true if no error occurred, false otherwise.
  378. bool usb_transfer_modify_flags( sUSBTransfer_t * transf, tUSBTransferFlags_t mask, tUSBTransferFlags_t value );
  379. // @usb_transfer_modify_flags_locks
  380. // Modifies the lock mask for user-dependent general-purpose flags using specified mask @mask and value @value
  381. // Returns: true if no error occurred, false otherwise.
  382. bool usb_transfer_modify_flags_locks( sUSBTransfer_t * transf, tUSBTransferFlags_t lockMask, tUSBTransferFlags_t lockValue );
  383. #endif
  384. #endif