rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions
TunerStudio Class Reference

#include <tunerstudio_impl.h>

Inheritance diagram for TunerStudio:
Inheritance graph
[legend]
Collaboration diagram for TunerStudio:
Collaboration graph
[legend]

Public Member Functions

int handleCrcCommand (TsChannelBase *tsChannel, char *data, int incomingPacketSize)
 
bool handlePlainCommand (TsChannelBase *tsChannel, uint8_t command)
 
void cmdOutputChannels (TsChannelBase *tsChannel, uint16_t offset, uint16_t count) override
 'Output' command sends out a snapshot of current values Gauges refresh
 
void handleQueryCommand (TsChannelBase *tsChannel, ts_response_format_e mode)
 
void handleExecuteCommand (TsChannelBase *tsChannel, char *data, int incomingPacketSize)
 
void handleWriteChunkCommand (TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count, void *content)
 
void handleCrc32Check (TsChannelBase *tsChannel, uint16_t offset, uint16_t count)
 
void handlePageReadCommand (TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count)
 
void handleScatteredReadCommand (TsChannelBase *tsChannel)
 

Private Member Functions

void sendErrorCode (TsChannelBase *tsChannel, uint8_t code, const char *msg="")
 

Additional Inherited Members

Detailed Description

Definition at line 23 of file tunerstudio_impl.h.

Member Function Documentation

◆ cmdOutputChannels()

void TunerStudio::cmdOutputChannels ( TsChannelBase tsChannel,
uint16_t  offset,
uint16_t  count 
)
overridevirtual

'Output' command sends out a snapshot of current values Gauges refresh

collect data from all models

Implements TunerStudioBase.

Definition at line 40 of file tunerstudio_commands.cpp.

40 {
41 if (offset + count > TS_TOTAL_OUTPUT_SIZE) {
42 efiPrintf("TS: Version Mismatch? Too much outputs requested offset=%d + count=%d/total=%d", offset, count,
43 TS_TOTAL_OUTPUT_SIZE);
44 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, "cmd_size");
45 return;
46 }
47
48 if (offset < BLOCKING_FACTOR) {
51 }
52
55 tsChannel->assertPacketSize(count, false);
56 // this method is invoked too often to print any debug information
57 uint8_t * scratchBuffer = (uint8_t *)tsChannel->scratchBuffer;
58 /**
59 * collect data from all models
60 */
61 copyRange(scratchBuffer + 3, getLiveDataFragments(), offset, count);
62
63 tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
64}
TunerStudioOutputChannels outputChannels
Definition engine.h:103
void crcAndWriteBuffer(const uint8_t responseCode, const size_t size)
char scratchBuffer[scratchBuffer_SIZE+30]
void assertPacketSize(size_t size, bool allowLongPackets)
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code, const char *msg="")
static Engine *const engine
Definition engine.h:390
FragmentList getLiveDataFragments()
tunerstudio_counters_s tsState
void updateTunerStudioState()
static Timer channelsRequestTimer

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleCrc32Check()

void TunerStudio::handleCrc32Check ( TsChannelBase tsChannel,
uint16_t  offset,
uint16_t  count 
)

Definition at line 247 of file tunerstudio.cpp.

