Jelajahi Sumber

usbtmc updates....

Nathan Conrad 6 tahun lalu
induk
melakukan
eea71a8b3b

+ 2 - 2
examples/device/usbtmc/src/tusb_config.h

@@ -56,8 +56,8 @@
 //------------- CLASS -------------//
 
 #define CFG_TUD_USBTMC           1
-#define CFG_TUD_USBTMC_ENABLE_INT_EP
-//#define USBTMC_CFG_ENABLE_488    0
+#define CFG_TUD_USBTMC_ENABLE_INT_EP 1
+#define USBTMC_CFG_ENABLE_488    1
 
 #ifdef __cplusplus
  }

+ 27 - 5
examples/device/usbtmc/src/usbtmc_app.c

@@ -64,8 +64,8 @@ usbtmcd_app_capabilities  =
     }
 #endif
 };
-//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer";
-static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps?\n";
+static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n";
+//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps? lets make it three transfers...\n";
 static volatile uint8_t status;
 
 // 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready?
@@ -154,14 +154,14 @@ void usbtmc_app_task_iter(void) {
     queryState = 2;
     break;
   case 2:
-    if( (board_millis() - queryDelayStart) > 5u) {
+    if( (board_millis() - queryDelayStart) > 200u) {
       queryDelayStart = board_millis();
       queryState=3;
       status |= 0x10u; // MAV
     }
     break;
   case 3:
-    if( (board_millis() - queryDelayStart) > 10u) {
+    if( (board_millis() - queryDelayStart) > 400u) {
       queryState = 4;
     }
     break;
@@ -169,6 +169,7 @@ void usbtmc_app_task_iter(void) {
     if(bulkInStarted) {
       queryState = 0;
       bulkInStarted = 0;
+      uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n");
       usbtmcd_transmit_dev_msg_data(rhport, idn,  tu_min32(sizeof(idn)-1,msgReqLen),false);
       // MAV is cleared in the transfer complete callback.
     }
@@ -189,7 +190,7 @@ bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult)
   return true;
 }
 
-bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp)
+bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp)
 {
   (void)rhport;
   queryState = 0;
@@ -199,6 +200,27 @@ bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t
   rsp->bmClear.BulkInFifoBytes = 0u;
   return true;
 }
+bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult)
+{
+  bulkInStarted = 0;
+  *tmcResult = USBTMC_STATUS_SUCCESS;
+  return true;
+}
+bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp)
+{
+  return true;
+}
+
+bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult)
+{
+  *tmcResult = USBTMC_STATUS_SUCCESS;
+  return true;
+
+}
+bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp)
+{
+  return true;
+}
 
 void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport)
 {

+ 14 - 0
src/class/usbtmc/usbtmc.h

@@ -237,6 +237,20 @@ typedef struct TU_ATTR_PACKED
 
 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

+ 213 - 66
src/class/usbtmc/usbtmc_device.c

@@ -93,8 +93,11 @@ typedef enum
   STATE_RCV,
   STATE_TX_REQUESTED,
   STATE_TX_INITIATED,
+  STATE_TX_SHORTED,
   STATE_CLEARING,
   STATE_ABORTING_BULK_IN,
+  STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission
+  STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been queued for transmission
   STATE_ABORTING_BULK_OUT,
   STATE_NUM_STATES
 } usbtmcd_state_enum;
@@ -113,6 +116,7 @@ typedef struct
   // OUT buffer receives one packet at a time
   uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE];
   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)
 
   uint8_t lastBulkOutTag; // used for aborts (mostly)
   uint8_t lastBulkInTag; // used for aborts (mostly)
@@ -128,6 +132,11 @@ static usbtmc_interface_state_t usbtmc_state =
     .ep_bulk_out = 0,
     .ep_int_in = 0
 };
+#ifdef xDEBUG
+#define TRACE(str) uart_tx_str_sync(str)
+#else
+#define TRACE(STR) do {} while (0)
+#endif
 
 // We need all headers to fit in a single packet in this implementation.
 TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small");
