usbtmclib_basic.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. #ifndef USBTMCLIB_BASIC_H
  2. #define USBTMCLIB_BASIC_H
  3. // USB Test And Measurement Control Protocol (TMC)
  4. // Library version 1.0
  5. // 23/07/19
  6. // Sychov A.
  7. //----------------------------------------------------------------
  8. // Refer to:
  9. // [1] USBTMC Standard, rev. 1.0, 14/04/2003
  10. // "Universal Serial Bus Test and Measurement Class Specification (USBTMC)"
  11. // [2] USBTMC-USB488 Standard, rev. 1.0, 14/04/2003
  12. // "Universal Serial Bus Test and Measurement Class, Subclass USB488 Specification (USBTMC-USB488)
  13. //----------------------------------------------------------------
  14. #include <stddef.h>
  15. #include <stdint.h>
  16. #include "usbtmclib/usbtmclib_types.h"
  17. #include "usbtmclib/usbtmclib_requests.h"
  18. #include "usbtmclib/usbtmclib_errors.h"
  19. #include "app/usb/usb_transfers.h"
  20. #include "app/usb/usb_transfer_flags.h"
  21. #define USBTMC_VERSION 0x0100 // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
  22. #define USB488_VERSION 0x0100 // 4.2.2 GET_CAPABILITIES, table 8, [2]
  23. typedef struct
  24. {
  25. bool bInProgress;
  26. uint32_t transferSize;
  27. uint32_t bytesCounter;
  28. bool bEndOfMessage;
  29. sUSBTransfer_t * transf;
  30. bool bNewTransfer;
  31. // @bytesCounter for BulkOut:
  32. // The total number of USBTMC message data bytes (not including
  33. // Bulk-OUT Header or alignment bytes) in the transfer received,
  34. // and not discarded, by the device
  35. // @bytesCounter for BulkIn:
  36. // The total number of USBTMC message data bytes (not including
  37. // Bulk-IN Header or alignment bytes) sent in the transfer
  38. // @bEndOfMessage for BulkOut:
  39. // Specifies if the EOM flag is set in Bulk-OUT header
  40. // See @bm_DEV_DEP_MSG_OUT_EOM for details.
  41. // @transf for BulkOUT:
  42. // Receiving buffer object
  43. // @transf for BulkIN:
  44. // Transmitting buffer object
  45. // @bNewTransfer for BulkOUT:
  46. // Set if new transfer just has been started
  47. // bLatestTag - the latest aborted/completed transaction bTag
  48. uint8_t bLatestTag;
  49. }
  50. sUSBTMCTransferState_t;
  51. typedef struct
  52. {
  53. bool bInProgress;
  54. uint32_t bytesCounter;
  55. bool bEndOfMessage;
  56. // @STB - status byte (IEEE 488.1/IEEE 488.2)
  57. // The part of USBTMC-USB488 Interrupt-IN Header, [2], 3.4 Interrupt-IN
  58. uint8_t STB;
  59. // @bTag - transfer identifier (bTag), [2], 4.3.1 READ_STATUS_BYTE
  60. // The part of USBTMC-USB488 Interrupt-IN Header, [2], 3.4 Interrupt-IN
  61. uint8_t bTag;
  62. // @transf for InterruptIn:
  63. // Transmitting buffer object
  64. sUSBTransfer_t * transf;
  65. // @bNewTransfer for InterruptIn:
  66. // Set if new transfer just has been started
  67. bool bNewTransfer;
  68. }
  69. sUSBTMCIntTransferState_t;
  70. typedef struct
  71. {
  72. sUSBTMCBulkOutHeader_t bulkOutHeader;
  73. sUSBTMCBulkInHeader_t bulkInHeader;
  74. sUSBTMCNotificationHeader_t interruptInHeader;
  75. sUSBTMCTransferState_t bulkOutState;
  76. sUSBTMCTransferState_t bulkInState;
  77. sUSBTMCIntTransferState_t interruptInState;
  78. sUSBTMCBulkInHeader_t * psActiveInHeader;
  79. sUSBTMCNotificationHeader_t * psActiveNotificationHeader;
  80. }
  81. sUSBTMCContext_t;
  82. typedef enum
  83. {
  84. tmclib_status_min = -2147483648,
  85. tmclib_status_invalid_param = -10, // ERROR/FAIL
  86. tmclib_status_invalid_length = -9, // ERROR/FAIL
  87. tmclib_status_halt_bulkin = -8, // ERROR/FAIL
  88. tmclib_status_unsupported_termchar = -7, // ERROR/FAIL
  89. tmclib_status_unsupported_message_error = -6, // ERROR/FAIL
  90. tmclib_status_invalid_message_error = -5, // ERROR/FAIL
  91. tmclib_status_header_error = -4, // ERROR/FAIL
  92. tmclib_status_read_error = -3, // ERROR/FAIL
  93. tmclib_status_header_fragmented_error = -2, // ERROR/FAIL
  94. tmclib_status_failure = -1, // ERROR/FAIL
  95. tmclib_status_success = 0, // SUCCESS/OK
  96. tmclib_status_in_progress = 1, // SIGNAL/WARNING
  97. tmclib_status_not_in_progress = 2, // SIGNAL/WARNING
  98. tmclib_status_again = 3, // SIGNAL/WARNING
  99. tmclib_status_need_data = 4, // SIGNAL/WARNING
  100. tmclib_status_need_read = 5, // SIGNAL/WARNING
  101. tmclib_status_no_more_data = 6, // SIGNAL/WARNING
  102. tmclib_status_max = 2147483647,
  103. }
  104. eTMCLibStatus_t;
  105. // @eTMCLibEvent_t
  106. // Common TMCLibrary event identifier.
  107. // Is used in tmclib_*_event() routines
  108. typedef enum
  109. {
  110. eTMCEventInterruptInStart, // InterruptIn initialize (only for Interrupt-IN)
  111. eTMCEventBulkIn, // BulkIn event
  112. eTMCEventBulkOut, // BulkOut event
  113. eTMCEventInterruptIn, // InterruptIn event
  114. eTMCEventBulkInStop, // BulkIn abort
  115. eTMCEventBulkOutStop, // BulkOut abort
  116. eTMCEventInterruptInStop, // InterruptIn abort
  117. eTMCEventDeviceClear, // Common Clear Event (*RST or Device Clear)
  118. }
  119. eTMCLibEvent_t;
  120. typedef struct
  121. {
  122. sUSBTransfer_t * tx;
  123. }
  124. sTMCBulkInEventCtx_t;
  125. #define DEFINE_tmclib_event_context_bulkin( _name, _tx ) \
  126. sTMCEventContext_t eventCtx = { \
  127. .event = (eTMCEventBulkIn),\
  128. .bulkIn = { \
  129. .tx = (_tx) \
  130. } \
  131. }
  132. #define COMPOUND_tmclib_event_context_bulkin( _name, _tx ) \
  133. &((sTMCEventContext_t){ \
  134. .event = (eTMCEventBulkIn),\
  135. .bulkIn = { \
  136. .tx = (_tx) \
  137. } \
  138. })
  139. typedef struct
  140. {
  141. sUSBTransfer_t * rx;
  142. }
  143. sTMCBulkOutEventCtx_t;
  144. #define DEFINE_tmclib_event_context_bulkout( _name, _rx ) \
  145. sTMCEventContext_t eventCtx = { \
  146. .event = (eTMCEventBulkOut),\
  147. .bulkOut = { \
  148. .rx = (_rx) \
  149. } \
  150. }
  151. #define COMPOUND_tmclib_event_context_bulkout( _name, _rx ) \
  152. &((sTMCEventContext_t){ \
  153. .event = (eTMCEventBulkOut),\
  154. .bulkOut = { \
  155. .rx = (_rx) \
  156. } \
  157. })
  158. typedef struct
  159. {
  160. sUSBTransfer_t * ntx;
  161. uint8_t bTag;
  162. }
  163. sTMCInterruptInEventCtx_t;
  164. #define DEFINE_tmclib_event_context_interruptin_start( _name, _ntx, _btag ) \
  165. sTMCEventContext_t _name = { \
  166. .event = (eTMCEventInterruptInStart),\
  167. .interruptIn = { \
  168. .ntx = (_ntx),\
  169. .bTag = (_btag) \
  170. } \
  171. }
  172. #define DEFINE_tmclib_event_context_interruptin( _name, _ntx ) \
  173. sTMCEventContext_t _name = { \
  174. .event = (eTMCEventInterruptIn),\
  175. .interruptIn = { \
  176. .ntx = (_ntx),\
  177. .bTag = (0) \
  178. } \
  179. }
  180. #define COMPOUND_tmclib_event_context_interruptin_start( _name, _ntx, _btag ) \
  181. &((sTMCEventContext_t){ \
  182. .event = (eTMCEventInterruptInStart),\
  183. .interruptIn = { \
  184. .ntx = (_ntx),\
  185. .bTag = (_btag) \
  186. } \
  187. })
  188. #define COMPOUND_tmclib_event_context_interruptin( _name, _ntx ) \
  189. &((sTMCEventContext_t){ \
  190. .event = (eTMCEventInterruptIn),\
  191. .interruptIn = { \
  192. .ntx = (_ntx),\
  193. .bTag = (0) \
  194. } \
  195. })
  196. typedef struct
  197. {
  198. // @force - makes to ignore the @transfer_bTag if true
  199. bool force;
  200. // @clearShortPacketIndicator - clear Short Packet Indicator assotiated with USB transfer
  201. bool clearShortPacketIndicator;
  202. // @noResetTransfer
  203. // By default shall be false.
  204. // If set, the transfer will not be reset. Is used only if buffer contains more data than
  205. // expected for the transfer
  206. bool noResetTransfer;
  207. // @transfer_bTag - The bTag value associated with the transfer to abort,
  208. // - BulkOut: see 4.2.1.2 [1]
  209. // - BulkIn: see 4.2.1.4 [1]
  210. // - InterruptIn: see 4.3.1 [2]
  211. uint8_t transfer_bTag;
  212. }
  213. sTMCAbortEventCtx_t;
  214. typedef struct
  215. {
  216. // @resetTransport - reset all the USBTMC transfers
  217. bool resetTransport;
  218. }
  219. sTMCDeviceClearEventCtx_t;
  220. #define DEFINE_tmclib_event_context_abort_bulkout( _name, _btag, _force ) \
  221. sTMCEventContext_t _name = { \
  222. .event = eTMCEventBulkOutStop,\
  223. .abort = { \
  224. .force = (_force),\
  225. .clearShortPacketIndicator = (false), \
  226. .noResetTransfer = (false), \
  227. .transfer_bTag = (_btag) \
  228. } \
  229. }
  230. #define DEFINE_tmclib_event_context_abort_bulkin( _name, _btag, _force ) \
  231. sTMCEventContext_t _name = { \
  232. .event = eTMCEventBulkInStop,\
  233. .abort = { \
  234. .force = (_force),\
  235. .clearShortPacketIndicator = (true), \
  236. .noResetTransfer = (false), \
  237. .transfer_bTag = (_btag) \
  238. } \
  239. }
  240. #define DEFINE_tmclib_event_context_complete_bulkin( _name, _btag ) \
  241. sTMCEventContext_t _name = { \
  242. .event = eTMCEventBulkInStop,\
  243. .abort = { \
  244. .force = (false),\
  245. .clearShortPacketIndicator = (false), \
  246. .noResetTransfer = (false), \
  247. .transfer_bTag = (_btag) \
  248. } \
  249. }
  250. #define DEFINE_tmclib_event_context_abort_interruptin( _name, _btag, _force ) \
  251. sTMCEventContext_t _name = { \
  252. .event = eTMCEventInterruptInStop,\
  253. .abort = { \
  254. .force = (_force),\
  255. .clearShortPacketIndicator = (false), \
  256. .noResetTransfer = (false), \
  257. .transfer_bTag = (_btag) \
  258. } \
  259. }
  260. #define COMPOUND_tmclib_event_context_abort_bulkout( _btag, _force ) \
  261. &((sTMCEventContext_t){ \
  262. .event = eTMCEventBulkOutStop,\
  263. .abort = { \
  264. .force = (_force),\
  265. .clearShortPacketIndicator = (false), \
  266. .noResetTransfer = (false), \
  267. .transfer_bTag = (_btag) \
  268. } \
  269. })
  270. #define COMPOUND_tmclib_event_context_abort_bulkout_noreset( _btag, _force ) \
  271. &((sTMCEventContext_t){ \
  272. .event = eTMCEventBulkOutStop,\
  273. .abort = { \
  274. .force = (_force),\
  275. .clearShortPacketIndicator = (false), \
  276. .noResetTransfer = (true), \
  277. .transfer_bTag = (_btag) \
  278. } \
  279. })
  280. #define COMPOUND_tmclib_event_context_abort_bulkin( _btag, _force ) \
  281. &((sTMCEventContext_t){ \
  282. .event = eTMCEventBulkInStop,\
  283. .abort = { \
  284. .force = (_force),\
  285. .clearShortPacketIndicator = (true), \
  286. .noResetTransfer = (false), \
  287. .transfer_bTag = (_btag) \
  288. } \
  289. })
  290. #define COMPOUND_tmclib_event_context_complete_bulkin( _btag, _force ) \
  291. &((sTMCEventContext_t){ \
  292. .event = eTMCEventBulkInStop,\
  293. .abort = { \
  294. .force = (_force),\
  295. .clearShortPacketIndicator = (false), \
  296. .noResetTransfer = (false), \
  297. .transfer_bTag = (_btag) \
  298. } \
  299. })
  300. #define COMPOUND_tmclib_event_context_abort_interruptin( _btag, _force ) \
  301. &((sTMCEventContext_t){ \
  302. .event = eTMCEventInterruptInStop,\
  303. .abort = { \
  304. .force = (_force),\
  305. .clearShortPacketIndicator = (false), \
  306. .noResetTransfer = (false), \
  307. .transfer_bTag = (_btag) \
  308. } \
  309. })
  310. #define COMPOUND_tmclib_event_context_device_clear( _fullReset ) \
  311. &((sTMCEventContext_t){ \
  312. .event = eTMCEventDeviceClear,\
  313. .clear = { \
  314. .resetTransport = (_fullReset),\
  315. } \
  316. })
  317. typedef struct
  318. {
  319. eTMCLibEvent_t event; // event identified
  320. union
  321. {
  322. sTMCBulkInEventCtx_t bulkIn; // for events: eTMCEventBulkIn
  323. sTMCBulkOutEventCtx_t bulkOut; // for events: eTMCEventBulkOut
  324. sTMCInterruptInEventCtx_t interruptIn; // for events: eTMCEventInterruptIn, eTMCEventBulkInStart
  325. sTMCAbortEventCtx_t abort; // for events: eTMCEventBulkInStop, eTMCEventBulkOutStop, eTMCEventInterruptInStop
  326. sTMCDeviceClearEventCtx_t clear; // for events: eTMCEventDeviceClear
  327. };
  328. }
  329. sTMCEventContext_t;
  330. #define USBTMC_CHECK_BITMAP( Bitmap, Flag ) ((bool)((Bitmap)&(Flag)))
  331. #define USBTMC_ERROR(status) ( tmclib_status_success > (status) )
  332. #define USBTMC_NOTERROR(status) ( tmclib_status_success <=(status) )
  333. #define USBTMC_WARNING(status) ( tmclib_status_success < (status) )
  334. // @tmclib_init()
  335. // Initialize TMC library
  336. // @rx - receiving buffer object
  337. // @tx - transmitting buffer object
  338. // @ntx - interrupt/notify transmitting buffer object
  339. eTMCLibStatus_t tmclib_init( sUSBTransfer_t * rx, sUSBTransfer_t * tx, sUSBTransfer_t * ntx );
  340. // @tmclib_deinit()
  341. // Deinitialize TMC library
  342. eTMCLibStatus_t tmclib_deinit();
  343. // // @tmclib_new_bulkout()
  344. // // Starts new BulkOUT transfer
  345. // eTMCLibStatus_t tmclib_new_bulkout();
  346. //
  347. // // @tmclib_new_bulkin()
  348. // // Starts new BulkIN transfer
  349. // eTMCLibStatus_t tmclib_new_bulkin();
  350. // @tmclib_bulkout_gettag
  351. // Returns the bTag field for current BulkOut transfer
  352. // @pbTag - pointer to the bTag to be filled, can not be NULL
  353. // Note: if there no transaction is, function returns bTag=0
  354. // Returns: returns @tmclib_status_success if @pbTag is not NULL,
  355. // otherwise returns @tmclib_status_failure
  356. eTMCLibStatus_t tmclib_bulkout_gettag( uint8_t * pbTag );
  357. // @tmclib_bulkin_gettag
  358. // Returns the bTag field for current BulkIn transfer
  359. // @pbTag - pointer to the bTag to be filled, can not be NULL
  360. // Note: if there no transaction is, function returns bTag=0
  361. // Returns: returns @tmclib_status_success if @pbTag is not NULL,
  362. // otherwise returns @tmclib_status_failure
  363. eTMCLibStatus_t tmclib_bulkin_gettag( uint8_t * pbTag );
  364. // @tmclib_bulkout_gettag_latest
  365. // Returns the bTag field for latest valid BulkOut transfer
  366. // @pbTag - pointer to the bTag to be filled, can not be NULL
  367. // Note: if there no transaction is, function returns bTag for the latest valid
  368. // BulkOut transfer, or bTag for current transaction otherwise.
  369. // Returns: returns @tmclib_status_success if @pbTag is not NULL,
  370. // otherwise returns @tmclib_status_invalid_param
  371. eTMCLibStatus_t tmclib_bulkout_gettag_latest( uint8_t * pbTag );
  372. // @tmclib_bulkin_gettag_latest
  373. // Returns the bTag field for latest valid BulkIn transfer
  374. // @pbTag - pointer to the bTag to be filled, can not be NULL
  375. // Note: if there no transaction is, function returns bTag for the latest valid
  376. // BulkIn transfer, or bTag for current transaction otherwise.
  377. // Returns: returns @tmclib_status_success if @pbTag is not NULL,
  378. // otherwise returns @tmclib_status_invalid_param
  379. eTMCLibStatus_t tmclib_bulkin_gettag_latest( uint8_t * pbTag );
  380. // @tmclib_bulkout_getcounter
  381. // Returns the bytes counter for current BulkOut transfer
  382. // @pnBytes - pointer to the uint32_t variable to be filled, can not be NULL
  383. // Note: if there no transaction is, function returns the counter for the last transfer
  384. // Returns: returns @tmclib_status_success if @pnBytes is not NULL,
  385. // otherwise returns @tmclib_status_failure
  386. eTMCLibStatus_t tmclib_bulkout_getcounter( uint32_t * pnBytes );
  387. // @tmclib_bulkin_getcounter
  388. // Returns the bytes counter for current BulkIn transfer
  389. // @pnBytes - pointer to the uint32_t variable to be filled, can not be NULL
  390. // Note: if there no transaction is, function returns the counter for the last transfer
  391. // Returns: returns @tmclib_status_success if @pnBytes is not NULL,
  392. // otherwise returns @tmclib_status_failure
  393. eTMCLibStatus_t tmclib_bulkin_getcounter( uint32_t * pnBytes );
  394. // @tmclib_generic_event()
  395. // Processes USBTMC specific event.
  396. // @eventCtx - event context, all the fields must be filled in accordance to @eventCtx->event code
  397. // @eventCtx->event - event identifier:
  398. //
  399. // +------------------------------------------------------------------------------------------------------------
  400. // * eTMCEventBulkInStop - Aborts currently running BulkIN transfer
  401. // |---> @eventCtx->abort:
  402. // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.2.1.4 [1]
  403. // | - @force - makes to ignore the @transfer_bTag if true
  404. // +------------------------------------------------------------------------------------------------------------
  405. // * eTMCEventBulkOutStop - Aborts currently running BulkOUT transfer
  406. // |---> @eventCtx->abort:
  407. // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.2.1.2 [1]
  408. // | - @force - makes to ignore the @transfer_bTag if true
  409. // +------------------------------------------------------------------------------------------------------------
  410. // * eTMCEventInterruptInStop - Aborts currently running InterruptIN transfer
  411. // |---> @eventCtx->abort:
  412. // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.3.1 [2]
  413. // | - @force - makes to ignore the @transfer_bTag if true
  414. // +------------------------------------------------------------------------------------------------------------
  415. // * eTMCEventBulkIn - Processes USBTMC Bulk-IN event
  416. // |---> @eventCtx->bulkIn:
  417. // | - @tx - the buffer object to be used to transmit data
  418. // +------------------------------------------------------------------------------------------------------------
  419. // * eTMCEventBulkOut - Processes USBTMC Bulk-OUT event
  420. // |---> @eventCtx->bulkOut:
  421. // | - @rx - the buffer object to be used to receive data
  422. // +------------------------------------------------------------------------------------------------------------
  423. // * eTMCEventInterruptInStart - Initialize new Interrupt-IN transfer w/o data processing
  424. // | ...The function only creates new transfer without calling Tx-Handler. This call must be
  425. // | ...provided before 'eTMCEventInterruptIn' event to prapare transfer.
  426. // |----> @eventCtx->interruptIn:
  427. // | - @ntx - must be NULL, or 'tmclib_status_invalid_param' will be returned otherwise
  428. // | - @bTag - the Tag identifier, [2], 3.4.2 Interrupt-IN DATA sent due to READ_STATUS_BYTE request,
  429. // +------------------------------------------------------------------------------------------------------------
  430. // * eTMCEventInterruptIn - Processes USBTMC Interrupt-IN event.
  431. // | Note that 'eTMCEventInterruptInStart' must be generated before 'eTMCEventInterruptIn' for normal operation.
  432. // | Note: Each event generates a single INTERRUPT-IN packet begining with Interrupt-IN header
  433. // | Note: Each interrupt-in event must be not longer than @ntx transfer length.
  434. // | Note: In case it is required to send more data than @ntx can carry, you need:
  435. // | - increase Interrupt-IN EP buffer (see USB specification) and increase @ntx transfer space
  436. // | or:
  437. // | - send the data using multiple packets (each packet begins with INTERRUPT-IN header), pay
  438. // | attention that @ctx->interruptInState will not be reset until user layer return tmclib_status_success
  439. // | or tmclib_status_no_more_data.
  440. // |----> @eventCtx->interruptIn:
  441. // | - @ntx - the buffer object to be used to transmit data
  442. // | - @bTag - don't care
  443. // +------------------------------------------------------------------------------------------------------------
  444. //
  445. // Returns: the operation status:
  446. // tmclib_status_success in case of success,
  447. // tmclib_status_failure otherwise
  448. //
  449. eTMCLibStatus_t tmclib_generic_event( sTMCEventContext_t * eventCtx );
  450. #endif