247 {
249
250 // Ensure we are reading from in bounds
251 if (validateOffsetCount(offset, count, tsChannel)) {
252 tunerStudioError(tsChannel, "ERROR: CRC out of range");
253 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
254 return;
255 }
256
257#if EFI_TS_SCATTER
258 /*
259 * highSpeedOffsets is noMsqSave, but located on settings page,
260 * zero highSpeedOffsets as TS expect all noMsqSave data to be zero during CRC matching
261 * TODO:
262 * Move highSpeedOffsets to separate page as it is done on MS devices
263 * Zero highSpeedOffsets on start and reconnect
264 * TODO:
265 * Is Crc check command good sing of new TS session?
266 * TODO:
267 * Support settings pages!
268 */
270#endif // EFI_TS_SCATTER
271
272 const uint8_t* start = getWorkingPageAddr() + offset;
273
274 uint32_t crc = SWAP_UINT32(crc32(start, count));
275 tsChannel->sendResponse(TS_CRC, (const uint8_t *) &crc, 4);
276 efiPrintf("TS <- Get CRC offset %d count %d result %08x", offset, count, (unsigned int)crc);
277}
void sendResponse(ts_response_format_e mode, const uint8_t *buffer, int size, bool allowLongPackets=false)
uint32_t SWAP_UINT32(uint32_t x)
Definition efilib.h:27
static constexpr engine_configuration_s * engineConfiguration
bool validateOffsetCount(size_t offset, size_t count, TsChannelBase *tsChannel)
uint8_t * getWorkingPageAddr()
void tunerStudioError(TsChannelBase *tsChannel, const char *msg)
@ TS_CRC

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleCrcCommand()

int TunerStudio::handleCrcCommand ( TsChannelBase tsChannel,
char data,
int  incomingPacketSize 
)

Definition at line 699 of file tunerstudio.cpp.