@@ -188,7 +197,7 @@ bool usbtmcd_transmit_dev_msg_data(
   if((packetLen + hdr->TransferSize) <= txBufLen)
   {
     memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize);
-    packetLen = (uint16_t)(packetLen+ hdr->TransferSize);
+    packetLen = (uint16_t)(packetLen + hdr->TransferSize);
     // Pad up to multiple of 4 bytes
     while((packetLen % 4) != 0)
     {
@@ -196,13 +205,15 @@ bool usbtmcd_transmit_dev_msg_data(
       packetLen++;
     }
     usbtmc_state.transfer_size_remaining = 0;
+    usbtmc_state.transfer_size_sent = len;
     usbtmc_state.devInBuffer = NULL;
   }
   else /* partial packet */
   {
     memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen);
-    usbtmc_state.devInBuffer += txBufLen - packetLen;
-    usbtmc_state.transfer_size_remaining = hdr->TransferSize - (txBufLen - packetLen);
+    usbtmc_state.devInBuffer = (uint8_t*)data + (txBufLen - packetLen);
+    usbtmc_state.transfer_size_remaining = len - (txBufLen - packetLen);
+    usbtmc_state.transfer_size_sent = txBufLen - packetLen;
     packetLen = txBufLen;
   }
 
@@ -210,7 +221,8 @@ bool usbtmcd_transmit_dev_msg_data(
   criticalEnter();
   {
     TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED);
-    usbtmc_state.state = STATE_TX_INITIATED;
+    // We used packetlen as a max, not the buffer size, so this is OK here, no need for modulus
+    usbtmc_state.state  = (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED;
   }
   criticalLeave();
 
@@ -322,6 +334,8 @@ void usbtmcd_reset(uint8_t rhport)
   usbtmc_state.ep_bulk_in = 0;
   usbtmc_state.ep_bulk_out = 0;
   usbtmc_state.ep_int_in = 0;
+  usbtmc_state.lastBulkInTag = 0;
+  usbtmc_state.lastBulkOutTag = 0;
 
   (void)rhport;
 }
@@ -351,10 +365,16 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack
   if(len > usbtmc_state.transfer_size_remaining)
     len = usbtmc_state.transfer_size_remaining;
   usbtmcd_app_msg_data(rhport,data, len, atEnd);
+
+  usbtmc_state.transfer_size_sent += len;
   if(atEnd)
+  {
     usbtmc_state.state = STATE_IDLE;
+  }
   else
+  {
     usbtmc_state.state = STATE_RCV;
+  }
   return true;
 }
 
@@ -363,8 +383,10 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len)
   TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in));
   usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data;
 
+#ifdef xDebug
   sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len);
-  uart_tx_str_sync(logMsg);
+  TRACE(logMsg);
+#endif
 
   criticalEnter();
   {
@@ -387,10 +409,13 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len)
 
 bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
 {
+  TRACE("USBTMC Xfer CB" );
   TU_VERIFY(result == XFER_RESULT_SUCCESS);
-  uart_tx_str_sync("USBTMC Xfer CB" );
+
+#ifdef xDebug
   sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state);
-  uart_tx_str_sync(logMsg);
+  TRACE(logMsg);
+#endif
 
   if(usbtmc_state.state == STATE_CLEARING) {
     return true; /* I think we can ignore everything here */
@@ -398,23 +423,26 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
 
   if(ep_addr == usbtmc_state.ep_bulk_out)
   {
-    uart_tx_str_sync("OUT");
+    usbtmc_msg_generic_t *msg = NULL;
+    TRACE("OUT");
     switch(usbtmc_state.state)
     {
     case STATE_IDLE:
       TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t));
-      usbtmc_msg_generic_t *msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf);
+      msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf);
       uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse);
       TU_VERIFY(msg->header.bTag == invInvTag);
       TU_VERIFY(msg->header.bTag != 0x00);
 
+#ifdef xDebug
       sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID);
