Zigbee multiple fixes (#24806)

This commit is contained in:
s-hadinger
2026-05-30 16:50:50 +02:00
committed by GitHub
parent 7edbc4b3d8
commit 944ad6de4b
6 changed files with 29 additions and 15 deletions
@@ -684,6 +684,7 @@ String Z_attribute::toString(bool prefix_comma) const {
res += '"';
if (val.bval) {
size_t blen = val.bval->len();
if (blen > 250) { blen = 250; } // safeguard: Zigbee frames never exceed 256 bytes; cap hex buffer to 500 bytes on stack
// print as HEX
char hex[2*blen+1];
ToHex_P(val.bval->getBuffer(), blen, hex, sizeof(hex));
@@ -40,7 +40,7 @@
// returns the lenght of consumed buffer, or -1 if error
int32_t hydrateDeviceWideData(class Z_Device & device, const SBuffer & buf, size_t start, size_t len) {
size_t segment_len = buf.get8(start);
if ((segment_len < 6) || (segment_len > len)) {
if ((segment_len < 7) || (segment_len > len)) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "invalid device wide data length=%d"), segment_len);
return -1;
}
@@ -77,6 +77,11 @@ bool convertGPDF_data(class Z_attribute_list &attr_list, uint16_t shortaddr, uin
// Handle GPDF Commissioning 0xE0 command
bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t shortaddr, bool wasbroadcast, const SBuffer &payload, size_t payload_start, size_t payload_len) {
uint32_t idx_offset = payload_start; // offset compared to minimal packet
size_t payload_end = payload_start + payload_len;
// (a) Need at least 2 bytes for gpd_device_id + gpd_options
if (payload_len < 2) { return false; }
uint8_t gpd_device_id = payload.get8(idx_offset++); // type of device
uint8_t gpd_options = payload.get8(idx_offset++);
@@ -90,6 +95,7 @@ bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t short
uint8_t gpd_options_ext = 0;
if (gpd_options_has_ext) {
if (idx_offset >= payload_end) { return false; }
gpd_options_ext = payload.get8(idx_offset++);
}
uint8_t gpd_sec_level_capa = (gpd_options_ext & 0x03);
@@ -101,17 +107,21 @@ bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t short
uint64_t gpd_key_low = 0;
uint64_t gpd_key_high = 0;
if (gpd_key_present) {
// (b) Need 16 bytes for the key
if (idx_offset + 16 > payload_end) { return false; }
gpd_key_low = payload.get64(idx_offset);
gpd_key_high = payload.get64(idx_offset + 8);
idx_offset += 16;
}
uint32_t gpd_key_mic = 0;
if (gpd_key_present && gpd_key_encryption) {
if (idx_offset + 4 > payload_end) { return false; }
gpd_key_mic = payload.get32(idx_offset);
idx_offset += 4;
}
uint32_t gpd_out_counter = 0;
if (gpd_out_counter_present) {
if (idx_offset + 4 > payload_end) { return false; }
gpd_out_counter = payload.get32(idx_offset);
idx_offset += 4;
}
@@ -145,7 +155,7 @@ bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t short
bool gp_app_cluster_reports_present = (gp_app_info & 0x08);
if (gp_app_manuf_present) {
uint16_t gp_app_manuf_id = payload.get8(idx_offset);
uint16_t gp_app_manuf_id = payload.get16(idx_offset);
idx_offset += 2;
ResponseAppend_P(PSTR(",\"manufid\":\"0x%04X\""), gp_app_manuf_id);
}
@@ -166,6 +166,7 @@ bool ZbLoad_inner(const char *filename, File &fp) {
// allocate only once the filename for multiple entries
// freed only by `ZbUnload`
filename_imported = (char*) malloc(strlen_P(filename)+1);
if (filename_imported == nullptr) { return false; } // L-34: guard against malloc failure
strcpy_P(filename_imported, filename);
}
@@ -232,7 +232,7 @@ void ZigbeeInputLoop(void) {
// compute CRC
for (uint32_t i=0; i<frame_len-2; i++) {
crc = crc ^ ((uint16_t)zigbee_buffer->get8(i) << 8);
for (uint32_t i=0; i<8; i++) {
for (uint32_t j=0; j<8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021; // polynom is x^16 + x^12 + x^5 + 1, CCITT standard
} else {
@@ -479,7 +479,7 @@ void ZigbeeEZSPSendRaw(const uint8_t *msg, size_t len, bool send_cancel) {
// compute CRC
crc = crc ^ ((uint16_t)out_byte << 8);
for (uint32_t i=0; i<8; i++) {
for (uint32_t j=0; j<8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021; // polynom is x^16 + x^12 + x^5 + 1, CCITT standard
} else {
@@ -37,6 +37,7 @@
#define XM_NAK 0x15
#define XM_CAN 0x18
#define XM_SUB 0x1a
#define XM_TIMEOUT (-1) // sentinel returned by XModemWaitACK() and ZigbeeUploadFlashRead() on error
enum ZbUploadSteps { ZBU_IDLE, ZBU_INIT,
ZBU_SOFTWARE_RESET, ZBU_SOFTWARE_SEND, ZBU_HARDWARE_RESET, ZBU_PROMPT,
@@ -65,10 +66,10 @@ uint32_t ZigbeeUploadAvailable(void) {
return available;
}
char ZigbeeUploadFlashRead(void) {
int16_t ZigbeeUploadFlashRead(void) {
if (nullptr == ZbUpload.buffer) {
if (!(ZbUpload.buffer = (char *)malloc(SPI_FLASH_SEC_SIZE))) {
return -1; // Not enough (memory) space
return XM_TIMEOUT; // Not enough (memory) space
}
}
@@ -80,7 +81,7 @@ char ZigbeeUploadFlashRead(void) {
// AddLog(LOG_LEVEL_DEBUG, "= sector %d %*_H", ZbUpload.sector_counter, 256, ZbUpload.buffer);
}
char data = ZbUpload.buffer[index];
int16_t data = (uint8_t)ZbUpload.buffer[index];
ZbUpload.byte_counter++;
if (ZbUpload.byte_counter > ZbUpload.ota_size) {
@@ -139,16 +140,16 @@ void XModemOutputByte(uint8_t out_char) {
}
// Wait for the remote to acknowledge or cancel.
// Returns the received char if no timeout occured or a CAN was received. In this cases, it returns -1.
char XModemWaitACK(void)
// Returns the received char, or XM_TIMEOUT (-1) on timeout, or XM_CAN if cancelled.
int16_t XModemWaitACK(void)
{
char in_char;
int16_t in_char;
do {
int i = 0;
while (!ZigbeeSerial->available()) {
delayMicroseconds(100);
i++;
if (i > 4000) { return -1; }
if (i > 4000) { return XM_TIMEOUT; }
}
in_char = ZigbeeSerial->read();
@@ -166,7 +167,7 @@ bool XModemSendPacket(uint32_t packet_no) {
// Sending a packet will be retried
uint32_t retries = 0;
char in_char;
int16_t in_char;
do {
// Seek to start of current data block,
// will advance through the file as block will be acked..
@@ -185,6 +186,7 @@ bool XModemSendPacket(uint32_t packet_no) {
ZigbeeSerial->write(~packet_num);
for (uint32_t i = 0; i < XMODEM_PACKET_SIZE; i++) {
in_char = ZigbeeUploadFlashRead();
if (XM_TIMEOUT == in_char) { return false; } // malloc failure
XModemOutputByte(in_char);
}
// Send out checksum, either CRC-16 CCITT or classical inverse of sum of bytes.
@@ -247,7 +249,7 @@ bool ZigbeeUploadBootloaderPrompt(void) {
// 3. ebl info[cr][lf]
// BL >
if (((uint8_t)bootloader_byte >=0) && (buf_len < sizeof(serial_buffer) -2)) {
if ((bootloader_byte >= 0) && (buf_len < sizeof(serial_buffer) -2)) {
serial_buffer[buf_len++] = bootloader_byte;
}
@@ -390,7 +392,7 @@ bool ZigbeeUploadXmodem(void) {
// [cr][lf]
// begin upload[cr][lf]
// C
char xmodem_sync = ZigbeeSerial->read();
int16_t xmodem_sync = ZigbeeSerial->read();
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("XMD: Rcvd2 0x%02X"), xmodem_sync);
@@ -441,7 +443,7 @@ bool ZigbeeUploadXmodem(void) {
return true;
}
if (ZigbeeSerial->available()) {
char xmodem_ack = XModemWaitACK();
int16_t xmodem_ack = XModemWaitACK();
if (XM_CAN == xmodem_ack) {
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Transfer invalid"));
ZbUpload.ota_step = ZBU_ERROR;