| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- #define USB_APPLICATION_USBTMC_C
- #include "usb/usb_config.h"
- #include "usb/usb_bridge.h"
- #include "usbd_usbtmc.h"
- #include "usbapp/usb_application_usbtmc.h"
- #include "usbapp/usbtmclib/usbtmclib_basic.h"
- #include "app/led/led.h"
- #include "my_assert.h"
- //----------------------------------------------------------------
- // Refer to:
- // [1] USBTMC Standard, rev. 1.0, 14/04/2003
- // "Universal Serial Bus Test and Measurement Class Specification (USBTMC)"
- // [2] USBTMC-USB488 Standard, rev. 1.0, 14/04/2003
- // "Universal Serial Bus Test and Measurement Class, Subclass USB488 Specification (USBTMC-USB488)
- // [3] IEEE 488.1 Standard, ANSI/IEEE Std 488.1-1987
- // "IEEE Standard Digital Interface, ANSI/IEEE Std 488.1-1987"
- // [4] IEEE 488.2 Standard, revision IEEE Std 488.2-1987
- // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
- // Standard Digital Interface for Programmable Instrumentation"
- // [5] SCPI Specification, revision 1999.0
- // "Standard Commands for Programmable Instruments (SCPI), VERSION 1999.0, May 1999"
- //----------------------------------------------------------------
- #if DEBUG_USBTMC_REQUESTS > 0
- #define MAX_DEBUG_LOG 10
- volatile int gDebugLogIdx = 0;
- volatile int gDebugLogRollover = 0;
- static uint32_t gDebugLog[ MAX_DEBUG_LOG ] = {0};
- void debug_log( uint8_t value, uint16_t value2 )
- {
- if( gDebugLogIdx == 0 )
- {
- memset( gDebugLog, 0, sizeof(gDebugLog) );
- }
- if( gDebugLogIdx >= MAX_DEBUG_LOG )
- {
- memset( gDebugLog, 0, sizeof(gDebugLog) );
- gDebugLogIdx = 0;
- gDebugLogRollover++;
- }
- gDebugLog[ gDebugLogIdx++ ] = (((uint32_t)value2) << 16) | value;
- }
- #define DEBUG_LOG_STATE_INITABIN 0x01
- #define DEBUG_LOG_STATE_CHKSTATUS_PEND 0x02
- #define DEBUG_LOG_STATE_CHKSTATUS_OK 0x03
- #define DEBUG_LOG_STATE_DATAIN 0x04
- #endif
- //----------------------------------------------------------------
- #define INDICATOR_PULSE_REQUEST_SUPPORT (CONFIG_LEDS) // enable INDICATOR_PULSE if CONFIG_LEDS is available
- //----------------------------------------------------------------
- static int8_t fUSBTMCProto_Init();
- static int8_t fUSBTMCProto_DeInit();
- static void fUSBTMCProto_Reset();
- static bool fUSBTMCProto_Setup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success );
- static size_t fUSBTMCProto_ControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining );
- static size_t fUSBTMCProto_ControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining );
- const sUSBAppEntry_Control_t usbapplication_USBTMC_control = {
- .fUsbInit = fUSBTMCProto_Init,
- .fUsbDeInit = fUSBTMCProto_DeInit,
- .fUsbSetup = fUSBTMCProto_Setup,
- .fUsbCtlEpRx = fUSBTMCProto_ControlRx,
- .fUsbCtlEpTx = fUSBTMCProto_ControlTx,
- .fResetEvent = fUSBTMCProto_Reset,
- };
- // USBTMC_datain_beginsend()
- // Begin the transmission using DataIN handler virtual call.
- // Due to the hardware does not support NAK-sent-interrupt, it is
- // required to initiate the first packet sending to start TX-flow (DataIN).
- // This function issues the first packet sending using virtual DataIN event.
- uint8_t USBTMC_datain_beginsend( uint8_t epnum );
- // USBTMC_datain_sendprepared()
- // Begin the transmission using already prepared TX-transfer.
- // Due to the hardware does not support NAK-sent-interrupt, it is
- // required to initiate the first packet sending to start TX-flow (DataIN).
- // This function issues the first packet sending using virtual DataIN event.
- uint8_t USBTMC_datain_sendprepared( uint8_t epnum );
- // USBTMC_datain_zerosend()
- // Queue zero packet in BulkIN EP without calling TX-handler
- uint8_t USBTMC_datain_zerosend( uint8_t epnum );
- static bool fUSBTMCProto_DataRxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * rx );
- static bool fUSBTMCProto_DataTxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * tx );
- static bool fUSBTMCProto_DataErrHandler( uint8_t bEpLogAddress, uint32_t error );
- static bool fUSBTMCProto_IntTxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * tx );
- static bool fUSBTMCProto_IntErrHandler( uint8_t bEpLogAddress, uint32_t error );
- // @usbapplication_USBTMC_dataapp
- // Data channel handler descriptor
- const sUSBAppEntry_Data_t usbapplication_USBTMC_dataapp = {
- .fDataInitHandler = NULL,
- .fDataRxHandler = fUSBTMCProto_DataRxHandler,
- .fDataTxHandler = fUSBTMCProto_DataTxHandler,
- .fDataErrHandler = fUSBTMCProto_DataErrHandler,
- .fDataDeInitHandler = NULL,
- };
- // @usbapplication_USBTMC_intapp
- // Interrupt channel handler descriptor
- const sUSBAppEntry_Data_t usbapplication_USBTMC_intapp = {
- .fDataInitHandler = NULL,
- .fDataRxHandler = NULL, // no data receiving is expected
- .fDataTxHandler = fUSBTMCProto_IntTxHandler,
- .fDataErrHandler = fUSBTMCProto_IntErrHandler,
- .fDataDeInitHandler = NULL,
- };
- //===========================================================================================
- #if INDICATOR_PULSE_REQUEST_SUPPORT
- // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
- // Refer to @sUSBTMC_GetCapabilities_Response_t
- #define USBTMC_IFACE_CAPABILITIES (USBTMC_IFACE_CAPABILITIES_INDICATOR_PULSE) // Indicator Pulse request is supported :)
- #else
- // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
- // Refer to @sUSBTMC_GetCapabilities_Response_t
- #define USBTMC_IFACE_CAPABILITIES (0) // No Indicator Pulse request supported :(
- #endif
- // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
- // Refer to @sUSBTMC_GetCapabilities_Response_t
- #define USBTMC_DEVICE_CAPABILITIES (0)
- // 4.2.2 GET_CAPABILITIES, table 8, [2]
- // Refer to @sUSB488_GetCapabilities_Response_t
- #define USB488_IFACE_CAPABILITIES (USB488_IFACE_CAPABILITIES_4882IF)
- // 4.2.2 GET_CAPABILITIES, table 8, [2]
- // Refer to @sUSB488_GetCapabilities_Response_t
- #define USB488_DEVICE_CAPABILITIES (USB488_DEVICE_CAPABILITIES_SERVICE_REQUEST | USB488_DEVICE_CAPABILITIES_SCPI)
- // ===================================================================================
- // @sUsbTmcContext
- // Local module context variables
- static struct {
- //sUSBTransfer_t * xBulkOutTransfer; // data buffer for Bulk-Out transfer
- //sUSBTransfer_t * xBulkInTransfer; // data buffer for Bulk-In transfer
- const USBD_DescriptorsTypeDef * xDescHandlers; // class GetDescriptor handlers set
- bool bInitiateBulkOutAbort; // Initiate BulkOut abort request flag: true if received, false otherwise
- bool bInitiateBulkInAbort; // Initiate BulkIn abort request flag: true if received, false otherwise
- bool bInitiateClear; // Initiate Clear request flag: true if received, false otherwise
- struct
- {
- union
- {
- uint8_t rawBytesResponse[1]; // byte-array access to avoid casting and warnings
- sUSBTMC_InitiateAbortBulkInOut_Response_t responseInitiateAbortBulkX;
- sUSBTMC_CheckAbortBulkOut_Response_t responseCheckAbortBulkOut;
- sUSBTMC_CheckAbortBulkIn_Response_t responseCheckAbortBulkIn;
- sUSBTMC_InitiateClear_Response_t responseInitiateClear;
- sUSBTMC_CheckClear_Response_t responseCheckClear;
- sUSBTMC_GetCapabilities_Response_t responseGetCapabilities;
- sUSBTMC_IndicatorPulse_Response_t responseIndicatorPulse;
- sUSBTMC_USB488_ReadStatusByte_Response_t responseUsb488ReadStatusByte;
- };
- }
- tmpSetup; // temporary variables are valid during single request: Setup -> Rx/Tx
- } sUsbTmcContext;
- // ===================================================================================
- static int8_t fUSBTMCProto_Init()
- {
- // Check the Control-OUT buffer size
- // If the buffer size is less than the maximum packet size to be sent:
- if( usbd_usbtmc_get_control_tx_transfer_size() < sizeof( sUsbTmcContext.tmpSetup ) )
- {
- // Error: the buffer size is less than the maximum packet size to be sent.
- // See @fUSBTMCProto_ControlTx for details.
- // The function @fUSBTMCProto_ControlTx does not support multi-packet mode
- return -1; // error:
- }
- // Register Bulk-Data handler -> @usbapplication_USBTMC_dataapp
- usb_bridge_register_dataapp( USBTMC_BULKIO_EP, &usbapplication_USBTMC_dataapp );
- // Register Interrupt-Data handler -> @usbapplication_USBTMC_intapp
- usb_bridge_register_dataapp( USBTMC_INTIO_EP, &usbapplication_USBTMC_intapp );
- sUsbTmcContext.bInitiateBulkOutAbort = false;
- sUsbTmcContext.bInitiateBulkInAbort = false;
- sUsbTmcContext.bInitiateClear = false;
- //sUsbTmcContext.xBulkOutTransfer = ;
- //sUsbTmcContext.xBulkInTransfer = USBD_USBTMC_GetDataTxTransferHandle();
- sUsbTmcContext.xDescHandlers = USBD_USBTMC_GetDescriptorHandlers();
- if( tmclib_status_success != tmclib_init(
- USBD_USBTMC_GetDataRxTransferHandle(),
- USBD_USBTMC_GetDataTxTransferHandle(),
- USBD_USBTMC_GetInterruptTxTransferHandle() )
- )
- {
- return -1; // error
- }
- return 0;
- }
- // ===================================================================================
- static int8_t fUSBTMCProto_DeInit()
- {
- usb_bridge_unregister_dataapp( USBTMC_BULKIO_EP );
- usb_bridge_unregister_dataapp( USBTMC_INTIO_EP );
- tmclib_deinit();
- return 0;
- }
- // ===================================================================================
- // @fUSBTMCProto_Reset
- // USB Bus reset event
- static void fUSBTMCProto_Reset()
- {
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkout(0, true) );
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkin(0, true) );
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_interruptin(0, true) );
- sUsbTmcContext.bInitiateBulkOutAbort = false;
- sUsbTmcContext.bInitiateBulkInAbort = false;
- sUsbTmcContext.bInitiateClear = false;
- }
- // ===================================================================================
- // @fUSBTMCProto_Setup
- // USBTMC protocol, USB Setup Handler
- // Processes the class requests and reacts to some standard requests
- static bool fUSBTMCProto_Setup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success )
- {
- // Check the request type
- switch( pSetup->bmRequest & USB_REQ_TYPE_MASK )
- {
- // Standard request: this call is performed BEFORE the ENDPOINT clearing by core
- case USB_REQ_TYPE_STANDARD:
- {
- // Check request ID:
- switch( pSetup->bRequest )
- {
- // USBTMC must process CLEAR_FEATURE standard request with type ENDPOINT_HALT:
- // see section 4.1 "Standard requests", [1]
- case USB_REQ_CLEAR_FEATURE:
- {
- // process ENDPOINT_HALT request type:
- if( USB_FEATURE_EP_HALT == pSetup->wValue )
- {
- // Host tries to restore synchronization: clear stalled endpoint
- // check the endpoint address:
- switch( pSetup->wIndex )
- {
- case USBTMC_BULKOUT_EP:
- // section 4.1.1.1 "USBTMC interface Bulk-OUT endpoints", [1]
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkout(0, true) ); // forced interrupt current transfer
- // Clear EP and reset the buffer, restart receiving
- USBD_USBTMC_ClearEP( USBTMC_BULKOUT_EP );
- return true; // pass this request, core does the job
- break;
- case USBTMC_BULKIN_EP:
- // section 4.1.1.2 "USBTMC interface Bulk-IN endpoints", [1]
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkin(0, true) ); // forced interrupt current transfer
- // Clear EP and reset the buffer
- USBD_USBTMC_NakEP( USBTMC_BULKIN_EP ); // set NAK instead of VALID
- return true; // pass this request, core does the job
- break;
- case USBTMC_INTERRUPTIN_EP:
- // [1] has no information about such event
- // Do processing in formal way: abort the transfer and set NAK state over EP
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_interruptin(0, true) ); // forced interrupt current transfer
- // Clear EP and reset the buffer
- USBD_USBTMC_NakEP( USBTMC_INTERRUPTIN_EP ); // set NAK instead of VALID
- return true; // pass this request, core does the job
- break;
- }
- }
- }
- break;
- }
- }
- break;
- // see 4.2.1 "USBTMC requests", [1]
- case USB_REQ_TYPE_CLASS:
- {
- // In accordance with USBTMC standard [1], the code "STATUS_SUCCESS" means
- // the device queued the INITIATE request to be performed.
- // @bInitiateBulkInAbort must remember if such request is queued in case
- // the host will try to queue another request. If host performs another
- // request, the device must discard the response for previously queued request
- // and queue new request only if the previous request is already done.
- // But if the device executes this request synchroniusly, there no previously
- // request pending, and the request is always done.
- // In other words, @bInitiateBulkInAbort shows only if is there the response
- // prepared for previously INITIATE request or not for next CHECK_STATUS request.
- // 4.2.1.1 "USBTMC split transactions", point 3, [1]
- if( sUsbTmcContext.bInitiateBulkOutAbort &&
- (eUSBTMC_INITIATE_ABORT_BULK_OUT == pSetup->bRequest ||
- eUSBTMC_INITIATE_CLEAR == pSetup->bRequest ) )
- {
- // reset the prepared response: comes down to reseting the flag
- sUsbTmcContext.bInitiateBulkOutAbort = false;
- }
- // ---
- // 4.2.1.1 "USBTMC split transactions", point 3, [1]
- if( sUsbTmcContext.bInitiateBulkInAbort &&
- (eUSBTMC_INITIATE_ABORT_BULK_IN == pSetup->bRequest ||
- eUSBTMC_INITIATE_CLEAR == pSetup->bRequest ) )
- {
- // reset the prepared response: comes down to reseting the flag
- sUsbTmcContext.bInitiateBulkInAbort = false;
- }
- // ---
- // 4.2.1.1 "USBTMC split transactions", point 3, [1]
- if( sUsbTmcContext.bInitiateClear && (eUSBTMC_CHECK_CLEAR_STATUS != pSetup->bRequest) )
- {
- // reset the prepared response: comes down to reseting the flag
- sUsbTmcContext.bInitiateClear = false;
- }
- // ---
- // Check request ID:
- switch( pSetup->bRequest )
- {
- // Aborts a Bulk-OUT transfer.
- // see 4.2.1.2 "INITIATE_ABORT_BULK_OUT", [1]
- case eUSBTMC_INITIATE_ABORT_BULK_OUT:
- {
- if( pSetup->wIndex != USBTMC_BULKOUT_EP )
- return false; // Error, 4.2.1.2 INITIATE_ABORT_BULK_OUT, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX) );
- // preserve the bTag to put the value into the response (fUSBTMCProto_ControlRx)
- tmclib_bulkout_gettag_latest( &sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.bTag );
- // try to abort BulkOut transfer with the specified bTag
- if( tmclib_status_success == tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkout((uint8_t)pSetup->wValue, false) ) )
- {
- // Halt the BulkOut endpoint to interrupt the transfer, 4.2.1.2, table 18 [1]
- USBD_USBTMC_StallEP( USBTMC_BULKOUT_EP );
- sUsbTmcContext.bInitiateBulkOutAbort = true; // INITIATE response prepared
- sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.USBTMC_status = eUSBTMC_STATUS_SUCCESS;
- }
- else
- {
- // error: transfer isn't in progress
- sUsbTmcContext.bInitiateBulkOutAbort = false; // INITIATE response not prepared
- sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.USBTMC_status = eUSBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS;
- }
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Returns the status of the previously sent INITIATE_ABORT_BULK_OUT request.
- case eUSBTMC_CHECK_ABORT_BULK_OUT_STATUS:
- {
- if( pSetup->wIndex != USBTMC_BULKOUT_EP )
- return false; // Error, 4.2.1.3 CHECK_ABORT_BULK_OUT_STATUS, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut) );
- if( sUsbTmcContext.bInitiateBulkOutAbort )
- {
- uint32_t NBYTES_RXD = 0;
- // retireve number of received bytes during last transfer
- tmclib_bulkout_getcounter( &NBYTES_RXD );
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut.NBYTES_RXD = NBYTES_RXD;
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfully aborted
- // clear the request indicator
- sUsbTmcContext.bInitiateBulkOutAbort = false;
- }
- else
- {
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut.USBTMC_status = eUSBTMC_STATUS_SPLIT_NOT_IN_PROGRESS; // not INITIATE request received
- }
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Aborts a Bulk-IN transfer.
- case eUSBTMC_INITIATE_ABORT_BULK_IN:
- {
- if( pSetup->wIndex != USBTMC_BULKIN_EP )
- return false; // Error, 4.2.1.4 INITIATE_ABORT_BULK_IN, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX) );
- // preserve the bTag to put the value into the response (fUSBTMCProto_ControlTx)
- tmclib_bulkin_gettag_latest( &sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.bTag );
- // try to abort BulkIn transfer with the specified bTag
- if( tmclib_status_success == tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkin((uint8_t)pSetup->wValue, false) ) )
- {
- // Restore endpoint, BulkIN EP must not be halted, due to:
- // - 4.2.1.4, table 26;
- // - 3.3.2.4 "Halt", table 12
- USBD_USBTMC_NakEP( USBTMC_BULKIN_EP );
- // [1], 4.2.1.4 INITIATE_ABORT_BULK_IN, Table 26
- // "If a short packet has not been queued, queue a shortpacket to terminate the transfer."
- // "If a short packet can not yet be queued, wait until a short packet can be queued."
- USBTMC_datain_zerosend( USBTMC_BULKIN_EP ); // queue a short packet to terminate transfer
- #if DEBUG_USBTMC_REQUESTS > 0
- debug_log( DEBUG_LOG_STATE_INITABIN, 0 );
- #endif
- sUsbTmcContext.bInitiateBulkInAbort = true; // INITIATE response prepared
- sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.USBTMC_status = eUSBTMC_STATUS_SUCCESS;
- }
- else
- {
- // error: transfer isn't in progress
- sUsbTmcContext.bInitiateBulkInAbort = false; // INITIATE response not prepared
- sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX.USBTMC_status = eUSBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS;
- }
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Returns the status of the previously sent INITIATE_ABORT_BULK_IN request.
- case eUSBTMC_CHECK_ABORT_BULK_IN_STATUS:
- {
- if( pSetup->wIndex != USBTMC_BULKIN_EP )
- return false; // Error, 4.2.1.5 CHECK_ABORT_BULK_IN_STATUS, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn) );
- if( sUsbTmcContext.bInitiateBulkInAbort )
- {
- uint32_t NBYTES_TXD = 0;
- // retireve number of transferred bytes during last transfer
- tmclib_bulkin_getcounter( &NBYTES_TXD );
- if( ! USBD_USBTMC_GetTxQueuedSize( USBTMC_BULKIN_EP, NULL ) )
- {
- // [1]. 4.2.1.5 CHECK_ABORT_BULK_IN_STATUS, Table 29 -- CHECK_ABORT_BULK_IN_STATUS USBTMC_status values
- // The device must set NBYTES_TXD to the appropriate value.
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.NBYTES_TXD = NBYTES_TXD;
- // BulkIN transfer already reset, FIFO is empty, so bmAbortBulkIn.D0 is zero.
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.bmAbortBulkIn = 0;
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfully aborted
- #if DEBUG_USBTMC_REQUESTS > 0
- debug_log( DEBUG_LOG_STATE_CHKSTATUS_OK, 0 );
- #endif
- // clear the request status
- sUsbTmcContext.bInitiateBulkInAbort = false;
- }
- else
- {
- // [1]. 4.2.1.5 CHECK_ABORT_BULK_IN_STATUS, Table 29 -- CHECK_ABORT_BULK_IN_STATUS USBTMC_status values
- // The device must set NBYTES_TXD = 0x00000000.
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.NBYTES_TXD = 0;
- // BulkIN transfer already reset, but FIFO is not empty and short packet must be send, so bmAbortBulkIn.D0 is set.
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.bmAbortBulkIn = 1;
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.USBTMC_status = eUSBTMC_STATUS_PENDING; // successfully aborted
- #if DEBUG_USBTMC_REQUESTS > 0
- debug_log( DEBUG_LOG_STATE_CHKSTATUS_PEND, 0 );
- #endif
- // keep the request status true
- sUsbTmcContext.bInitiateBulkInAbort = true;
- }
- }
- else
- {
- sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn.USBTMC_status = eUSBTMC_STATUS_SPLIT_NOT_IN_PROGRESS; // not INITIATE request received
- }
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Clears all previously sent pending and
- // unprocessed Bulk-OUT USBTMC message
- // content and clears all pending Bulk-IN transfers
- // from the USBTMC interface.
- case eUSBTMC_INITIATE_CLEAR:
- {
- //#error sUsbTmcContext.xDescHandler
- if( pSetup->wIndex != USB_TMC_INTERFACE_VALUE )
- return false; // Error, see 4.2.1.6 INITIATE_CLEAR, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseInitiateClear) );
- // 4.2.1.6 INITIATE_CLEAR, [2]
- // Halt Bulk-OUT EP and clear FIFO
- USBD_USBTMC_StallEP( USBTMC_BULKOUT_EP );
- // Abort bulk-out transfer and clear the state
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkout(0, true) );
- // 4.2.1.6 INITIATE_CLEAR, [2]
- // Remove all queued packets and clear FIFO for BulkIn
- // Set NAK status to interrupt the transfer and clear buffer
- USBD_USBTMC_NakEP( USBTMC_BULKIN_EP );
- // Abort bulk-in transfer and clear the state
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_bulkin(0, true) );
- // --------------- Non-standard -----------------------------------------------------
- // There no recomendations for Interrupt-IN EP during INITIATE_CLEAR request
- // But it is good to restore the initial state to clear Interrupt-IN EP here.
- // Set NAK state for Interrupt-IN EP
- USBD_USBTMC_NakEP( USBTMC_INTERRUPTIN_EP );
- // abort interrupt-in transfer
- tmclib_generic_event( COMPOUND_tmclib_event_context_abort_interruptin(0, true) );
- // ----------------------------------------------------------------------------------
- // Clean up USBTMC and SCPI module
- tmclib_generic_event( COMPOUND_tmclib_event_context_device_clear(false) );
- sUsbTmcContext.tmpSetup.responseInitiateClear.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfully cleared
- sUsbTmcContext.bInitiateClear = true;
- #if DEBUG_USB > 0 // SCPI debug only
- extern void spy_tx_log_cleanup();
- spy_tx_log_cleanup();
- #endif
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Returns the status of the previously sent INITIATE_CLEAR request.
- case eUSBTMC_CHECK_CLEAR_STATUS:
- {
- if( pSetup->wIndex != USB_TMC_INTERFACE_VALUE )
- return false; // Error, see 4.2.1.7 CHECK_CLEAR_STATUS, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseCheckClear) );
- // [1], 4.2.1.7 CHECK_CLEAR_STATUS
- if( sUsbTmcContext.bInitiateClear )
- {
- sUsbTmcContext.tmpSetup.responseCheckClear.bmClear = 0; // all FIFOs are cleared, bmClear.D0 is zero
- sUsbTmcContext.tmpSetup.responseCheckClear.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfully aborted
- // clear the request indicator
- sUsbTmcContext.bInitiateClear = false;
- }
- else
- {
- sUsbTmcContext.tmpSetup.responseCheckClear.USBTMC_status = eUSBTMC_STATUS_SPLIT_NOT_IN_PROGRESS; // not INITIATE request received
- }
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // Returns attributes and capabilities of the USBTMC interface.
- case eUSBTMC_GET_CAPABILITIES:
- {
- if( pSetup->wIndex != USB_TMC_INTERFACE_VALUE )
- return false; // Error, see 4.2.1.8 GET_CAPABILITIES, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseGetCapabilities) );
- sUsbTmcContext.tmpSetup.responseGetCapabilities.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfull
- sUsbTmcContext.tmpSetup.responseGetCapabilities.bcdUSBTMC = USBTMC_VERSION;
- sUsbTmcContext.tmpSetup.responseGetCapabilities.ifaceCaps = USBTMC_IFACE_CAPABILITIES;
- sUsbTmcContext.tmpSetup.responseGetCapabilities.devCaps = USBTMC_DEVICE_CAPABILITIES;
- sUsbTmcContext.tmpSetup.responseGetCapabilities.usb488.bcdUSB488 = USB488_VERSION;
- sUsbTmcContext.tmpSetup.responseGetCapabilities.usb488.ifaceCaps = USB488_IFACE_CAPABILITIES;
- sUsbTmcContext.tmpSetup.responseGetCapabilities.usb488.devCaps = USB488_DEVICE_CAPABILITIES;
- return true; // pass this request -> fUSBTMCProto_ControlTx
- }
- break;
- // A mechanism to turn on an activity indicator for
- // identification purposes. The device indicates
- // whether or not it supports this request in the
- // GET_CAPABILITIES response packet.
- case eUSBTMC_INDICATOR_PULSE:
- {
- #if INDICATOR_PULSE_REQUEST_SUPPORT
- if( pSetup->wIndex != USB_TMC_INTERFACE_VALUE )
- return false; // Error, see 4.2.1.9 INDICATOR_PULSE, [1]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseIndicatorPulse) );
- sUsbTmcContext.tmpSetup.responseIndicatorPulse.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfull
- // Perform LED Signaling
- LEDHandle.SetMode( eLedMode_Signaling );
- return true; // pass this request -> fUSBTMCProto_ControlTx
- #else
- return false; // Error, see 4.2.1.9 INDICATOR_PULSE, [1]
- #endif
- }
- break;
- #warning SCPI Add "default:" and route to USB488 dependent request processor (4.3 USB488 subclass specific requests)
- // Allows to read the status byte using class request
- case eUSBTMC_USB488_READ_STATUS_BYTE:
- {
- if( pSetup->wIndex != USB_TMC_INTERFACE_VALUE )
- return false; // Error, see 4.3.1 READ_STATUS_BYTE, [2]
- if( pSetup->wValue & 0x80 ||
- (pSetup->wValue & 0x7F) < 2 )
- return false; // Error, see 4.3.1 READ_STATUS_BYTE, [2]
- // zero init the response bytes
- memset( sUsbTmcContext.tmpSetup.rawBytesResponse, 0, sizeof(sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte) );
- sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte.USBTMC_status = eUSBTMC_STATUS_SUCCESS; // successfull
- sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte.bTag = pSetup->wValue & 0x7F;
- // 4.3.1.2 Response format for USB488 interfaces with an Interrupt-IN endpoint, [2]
- sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte.bStatusByte = 0; // forward set to constant
- // Set NAK state for Interrupt-IN EP
- USBD_USBTMC_NakEP( USBTMC_BULKIN_EP );
- // Initiate Interrupt-In transfer
- tmclib_generic_event( COMPOUND_tmclib_event_context_interruptin_start( eventCtx, NULL, sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte.bTag ) );
- return true; // pass this request -> fUSBTMCProto_ControlTx
-
- }
- break;
- }
- }
- break;
- }
- return false;
- }
- // ===================================================================================
- // fUSBTMCProto_ControlRx()
- // The setup packet has been processed and filtered already in @fUSBTMCProto_Setup()
- // This function receives the SETUP packet DATA payload
- static size_t fUSBTMCProto_ControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining )
- {
- // No incoming packets expected via CONTROL-transfer
- return 0;
- }
- // ===================================================================================
- // fUSBTMCProto_ControlTx()
- // The setup packet has been processed and filtered already in @fUSBTMCProto_Setup()
- // This function queues the response only.
- static size_t fUSBTMCProto_ControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining )
- {
- // All the followed requests require the response.
- // To simplify the implementation this function requires
- // the control endpoint MAX_PACKET_SIZE to be not less than
- // the higest incoming packet.
- // This function does not support multi-packet mode, the buffer size
- // must have enough space to place the biggest possible response.
- // see @fUSBTMCProto_Init for details.
- size_t bytes = 0;
- if( 0 != idx )
- return 0; // multi-packet transaction: wtf? see the comment above
- // Check the request type
- switch( pSetup->bmRequest & USB_REQ_TYPE_MASK )
- {
- // see 4.2.1 "USBTMC requests", [1]
- case USB_REQ_TYPE_CLASS:
- {
- // Check request ID:
- switch( pSetup->bRequest )
- {
- case eUSBTMC_INITIATE_ABORT_BULK_OUT: // Aborts a Bulk-OUT transfer.
- case eUSBTMC_INITIATE_ABORT_BULK_IN: // Aborts a Bulk-IN transfer.
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX) == bytesRemaining ) // 4.2.1.2, Table 19, [1]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseInitiateAbortBulkX) );
- }
- }
- break;
- // Returns the status of the previously sent INITIATE_ABORT_BULK_OUT request.
- case eUSBTMC_CHECK_ABORT_BULK_OUT_STATUS:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut) == bytesRemaining ) // 4.2.1.3, Table 22, [1]
- {
- bytes += usb_write_transfer( tx, &sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkOut) );
- }
- }
- break;
- // Returns the status of the previously sent INITIATE_ABORT_BULK_IN request.
- case eUSBTMC_CHECK_ABORT_BULK_IN_STATUS:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn) == bytesRemaining ) // 4.2.1.5, Table 28, [1]
- {
- bytes += usb_write_transfer( tx, &sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseCheckAbortBulkIn) );
- }
- }
- break;
- // Clears all previously sent pending and
- // unprocessed Bulk-OUT USBTMC message
- // content and clears all pending Bulk-IN transfers
- // from the USBTMC interface.
- case eUSBTMC_INITIATE_CLEAR:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseInitiateClear) == bytesRemaining ) // 4.2.1.6, Table 30, [1]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseInitiateClear) );
- }
- }
- break;
- // Returns the status of the previously sent INITIATE_CLEAR request.
- case eUSBTMC_CHECK_CLEAR_STATUS:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseCheckClear) == bytesRemaining ) // 4.2.1.7, Table 34, [1]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseCheckClear) );
- }
- }
- break;
- // Returns attributes and capabilities of the USBTMC interface.
- case eUSBTMC_GET_CAPABILITIES:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseGetCapabilities) == bytesRemaining ) // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseGetCapabilities) );
- }
- }
- break;
- // A mechanism to turn on an activity indicator for
- // identification purposes. The device indicates
- // whether or not it supports this request in the
- // GET_CAPABILITIES response packet.
- case eUSBTMC_INDICATOR_PULSE:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseIndicatorPulse) == bytesRemaining ) // 4.2.1.9 INDICATOR_PULSE, table 39, [1]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseIndicatorPulse) );
- }
- }
- break;
- // Allows to read the status byte using class request
- case eUSBTMC_USB488_READ_STATUS_BYTE:
- {
- if( sizeof(sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte) == bytesRemaining ) // 4.3.1 READ_STATUS_BYTE, [2]
- {
- bytes += usb_write_transfer( tx, sUsbTmcContext.tmpSetup.rawBytesResponse, sizeof(sUsbTmcContext.tmpSetup.responseUsb488ReadStatusByte) );
- // need to force-call Interrupt-IN handler (fUSBTMCProto_IntTxHandler();)
- USBTMC_datain_beginsend( USBTMC_INTERRUPTIN_EP );
- }
- }
- break;
- }
- }
- break;
- }
- return bytes;
- }
- // ===================================================================================
- // @fUSBTMCProto_DataRxHandler
- // USBTMC Data Incoming handler (Bulk-Out)
- static bool fUSBTMCProto_DataRxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * rx )
- {
- eTMCLibStatus_t status;
- bulk_out_label:
- status = tmclib_generic_event( COMPOUND_tmclib_event_context_bulkout( eventCtx, rx ) );
- if( USBTMC_NOTERROR(status) )
- {
- if( USBTMC_WARNING(status) )
- {
- switch( status )
- {
- case tmclib_status_invalid_param:
- {
- my_assert( status != tmclib_status_invalid_param ); // 'tmclib_bulkout_event' SHALL never return 'tmclib_status_invalid_param'
- }
- break;
- case tmclib_status_in_progress:
- {
- my_assert( status != tmclib_status_in_progress ); // 'tmclib_bulkout_event' never returns 'tmclib_status_in_progress'
- }
- break;
- case tmclib_status_again:
- {
- // there is some data in @rx transfer required to be processed
- }
- goto bulk_out_label;;
- case tmclib_status_need_data:
- {
- my_assert( status != tmclib_status_need_data ); // 'tmclib_bulkout_event' never returns 'tmclib_status_need_data'
- }
- break;
- case tmclib_status_not_in_progress:
- {
- my_assert( status != tmclib_status_not_in_progress ); // 'tmclib_bulkout_event' never returns 'tmclib_status_not_in_progress'
- }
- break;
- case tmclib_status_no_more_data:
- {
- my_assert( status != tmclib_status_no_more_data ); // 'tmclib_bulkout_event' never returns 'tmclib_status_no_more_data'
- }
- break;
- case tmclib_status_need_read:
- {
- // normal operation
- uint8_t rc = USBTMC_datain_sendprepared( USBTMC_BULKIN_EP );
- (void)rc;
- }
- break;
- default:
- my_assert( status == tmclib_status_success ); // 'tmclib_bulkout_event' returns undefined code
- }
- }
- }
- else
- {
- if( status == tmclib_status_halt_bulkin )
- {
- // 3.3.2.4 Halt, [1]
- USBD_USBTMC_StallEP( USBTMC_BULKIN_EP );
- }
- // 3.2.2.3 Bulk-OUT transfer protocol errors, [1]
- // 3.2.2.4 Halt, [1]
- USBD_USBTMC_StallEP( USBTMC_BULKOUT_EP );
- }
- return USBTMC_NOTERROR(status);
- }
- // ===================================================================================
- // @fUSBTMCProto_DataTxHandler
- // USBTMC Data Outcoming handler (Bulk-IN)
- // Note: User shall reset Short-Packet indicator using @usb_transfer_modify_flags
- // ... routine to avoid sending short packet in case no data queued into the transfer
- // ... after successful call (return true with empty transfer)
- static bool fUSBTMCProto_DataTxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * tx )
- {
- eTMCLibStatus_t status = tmclib_generic_event( COMPOUND_tmclib_event_context_bulkin( eventCtx, tx ) );
- if( USBTMC_NOTERROR(status) )
- {
- if( USBTMC_WARNING(status) )
- {
- switch( status )
- {
- case tmclib_status_invalid_param:
- {
- my_assert( status != tmclib_status_invalid_param ); // 'tmclib_bulkin_event' SHALL never return 'tmclib_status_invalid_param'
- }
- break;
- case tmclib_status_in_progress:
- {
- my_assert( status != tmclib_status_in_progress ); // 'tmclib_bulkin_event' never returns 'tmclib_status_in_progress'
- }
- break;
- case tmclib_status_again:
- {
- my_assert( status != tmclib_status_again ); // 'tmclib_bulkin_event' never returns 'tmclib_status_again'
- }
- break;
- case tmclib_status_need_data:
- {
- my_assert( status != tmclib_status_need_data ); // 'tmclib_bulkin_event' never returns 'tmclib_status_need_data'
- }
- break;
- case tmclib_status_not_in_progress:
- case tmclib_status_no_more_data: // need set NAK condition over EP
- {
- // cleanup EP IN to provide NAK response in next IN transaction
- USBD_USBTMC_NakEP( USBTMC_BULKIN_EP );
- }
- break;
- case tmclib_status_need_read:
- {
- // normal operation
- }
- break;
- default:
- my_assert( status == tmclib_status_success ); // 'tmclib_bulkin_event' returns undefined code
- }
- }
- return true;
- }
- return false;
- }
- // ===================================================================================
- // @fUSBTMCProto_DataErrHandler
- // USBTMC Error handler for Data channel
- static bool fUSBTMCProto_DataErrHandler( uint8_t bEpLogAddress, uint32_t error )
- {
- #warning BulkOut -> Stall
- return true; // bibb
- }
- // ===================================================================================
- // @fUSBTMCProto_IntTxHandler
- // USBTMC Interrupt Outcoming handler (Interrupt-IN)
- static bool fUSBTMCProto_IntTxHandler( uint8_t bEpLogAddress, sUSBTransfer_t * ntx )
- {
- eTMCLibStatus_t status = tmclib_generic_event( COMPOUND_tmclib_event_context_interruptin( eventCtx, ntx ) );
- if( USBTMC_NOTERROR(status) )
- {
- switch( status )
- {
- case tmclib_status_invalid_param:
- {
- my_assert( status != tmclib_status_invalid_param ); // 'tmclib_interruptin_event' SHALL never return 'tmclib_status_invalid_param'
- }
- break;
- case tmclib_status_in_progress:
- {
- my_assert( status != tmclib_status_in_progress ); // 'tmclib_interruptin_event' never returns 'tmclib_status_in_progress'
- }
- break;
- case tmclib_status_again:
- {
- my_assert( status != tmclib_status_again ); // 'tmclib_interruptin_event' never returns 'tmclib_status_again'
- }
- break;
- case tmclib_status_need_data:
- {
- my_assert( status != tmclib_status_need_data ); // 'tmclib_interruptin_event' never returns 'tmclib_status_need_data'
- }
- break;
- case tmclib_status_not_in_progress:
- case tmclib_status_no_more_data: // need set NAK condition over EP
- {
- // cleanup EP IN to provide NAK response in next IN transaction
- USBD_USBTMC_NakEP( USBTMC_INTERRUPTIN_EP );
- }
- break;
- case tmclib_status_success:
- case tmclib_status_need_read:
- {
- // normal operation
- }
- break;
- default:
- my_assert( status == tmclib_status_success ); // 'tmclib_interruptin_event' returns undefined code
- }
- return true;
- }
- return false;
- }
- // ===================================================================================
- // @fUSBTMCProto_IntErrHandler
- // USBTMC Error handler for Interrupt channel
- static bool fUSBTMCProto_IntErrHandler( uint8_t bEpLogAddress, uint32_t error )
- {
- return true; // bibb
- }
- // ===================================================================================
- // USBTMC_datain_beginsend()
- // Begin the transmission using DataIN handler virtual call.
- // Due to the hardware does not support NAK-sent-interrupt, it is
- // required to initiate the first packet sending to start TX-flow (DataIN).
- // This function issues the first packet sending using virtual DataIN event.
- //
- uint8_t USBTMC_datain_beginsend( uint8_t epnum )
- {
- // issue virtual DataIN event:
- return USBD_USBTMC_DataIn_BeginSend( epnum, false );
- }
- // ===================================================================================
- // USBTMC_datain_sendprepared()
- // Begin the transmission using already prepared TX-transfer.
- // Due to the hardware does not support NAK-sent-interrupt, it is
- // required to initiate the first packet sending to start TX-flow (DataIN).
- // This function issues the first packet sending using virtual DataIN event.
- //
- uint8_t USBTMC_datain_sendprepared( uint8_t epnum )
- {
- // issue virtual DataIN event:
- return USBD_USBTMC_DataIn_BeginSend( epnum, true );
- }
- // ===================================================================================
- // USBTMC_datain_zerosend()
- // Queue zero packet in BulkIN EP without calling TX-handler
- //
- uint8_t USBTMC_datain_zerosend( uint8_t epnum )
- {
- return USBD_USBTMC_DataIn_ZeroSend( epnum );
- }
|