1 //-----------------------------------------------------------------------------
2 //
3 // CRC16Encap.cpp
4 //
5 // Implementation of the Z-Wave COMMAND_CLASS_CRC_16_ENCAP
6 //
7 // Copyright (c) 2012 Greg Satz <satz@iranger.com>
8 //
9 // SOFTWARE NOTICE AND LICENSE
10 //
11 // This file is part of OpenZWave.
12 //
13 // OpenZWave is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published
15 // by the Free Software Foundation, either version 3 of the License,
16 // or (at your option) any later version.
17 //
18 // OpenZWave is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with OpenZWave. If not, see <http://www.gnu.org/licenses/>.
25 //
26 //-----------------------------------------------------------------------------
27
28 #include "command_classes/CommandClasses.h"
29 #include "command_classes/CRC16Encap.h"
30 #include "Defs.h"
31 #include "Msg.h"
32 #include "Node.h"
33 #include "Driver.h"
34 #include "platform/Log.h"
35
36 using namespace OpenZWave;
37
38 //
39 // CRC-CCITT (0x1D0F)
40 //
crc16(uint8 const * data_p,uint32 const _length)41 uint16 crc16(uint8 const * data_p, uint32 const _length){
42 uint8 x;
43 uint16 crc = 0xF6AF; // 0x1D0F with first byte 0x56;
44 uint32 length = _length;
45
46 while (length--){
47 x = crc >> 8 ^ *data_p++;
48 x ^= x>>4;
49 crc = (crc << 8) ^ ((uint16)(x << 12)) ^ ((uint16)(x <<5)) ^ ((uint16)x);
50 }
51 return crc;
52 }
53
54 enum CRC16EncapCmd
55 {
56 CRC16EncapCmd_Encap = 0x01
57 };
58
59
60 //-----------------------------------------------------------------------------
61 // <CRC16Encap::HandleMsg>
62 // Handle a message from the Z-Wave network
63 //-----------------------------------------------------------------------------
HandleMsg(uint8 const * _data,uint32 const _length,uint32 const _instance)64 bool CRC16Encap::HandleMsg
65 (
66 uint8 const* _data,
67 uint32 const _length,
68 uint32 const _instance // = 1
69 )
70 {
71 if( CRC16EncapCmd_Encap == (CRC16EncapCmd)_data[0] )
72 {
73 Log::Write( LogLevel_Info, GetNodeId(), "Received CRC16-command from node %d", GetNodeId());
74
75 uint16 crcM = (_data[_length - 3] << 8) + _data[_length - 2] ; // crc as reported in msg
76 uint16 crcC = crc16(&_data[0], _length - 3 ); // crc calculated
77
78 if ( crcM != crcC )
79 {
80 Log::Write( LogLevel_Info, GetNodeId(), "CRC check failed, message contains 0x%.4x but should be 0x%.4x", crcM, crcC);
81 return false;
82 }
83
84 if( Node const* node = GetNodeUnsafe() )
85 {
86 uint8 commandClassId = _data[1];
87
88 if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) )
89 {
90 pCommandClass->HandleMsg( &_data[2], _length - 4 );
91 }
92 }
93
94 return true;
95 }
96 return false;
97 }
98