-      uart_tx_str_sync(logMsg);
+      TRACE(logMsg);
+#endif
 
       switch(msg->header.MsgID) {
       case USBTMC_MSGID_DEV_DEP_MSG_OUT:
+        usbtmc_state.transfer_size_sent = 0u;
         TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes));
-        TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE));
         usbtmc_state.lastBulkOutTag = msg->header.bTag;
         break;
 
@@ -428,7 +456,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
         // Spec says we halt the EP if we didn't declare we support it.
         TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger);
         TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg));
-        TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE));
 
         break;
 #endif
@@ -439,58 +466,95 @@ 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:
       TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes));
       return true;
 
+    case STATE_ABORTING_BULK_OUT:
+      TU_VERIFY(false);
+      return false; // Shold be stalled by now...
     case STATE_TX_REQUESTED:
     case STATE_TX_INITIATED:
     case STATE_ABORTING_BULK_IN:
-    case STATE_ABORTING_BULK_OUT:
+    case STATE_ABORTING_BULK_IN_SHORTED:
+    case STATE_ABORTING_BULK_IN_ABORTED:
     default:
+
+#ifdef xDebug
       if(msg == NULL)
         sprintf(logMsg," Unknown received control?\r\n ");
       else {
         sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID);
       }
-      uart_tx_str_sync(logMsg);
+      TRACE(logMsg);
+#endif
       TU_VERIFY(false);
     }
   }
   else if(ep_addr == usbtmc_state.ep_bulk_in)
   {
+#ifdef xDebug
     sprintf(logMsg,"IN\r\n");
-    uart_tx_str_sync(logMsg);
-    TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED);
-    if(usbtmc_state.transfer_size_remaining == 0)
-    {
+    TRACE(logMsg);
+#endif
+    switch(usbtmc_state.state) {
+    case STATE_TX_SHORTED:
+
+      TRACE("IN TX shorted done\r\n");
+
       usbtmc_state.state = STATE_IDLE;
       TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport));
-      TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE));
-    }
-    else if(usbtmc_state.transfer_size_remaining > sizeof(usbtmc_state.devInBuffer))
-    {
-      memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf));
-      usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer);
-      usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer);
-      TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer)));
-    }
-    else // last packet
-    {
-      size_t packetLen = usbtmc_state.transfer_size_remaining;
-      memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining);
-      while((packetLen % 4) != 0)
+      break;
+
+    case STATE_TX_INITIATED:
+      if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf))
       {
-        usbtmc_state.ep_bulk_in_buf[packetLen] = 0;
-        packetLen++;
+        TRACE("IN TX continuing\r\n");
+        memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf));
+        usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer);
+        usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer);
+        usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer);
+        TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer)));
       }
-      usbtmc_state.transfer_size_remaining = 0;
-      usbtmc_state.devInBuffer = NULL;
-      TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen));
+      else // last packet
+      {
+        TRACE("IN TX last packet\r\n");
+        size_t packetLen = usbtmc_state.transfer_size_remaining;
+        memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining);
+        while((packetLen % 4) != 0)
+        {
+          usbtmc_state.ep_bulk_in_buf[packetLen] = 0u;
+          packetLen++;
+        }
+        usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining);
+        usbtmc_state.transfer_size_remaining = 0;
+        usbtmc_state.devInBuffer = NULL;
+        TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen));
+        if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 ))
+        {
+          usbtmc_state.state = STATE_TX_SHORTED;
+        }
+      }
+      return true;
+    case STATE_ABORTING_BULK_IN:
+      // need to send short packet  (ZLP?)
+      TRACE("IN aborting\r\n");
+      TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u));
+      usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED;
+      return true;
+    case STATE_ABORTING_BULK_IN_SHORTED:
+      /* Done. :)*/
+      TRACE("IN shorted\r\n");
+      usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED;
+      return true;
+    default:
+      TRACE("IN unknown\r\n");
+      TU_ASSERT(false);
+      return false;
     }
