@@ -222,7 +222,7 @@ struct EEPROMVALUES {
222
222
byte sig1; // 0x6D signature 1, EPROM values are valid of both signatures match.
223
223
byte sig2; // 0x68 signature 2
224
224
uint16_t startAddress; // the DMX start address can be changed by a RDM command.
225
- char deviceLabel[DMXSERIAL_MAX_RDM_STRING_LENGTH]; // the device Label can be changed by a RDM command.
225
+ char deviceLabel[DMXSERIAL_MAX_RDM_STRING_LENGTH]; // the device Label can be changed by a RDM command. Don't store the null in the EPROM for backwards compatibility.
226
226
DEVICEID deviceID; // store the device ID to allow easy software updates.
227
227
}; // struct EEPROMVALUES
228
228
@@ -255,7 +255,7 @@ DEVICEID _devIDAll = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
255
255
256
256
257
257
// This is the buffer for RDM packets being received and sent.
258
- // this structure is needed to RDM data separate from DMX data.
258
+ // This structure is needed to separate RDM data from DMX data.
259
259
union RDMMEM {
260
260
// the most common RDM packet layout for commands
261
261
struct RDMDATA packet;
@@ -264,10 +264,12 @@ union RDMMEM {
264
264
struct DISCOVERYMSG discovery;
265
265
266
266
// the byte array used while receiving and sending.
267
- byte buffer[60 ];
267
+ // This is the max size of any RDM packet and it's max PDL, to allow an
268
+ // aribitrary length packet to be received. Thanks to the union it doesn't
269
+ // need any more memory
270
+ byte buffer[sizeof (packet)];
268
271
} _rdm; // union RDMMEM
269
272
270
-
271
273
// This flag will be set when a full RDM packet was received.
272
274
bool8 _rdmAvailable;
273
275
@@ -354,7 +356,8 @@ void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, R
354
356
// check if the EEPROM values are from the RDM library
355
357
if ((eeprom.sig1 == 0x6D ) && (eeprom.sig2 == 0x68 )) {
356
358
_startAddress = eeprom.startAddress ;
357
- strcpy (deviceLabel, eeprom.deviceLabel );
359
+ // Restricting this to 32 characters or the length, whichever is shorter
360
+ strncpy (deviceLabel, eeprom.deviceLabel , DMXSERIAL_MAX_RDM_STRING_LENGTH);
358
361
DeviceIDCpy (_devID, eeprom.deviceID );
359
362
360
363
// setup the manufacturer addressing device-ID
@@ -364,7 +367,7 @@ void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, R
364
367
} else {
365
368
// set default values
366
369
_startAddress = 1 ;
367
- strcpy (deviceLabel, " new" );
370
+ strncpy (deviceLabel, " new" , DMXSERIAL_MAX_RDM_STRING_LENGTH );
368
371
_devID[4 ] = random255 (); // random(255);
369
372
_devID[5 ] = random255 (); // random(255);
370
373
} // if
@@ -500,7 +503,7 @@ void DMXSerialClass2::tick(void)
500
503
// check if my _devID is in the discovery range
501
504
if ((DeviceIDCmp (rdm->Data , _devID) <= 0 ) && (DeviceIDCmp (_devID, rdm->Data +6 ) <= 0 )) {
502
505
503
- // respond a special discovery message !
506
+ // respond with a special discovery message !
504
507
struct DISCOVERYMSG *disc = &_rdm.discovery ;
505
508
_rdmCheckSum = 6 * 0xFF ;
506
509
@@ -595,7 +598,7 @@ void DMXSerialClass2::term(void)
595
598
596
599
// Process the RDM Command Message by changing the _rdm buffer and returning (true).
597
600
// if returning (false) a NAK will be sent.
598
- // This method processes the commands/parameters regarding mute, DEviceInfo , devicelabel,
601
+ // This method processes the commands/parameters regarding mute, DeviceInfo , devicelabel,
599
602
// manufacturer label, DMX Start address.
600
603
// When parameters are changed by a SET command they are persisted into EEPROM.
601
604
// When doRespond is true, send an answer back to the controller node.
@@ -638,59 +641,74 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool
638
641
}
639
642
} // if
640
643
641
- } else if ((CmdClass == E120_GET_COMMAND) && (Parameter == SWAPINT (E120_DEVICE_INFO))) { // 0x0060
642
- if (_rdm.packet .DataLength > 0 ) {
643
- // Unexpected data
644
- nackReason = E120_NR_FORMAT_ERROR;
645
- } else if (_rdm.packet .SubDev != 0 ) {
646
- // No sub-devices supported
647
- nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
648
- } else {
649
- // return all device info data
650
- DEVICEINFO *devInfo = (DEVICEINFO *)(_rdm.packet .Data ); // The data has to be responded in the Data buffer.
651
-
652
- devInfo->protocolMajor = 1 ;
653
- devInfo->protocolMinor = 0 ;
654
- devInfo->deviceModel = SWAPINT (_initData->deviceModelId );
655
- devInfo->productCategory = SWAPINT (E120_PRODUCT_CATEGORY_DIMMER_CS_LED);
656
- devInfo->softwareVersion = SWAPINT32 (0x01000000 );// 0x04020900;
657
- devInfo->footprint = SWAPINT (_initData->footprint );
658
- devInfo->currentPersonality = 1 ;
659
- devInfo->personalityCount = 1 ;
660
- devInfo->startAddress = SWAPINT (_startAddress);
661
- devInfo->subDeviceCount = 0 ;
662
- devInfo->sensorCount = _initData->sensorsLength ;
663
-
664
- _rdm.packet .DataLength = sizeof (DEVICEINFO);
665
- handled = true ;
644
+ } else if (Parameter == SWAPINT (E120_DEVICE_INFO)) { // 0x0060
645
+ if (CmdClass == E120_GET_COMMAND) {
646
+ if (_rdm.packet .DataLength > 0 ) {
647
+ // Unexpected data
648
+ nackReason = E120_NR_FORMAT_ERROR;
649
+ } else if (_rdm.packet .SubDev != 0 ) {
650
+ // No sub-devices supported
651
+ nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
652
+ } else {
653
+ // return all device info data
654
+ DEVICEINFO *devInfo = (DEVICEINFO *)(_rdm.packet .Data ); // The data has to be responded in the Data buffer.
655
+
656
+ devInfo->protocolMajor = 1 ;
657
+ devInfo->protocolMinor = 0 ;
658
+ devInfo->deviceModel = SWAPINT (_initData->deviceModelId );
659
+ devInfo->productCategory = SWAPINT (E120_PRODUCT_CATEGORY_DIMMER_CS_LED);
660
+ devInfo->softwareVersion = SWAPINT32 (0x01000000 );// 0x04020900;
661
+ devInfo->footprint = SWAPINT (_initData->footprint );
662
+ devInfo->currentPersonality = 1 ;
663
+ devInfo->personalityCount = 1 ;
664
+ devInfo->startAddress = SWAPINT (_startAddress);
665
+ devInfo->subDeviceCount = 0 ;
666
+ devInfo->sensorCount = _initData->sensorsLength ;
667
+
668
+ _rdm.packet .DataLength = sizeof (DEVICEINFO);
669
+ handled = true ;
670
+ }
671
+ } else if (CmdClass == E120_SET_COMMAND) {
672
+ // Unexpected set
673
+ nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS;
666
674
}
667
675
668
- } else if ((CmdClass == E120_GET_COMMAND) && (Parameter == SWAPINT (E120_MANUFACTURER_LABEL))) { // 0x0081
669
- if (_rdm.packet .DataLength > 0 ) {
670
- // Unexpected data
671
- nackReason = E120_NR_FORMAT_ERROR;
672
- } else if (_rdm.packet .SubDev != 0 ) {
673
- // No sub-devices supported
674
- nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
675
- } else {
676
- // return the manufacturer label
677
- _rdm.packet .DataLength = strlen (_initData->manufacturerLabel );
678
- memcpy (_rdm.packet .Data , _initData->manufacturerLabel , _rdm.packet .DataLength );
679
- handled = true ;
676
+ } else if (Parameter == SWAPINT (E120_MANUFACTURER_LABEL)) { // 0x0081
677
+ if (CmdClass == E120_GET_COMMAND) {
678
+ if (_rdm.packet .DataLength > 0 ) {
679
+ // Unexpected data
680
+ nackReason = E120_NR_FORMAT_ERROR;
681
+ } else if (_rdm.packet .SubDev != 0 ) {
682
+ // No sub-devices supported
683
+ nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
684
+ } else {
685
+ // return the manufacturer label
686
+ _rdm.packet .DataLength = strnlen (_initData->manufacturerLabel , DMXSERIAL_MAX_RDM_STRING_LENGTH);
687
+ memcpy (_rdm.packet .Data , _initData->manufacturerLabel , _rdm.packet .DataLength );
688
+ handled = true ;
689
+ }
690
+ } else if (CmdClass == E120_SET_COMMAND) {
691
+ // Unexpected set
692
+ nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS;
680
693
}
681
694
682
- } else if ((CmdClass == E120_GET_COMMAND) && (Parameter == SWAPINT (E120_DEVICE_MODEL_DESCRIPTION))) { // 0x0080
683
- if (_rdm.packet .DataLength > 0 ) {
684
- // Unexpected data
685
- nackReason = E120_NR_FORMAT_ERROR;
686
- } else if (_rdm.packet .SubDev != 0 ) {
687
- // No sub-devices supported
688
- nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
689
- } else {
690
- // return the DEVICE MODEL DESCRIPTION
691
- _rdm.packet .DataLength = strlen (_initData->deviceModel );
692
- memcpy (_rdm.packet .Data , _initData->deviceModel , _rdm.packet .DataLength );
693
- handled = true ;
695
+ } else if (Parameter == SWAPINT (E120_DEVICE_MODEL_DESCRIPTION)) { // 0x0080
696
+ if (CmdClass == E120_GET_COMMAND) {
697
+ if (_rdm.packet .DataLength > 0 ) {
698
+ // Unexpected data
699
+ nackReason = E120_NR_FORMAT_ERROR;
700
+ } else if (_rdm.packet .SubDev != 0 ) {
701
+ // No sub-devices supported
702
+ nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
703
+ } else {
704
+ // return the DEVICE MODEL DESCRIPTION
705
+ _rdm.packet .DataLength = strnlen (_initData->deviceModel , DMXSERIAL_MAX_RDM_STRING_LENGTH);
706
+ memcpy (_rdm.packet .Data , _initData->deviceModel , _rdm.packet .DataLength );
707
+ handled = true ;
708
+ }
709
+ } else if (CmdClass == E120_SET_COMMAND) {
710
+ // Unexpected set
711
+ nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS;
694
712
}
695
713
696
714
} else if (Parameter == SWAPINT (E120_DEVICE_LABEL)) { // 0x0082
@@ -700,7 +718,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool
700
718
nackReason = E120_NR_FORMAT_ERROR;
701
719
} else {
702
720
memcpy (deviceLabel, _rdm.packet .Data , _rdm.packet .DataLength );
703
- deviceLabel[_rdm.packet .DataLength ] = ' \0 ' ;
721
+ deviceLabel[min ( _rdm.packet .DataLength , DMXSERIAL_MAX_RDM_STRING_LENGTH) ] = ' \0 ' ;
704
722
_rdm.packet .DataLength = 0 ;
705
723
// persist in EEPROM
706
724
_saveEEPRom ();
@@ -714,24 +732,29 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool
714
732
// No sub-devices supported
715
733
nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
716
734
} else {
717
- _rdm.packet .DataLength = strlen (deviceLabel);
735
+ _rdm.packet .DataLength = strnlen (deviceLabel, DMXSERIAL_MAX_RDM_STRING_LENGTH );
718
736
memcpy (_rdm.packet .Data , deviceLabel, _rdm.packet .DataLength );
719
737
handled = true ;
720
738
}
721
739
} // if
722
740
723
- } else if ((CmdClass == E120_GET_COMMAND) && (Parameter == SWAPINT (E120_SOFTWARE_VERSION_LABEL))) { // 0x00C0
724
- if (_rdm.packet .DataLength > 0 ) {
725
- // Unexpected data
726
- nackReason = E120_NR_FORMAT_ERROR;
727
- } else if (_rdm.packet .SubDev != 0 ) {
728
- // No sub-devices supported
729
- nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
730
- } else {
731
- // return the SOFTWARE_VERSION_LABEL
732
- _rdm.packet .DataLength = strlen (_softwareLabel);
733
- memcpy (_rdm.packet .Data , _softwareLabel, _rdm.packet .DataLength );
734
- handled = true ;
741
+ } else if (Parameter == SWAPINT (E120_SOFTWARE_VERSION_LABEL)) { // 0x00C0
742
+ if (CmdClass == E120_GET_COMMAND) {
743
+ if (_rdm.packet .DataLength > 0 ) {
744
+ // Unexpected data
745
+ nackReason = E120_NR_FORMAT_ERROR;
746
+ } else if (_rdm.packet .SubDev != 0 ) {
747
+ // No sub-devices supported
748
+ nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE;
749
+ } else {
750
+ // return the SOFTWARE_VERSION_LABEL
751
+ _rdm.packet .DataLength = strnlen (_softwareLabel, DMXSERIAL_MAX_RDM_STRING_LENGTH);
752
+ memcpy (_rdm.packet .Data , _softwareLabel, _rdm.packet .DataLength );
753
+ handled = true ;
754
+ }
755
+ } else if (CmdClass == E120_SET_COMMAND) {
756
+ // Unexpected set
757
+ nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS;
735
758
}
736
759
737
760
} else if (Parameter == SWAPINT (E120_DMX_START_ADDRESS)) { // 0x00F0
@@ -822,7 +845,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool
822
845
// Out of range sensor
823
846
nackReason = E120_NR_DATA_OUT_OF_RANGE;
824
847
} else {
825
- _rdm.packet .DataLength = 13 + strlen (_initData->sensors [sensorNr].description );
848
+ _rdm.packet .DataLength = 13 + strnlen (_initData->sensors [sensorNr].description , DMXSERIAL_MAX_RDM_STRING_LENGTH );
826
849
_rdm.packet .Data [0 ] = sensorNr;
827
850
_rdm.packet .Data [1 ] = _initData->sensors [sensorNr].type ;
828
851
_rdm.packet .Data [2 ] = _initData->sensors [sensorNr].unit ;
@@ -922,12 +945,13 @@ void DMXSerialClass2::_saveEEPRom()
922
945
eeprom.sig1 = 0x6D ;
923
946
eeprom.sig2 = 0x68 ;
924
947
eeprom.startAddress = _startAddress;
925
- strcpy (eeprom.deviceLabel , deviceLabel);
948
+ // This needs restricting to 32 chars (potentially no null), for backwards compatibility
949
+ strncpy (eeprom.deviceLabel , deviceLabel, DMXSERIAL_MAX_RDM_STRING_LENGTH);
926
950
DeviceIDCpy (eeprom.deviceID , _devID);
927
951
928
952
for (unsigned int i = 0 ; i < sizeof (eeprom); i++) {
929
- if (((byte *)(&eeprom))[i] != EEPROM. read (i))
930
- EEPROM.write (i, ((byte *)(&eeprom))[i]);
953
+ // EEPROM.update does a read/write check and only writes on a change
954
+ EEPROM.update (i, ((byte *)(&eeprom))[i]);
931
955
} // for
932
956
} // _saveEEPRom
933
957
0 commit comments