2019-09-14 12:13:11 -04:00
/*
* The MIT License ( MIT )
*
2019-09-18 21:31:38 -04:00
* Copyright ( c ) 2019 Nathan Conrad
2019-09-14 12:13:11 -04:00
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*
*/
# include <strings.h>
2019-09-18 23:53:28 -04:00
# include <stdlib.h> /* atoi */
2019-09-14 12:13:11 -04:00
# include "class/usbtmc/usbtmc_device.h"
2019-09-14 21:24:52 -04:00
# include "bsp/board.h"
2019-09-14 18:07:12 -04:00
# include "main.h"
2019-09-14 12:13:11 -04:00
# if (USBTMC_CFG_ENABLE_488)
usbtmc_response_capabilities_488_t const
# else
usbtmc_response_capabilities_t const
# endif
usbtmcd_app_capabilities =
{
. USBTMC_status = USBTMC_STATUS_SUCCESS ,
. bcdUSBTMC = USBTMC_VERSION ,
. bmIntfcCapabilities =
{
. listenOnly = 0 ,
. talkOnly = 0 ,
2019-09-14 18:07:12 -04:00
. supportsIndicatorPulse = 1
2019-09-14 12:13:11 -04:00
} ,
. bmDevCapabilities = {
. canEndBulkInOnTermChar = 0
} ,
# if (USBTMC_CFG_ENABLE_488)
. bcdUSB488 = USBTMC_488_VERSION ,
. bmIntfcCapabilities488 =
{
2019-09-14 16:56:53 -04:00
. supportsTrigger = 1 ,
2019-09-14 12:13:11 -04:00
. supportsREN_GTL_LLO = 0 ,
. is488_2 = 1
} ,
. bmDevCapabilities488 =
{
. SCPI = 1 ,
. SR1 = 0 ,
. RL1 = 0 ,
. DT1 = 0 ,
}
# endif
} ;
2019-09-18 19:24:54 -04:00
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";
2019-09-14 21:24:52 -04:00
static volatile uint8_t status ;
2019-09-14 12:13:11 -04:00
2019-09-14 21:24:52 -04:00
// 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready?
// (to simulate delay)
static volatile uint16_t queryState = 0 ;
static volatile uint32_t queryDelayStart ;
static volatile uint32_t bulkInStarted ;
2019-09-18 21:31:38 -04:00
static volatile uint32_t idnQuery ;
2019-09-18 23:53:28 -04:00
static uint32_t resp_delay = 125u ; // Adjustable delay, to allow for better testing
2019-09-18 21:31:38 -04:00
static size_t buffer_len ;
static uint8_t buffer [ 225 ] ; // A few packets long should be enough.
2019-09-14 21:24:52 -04:00
static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = {
. bmTransferAttributes =
{
. EOM = 1 ,
. UsingTermChar = 0
}
} ;
2019-09-14 12:13:11 -04:00
2019-09-18 21:31:38 -04:00
bool usbtmcd_app_msg_trigger ( uint8_t rhport , usbtmc_msg_generic_t * msg ) {
2019-09-14 16:56:53 -04:00
( void ) rhport ;
2019-09-18 21:31:38 -04:00
( void ) msg ;
2019-09-14 12:13:11 -04:00
return true ;
}
2019-09-18 21:31:38 -04:00
bool usbtmcd_app_msgBulkOut_start ( uint8_t rhport , usbtmc_msg_request_dev_dep_out const * msgHeader )
{
2019-09-14 16:56:53 -04:00
( void ) rhport ;
2019-09-18 21:31:38 -04:00
( void ) msgHeader ;
# ifdef xDEBUG
uart_tx_str_sync ( " MSG_OUT_DATA: start \r \n " ) ;
# endif
buffer_len = 0 ;
2019-09-14 16:56:53 -04:00
return true ;
}
2019-09-14 12:13:11 -04:00
2019-09-14 16:56:53 -04:00
bool usbtmcd_app_msg_data ( uint8_t rhport , void * data , size_t len , bool transfer_complete )
2019-09-14 12:13:11 -04:00
{
2019-09-14 16:56:53 -04:00
( void ) rhport ;
2019-09-14 22:55:42 -04:00
// If transfer isn't finished, we just ignore it (for now)
2019-09-18 21:31:38 -04:00
# ifdef xDEBUG
uart_tx_str_sync ( " MSG_OUT_DATA: <<< " ) ;
2019-09-17 13:26:10 -04:00
uart_tx_sync ( data , len ) ;
uart_tx_str_sync ( " >>> \r \n " ) ;
if ( transfer_complete )
uart_tx_str_sync ( " MSG_OUT_DATA: Complete \r \n " ) ;
2019-09-18 23:53:28 -04:00
sprintf ( bigMsg , " len=%u complete=%u \r \n " , len , ( uint32_t ) transfer_complete ) ;
uart_tx_str_sync ( bigMsg ) ;
2019-09-18 21:31:38 -04:00
# endif
if ( len + buffer_len < sizeof ( buffer ) )
{
memcpy ( & ( buffer [ buffer_len ] ) , data , len ) ;
buffer_len + = len ;
}
queryState = transfer_complete ;
idnQuery = 0 ;
if ( transfer_complete & & ( len > = 4 ) & & ! strncasecmp ( " *idn? " , data , 4 ) )
{
idnQuery = 1 ;
2019-09-14 12:13:11 -04:00
}
2019-09-18 23:53:28 -04:00
if ( transfer_complete & & ! strncasecmp ( " delay " , data , 5 ) )
{
queryState = 0 ;
resp_delay = atoi ( ( char * ) data + 5 ) ;
if ( resp_delay > 10000u )
resp_delay = 10000u ;
}
2019-09-14 12:13:11 -04:00
return true ;
}
bool usbtmcd_app_msgBulkIn_complete ( uint8_t rhport )
{
( void ) rhport ;
2019-09-14 22:55:42 -04:00
2019-09-18 21:31:38 -04:00
status & = ( uint8_t ) ~ ( 0x50u ) ; // clear MAV and SRQ
2019-09-14 22:55:42 -04:00
2019-09-14 12:13:11 -04:00
return true ;
}
2019-09-17 13:26:10 -04:00
static unsigned int msgReqLen ;
2019-09-14 12:13:11 -04:00
bool usbtmcd_app_msgBulkIn_request ( uint8_t rhport , usbtmc_msg_request_dev_dep_in const * request )
{
2019-09-15 14:57:02 -04:00
( void ) rhport ;
2019-09-17 13:26:10 -04:00
2019-09-14 21:24:52 -04:00
rspMsg . header . MsgID = request - > header . MsgID ,
rspMsg . header . bTag = request - > header . bTag ,
rspMsg . header . bTagInverse = request - > header . bTagInverse ;
2019-09-17 13:26:10 -04:00
msgReqLen = request - > TransferSize ;
2019-09-18 21:31:38 -04:00
# ifdef xDEBUG
uart_tx_str_sync ( " MSG_IN_DATA: Requested! \r \n " ) ;
# endif
2019-09-14 22:55:42 -04:00
TU_ASSERT ( bulkInStarted = = 0 ) ;
bulkInStarted = 1 ;
// > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message
// that expects a response, the device must NAK the request
2019-09-14 21:24:52 -04:00
// Always return true indicating not to stall the EP.
2019-09-14 12:13:11 -04:00
return true ;
}
2019-09-14 21:24:52 -04:00
void usbtmc_app_task_iter ( void ) {
uint8_t const rhport = 0 ;
switch ( queryState ) {
2019-09-15 14:57:02 -04:00
case 0 :
break ;
2019-09-14 21:24:52 -04:00
case 1 :
queryDelayStart = board_millis ( ) ;
queryState = 2 ;
break ;
case 2 :
2019-09-18 23:53:28 -04:00
if ( ( board_millis ( ) - queryDelayStart ) > resp_delay ) {
2019-09-14 21:24:52 -04:00
queryDelayStart = board_millis ( ) ;
queryState = 3 ;
status | = 0x10u ; // MAV
2019-09-18 21:31:38 -04:00
status | = 0x40u ; // SRQ
2019-09-14 21:24:52 -04:00
}
break ;
case 3 :
2019-09-18 23:53:28 -04:00
if ( ( board_millis ( ) - queryDelayStart ) > resp_delay ) {
2019-09-14 21:24:52 -04:00
queryState = 4 ;
}
break ;
case 4 : // time to transmit;
if ( bulkInStarted ) {
queryState = 0 ;
bulkInStarted = 0 ;
2019-09-18 21:31:38 -04:00
# ifdef xDEBUG
uart_tx_str_sync ( " usbtmc_app_task_iter: sending rsp! \r \n " ) ;
# endif
if ( idnQuery )
{
2019-09-18 23:53:28 -04:00
usbtmcd_transmit_dev_msg_data ( rhport , idn , tu_min32 ( sizeof ( idn ) - 1 , msgReqLen ) , false ) ;
2019-09-18 21:31:38 -04:00
}
else
{
usbtmcd_transmit_dev_msg_data ( rhport , buffer , tu_min32 ( buffer_len , msgReqLen ) , false ) ;
}
2019-09-14 22:55:42 -04:00
// MAV is cleared in the transfer complete callback.
2019-09-14 21:24:52 -04:00
}
break ;
2019-09-14 22:55:42 -04:00
default :
TU_ASSERT ( false , ) ;
return ;
2019-09-14 21:24:52 -04:00
}
}
2019-09-15 14:57:02 -04:00
bool usbtmcd_app_initiate_clear ( uint8_t rhport , uint8_t * tmcResult )
{
2019-09-14 22:55:42 -04:00
( void ) rhport ;
* tmcResult = USBTMC_STATUS_SUCCESS ;
2019-09-15 14:57:02 -04:00
queryState = 0 ;
bulkInStarted = false ;
status = 0 ;
2019-09-14 22:55:42 -04:00
return true ;
}
2019-09-18 19:24:54 -04:00
bool usbtmcd_app_check_clear ( uint8_t rhport , usbtmc_get_clear_status_rsp_t * rsp )
2019-09-15 14:57:02 -04:00
{
2019-09-14 22:55:42 -04:00
( void ) rhport ;
2019-09-15 14:57:02 -04:00
queryState = 0 ;
bulkInStarted = false ;
status = 0 ;
2019-09-14 22:55:42 -04:00
rsp - > USBTMC_status = USBTMC_STATUS_SUCCESS ;
rsp - > bmClear . BulkInFifoBytes = 0u ;
return true ;
}
2019-09-18 19:24:54 -04:00
bool usbtmcd_app_initiate_abort_bulk_in ( uint8_t rhport , uint8_t * tmcResult )
{
2019-09-18 23:53:28 -04:00
( void ) rhport ;
2019-09-18 19:24:54 -04:00
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 )
{
2019-09-18 23:53:28 -04:00
( void ) rhport ;
2019-09-18 19:24:54 -04:00
return true ;
}
bool usbtmcd_app_initiate_abort_bulk_out ( uint8_t rhport , uint8_t * tmcResult )
{
2019-09-18 23:53:28 -04:00
( void ) rhport ;
2019-09-18 19:24:54 -04:00
* 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 ;
}
2019-09-17 13:26:10 -04:00
2019-09-15 14:57:02 -04:00
void usmtmcd_app_bulkIn_clearFeature ( uint8_t rhport )
{
( void ) rhport ;
}
void usmtmcd_app_bulkOut_clearFeature ( uint8_t rhport )
{
( void ) rhport ;
}
2019-09-14 22:55:42 -04:00
2019-09-14 12:13:11 -04:00
// Return status byte, but put the transfer result status code in the rspResult argument.
2019-09-14 21:24:52 -04:00
uint8_t usbtmcd_app_get_stb ( uint8_t rhport , uint8_t * tmcResult )
2019-09-14 12:13:11 -04:00
{
( void ) rhport ;
2019-09-18 21:31:38 -04:00
uint8_t old_status = status ;
2019-09-18 23:53:28 -04:00
status = status & ~ ( 0x40u ) ; // clear SRQ
2019-09-18 21:31:38 -04:00
2019-09-14 21:24:52 -04:00
* tmcResult = USBTMC_STATUS_SUCCESS ;
2019-09-14 12:13:11 -04:00
// Increment status so that we see different results on each read...
2019-09-18 21:31:38 -04:00
return old_status ;
2019-09-14 12:13:11 -04:00
}
2019-09-14 21:24:52 -04:00
bool usbtmcd_app_indicator_pluse ( uint8_t rhport , tusb_control_request_t const * msg , uint8_t * tmcResult )
2019-09-14 18:07:12 -04:00
{
2019-09-14 21:24:52 -04:00
( void ) rhport ;
( void ) msg ;
2019-09-14 18:07:12 -04:00
led_indicator_pulse ( ) ;
2019-09-14 21:24:52 -04:00
* tmcResult = USBTMC_STATUS_SUCCESS ;
return true ;
2019-09-14 18:07:12 -04:00
}