699 {
701
702 char command = data[0];
703 data++;
704
705 const uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
706
707 // only few command have page argument, default page is 0
708 uint16_t page = 0;
709 uint16_t offset = 0;
710 uint16_t count = 0;
711
712 // command may not have offset field - keep safe default value
713 // not used by .ini at the moment TODO actually use that version of the command in the .ini
714 if (incomingPacketSize >= 3) {
715 offset = data16[0];
716 }
717 // command may not have count/size filed - keep safe default value
718 if (incomingPacketSize >= 5) {
719 count = data16[1];
720 }
721
722 switch(command)
723 {
724 case TS_OUTPUT_COMMAND:
725 if (incomingPacketSize == 1) {
726 // Read command with no offset and size - read whole livedata
727 count = TS_TOTAL_OUTPUT_SIZE;
728 }
729 cmdOutputChannels(tsChannel, offset, count);
730 break;
731 case TS_OUTPUT_ALL_COMMAND:
732 offset = 0;
733 count = TS_TOTAL_OUTPUT_SIZE;
734 // TS will not use this command until ochBlockSize is bigger than blockingFactor and prefer ochGetCommand :(
735 cmdOutputChannels(tsChannel, offset, count);
736 break;
737 case TS_HELLO_COMMAND:
738 tunerStudioDebug(tsChannel, "got Query command");
739 handleQueryCommand(tsChannel, TS_CRC);
740 break;
741 case TS_GET_FIRMWARE_VERSION:
742 handleGetVersion(tsChannel);
743 break;
744#if EFI_TEXT_LOGGING
745 case TS_GET_TEXT:
746 handleGetText(tsChannel);
747 break;
748#endif // EFI_TEXT_LOGGING
749 case TS_EXECUTE:
750 handleExecuteCommand(tsChannel, data, incomingPacketSize - 1);
751 break;
752 case TS_CHUNK_WRITE_COMMAND:
753 // command with no page argument, default page = 0
754 handleWriteChunkCommand(tsChannel, page, offset, count, data + sizeof(TunerStudioRWChunkRequest));
755 calibrationsWriteTimer.reset();
756 break;
757 case TS_SINGLE_WRITE_COMMAND:
758 // command with no page argument, default page = 0
759 // This command writes 1 byte
760 count = 1;
761 handleWriteChunkCommand(tsChannel, page, offset, count, data + sizeof(offset));
762 calibrationsWriteTimer.reset();
763 break;
764 case TS_GET_SCATTERED_GET_COMMAND:
765#if EFI_TS_SCATTER
767#else
768 criticalError("Slow/wireless mode not supported");
769#endif // EFI_TS_SCATTER
770 break;
771 case TS_CRC_CHECK_COMMAND:
772 handleCrc32Check(tsChannel, offset, count);
773 break;
774 case TS_BURN_COMMAND:
775 handleBurnCommand(tsChannel);
776 break;
777 case TS_READ_COMMAND:
778 // command with no page argument, default page = 0
779 handlePageReadCommand(tsChannel, page, offset, count);
780 break;
781 case TS_TEST_COMMAND:
782 [[fallthrough]];
783 case 'T':
784 handleTestCommand(tsChannel);
785 break;
786#if EFI_SIMULATOR
787 case TS_SIMULATE_CAN:
788 void handleWrapCan(TsChannelBase* tsChannel, char *data, int incomingPacketSize);
789 handleWrapCan(tsChannel, data, incomingPacketSize - 1);
790 break;
791#endif // EFI_SIMULATOR
792 case TS_IO_TEST_COMMAND:
793 {
794#if EFI_PROD_CODE
795 uint16_t subsystem = SWAP_UINT16(data16[0]);
796 uint16_t index = SWAP_UINT16(data16[1]);
797
798 executeTSCommand(subsystem, index);
799#endif /* EFI_PROD_CODE */
800 sendOkResponse(tsChannel);
801 }
802 break;
803#if EFI_TOOTH_LOGGER
804 case TS_SET_LOGGER_SWITCH:
805 switch(data[0]) {
806 case TS_COMPOSITE_ENABLE:
808 break;
809 case TS_COMPOSITE_DISABLE:
811 break;
812 case TS_COMPOSITE_READ:
813 {
814 auto toothBuffer = GetToothLoggerBufferNonblocking();
815
816 if (toothBuffer) {
817 tsChannel->sendResponse(TS_CRC, reinterpret_cast<const uint8_t*>(toothBuffer->buffer), toothBuffer->nextIdx * sizeof(composite_logger_s), true);
818
819 ReturnToothLoggerBuffer(toothBuffer);
820 } else {
821 // TS asked for a tooth logger buffer, but we don't have one to give it.
822 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
823 }
824 }
825 break;
826#ifdef TRIGGER_SCOPE
827 case TS_TRIGGER_SCOPE_ENABLE:
829 break;
830 case TS_TRIGGER_SCOPE_DISABLE:
832 break;
833 case TS_TRIGGER_SCOPE_READ:
834 {
835 const auto& buffer = triggerScopeGetBuffer();
836
837 if (buffer) {
838 tsChannel->sendResponse(TS_CRC, buffer.get<uint8_t>(), buffer.size(), true);
839 } else {
840 // TS asked for a tooth logger buffer, but we don't have one to give it.
841 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
842 }
843 }
844 break;
845#endif // TRIGGER_SCOPE
846 default:
847 // dunno what that was, send NAK
848 return false;
849 }
850
851 sendOkResponse(tsChannel);
852
853 break;
854 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
855 {
857
858 auto toothBuffer = GetToothLoggerBufferNonblocking();
859
860 if (toothBuffer) {
861 tsChannel->sendResponse(TS_CRC, reinterpret_cast<const uint8_t*>(toothBuffer->buffer), toothBuffer->nextIdx * sizeof(composite_logger_s), true);
862
863 ReturnToothLoggerBuffer(toothBuffer);
864 } else {
865 // TS asked for a tooth logger buffer, but we don't have one to give it.
866 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
867 }
868 }
869
870 break;
871#else // EFI_TOOTH_LOGGER
872 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
873 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
874 break;
875#endif /* EFI_TOOTH_LOGGER */
876#if ENABLE_PERF_TRACE
877 case TS_PERF_TRACE_BEGIN:
879 sendOkResponse(tsChannel);
880 break;
881 case TS_PERF_TRACE_GET_BUFFER:
882 {
883 auto trace = perfTraceGetBuffer();
884 tsChannel->sendResponse(TS_CRC, trace.get<uint8_t>(), trace.size(), true);
885 }
886
887 break;
888#else
889 case TS_PERF_TRACE_BEGIN:
890 criticalError("TS_PERF_TRACE not supported");
891 break;
892 case TS_PERF_TRACE_GET_BUFFER:
893 criticalError("TS_PERF_TRACE_GET_BUFFER not supported");
894 break;
895#endif /* ENABLE_PERF_TRACE */
896 case TS_GET_CONFIG_ERROR: {
897 const char* configError = hasFirmwareError()? getCriticalErrorMessage() : getConfigErrorMessage();
898 tsChannel->sendResponse(TS_CRC, reinterpret_cast<const uint8_t*>(configError), strlen(configError), true);
899 break;
900 }
901 case TS_QUERY_BOOTLOADER: {
902 uint8_t bldata = TS_QUERY_BOOTLOADER_NONE;
903#if EFI_USE_OPENBLT
904 bldata = TS_QUERY_BOOTLOADER_OPENBLT;
905#endif
906
907 tsChannel->sendResponse(TS_CRC, &bldata, 1, false);
908 break;
909 }
910 default:
911 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND, "unknown_command");
912static char tsErrorBuff[80];
913 chsnprintf(tsErrorBuff, sizeof(tsErrorBuff), "ERROR: ignoring unexpected command %d [%c]", command, command);
914 tunerStudioError(tsChannel, tsErrorBuff);
915 return false;
916 }
917
918 return true;
919}
void executeTSCommand(uint16_t subsystem, uint16_t index)
size_t size() const
Definition big_buffer.h:43
const TBuffer * get() const
Definition big_buffer.h:34
void handleScatteredReadCommand(TsChannelBase *tsChannel)
void handleQueryCommand(TsChannelBase *tsChannel, ts_response_format_e mode)
void cmdOutputChannels(TsChannelBase *tsChannel, uint16_t offset, uint16_t count) override
'Output' command sends out a snapshot of current values Gauges refresh
void handleCrc32Check(TsChannelBase *tsChannel, uint16_t offset, uint16_t count)
void handlePageReadCommand(TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count)
void handleWriteChunkCommand(TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count, void *content)
void handleExecuteCommand(TsChannelBase *tsChannel, char *data, int incomingPacketSize)
uint16_t SWAP_UINT16(uint16_t x)
Definition efilib.h:22
const char * getCriticalErrorMessage()
void configError(const char *fmt,...)
const char * getConfigErrorMessage()
const BigBufferHandle perfTraceGetBuffer()
void perfTraceEnable()
@ TunerStudioHandleCrcCommand
void DisableToothLogger()
void EnableToothLogger()
CompositeBuffer * GetToothLoggerBufferNonblocking()
void ReturnToothLoggerBuffer(CompositeBuffer *buffer)
void EnableToothLoggerIfNotEnabled()
composite_logger_s
void triggerScopeEnable()
const BigBufferHandle & triggerScopeGetBuffer()
static BigBufferHandle buffer
void triggerScopeDisable()
static void handleBurnCommand(TsChannelBase *tsChannel)
static void handleGetVersion(TsChannelBase *tsChannel)
static void handleGetText(TsChannelBase *tsChannel)
static void sendOkResponse(TsChannelBase *tsChannel)
static void handleTestCommand(TsChannelBase *tsChannel)
void tunerStudioDebug(TsChannelBase *tsChannel, const char *msg)

