Merge pull request #2494 from tommie/usbtmcnotif
Add notification support for device class USBTMC
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -57,6 +57,7 @@ hw/mcu/st/cmsis_device_f4
|
|||||||
hw/mcu/st/cmsis_device_f7
|
hw/mcu/st/cmsis_device_f7
|
||||||
hw/mcu/st/cmsis_device_g0
|
hw/mcu/st/cmsis_device_g0
|
||||||
hw/mcu/st/cmsis_device_g4
|
hw/mcu/st/cmsis_device_g4
|
||||||
|
hw/mcu/st/cmsis_device_h5
|
||||||
hw/mcu/st/cmsis_device_h7
|
hw/mcu/st/cmsis_device_h7
|
||||||
hw/mcu/st/cmsis_device_l0
|
hw/mcu/st/cmsis_device_l0
|
||||||
hw/mcu/st/cmsis_device_l1
|
hw/mcu/st/cmsis_device_l1
|
||||||
@@ -72,6 +73,7 @@ hw/mcu/st/stm32f4xx_hal_driver
|
|||||||
hw/mcu/st/stm32f7xx_hal_driver
|
hw/mcu/st/stm32f7xx_hal_driver
|
||||||
hw/mcu/st/stm32g0xx_hal_driver
|
hw/mcu/st/stm32g0xx_hal_driver
|
||||||
hw/mcu/st/stm32g4xx_hal_driver
|
hw/mcu/st/stm32g4xx_hal_driver
|
||||||
|
hw/mcu/st/stm32h5xx_hal_driver
|
||||||
hw/mcu/st/stm32h7xx_hal_driver
|
hw/mcu/st/stm32h7xx_hal_driver
|
||||||
hw/mcu/st/stm32l0xx_hal_driver
|
hw/mcu/st/stm32l0xx_hal_driver
|
||||||
hw/mcu/st/stm32l1xx_hal_driver
|
hw/mcu/st/stm32l1xx_hal_driver
|
||||||
|
|||||||
@@ -183,6 +183,23 @@ typedef enum {
|
|||||||
|
|
||||||
} usmtmc_request_type_enum;
|
} 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 {
|
typedef enum {
|
||||||
USBTMC_STATUS_SUCCESS = 0x01,
|
USBTMC_STATUS_SUCCESS = 0x01,
|
||||||
USBTMC_STATUS_PENDING = 0x02,
|
USBTMC_STATUS_PENDING = 0x02,
|
||||||
@@ -303,6 +320,14 @@ typedef struct TU_ATTR_PACKED
|
|||||||
|
|
||||||
TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length");
|
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
|
typedef struct TU_ATTR_PACKED
|
||||||
{
|
{
|
||||||
struct TU_ATTR_PACKED
|
struct TU_ATTR_PACKED
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ tu_static char logMsg[150];
|
|||||||
// imposes a minimum buffer size of 32 bytes.
|
// imposes a minimum buffer size of 32 bytes.
|
||||||
#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||||
|
|
||||||
|
// Interrupt endpoint buffer size, default to 2 bytes as USB488 specification.
|
||||||
|
#ifndef CFG_TUD_USBTMC_INT_EP_SIZE
|
||||||
|
#define CFG_TUD_USBTMC_INT_EP_SIZE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The state machine does not allow simultaneous reading and writing. This is
|
* The state machine does not allow simultaneous reading and writing. This is
|
||||||
* consistent with USBTMC.
|
* consistent with USBTMC.
|
||||||
@@ -124,13 +129,15 @@ typedef struct
|
|||||||
uint8_t ep_bulk_in;
|
uint8_t ep_bulk_in;
|
||||||
uint8_t ep_bulk_out;
|
uint8_t ep_bulk_out;
|
||||||
uint8_t ep_int_in;
|
uint8_t ep_int_in;
|
||||||
|
uint32_t ep_bulk_in_wMaxPacketSize;
|
||||||
|
uint32_t ep_bulk_out_wMaxPacketSize;
|
||||||
// IN buffer is only used for first packet, not the remainder
|
// IN buffer is only used for first packet, not the remainder
|
||||||
// in order to deal with prepending header
|
// in order to deal with prepending header
|
||||||
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE];
|
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE];
|
||||||
uint32_t ep_bulk_in_wMaxPacketSize;
|
|
||||||
// OUT buffer receives one packet at a time
|
// OUT buffer receives one packet at a time
|
||||||
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE];
|
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE];
|
||||||
uint32_t ep_bulk_out_wMaxPacketSize;
|
// Buffer int msg to ensure alignment and placement correctness
|
||||||
|
CFG_TUSB_MEM_ALIGN uint8_t ep_int_in_buf[CFG_TUD_USBTMC_INT_EP_SIZE];
|
||||||
|
|
||||||
uint32_t transfer_size_remaining; // also used for requested length for bulk IN.
|
uint32_t transfer_size_remaining; // also used for requested length for bulk IN.
|
||||||
uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes)
|
uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes)
|
||||||
@@ -240,6 +247,19 @@ bool tud_usbtmc_transmit_dev_msg_data(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tud_usbtmc_transmit_notification_data(const void * data, size_t len)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
TU_ASSERT(len > 0);
|
||||||
|
TU_ASSERT(usbtmc_state.ep_int_in != 0);
|
||||||
|
#endif
|
||||||
|
TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in));
|
||||||
|
|
||||||
|
TU_VERIFY(tu_memcpy_s(usbtmc_state.ep_int_in_buf, sizeof(usbtmc_state.ep_int_in_buf), data, len) == 0);
|
||||||
|
TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_state.ep_int_in_buf, (uint16_t)len));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void usbtmcd_init_cb(void)
|
void usbtmcd_init_cb(void)
|
||||||
{
|
{
|
||||||
usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb();
|
usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb();
|
||||||
@@ -547,9 +567,10 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
|||||||
case STATE_TX_INITIATED:
|
case STATE_TX_INITIATED:
|
||||||
if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf))
|
if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf))
|
||||||
{
|
{
|
||||||
// FIXME! This removes const below!
|
// Copy buffer to ensure alignment correctness
|
||||||
|
memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf));
|
||||||
TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
|
TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
|
||||||
(void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)));
|
usbtmc_state.ep_bulk_in_buf, sizeof(usbtmc_state.ep_bulk_in_buf)));
|
||||||
usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf);
|
usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||||
usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf);
|
usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||||
usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf);
|
usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||||
@@ -585,7 +606,9 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ep_addr == usbtmc_state.ep_int_in) {
|
else if (ep_addr == usbtmc_state.ep_int_in) {
|
||||||
// Good?
|
if (tud_usbtmc_notification_complete_cb) {
|
||||||
|
TU_VERIFY(tud_usbtmc_notification_complete_cb());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp);
|
|||||||
bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp);
|
bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp);
|
||||||
bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp);
|
bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp);
|
||||||
|
|
||||||
|
// The interrupt-IN endpoint buffer was transmitted to the host. Use
|
||||||
|
// tud_usbtmc_transmit_notification_data to send another notification.
|
||||||
|
TU_ATTR_WEAK bool tud_usbtmc_notification_complete_cb(void);
|
||||||
|
|
||||||
// Indicator pulse should be 0.5 to 1.0 seconds long
|
// Indicator pulse should be 0.5 to 1.0 seconds long
|
||||||
TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult);
|
TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult);
|
||||||
|
|
||||||
@@ -82,17 +86,23 @@ TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg);
|
|||||||
//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb();
|
//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*******************************************
|
// Called from app
|
||||||
* Called from app
|
//
|
||||||
*
|
// We keep a reference to the buffer, so it MUST not change until the app is
|
||||||
* We keep a reference to the buffer, so it MUST not change until the app is
|
// notified that the transfer is complete.
|
||||||
* notified that the transfer is complete.
|
|
||||||
******************************************/
|
|
||||||
|
|
||||||
bool tud_usbtmc_transmit_dev_msg_data(
|
bool tud_usbtmc_transmit_dev_msg_data(
|
||||||
const void * data, size_t len,
|
const void * data, size_t len,
|
||||||
bool endOfMessage, bool usingTermChar);
|
bool endOfMessage, bool usingTermChar);
|
||||||
|
|
||||||
|
// Buffers a notification to be sent to the host. The data starts
|
||||||
|
// with the bNotify1 field, see the USBTMC Specification, Table 13.
|
||||||
|
//
|
||||||
|
// If the previous notification data has not yet been sent, this
|
||||||
|
// returns false.
|
||||||
|
//
|
||||||
|
// Requires an interrupt endpoint in the interface.
|
||||||
|
bool tud_usbtmc_transmit_notification_data(const void * data, size_t len);
|
||||||
|
|
||||||
bool tud_usbtmc_start_bus_read(void);
|
bool tud_usbtmc_start_bus_read(void);
|
||||||
|
|
||||||
|
|
||||||
@@ -105,9 +115,4 @@ void usbtmcd_reset_cb(uint8_t rhport);
|
|||||||
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||||
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
* USBTMC Descriptor Templates
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */
|
#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user