-    return true;
   }
   else if (ep_addr == usbtmc_state.ep_int_in) {
     // Good?
@@ -505,13 +569,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
 #if (USBTMC_CFG_ENABLE_488)
   uint8_t bTag;
 #endif
+  TRACE("xfer cb\r\n");
 
   if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) &&
       (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) &&
       (request->bRequest == TUSB_REQ_CLEAR_FEATURE) &&
       (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT))
   {
-    uart_tx_str_sync("feature clear\r\n");
+    TRACE("feature clear\r\n");
     if((request->wIndex) == usbtmc_state.ep_bulk_out)
     {
       usmtmcd_app_bulkOut_clearFeature(rhport);
@@ -536,42 +601,124 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
   {
   // USBTMC required requests
   case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT:
-  case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS:
   {
-    TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP
-    TU_VERIFY(request->wLength == 1u);
-    tmcStatusCode = USBTMC_STATUS_FAILED;
-    usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode));
+    usbtmc_initiate_abort_rsp_t rsp = {
+        .bTag = usbtmc_state.lastBulkOutTag,
+    };
+    TRACE("init abort bulk out\r\n");
+    TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface
+    TU_VERIFY(request->wLength == sizeof(rsp));
+    TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out);
+
+    // wValue is the requested bTag to abort
+    if(usbtmc_state.state != STATE_RCV)
+    {
+      rsp.USBTMC_status = USBTMC_STATUS_FAILED;
+      TRACE("init abort bulk out failed\r\n");
+    }
+    else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u))
+    {
+      rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS;
+      TRACE("init abort bulk out not inprogress\r\n");
+    }
+    else
+    {
+      rsp.USBTMC_status = USBTMC_STATUS_SUCCESS;
+      // Check if we've queued a short packet
+      usbtmc_state.state = STATE_ABORTING_BULK_OUT;
+      TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status)));
+      usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
+      TRACE("init abort bulk out success\r\n");
+    }
+    TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp)));
     return true;
   }
-  case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS:
+  case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS:
   {
+    TRACE("init check abort bulk out\r\n");
+    usbtmc_check_abort_bulk_rsp_t rsp = {
+        .USBTMC_status = USBTMC_STATUS_SUCCESS,
+        .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent
+    };
     TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP
-    TU_VERIFY(request->wLength == 1u);
-    usbtmc_get_clear_status_rsp_t clearStatusRsp = {0};
-    tmcStatusCode = USBTMC_STATUS_FAILED;
-    usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode));
+    TU_VERIFY(request->wLength == sizeof(rsp));
+    TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out);
+    TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &(rsp.USBTMC_status)));
+    TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp)));
     return true;
   }
 
   case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN:
   {
-    usbtmc_initiate_abort_rsp_t rsp = {0};
-    uart_tx_str_sync("init abort bulk in\r\n");
-    TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
-    TU_VERIFY(request->wLength == sizeof(tmcStatusCode));
-    TU_VERIFY(request->wIndex == usbtmc_state.ep_int_in);
+    usbtmc_initiate_abort_rsp_t rsp = {
+        .bTag = usbtmc_state.lastBulkInTag,
+    };
+    TRACE("init abort bulk in\r\n");
+    TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface
+    TU_VERIFY(request->wLength == sizeof(rsp));
+    TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in);
     // wValue is the requested bTag to abort
