mirror of
https://github.com/arendst/Tasmota.git
synced 2026-07-28 04:15:53 +00:00
Zigbee multiple fixes (#24806)
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user