Referenced by tsProcessOne().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleExecuteCommand()

void TunerStudio::handleExecuteCommand ( TsChannelBase tsChannel,
char data,
int  incomingPacketSize 
)

Definition at line 688 of file tunerstudio.cpp.

688 {
689 data[incomingPacketSize] = 0;
690 char *trimmed = efiTrim(data);
691#if EFI_SIMULATOR
692 logMsg("execute [%s]\r\n", trimmed);
693#endif // EFI_SIMULATOR
694 (console_line_callback)(trimmed);
695
696 tsChannel->writeCrcResponse(TS_RESPONSE_OK);
697}
void writeCrcResponse(uint8_t responseCode)
char * efiTrim(char *param)
Definition efilib.cpp:39
CommandHandler console_line_callback

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handlePageReadCommand()

void TunerStudio::handlePageReadCommand ( TsChannelBase tsChannel,
uint16_t  page,
uint16_t  offset,
uint16_t  count 
)

Definition at line 325 of file tunerstudio.cpp.

325 {
327
328 efiPrintf("TS <- Page %d read chunk offset %d count %d", page, offset, count);
329
330 if (page == 0) {
331 if (validateOffsetCount(offset, count, tsChannel)) {
332 tunerStudioError(tsChannel, "ERROR: RD out of range");
333 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
334 return;
335 }
336
337 uint8_t* addr;
338 if (isLockedFromUser()) {
339 // to have rusEFI console happy just send all zeros within a valid packet
340 addr = (uint8_t*)&tsChannel->scratchBuffer + TS_PACKET_HEADER_SIZE;
341 memset(addr, 0, count);
342 } else {
343 addr = getWorkingPageAddr() + offset;
344 }
345 tsChannel->sendResponse(TS_CRC, addr, count);
346#if EFI_TUNER_STUDIO_VERBOSE
347// efiPrintf("Sending %d done", count);
348#endif
349 } else {
350 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, "ERROR: RD invalid page");
351 }
352}
constexpr uint8_t addr
Definition ads1015.cpp:5
bool isLockedFromUser()
Definition engine2.cpp:263

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handlePlainCommand()

