| /* | |
| * SPDX-FileCopyrightText: Copyright (c) 2019 Nathan Conrad | |
| * SPDX-FileCopyrightText: Copyright (c) 2019 Ha Thach (tinyusb.org) | |
| * SPDX-License-Identifier: MIT | |
| * | |
| * This file is part of the TinyUSB stack. | |
| */ | |
| #ifndef TUSB_USBTMC_H__ | |
| #define TUSB_USBTMC_H__ | |
| #include "common/tusb_common.h" | |
| /* Implements USBTMC Revision 1.0, April 14, 2003 | |
| String descriptors must have a "LANGID=0x409"/US English string. | |
| Characters must be 0x20 (' ') to 0x7E ('~') ASCII, | |
| But MUST not contain: "/:?\* | |
| Also must not have leading or trailing space (' ') | |
| Device descriptor must state USB version 0x0200 or greater | |
| If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. | |
| */ | |
| #define USBTMC_VERSION 0x0100 | |
| #define USBTMC_488_VERSION 0x0100 | |
| typedef enum { | |
| USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, | |
| USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, | |
| USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, | |
| USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, | |
| USBTMC_MSGID_USB488_TRIGGER = 128u, | |
| } usbtmc_msgid_enum; | |
| /// \brief Message header (For BULK OUT and BULK IN); 4 bytes | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) | |
| uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 | |
| uint8_t bTagInverse ; ///< Complement of the tag | |
| uint8_t _reserved ; ///< Must be 0x00 | |
| } usbtmc_msg_header_t; | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| usbtmc_msg_header_t header; | |
| uint8_t data[8]; | |
| } usbtmc_msg_generic_t; | |
| /* Uses on the bulk-out endpoint: */ | |
| // Next 8 bytes are message-specific | |
| typedef struct TU_ATTR_PACKED { | |
| usbtmc_msg_header_t header ; ///< Header | |
| uint32_t TransferSize ; ///< Transfer size; LSB first | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int EOM : 1 ; ///< EOM set on last byte | |
| } bmTransferAttributes; | |
| uint8_t _reserved[3]; | |
| } usbtmc_msg_request_dev_dep_out; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); | |
| // Next 8 bytes are message-specific | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| usbtmc_msg_header_t header ; ///< Header | |
| uint32_t TransferSize ; ///< Transfer size; LSB first | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar | |
| } bmTransferAttributes; | |
| uint8_t TermChar; | |
| uint8_t _reserved[2]; | |
| } usbtmc_msg_request_dev_dep_in; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); | |
| /* Bulk-in headers */ | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| usbtmc_msg_header_t header; | |
| uint32_t TransferSize; | |
| struct TU_ATTR_PACKED | |
| { | |
| uint8_t EOM: 1; ///< Last byte of transfer is the end of the message | |
| uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar | |
| } bmTransferAttributes; | |
| uint8_t _reserved[3]; | |
| } usbtmc_msg_dev_dep_msg_in_header_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); | |
| /* Unsupported vendor things.... Are these ever used?*/ | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| usbtmc_msg_header_t header ; ///< Header | |
| uint32_t TransferSize ; ///< Transfer size; LSB first | |
| uint8_t _reserved[4]; | |
| } usbtmc_msg_request_vendor_specific_out; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| usbtmc_msg_header_t header ; ///< Header | |
| uint32_t TransferSize ; ///< Transfer size; LSB first | |
| uint8_t _reserved[4]; | |
| } usbtmc_msg_request_vendor_specific_in; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); | |
| // Control request type should use tusb_control_request_t | |
| /* | |
| typedef struct TU_ATTR_PACKED { | |
| struct { | |
| unsigned int Recipient : 5 ; ///< EOM set on last byte | |
| unsigned int Type : 2 ; ///< EOM set on last byte | |
| unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN | |
| } bmRequestType; | |
| uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum | |
| uint16_t wValue ; | |
| uint16_t wIndex ; | |
| uint16_t wLength ; // Number of bytes in data stage | |
| } usbtmc_class_specific_control_req; | |
| */ | |
| // bulk-in protocol errors | |
| enum { | |
| USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, | |
| USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, | |
| USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, | |
| USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, | |
| USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, | |
| }; | |
| // built-in halt errors | |
| enum { | |
| USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a | |
| /// Bulk-IN transfer is in progress | |
| }; | |
| typedef enum { | |
| USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, | |
| USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, | |
| USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, | |
| USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, | |
| USBTMC_bREQUEST_INITIATE_CLEAR = 5u, | |
| USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, | |
| USBTMC_bREQUEST_GET_CAPABILITIES = 7u, | |
| USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional | |
| /****** USBTMC 488 *************/ | |
| USB488_bREQUEST_READ_STATUS_BYTE = 128u, | |
| USB488_bREQUEST_REN_CONTROL = 160u, | |
| USB488_bREQUEST_GO_TO_LOCAL = 161u, | |
| USB488_bREQUEST_LOCAL_LOCKOUT = 162u, | |
| } usmtmc_request_type_enum; | |
| typedef enum { | |
| // The last and first valid bNotify1 for use by the USBTMC class specification. | |
| USBTMC_bNOTIFY1_USBTMC_FIRST = 0x00, | |
| USBTMC_bNOTIFY1_USBTMC_LAST = 0x3F, | |
| // The last and first valid bNotify1 for use by vendors. | |
| USBTMC_bNOTIFY1_VENDOR_SPECIFIC_FIRST = 0x40, | |
| USBTMC_bNOTIFY1_VENDOR_SPECIFIC_LAST = 0x7F, | |
| // The last and first valid bNotify1 for use by USBTMC subclass specifications. | |
| USBTMC_bNOTIFY1_SUBCLASS_FIRST = 0x80, | |
| USBTMC_bNOTIFY1_SUBCLASS_LAST = 0xFF, | |
| // From the USB488 Subclass Specification, Section 3.4. | |
| USB488_bNOTIFY1_SRQ = 0x81, | |
| } usbtmc_int_in_payload_format; | |
| typedef enum { | |
| USBTMC_STATUS_SUCCESS = 0x01, | |
| USBTMC_STATUS_PENDING = 0x02, | |
| USBTMC_STATUS_FAILED = 0x80, | |
| USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, | |
| USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, | |
| USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83, | |
| /****** USBTMC 488 *************/ | |
| USB488_STATUS_INTERRUPT_IN_BUSY = 0x20 | |
| } usbtmc_status_enum; | |
| /************************************************************ | |
| * Control Responses | |
| */ | |
| typedef struct TU_ATTR_PACKED { | |
| uint8_t USBTMC_status; ///< usbtmc_status_enum | |
| uint8_t _reserved; | |
| uint16_t bcdUSBTMC; ///< USBTMC_VERSION | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int listenOnly :1; | |
| unsigned int talkOnly :1; | |
| unsigned int supportsIndicatorPulse :1; | |
| } bmIntfcCapabilities; | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int canEndBulkInOnTermChar :1; | |
| } bmDevCapabilities; | |
| uint8_t _reserved2[6]; | |
| uint8_t _reserved3[12]; | |
| } usbtmc_response_capabilities_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t USBTMC_status; | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int BulkInFifoBytes :1; | |
| } bmClear; | |
| } usbtmc_get_clear_status_rsp_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); | |
| // Used for both abort bulk IN and bulk OUT | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t USBTMC_status; | |
| uint8_t bTag; | |
| } usbtmc_initiate_abort_rsp_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); | |
| // Used for both check_abort_bulk_in_status and check_abort_bulk_out_status | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t USBTMC_status; | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued | |
| } bmAbortBulkIn; | |
| uint8_t _reserved[2]; ///< Must be zero | |
| uint32_t NBYTES_RXD_TXD; | |
| } usbtmc_check_abort_bulk_rsp_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t USBTMC_status; ///< usbtmc_status_enum | |
| uint8_t _reserved; | |
| uint16_t bcdUSBTMC; ///< USBTMC_VERSION | |
| struct TU_ATTR_PACKED | |
| { | |
| uint8_t listenOnly :1; | |
| uint8_t talkOnly :1; | |
| uint8_t supportsIndicatorPulse :1; | |
| } bmIntfcCapabilities; | |
| struct TU_ATTR_PACKED | |
| { | |
| uint8_t canEndBulkInOnTermChar :1; | |
| } bmDevCapabilities; | |
| uint8_t _reserved2[6]; | |
| uint16_t bcdUSB488; | |
| struct TU_ATTR_PACKED | |
| { | |
| uint8_t supportsTrigger :1; | |
| uint8_t supportsREN_GTL_LLO :1; | |
| uint8_t is488_2 :1; | |
| } bmIntfcCapabilities488; | |
| struct TU_ATTR_PACKED | |
| { | |
| uint8_t DT1 :1; | |
| uint8_t RL1 :1; | |
| uint8_t SR1 :1; | |
| uint8_t SCPI :1; | |
| } bmDevCapabilities488; | |
| uint8_t _reserved3[8]; | |
| } usbtmc_response_capabilities_488_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t USBTMC_status; | |
| uint8_t bTag; | |
| uint8_t statusByte; | |
| } usbtmc_read_stb_rsp_488_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| uint8_t bNotify1; // Must be USB488_bNOTIFY1_SRQ | |
| uint8_t StatusByte; | |
| } usbtmc_srq_interrupt_488_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_srq_interrupt_488_t) == 2u, "struct wrong length"); | |
| typedef struct TU_ATTR_PACKED | |
| { | |
| struct TU_ATTR_PACKED | |
| { | |
| unsigned int bTag : 7; | |
| unsigned int one : 1; | |
| } bNotify1; | |
| uint8_t StatusByte; | |
| } usbtmc_read_stb_interrupt_488_t; | |
| TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); | |
| #endif |