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