bool TunerStudio::handlePlainCommand ( TsChannelBase tsChannel,
uint8_t  command 
)

handle non CRC wrapped command

Returns
true if legacy command was processed, false otherwise

http://www.msextra.com/forums/viewtopic.php?f=122&t=48327 Response from TS support: This is an optional command * "The F command is used to find what ini. file needs to be loaded in TunerStudio to match the controller. If you are able to just make your firmware ignore the command that would work. Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."

Definition at line 465 of file tunerstudio.cpp.

465 {
466 // Bail fast if guaranteed not to be a plain command
467 if (command == 0) {
468 return false;
469 } else if (command == TS_HELLO_COMMAND || command == TS_QUERY_COMMAND) {
470 // We interpret 'Q' as TS_HELLO_COMMAND, since TS uses hardcoded 'Q' during ECU detection (scan all serial ports)
471 efiPrintf("Got naked Query command");
472 handleQueryCommand(tsChannel, TS_PLAIN);
473 return true;
474 } else if (command == TS_TEST_COMMAND || command == 'T') {
475 handleTestCommand(tsChannel);
476 return true;
477 } else if (command == TS_COMMAND_F) {
478 /**
479 * http://www.msextra.com/forums/viewtopic.php?f=122&t=48327
480 * Response from TS support: This is an optional command *
481 * "The F command is used to find what ini. file needs to be loaded in TunerStudio to match the controller.
482 * If you are able to just make your firmware ignore the command that would work.
483 * Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
484 */
485
486 tunerStudioDebug(tsChannel, "not ignoring F");
487 tsChannel->write((const uint8_t *)TS_PROTOCOL, strlen(TS_PROTOCOL));
488 tsChannel->flush();
489 return true;
490 } else {
491 // This wasn't a valid command
492 return false;
493 }
494}
virtual void flush()
virtual void write(const uint8_t *buffer, size_t size, bool isEndOfPacket=false)=0
@ TS_PLAIN

Referenced by tsProcessOne().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleQueryCommand()

void TunerStudio::handleQueryCommand ( TsChannelBase tsChannel,
ts_response_format_e  mode 
)

this command is part of protocol initialization

this command is part of protocol initialization

Query with CRC takes place while re-establishing connection Query without CRC takes place on TunerStudio startup

Definition at line 452 of file tunerstudio.cpp.

452 {
454 const char *signature = getTsSignature();
455
456 efiPrintf("TS <- Query signature: %s", signature);
457 tsChannel->sendResponse(mode, (const uint8_t *)signature, strlen(signature) + 1);
458}
const char * getTsSignature()
Definition signature.cpp:31

Referenced by handleCrcCommand(), and handlePlainCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleScatteredReadCommand()