-    usbtmc_state.transfer_size_remaining = 0;
-    usbtmc_state.state = STATE_ABORTING_BULK_IN;
-    TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode));
-    TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode)));
+    if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) &&
+        usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u))
+    {
+      rsp.USBTMC_status = USBTMC_STATUS_SUCCESS;
+      usbtmc_state.transfer_size_remaining = 0;
+      // Check if we've queued a short packet
+      usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ?
+              STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED;
+      TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status)));
+      TRACE("init abort bulk success\r\n");
+    }
+    else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED))
+    { // FIXME: Unsure how to check  if the OUT endpoint fifo is non-empty....
+      rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS;
+      TRACE("init abort bulk in not in progress\r\n");
+    }
+    else
+    {
+      rsp.USBTMC_status = USBTMC_STATUS_FAILED;
+      TRACE("init abort bulk in failed\r\n");
+    }
+    TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp)));
+    return true;
+  }
+
+  case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS:
+  {
+    TRACE("xfer check abort in\r\n");
+    TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP
+    TU_VERIFY(request->wLength == 8u);
+
+    usbtmc_check_abort_bulk_rsp_t rsp =
+    {
+        .USBTMC_status = USBTMC_STATUS_FAILED,
+        .bmAbortBulkIn =
+        {
+            .BulkInFifoBytes = (usbtmc_state.state == STATE_ABORTING_BULK_IN_ABORTED)
+        },
+        .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent,
+    };
+    TU_VERIFY(usbtmcd_app_check_abort_bulk_in(rhport, &rsp));
+    switch(usbtmc_state.state)
+    {
+    case STATE_ABORTING_BULK_IN_ABORTED:
+      rsp.USBTMC_status = USBTMC_STATUS_SUCCESS;
+      break;
+    case STATE_ABORTING_BULK_IN:
+    case STATE_ABORTING_BULK_OUT:
+      rsp.USBTMC_status = USBTMC_STATUS_PENDING;
+      break;
+    default:
+      break;
+    }
+    TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp)));
+
     return true;
   }
 
   case USBTMC_bREQUEST_INITIATE_CLEAR:
     {
-      uart_tx_str_sync("init clear\r\n");
+      TRACE("init clear\r\n");
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       TU_VERIFY(request->wLength == sizeof(tmcStatusCode));
       // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the
@@ -586,7 +733,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
 
   case USBTMC_bREQUEST_CHECK_CLEAR_STATUS:
     {
-      uart_tx_str_sync("check clear\r\n");
+      TRACE("check clear\r\n");
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       usbtmc_get_clear_status_rsp_t clearStatusRsp = {0};
       TU_VERIFY(request->wLength == sizeof(clearStatusRsp));
@@ -600,7 +747,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
       else
       {
         // Let app check if it's clear
-        TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp));
+        TU_VERIFY(usbtmcd_app_check_clear(rhport, &clearStatusRsp));
       }
       if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS)
         usbtmc_state.state = STATE_IDLE;
@@ -610,7 +757,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
 
   case USBTMC_bREQUEST_GET_CAPABILITIES:
     {
-      uart_tx_str_sync("get capabilities\r\n");
+      TRACE("get capabilities\r\n");
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities));
       TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities)));
@@ -620,7 +767,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
 
   case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional
     {
-      uart_tx_str_sync("indicate\r\n");
+      TRACE("indicate\r\n");
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       TU_VERIFY(request->wLength == sizeof(tmcStatusCode));
       TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse);
@@ -633,7 +780,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
     // USB488 required requests
   case USBTMC488_bREQUEST_READ_STATUS_BYTE:
     {
-      uart_tx_str_sync("read stb\r\n");
+      TRACE("read stb\r\n");
       usbtmc_read_stb_rsp_488_t rsp;
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface
@@ -672,7 +819,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
   case USBTMC488_bREQUEST_GO_TO_LOCAL:
   case USBTMC488_bREQUEST_LOCAL_LOCKOUT:
     {
-      uart_tx_str_sync("Unsupported REN/GTL/LLO\r\n");
+      TRACE("Unsupported REN/GTL/LLO\r\n");
       TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
       TU_VERIFY(false);
       return false;
@@ -680,7 +827,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ
 #endif
 
   default:
-    uart_tx_str_sync("Default CTRL handler\r\n");
+    TRACE("Default CTRL handler\r\n");
     TU_VERIFY(false);
     return false;
   }

+ 5 - 1
src/class/usbtmc/usbtmc_device.h

@@ -64,9 +64,13 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in
 bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport);
 void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer
 
+bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult);
+bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult);
 bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult);
 
-bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp);
+bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp);
+bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp);
+bool usbtmcd_app_check_clear(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 usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult);