summaryrefslogtreecommitdiff
path: root/src/class
diff options
context:
space:
mode:
authorNathan Conrad <[email protected]>2019-09-24 13:11:45 -0400
committerNathan Conrad <[email protected]>2019-09-24 13:11:45 -0400
commit10105557dc5d9bd315f70243f947386728c7d86c (patch)
tree9918dc7c2473409c0c35744790c8fd7c7b890ea3 /src/class
parente61f2b7393382387634ab38e14ac5fab70e3c122 (diff)
Let application control interface latency...
Diffstat (limited to 'src/class')
-rw-r--r--src/class/usbtmc/usbtmc_device.c62
-rw-r--r--src/class/usbtmc/usbtmc_device.h15
2 files changed, 59 insertions, 18 deletions
diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c
index e3d2c316e..401b4acc4 100644
--- a/src/class/usbtmc/usbtmc_device.c
+++ b/src/class/usbtmc/usbtmc_device.c
@@ -99,9 +99,10 @@ static char logMsg[150];
typedef enum
{
- STATE_CLOSED,
- STATE_IDLE,
- STATE_RCV,
+ STATE_CLOSED, // Endpoints have not yet been opened since USB reset
+ STATE_NAK, // Bulk-out endpoint is in NAK state.
+ STATE_IDLE, // Bulk-out endpoint is waiting for CMD.
+ STATE_RCV, // Bulk-out is receiving DEV_DEP message
STATE_TX_REQUESTED,
STATE_TX_INITIATED,
STATE_TX_SHORTED,
@@ -243,7 +244,7 @@ void usbtmcd_init_cb(void)
TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,);
# endif
if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse)
- TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,);
+ TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,);
#endif
usbtmcLock = osal_mutex_create(&usbtmcLockBuffer);
@@ -322,11 +323,37 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
}
#endif
#endif
- usbtmc_state.state = STATE_IDLE;
- TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64));
+ atomicChangeState(STATE_CLOSED, STATE_NAK);
+ tud_usbtmc_app_open_cb(rhport, itf_desc->iInterface);
return true;
}
+// Tell USBTMC class to set its bulk-in EP to ACK so that it can
+// receive USBTMC commands.
+// Returns false if it was already in an ACK state or is busy
+// processing a command (such as a clear). Returns true if it was
+// in the NAK state and successfully transitioned to the ACK wait
+// state.
+bool usbtmcd_start_bus_read(uint8_t rhport)
+{
+ usbtmcd_state_enum oldState = usbtmc_state.state;
+ switch(oldState)
+ {
+ // These may transition to IDLE
+ case STATE_NAK:
+ case STATE_ABORTING_BULK_IN_ABORTED:
+ TU_VERIFY(atomicChangeState(oldState, STATE_IDLE));
+ break;
+ // When receiving, let it remain receiving
+ case STATE_RCV:
+ break;
+ default:
+ TU_VERIFY(false);
+ }
+ TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64));
+ return true;
+}
+
void usbtmcd_reset_cb(uint8_t rhport)
{
(void)rhport;
@@ -367,19 +394,21 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack
if(len >= usbtmc_state.transfer_size_remaining || shortPacket)
{
atEnd = true;
+ TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK));
}
len = tu_min32(len, usbtmc_state.transfer_size_remaining);
+ usbtmc_state.transfer_size_remaining -= len;
+ usbtmc_state.transfer_size_sent += len;
+
+ // App may (should?) call the wait_for_bus() command at this point
if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd))
{
// TODO: Go to an error state upon failure other than just stalling the EP?
return false;
}
- usbtmc_state.transfer_size_remaining -= len;
- usbtmc_state.transfer_size_sent += len;
- TU_VERIFY(atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV));
return true;
}
@@ -453,7 +482,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
TU_VERIFY(false);
return false;
}
- TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE));
return true;
case STATE_RCV:
@@ -462,7 +490,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
TU_VERIFY(false);
}
- TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE));
return true;
case STATE_ABORTING_BULK_OUT:
@@ -482,8 +509,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
{
switch(usbtmc_state.state) {
case STATE_TX_SHORTED:
-
- usbtmc_state.state = STATE_IDLE;
+ TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK));
TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport));
break;
@@ -508,7 +534,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 ))
{
usbtmc_state.state = STATE_TX_SHORTED;
- }
+ }
}
return true;
case STATE_ABORTING_BULK_IN:
@@ -548,9 +574,10 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r
if(ep_addr == usbtmc_state.ep_bulk_out)
{
+ criticalEnter();
+ usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us
+ criticalLeave();
usmtmcd_app_bulkOut_clearFeature_cb(rhport);
- // And start a new OUT xfer request now that things are clear
- TU_ASSERT( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64));
}
else if (ep_addr == usbtmc_state.ep_bulk_in)
{
@@ -605,6 +632,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r
TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp)));
return true;
}
+
case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS:
{
usbtmc_check_abort_bulk_rsp_t rsp = {
@@ -750,7 +778,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r
TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
TU_VERIFY(request->wLength == sizeof(tmcStatusCode));
TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse);
- TU_VERIFY(tud_usbtmc_app_indicator_pluse_cb(rhport, request, &tmcStatusCode));
+ TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(rhport, request, &tmcStatusCode));
TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode)));
return true;
}
diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h
index d33d73905..3638b5527 100644
--- a/src/class/usbtmc/usbtmc_device.h
+++ b/src/class/usbtmc/usbtmc_device.h
@@ -55,6 +55,17 @@ extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities;
extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities;
#endif
+// In order to proceed, app must call call usbtmcd_start_bus_read(rhport) during or soon after:
+// * tud_usbtmc_app_open_cb
+// * tud_usbtmc_app_msg_data_cb
+// * tud_usbtmc_app_msgBulkIn_complete_cb
+// * tud_usbtmc_app_msg_trigger_cb
+// * (successful) tud_usbtmc_app_check_abort_bulk_out_cb
+// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb
+// * (successful) usmtmcd_app_bulkOut_clearFeature_cb
+
+void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id);
+
bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader);
// transfer_complete does not imply that a message is complete.
bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete);
@@ -73,7 +84,7 @@ bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_b
bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp);
// Indicator pulse should be 0.5 to 1.0 seconds long
-TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult);
+TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult);
#if (CFG_USBTMC_CFG_ENABLE_488)
uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult);
@@ -93,6 +104,8 @@ bool usbtmcd_transmit_dev_msg_data(
const void * data, size_t len,
bool endOfMessage, bool usingTermChar);
+bool usbtmcd_start_bus_read(uint8_t rhport);
+
/* "callbacks" from USB device core */