void TunerStudio::handleScatteredReadCommand ( TsChannelBase tsChannel)

Definition at line 280 of file tunerstudio.cpp.

280 {
281 int totalResponseSize = 0;
282 for (int i = 0; i < HIGH_SPEED_COUNT; i++) {
283 uint16_t packed = engineConfiguration->highSpeedOffsets[i];
284 uint16_t type = packed >> 13;
285
286 size_t size = type == 0 ? 0 : 1 << (type - 1);
287#if EFI_SIMULATOR
288// printf("handleScatteredReadCommand 0x%x %d %d\n", packed, size, offset);
289#endif /* EFI_SIMULATOR */
290 totalResponseSize += size;
291 }
292#if EFI_SIMULATOR
293// printf("totalResponseSize %d\n", totalResponseSize);
294#endif /* EFI_SIMULATOR */
295
296
297 // Command part of CRC
298 uint32_t crc = tsChannel->writePacketHeader(TS_RESPONSE_OK, totalResponseSize);
299
300 uint8_t dataBuffer[8];
301 for (int i = 0; i < HIGH_SPEED_COUNT; i++) {
302 uint16_t packed = engineConfiguration->highSpeedOffsets[i];
303 uint16_t type = packed >> 13;
304 uint16_t offset = packed & 0x1FFF;
305
306 if (type == 0)
307 continue;
308 size_t size = 1 << (type - 1);
309
310 // write each data point and CRC incrementally
311 copyRange(dataBuffer, getLiveDataFragments(), offset, size);
312 tsChannel->write(dataBuffer, size, false);
313 crc = crc32inc((void*)dataBuffer, crc, size);
314 }
315#if EFI_SIMULATOR
316// printf("CRC %x\n", crc);
317#endif /* EFI_SIMULATOR */
318 // now write total CRC
319 *(uint32_t*)dataBuffer = SWAP_UINT32(crc);
320 tsChannel->write(reinterpret_cast<uint8_t*>(dataBuffer), 4, true);
321 tsChannel->flush();
322}
uint32_t writePacketHeader(const uint8_t responseCode, const size_t size)
composite packet size

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleWriteChunkCommand()

void TunerStudio::handleWriteChunkCommand ( TsChannelBase tsChannel,
uint16_t  page,
uint16_t  offset,
uint16_t  count,
void *  content 
)

This command is needed to make the whole transfer a bit faster

Definition at line 214 of file tunerstudio.cpp.

215 {
217
218 efiPrintf("TS -> Page %d write chunk offset %d count %d (output_count=%d)",
219 page, offset, count, tsState.outputChannelsCommandCounter);
220
221 if (page == 0) {
222 if (isLockedFromUser()) {
223 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND, "locked");
224 return;
225 }
226
227 if (validateOffsetCount(offset, count, tsChannel)) {
228 tunerStudioError(tsChannel, "ERROR: WR out of range");
229 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
230 return;
231 }
232
233 // Skip the write if a preset was just loaded - we don't want to overwrite it
234 if (!needToTriggerTsRefresh()) {
235 uint8_t * addr = (uint8_t *) (getWorkingPageAddr() + offset);
236 memcpy(addr, content, count);
237 }
238 // Force any board configuration options that humans shouldn't be able to change
240
241 sendOkResponse(tsChannel);
242 } else {
243 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, "ERROR: WR invalid page");
244 }
245}
void setBoardConfigOverrides()
bool needToTriggerTsRefresh()

Referenced by handleCrcCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendErrorCode()

void TunerStudio::sendErrorCode ( TsChannelBase tsChannel,
uint8_t  code,
const char msg = "" 
)
private

Definition at line 193 of file tunerstudio.cpp.

193 {
194 ::sendErrorCode(tsChannel, code, msg);
195}
uint8_t code
Definition bluetooth.cpp:40

Referenced by cmdOutputChannels(), handleCrc32Check(), handleCrcCommand(), handlePageReadCommand(), handleWriteChunkCommand(), and sendErrorCode().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: