From 1245d9021b6df40c223a50ceaf308c349e41ce79 Mon Sep 17 00:00:00 2001 From: HeFeng1947 Date: Thu, 13 Jan 2022 17:05:12 +0800 Subject: [PATCH] Merge Dev branch -- support 700 series bridge firmware --- cpp/src/Defs.h | 2 + cpp/src/Driver.cpp | 148 ++++++++++++++++++++++++++++++-------------- cpp/src/Node.cpp | 19 +++--- dist/openzwave.spec | 4 +- 4 files changed, 117 insertions(+), 56 deletions(-) diff --git a/cpp/src/Defs.h b/cpp/src/Defs.h index 2789311d88..0ba346311b 100644 --- a/cpp/src/Defs.h +++ b/cpp/src/Defs.h @@ -310,6 +310,8 @@ namespace OpenZWave #define FUNC_ID_ZW_SET_SLAVE_LEARN_MODE 0xA4 // Enter slave learn mode #define FUNC_ID_ZW_GET_VIRTUAL_NODES 0xA5 // Return all virtual nodes #define FUNC_ID_ZW_IS_VIRTUAL_NODE 0xA6 // Virtual node test +#define FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE 0xA8 // Bridge Version of FUNC_ID_APPLICATION_COMMAND_HANDLER +#define FUNC_ID_ZW_SEND_DATA_BRIDGE 0xA9 // Bridge Version of FUNC_ID_SEND_DATA #define FUNC_ID_ZW_SET_PROMISCUOUS_MODE 0xD0 // Set controller into promiscuous mode to listen to all frames #define FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER 0xD1 diff --git a/cpp/src/Driver.cpp b/cpp/src/Driver.cpp index 84124da920..1b0abaf1d6 100644 --- a/cpp/src/Driver.cpp +++ b/cpp/src/Driver.cpp @@ -1275,7 +1275,7 @@ bool Driver::WriteMsg(string const &msg) { node->m_sentCnt++; node->m_sentTS.SetTime(); - if (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER) + if ( (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER) || (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) ) { Internal::CC::CommandClass *cc = node->GetCommandClass(m_expectedCommandClassId); if (cc != NULL) @@ -1795,6 +1795,21 @@ bool Driver::ReadMsg() return true; } +bool checkReplyForCommandHandler(uint8 expectedReply, uint8 reply) { + if ( ( expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER) || (expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) ) { + if (reply == FUNC_ID_APPLICATION_COMMAND_HANDLER) { + return true; + } else if (reply == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) { + return true; + } + return false; + } else if (expectedReply == reply) { + return true; + } + return false; +} + + //----------------------------------------------------------------------------- // // Process data received from the Z-Wave PC interface @@ -1803,47 +1818,66 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) { bool handleCallback = true; bool wasencrypted = false; - //uint8 nodeId = GetNodeNumber( m_currentMsg ); + uint8 node; + uint8 cc; + uint8 cccmd; + uint8 startdata; + uint8 pktlength; - if ((REQUEST == _data[0]) && FUNC_ID_APPLICATION_COMMAND_HANDLER == _data[1] && (Internal::CC::Security::StaticGetCommandClassId() == _data[5])) + if (_data[1] == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) { + node = _data[4]; + cc = _data[6]; + cccmd = _data[7]; + startdata = 8; + pktlength = 5; + + } else { + node = _data[3]; + cc = _data[5]; + cccmd = _data[6]; + startdata = 7; + pktlength = 4; + } + + if ((REQUEST == _data[0]) && ( ( FUNC_ID_APPLICATION_COMMAND_HANDLER == _data[1] ) || ( FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE == _data[1] ) ) && (Internal::CC::Security::StaticGetCommandClassId() == cc)) { /* if this message is a NONCE Report - Then just Trigger the Encrypted Send */ - if (Internal::CC::SecurityCmd_NonceReport == _data[6]) + if (Internal::CC::SecurityCmd_NonceReport == cccmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceReport from node %d", _data[3]); + Log::Write(LogLevel_Info, node, "Received SecurityCmd_NonceReport from node %d", node); /* handle possible resends of NONCE_REPORT messages.... See Issue #931 */ if (!m_currentMsg) { - Log::Write(LogLevel_Warning, _data[3], "Received a NonceReport from node, but no pending messages. Dropping.."); + Log::Write(LogLevel_Warning, node, "Received a NonceReport from node, but no pending messages. Dropping.."); return; } // No Need to triger a WriteMsg here - It should be handled automatically - m_currentMsg->setNonce(&_data[7]); + m_currentMsg->setNonce(&_data[startdata]); this->SendEncryptedMessage(); return; /* if this is a NONCE Get - Then call to the CC directly, process it, and then bail out. */ } - else if (Internal::CC::SecurityCmd_NonceGet == _data[6]) + else if (Internal::CC::SecurityCmd_NonceGet == cccmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceGet from node %d", _data[3]); + Log::Write(LogLevel_Info, node, "Received SecurityCmd_NonceGet from node %d", node); { uint8 *nonce = NULL; Internal::LockGuard LG(m_nodeMutex); - Node* node = GetNode(_data[3]); + Node* nodeobj = GetNode(node); if (node) { - nonce = node->GenerateNonceKey(); + nonce = nodeobj->GenerateNonceKey(); } else { - Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); + Log::Write(LogLevel_Warning, node, "Couldn't Generate Nonce Key for Node %d", node); return; } - SendNonceKey(_data[3], nonce); + SendNonceKey(node, nonce); } /* don't continue processing */ @@ -1851,10 +1885,10 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) /* if this message is encrypted, decrypt it first */ } - else if ((Internal::CC::SecurityCmd_MessageEncap == _data[6]) || (Internal::CC::SecurityCmd_MessageEncapNonceGet == _data[6])) + else if ((Internal::CC::SecurityCmd_MessageEncap == cccmd) || (Internal::CC::SecurityCmd_MessageEncapNonceGet == cccmd)) { uint8 _newdata[256]; - uint8 SecurityCmd = _data[6]; + uint8 SecurityCmd = cccmd; uint8 *_nonce; /* clear out NONCE Report tracking */ @@ -1864,51 +1898,62 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) /* make sure the Node Exists, and it has the Security CC */ { Internal::LockGuard LG(m_nodeMutex); - Node* node = GetNode(_data[3]); - if (node) + Node* nodeobj = GetNode(node); + if (nodeobj) { - _nonce = node->GetNonceKey(_data[_data[4] - 4]); + uint8 nonceid; + if (_data[1] == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) + { + nonceid = _data[_data[pktlength]-3]; + }else{ + nonceid = _data[_data[pktlength]-4]; + } + + _nonce = nodeobj->GetNonceKey(nonceid); if (!_nonce) { - Log::Write(LogLevel_Warning, _data[3], "Could Not Retrieve Nonce for Node %d", _data[3]); + Log::Write(LogLevel_Warning, node, "Could Not Retrieve Nonce for Node %d", node); return; } } else { - Log::Write(LogLevel_Warning, _data[3], "Can't Find Node %d for Encrypted Message", _data[3]); + Log::Write(LogLevel_Warning, node, "Can't Find Node %d for Encrypted Message", node); return; } } - if (Internal::DecryptBuffer(&_data[5], _data[4] + 1, this, _data[3], this->GetControllerNodeId(), _nonce, &_newdata[0])) + /* StartData - 2 as we start at the CC ID */ + if (Internal::DecryptBuffer(&_data[startdata-2], _data[pktlength]+1, this, node, this->GetControllerNodeId(), _nonce, &_newdata[0])) { /* Ok - _newdata now contains the decrypted packet */ /* copy it back to the _data packet for processing */ /* New Length - See Decrypt Packet for why these numbers*/ - _data[4] = _data[4] - 8 - 8 - 2 - 2; + _data[pktlength] = _data[pktlength] - 8 - 8 - 2 - 2; /* now copy the decrypted packet */ - memcpy(&_data[5], &_newdata[1], _data[4]); + memcpy(&_data[pktlength+1], &_newdata[1], _data[pktlength]); //PrintHex("Decrypted Packet", _data, _data[4]+5); /* if the Node has something else to send, it will encrypt a message and send it as a MessageEncapNonceGet */ if (Internal::CC::SecurityCmd_MessageEncapNonceGet == SecurityCmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3]); + Log::Write(LogLevel_Info, node, "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", node); Internal::LockGuard LG(m_nodeMutex); - Node* node = GetNode(_data[3]); - if (node) + Node* nodeobj = GetNode(node); + if (nodeobj) { - _nonce = node->GenerateNonceKey(); + _nonce = nodeobj->GenerateNonceKey(); } else { - Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); + Log::Write(LogLevel_Warning, node, "Couldn't Generate Nonce Key for Node %d", node); return; } - SendNonceKey(_data[3], _nonce); + SendNonceKey(node, _nonce); } + /* reset our CC as its now decrypted */ + cc = _data[1] == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE ? _data[6] : _data[5]; wasencrypted = true; } @@ -1917,19 +1962,19 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) /* if the Node has something else to send, it will encrypt a message and send it as a MessageEncapNonceGet */ if (Internal::CC::SecurityCmd_MessageEncapNonceGet == SecurityCmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3]); + Log::Write(LogLevel_Info, node, "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", node); Internal::LockGuard LG(m_nodeMutex); - Node* node = GetNode(_data[3]); + Node* nodeobj = GetNode(node); if (node) { - _nonce = node->GenerateNonceKey(); + _nonce = nodeobj->GenerateNonceKey(); } else { - Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); + Log::Write(LogLevel_Warning, node, "Couldn't Generate Nonce Key for Node %d", node); return; } - SendNonceKey(_data[3], _nonce); + SendNonceKey(node, _nonce); } /* it failed for some reason, lets just move on */ m_expectedReply = 0; @@ -2202,6 +2247,7 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) switch (_data[1]) { case FUNC_ID_APPLICATION_COMMAND_HANDLER: + case FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE: { Log::Write(LogLevel_Detail, ""); HandleApplicationCommandHandlerRequest(_data, wasencrypted); @@ -2385,13 +2431,17 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) } if (m_expectedReply) { - if (m_expectedReply == _data[1]) + /* if m_expectedReply was FUNC_ID_APPLICATION_COMMAND_HANDLER then the actual reply can either be + * FUNC_ID_APPLICATION_COMMAND_HANDLER - For Static Controllers or + * FUNC_ID_APPLICATION_COMMAND_HANDLER || FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE for Bridge Controllers + */ + if ( checkReplyForCommandHandler(m_expectedReply, _data[1]) ) { - if (m_expectedCommandClassId && (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER)) + if (m_expectedCommandClassId && ( ( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER) || ( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) ) ) { - if (m_expectedCallbackId == 0 && m_expectedCommandClassId == _data[5] && m_expectedNodeId == _data[3]) + if (m_expectedCallbackId == 0 && m_expectedCommandClassId == cc && m_expectedNodeId == node) { - Log::Write(LogLevel_Detail, _data[3], " Expected reply and command class was received"); + Log::Write(LogLevel_Detail, node, " Expected reply and command class was received"); m_waitingForAck = false; m_expectedReply = 0; m_expectedCommandClassId = 0; @@ -2400,7 +2450,7 @@ void Driver::ProcessMsg(uint8* _data, uint8 _length) } else { - if (IsExpectedReply(_data[3])) + if (IsExpectedReply(node)) { Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), " Expected reply was received"); @@ -2443,10 +2493,10 @@ void Driver::HandleGetVersionResponse(uint8* _data) } Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_GET_VERSION:"); Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " %s library, version %s", m_libraryTypeName.c_str(), m_libraryVersion.c_str()); - if (!((m_libraryType == ZW_LIB_CONTROLLER_STATIC) || (m_libraryType == ZW_LIB_CONTROLLER))) + if (!((m_libraryType == ZW_LIB_CONTROLLER_STATIC) || (m_libraryType == ZW_LIB_CONTROLLER) || (m_libraryType == ZW_LIB_CONTROLLER_BRIDGE) )) { Log::Write(LogLevel_Fatal, GetNodeNumber(m_currentMsg), "Z-Wave Interface is not a Supported Library Type: %s", m_libraryTypeName.c_str()); - Log::Write(LogLevel_Fatal, GetNodeNumber(m_currentMsg), "Z-Wave Interface should be a Static Controller Library Type"); + Log::Write(LogLevel_Fatal, GetNodeNumber(m_currentMsg), "Z-Wave Interface should be a Static or Bridge Controller Library Type"); { Notification* notification = new Notification(Notification::Type_UserAlerts); @@ -2575,7 +2625,7 @@ void Driver::HandleGetSerialAPICapabilitiesResponse(uint8* _data) } SendMsg(new Internal::Msg("FUNC_ID_SERIAL_API_GET_INIT_DATA", 0xff, REQUEST, FUNC_ID_SERIAL_API_GET_INIT_DATA, false), MsgQueue_Command); - if (!IsBridgeController()) + // if (!IsBridgeController()) { Internal::Msg* msg = new Internal::Msg("FUNC_ID_SERIAL_API_SET_TIMEOUTS", 0xff, REQUEST, FUNC_ID_SERIAL_API_SET_TIMEOUTS, false); msg->Append( ACK_TIMEOUT / 10); @@ -2591,7 +2641,9 @@ void Driver::HandleGetSerialAPICapabilitiesResponse(uint8* _data) list advertisedCommandClasses = Internal::CC::CommandClasses::GetAdvertisedCommandClasses(); msg->Append((uint8) advertisedCommandClasses.size()); // Length for (list::iterator it = advertisedCommandClasses.begin(); it != advertisedCommandClasses.end(); ++it) + { msg->Append(*it); + } SendMsg(msg, MsgQueue_Command); } @@ -3578,8 +3630,9 @@ void Driver::HandleApplicationCommandHandlerRequest(uint8* _data, bool encrypted { uint8 status = _data[2]; - uint8 nodeId = _data[3]; - uint8 classId = _data[5]; + uint8 nodeId = this->IsBridgeController() ? _data[4] : _data[3]; + uint8 classId = this->IsBridgeController() ? _data[6] : _data[5]; + uint8 lengthbyte = this->IsBridgeController() ? _data[5] : _data[4]; Node* node = GetNodeUnsafe(nodeId); if ((status & RECEIVE_STATUS_ROUTED_BUSY) != 0) @@ -3605,7 +3658,7 @@ void Driver::HandleApplicationCommandHandlerRequest(uint8* _data, bool encrypted memcpy(node->m_lastReceivedMessage, _data, sizeof(node->m_lastReceivedMessage)); } node->m_receivedTS.SetTime(); - if (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER && m_expectedNodeId == nodeId) + if ( ( ( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER ) || ( m_expectedReply = FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE) ) && ( m_expectedNodeId == nodeId ) ) { // Need to confirm this is the correct response to the last sent request. // At least ignore any received messages prior to the send data request. @@ -3640,7 +3693,7 @@ void Driver::HandleApplicationCommandHandlerRequest(uint8* _data, bool encrypted { if (m_controllerReplication && m_currentControllerCommand && (ControllerCommand_ReceiveConfiguration == m_currentControllerCommand->m_controllerCommand)) { - m_controllerReplication->HandleMsg(&_data[6], _data[4]); + m_controllerReplication->HandleMsg(&_data[6], _data[lengthbyte]); UpdateControllerState(ControllerState_InProgress); } @@ -6458,6 +6511,9 @@ uint8 Driver::NodeFromMessage(uint8 const* buffer) case FUNC_ID_APPLICATION_COMMAND_HANDLER: nodeId = buffer[5]; break; + case FUNC_ID_APPLICATION_COMMAND_HANDLER_BRIDGE: + nodeId = buffer[6]; + break; case FUNC_ID_ZW_APPLICATION_UPDATE: nodeId = buffer[5]; break; diff --git a/cpp/src/Node.cpp b/cpp/src/Node.cpp index 0ecd05a092..42fc3beb1b 100644 --- a/cpp/src/Node.cpp +++ b/cpp/src/Node.cpp @@ -2044,7 +2044,10 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted ) { - if (Internal::CC::CommandClass* pCommandClass = GetCommandClass(_data[5])) + uint8_t cc = GetDriver()->IsBridgeController() ? _data[6] : _data[5]; + uint8_t startdata = GetDriver()->IsBridgeController() ? 7 : 6; + uint8_t lendata = GetDriver()->IsBridgeController() ? 5 : 4; + if (Internal::CC::CommandClass* pCommandClass = GetCommandClass(cc)) { if (pCommandClass->IsSecured() && !encrypted) { @@ -2065,14 +2068,14 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted pCommandClass->ReceivedCntIncr(); if (!pCommandClass->IsAfterMark()) { - if (!pCommandClass->HandleMsg(&_data[6], _data[4])) + if (!pCommandClass->HandleMsg(&_data[startdata], _data[lendata])) { Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandlerMsg Returned False", pCommandClass->GetCommandClassName().c_str()); } } else { - if (!pCommandClass->HandleIncomingMsg(&_data[6], _data[4])) + if (!pCommandClass->HandleIncomingMsg(&_data[startdata], _data[lendata])) { Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncomingMsg Returned False", pCommandClass->GetCommandClassName().c_str()); } @@ -2080,7 +2083,7 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted } else { - if (_data[5] == Internal::CC::ControllerReplication::StaticGetCommandClassId()) + if (cc == Internal::CC::ControllerReplication::StaticGetCommandClassId()) { // This is a controller replication message, and we do not support it. // We have to at least acknowledge the message to avoid locking the sending device. @@ -2089,7 +2092,7 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted Internal::Msg* msg = new Internal::Msg("Replication Command Complete", m_nodeId, REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false); GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); } - else if (_data[5] == Internal::CC::MultiInstance::StaticGetCommandClassId()) + else if (cc == Internal::CC::MultiInstance::StaticGetCommandClassId()) { // Devices that support MultiChannelAssociation may send a MultiChannel Encapsulated message if there is a Instance set in the Association Groups // So we will dynamically load the MultiChannel CC if we receive a encapsulated message @@ -2107,14 +2110,14 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted pCommandClass->ReceivedCntIncr(); if (!pCommandClass->IsAfterMark()) { - if (!pCommandClass->HandleMsg(&_data[6], _data[4])) + if (!pCommandClass->HandleMsg(&_data[startdata], _data[lendata])) { Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleMsg returned false", pCommandClass->GetCommandClassName().c_str()); } } else { - if (!pCommandClass->HandleIncomingMsg(&_data[6], _data[4])) + if (!pCommandClass->HandleIncomingMsg(&_data[startdata], _data[lendata])) { Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncommingMsg returned false", pCommandClass->GetCommandClassName().c_str()); } @@ -2123,7 +2126,7 @@ void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted } else { - Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", _data[5]); + Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", cc); } } } diff --git a/dist/openzwave.spec b/dist/openzwave.spec index b05b46db51..08c6af54bb 100644 --- a/dist/openzwave.spec +++ b/dist/openzwave.spec @@ -3,7 +3,7 @@ %endif Name: openzwave -Version: 1.6.1545 +Version: 1.6.1956 Release: 1.0%{?dist} Summary: Sample Executables for OpenZWave URL: http://www.openzwave.net @@ -135,7 +135,7 @@ getent group zwave >/dev/null || groupadd -f -r zwave %changelog -* Wed May 08 2019 Justin Hammond - 1.6.1545 +* Wed May 08 2019 Justin Hammond - 1.6.1956 - Update to new release of OpenZwave - 1.6 * Fri Feb 01 2019 Fedora Release Engineering - 1.5.0-0.20180624git1e36dcc.0