diff --git a/Firmata.cpp b/Firmata.cpp index 250d5f12..755048a9 100644 --- a/Firmata.cpp +++ b/Firmata.cpp @@ -94,8 +94,8 @@ FirmataClass::FirmataClass() parser.attach(SET_DIGITAL_PIN_VALUE, (FirmataParser::callbackFunction)staticPinValueCallback, (void *)NULL); parser.attach(STRING_DATA, (FirmataParser::stringCallbackFunction)staticStringCallback, (void *)NULL); parser.attach(START_SYSEX, (FirmataParser::sysexCallbackFunction)staticSysexCallback, (void *)NULL); - parser.attach(REPORT_FIRMWARE, (FirmataParser::systemCallbackFunction)staticReportFirmwareCallback, this); - parser.attach(REPORT_VERSION, (FirmataParser::systemCallbackFunction)staticReportVersionCallback, this); + parser.attach(REPORT_FIRMWARE, (FirmataParser::versionCallbackFunction)staticReportFirmwareCallback, this); + parser.attach(REPORT_VERSION, (FirmataParser::versionCallbackFunction)staticReportVersionCallback, this); parser.attach(SYSTEM_RESET, (FirmataParser::systemCallbackFunction)staticSystemResetCallback, (void *)NULL); } diff --git a/Firmata.h b/Firmata.h index 60eef9eb..3048dcc4 100644 --- a/Firmata.h +++ b/Firmata.h @@ -148,10 +148,10 @@ class FirmataClass inline static void staticPinValueCallback (void *, uint8_t command, uint16_t value) { if ( currentPinValueCallback ) { currentPinValueCallback(command, (int)value); } } inline static void staticReportAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentReportAnalogCallback ) { currentReportAnalogCallback(command, (int)value); } } inline static void staticReportDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentReportDigitalCallback ) { currentReportDigitalCallback(command, (int)value); } } - inline static void staticStringCallback (void *, char * c_str) { if ( currentStringCallback ) { currentStringCallback(c_str); } } + inline static void staticStringCallback (void *, const char * c_str) { if ( currentStringCallback ) { currentStringCallback((char *)c_str); } } inline static void staticSysexCallback (void *, uint8_t command, size_t argc, uint8_t *argv) { if ( currentSysexCallback ) { currentSysexCallback(command, (uint8_t)argc, argv); } } - inline static void staticReportFirmwareCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printFirmwareVersion(); } } - inline static void staticReportVersionCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printVersion(); } } + inline static void staticReportFirmwareCallback (void * context, size_t sv_major, size_t sv_minor, const char * description) { (void)sv_major; (void)sv_minor; (void)description; if ( context ) { ((FirmataClass *)context)->printFirmwareVersion(); } } + inline static void staticReportVersionCallback (void * context, size_t sv_major, size_t sv_minor, const char * description) { (void)sv_major; (void)sv_minor; (void)description; if ( context ) { ((FirmataClass *)context)->printVersion(); } } inline static void staticSystemResetCallback (void *) { if ( currentSystemResetCallback ) { currentSystemResetCallback(); } } }; diff --git a/FirmataMarshaller.cpp b/FirmataMarshaller.cpp index 2b1f45a9..732b0acd 100644 --- a/FirmataMarshaller.cpp +++ b/FirmataMarshaller.cpp @@ -168,6 +168,8 @@ const if ( (Stream *)NULL == FirmataStream ) { return; } FirmataStream->write(START_SYSEX); FirmataStream->write(REPORT_FIRMWARE); + FirmataStream->write(firmata::FIRMWARE_MAJOR_VERSION); + FirmataStream->write(firmata::FIRMWARE_MINOR_VERSION); FirmataStream->write(END_SYSEX); } @@ -179,6 +181,8 @@ const { if ( (Stream *)NULL == FirmataStream ) { return; } FirmataStream->write(REPORT_VERSION); + FirmataStream->write(firmata::PROTOCOL_MAJOR_VERSION); + FirmataStream->write(firmata::PROTOCOL_MINOR_VERSION); } /** diff --git a/FirmataParser.cpp b/FirmataParser.cpp index e446078d..ddd0dca4 100644 --- a/FirmataParser.cpp +++ b/FirmataParser.cpp @@ -60,8 +60,8 @@ FirmataParser::FirmataParser(uint8_t * const dataBuffer, size_t dataBufferSize) currentDataBufferOverflowCallback((dataBufferOverflowCallbackFunction)NULL), currentStringCallback((stringCallbackFunction)NULL), currentSysexCallback((sysexCallbackFunction)NULL), - currentReportFirmwareCallback((systemCallbackFunction)NULL), - currentReportVersionCallback((systemCallbackFunction)NULL), + currentReportFirmwareCallback((versionCallbackFunction)NULL), + currentReportVersionCallback((versionCallbackFunction)NULL), currentSystemResetCallback((systemCallbackFunction)NULL) { allowBufferUpdate = ((uint8_t *)NULL == dataBuffer); @@ -130,6 +130,9 @@ void FirmataParser::parse(uint8_t inputData) if (currentReportDigitalCallback) (*currentReportDigitalCallback)(currentReportDigitalCallbackContext, multiByteChannel, dataBuffer[0]); break; + case REPORT_VERSION: + if (currentReportVersionCallback) + (*currentReportVersionCallback)(currentReportVersionCallbackContext, dataBuffer[0], dataBuffer[1], (const char *)NULL); } executeMultiByteCommand = 0; } @@ -163,8 +166,8 @@ void FirmataParser::parse(uint8_t inputData) systemReset(); break; case REPORT_VERSION: - if (currentReportVersionCallback) - (*currentReportVersionCallback)(currentReportVersionCallbackContext); + waitForData = 2; // two data bytes needed + executeMultiByteCommand = command; break; } } @@ -244,15 +247,15 @@ void FirmataParser::attach(uint8_t command, callbackFunction newFunction, void * } /** - * Attach a system callback function (options are: REPORT_FIRMWARE, REPORT_VERSION - * and SYSTEM_RESET). + * Attach a version callback function (options are: REPORT_FIRMWARE, REPORT_VERSION). * @param command The ID of the command to attach a callback function to. * @param newFunction A reference to the callback function to attach. * @param context An optional context to be provided to the callback function (NULL by default). * @note The context parameter is provided so you can pass a parameter, by reference, to * your callback function. + * @note The description value in the REPORT_VERSION callback will always be NULL */ -void FirmataParser::attach(uint8_t command, systemCallbackFunction newFunction, void * context) +void FirmataParser::attach(uint8_t command, versionCallbackFunction newFunction, void * context) { switch (command) { case REPORT_FIRMWARE: @@ -263,6 +266,20 @@ void FirmataParser::attach(uint8_t command, systemCallbackFunction newFunction, currentReportVersionCallback = newFunction; currentReportVersionCallbackContext = context; break; + } +} + +/** + * Attach a system callback function (currently supports SYSTEM_RESET). + * @param command The ID of the command to attach a callback function to. + * @param newFunction A reference to the callback function to attach. + * @param context An optional context to be provided to the callback function (NULL by default). + * @note The context parameter is provided so you can pass a parameter, by reference, to + * your callback function. + */ +void FirmataParser::attach(uint8_t command, systemCallbackFunction newFunction, void * context) +{ + switch (command) { case SYSTEM_RESET: currentSystemResetCallback = newFunction; currentSystemResetCallbackContext = context; @@ -326,6 +343,8 @@ void FirmataParser::detach(uint8_t command) switch (command) { case REPORT_FIRMWARE: case REPORT_VERSION: + attach(command, (versionCallbackFunction)NULL, NULL); + break; case SYSTEM_RESET: attach(command, (systemCallbackFunction)NULL, NULL); break; @@ -394,14 +413,24 @@ void FirmataParser::processSysexMessage(void) { switch (dataBuffer[0]) { //first byte in buffer is command case REPORT_FIRMWARE: - if (currentReportFirmwareCallback) - (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext); + if (currentReportFirmwareCallback) { + size_t sv_major = dataBuffer[1], sv_minor = dataBuffer[2]; + size_t i = 0, j = 3; + while (j < sysexBytesRead) { + // The string length will only be at most half the size of the + // stored input buffer so we can decode the string within the buffer. + bufferDataAtPosition(dataBuffer[j], i); + ++i; + ++j; + } + bufferDataAtPosition('\0', i); // Terminate the string + (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext, sv_major, sv_minor, (const char *)&dataBuffer[0]); + } break; case STRING_DATA: if (currentStringCallback) { size_t bufferLength = (sysexBytesRead - 1) / 2; - size_t i = 1; - size_t j = 0; + size_t i = 1, j = 0; while (j < bufferLength) { // The string length will only be at most half the size of the // stored input buffer so we can decode the string within the buffer. @@ -417,7 +446,7 @@ void FirmataParser::processSysexMessage(void) if (dataBuffer[j - 1] != '\0') { bufferDataAtPosition('\0', j); } - (*currentStringCallback)(currentStringCallbackContext, (char *)&dataBuffer[0]); + (*currentStringCallback)(currentStringCallbackContext, (const char *)&dataBuffer[0]); } break; default: diff --git a/FirmataParser.h b/FirmataParser.h index a9516dae..82dff1a9 100644 --- a/FirmataParser.h +++ b/FirmataParser.h @@ -30,9 +30,10 @@ class FirmataParser /* callback function types */ typedef void (*callbackFunction)(void * context, uint8_t command, uint16_t value); typedef void (*dataBufferOverflowCallbackFunction)(void * context); - typedef void (*stringCallbackFunction)(void * context, char * c_str); + typedef void (*stringCallbackFunction)(void * context, const char * c_str); typedef void (*sysexCallbackFunction)(void * context, uint8_t command, size_t argc, uint8_t * argv); typedef void (*systemCallbackFunction)(void * context); + typedef void (*versionCallbackFunction)(void * context, size_t sv_major, size_t sv_minor, const char * description); FirmataParser(uint8_t * dataBuffer = (uint8_t *)NULL, size_t dataBufferSize = 0); @@ -47,6 +48,7 @@ class FirmataParser void attach(uint8_t command, stringCallbackFunction newFunction, void * context = NULL); void attach(uint8_t command, sysexCallbackFunction newFunction, void * context = NULL); void attach(uint8_t command, systemCallbackFunction newFunction, void * context = NULL); + void attach(uint8_t command, versionCallbackFunction newFunction, void * context = NULL); void detach(uint8_t command); void detach(dataBufferOverflowCallbackFunction); @@ -87,14 +89,14 @@ class FirmataParser dataBufferOverflowCallbackFunction currentDataBufferOverflowCallback; stringCallbackFunction currentStringCallback; sysexCallbackFunction currentSysexCallback; - systemCallbackFunction currentReportFirmwareCallback; - systemCallbackFunction currentReportVersionCallback; + versionCallbackFunction currentReportFirmwareCallback; + versionCallbackFunction currentReportVersionCallback; systemCallbackFunction currentSystemResetCallback; /* private methods ------------------------------ */ + bool bufferDataAtPosition(const uint8_t data, const size_t pos); void processSysexMessage(void); void systemReset(void); - bool bufferDataAtPosition(const uint8_t data, const size_t pos); }; } // firmata