ansible4ozw 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. data/lib/ansible.rb +12 -9
  2. data/lib/ansible/ansible_device.rb +1 -1
  3. data/lib/ansible/ansible_value.rb +1 -1
  4. data/lib/ansible/config.rb +8 -5
  5. data/lib/ansible/devices.rb +1 -0
  6. data/lib/ansible/knx.rb +0 -0
  7. data/lib/ansible/knx/dpt/tests/test_dpt10.rb~ +45 -0
  8. data/lib/ansible/knx/dpt/tests/test_dpt9.rb~ +55 -0
  9. data/lib/ansible/transceiver.rb +0 -3
  10. data/lib/ansible/version.rb +3 -0
  11. data/lib/ansible/zwave.rb +1 -0
  12. data/lib/ansible/{openzwave → zwave/openzwave}/ozw_constants.rb +1 -2
  13. data/lib/ansible/{openzwave → zwave/openzwave}/ozw_headers.rb +2 -6
  14. data/lib/ansible/{openzwave → zwave/openzwave}/ozw_remote_manager.rb +0 -3
  15. data/lib/ansible/{openzwave → zwave/openzwave}/ozw_types.rb +0 -0
  16. data/lib/ansible/zwave/openzwave/src/Driver.h +695 -0
  17. data/lib/ansible/zwave/openzwave/src/Notification.h +165 -0
  18. data/lib/ansible/zwave/openzwave/src/command_classes/Alarm.cpp +142 -0
  19. data/lib/ansible/zwave/openzwave/src/command_classes/Alarm.h +69 -0
  20. data/lib/ansible/zwave/openzwave/src/command_classes/ApplicationStatus.cpp +93 -0
  21. data/lib/ansible/zwave/openzwave/src/command_classes/ApplicationStatus.h +57 -0
  22. data/lib/ansible/zwave/openzwave/src/command_classes/Association.cpp +385 -0
  23. data/lib/ansible/zwave/openzwave/src/command_classes/Association.h +73 -0
  24. data/lib/ansible/zwave/openzwave/src/command_classes/AssociationCommandConfiguration.cpp +277 -0
  25. data/lib/ansible/zwave/openzwave/src/command_classes/AssociationCommandConfiguration.h +70 -0
  26. data/lib/ansible/zwave/openzwave/src/command_classes/Basic.cpp +212 -0
  27. data/lib/ansible/zwave/openzwave/src/command_classes/Basic.h +72 -0
  28. data/lib/ansible/zwave/openzwave/src/command_classes/BasicWindowCovering.cpp +118 -0
  29. data/lib/ansible/zwave/openzwave/src/command_classes/BasicWindowCovering.h +64 -0
  30. data/lib/ansible/zwave/openzwave/src/command_classes/Battery.cpp +141 -0
  31. data/lib/ansible/zwave/openzwave/src/command_classes/Battery.h +65 -0
  32. data/lib/ansible/zwave/openzwave/src/command_classes/ClimateControlSchedule.cpp +415 -0
  33. data/lib/ansible/zwave/openzwave/src/command_classes/ClimateControlSchedule.h +71 -0
  34. data/lib/ansible/zwave/openzwave/src/command_classes/Clock.cpp +227 -0
  35. data/lib/ansible/zwave/openzwave/src/command_classes/Clock.h +67 -0
  36. data/lib/ansible/zwave/openzwave/src/command_classes/CommandClass.cpp +546 -0
  37. data/lib/ansible/zwave/openzwave/src/command_classes/CommandClass.h +145 -0
  38. data/lib/ansible/zwave/openzwave/src/command_classes/CommandClasses.cpp +291 -0
  39. data/lib/ansible/zwave/openzwave/src/command_classes/CommandClasses.h +79 -0
  40. data/lib/ansible/zwave/openzwave/src/command_classes/Configuration.cpp +258 -0
  41. data/lib/ansible/zwave/openzwave/src/command_classes/Configuration.h +67 -0
  42. data/lib/ansible/zwave/openzwave/src/command_classes/ControllerReplication.cpp +142 -0
  43. data/lib/ansible/zwave/openzwave/src/command_classes/ControllerReplication.h +63 -0
  44. data/lib/ansible/zwave/openzwave/src/command_classes/EnergyProduction.cpp +163 -0
  45. data/lib/ansible/zwave/openzwave/src/command_classes/EnergyProduction.h +65 -0
  46. data/lib/ansible/zwave/openzwave/src/command_classes/Hail.cpp +68 -0
  47. data/lib/ansible/zwave/openzwave/src/command_classes/Hail.h +58 -0
  48. data/lib/ansible/zwave/openzwave/src/command_classes/Indicator.cpp +159 -0
  49. data/lib/ansible/zwave/openzwave/src/command_classes/Indicator.h +66 -0
  50. data/lib/ansible/zwave/openzwave/src/command_classes/Language.cpp +159 -0
  51. data/lib/ansible/zwave/openzwave/src/command_classes/Language.h +65 -0
  52. data/lib/ansible/zwave/openzwave/src/command_classes/Lock.cpp +159 -0
  53. data/lib/ansible/zwave/openzwave/src/command_classes/Lock.h +66 -0
  54. data/lib/ansible/zwave/openzwave/src/command_classes/ManufacturerSpecific.cpp +439 -0
  55. data/lib/ansible/zwave/openzwave/src/command_classes/ManufacturerSpecific.h +116 -0
  56. data/lib/ansible/zwave/openzwave/src/command_classes/Meter.cpp +541 -0
  57. data/lib/ansible/zwave/openzwave/src/command_classes/Meter.h +73 -0
  58. data/lib/ansible/zwave/openzwave/src/command_classes/MeterPulse.cpp +137 -0
  59. data/lib/ansible/zwave/openzwave/src/command_classes/MeterPulse.h +65 -0
  60. data/lib/ansible/zwave/openzwave/src/command_classes/MultiCmd.cpp +77 -0
  61. data/lib/ansible/zwave/openzwave/src/command_classes/MultiCmd.h +63 -0
  62. data/lib/ansible/zwave/openzwave/src/command_classes/MultiInstance.cpp +568 -0
  63. data/lib/ansible/zwave/openzwave/src/command_classes/MultiInstance.h +96 -0
  64. data/lib/ansible/zwave/openzwave/src/command_classes/MultiInstanceAssociation.cpp +61 -0
  65. data/lib/ansible/zwave/openzwave/src/command_classes/MultiInstanceAssociation.h +59 -0
  66. data/lib/ansible/zwave/openzwave/src/command_classes/NodeNaming.cpp +525 -0
  67. data/lib/ansible/zwave/openzwave/src/command_classes/NodeNaming.h +66 -0
  68. data/lib/ansible/zwave/openzwave/src/command_classes/Powerlevel.cpp +157 -0
  69. data/lib/ansible/zwave/openzwave/src/command_classes/Powerlevel.h +82 -0
  70. data/lib/ansible/zwave/openzwave/src/command_classes/Proprietary.cpp +62 -0
  71. data/lib/ansible/zwave/openzwave/src/command_classes/Proprietary.h +58 -0
  72. data/lib/ansible/zwave/openzwave/src/command_classes/Protection.cpp +177 -0
  73. data/lib/ansible/zwave/openzwave/src/command_classes/Protection.h +73 -0
  74. data/lib/ansible/zwave/openzwave/src/command_classes/SensorAlarm.cpp +208 -0
  75. data/lib/ansible/zwave/openzwave/src/command_classes/SensorAlarm.h +77 -0
  76. data/lib/ansible/zwave/openzwave/src/command_classes/SensorBinary.cpp +134 -0
  77. data/lib/ansible/zwave/openzwave/src/command_classes/SensorBinary.h +65 -0
  78. data/lib/ansible/zwave/openzwave/src/command_classes/SensorMultilevel.cpp +237 -0
  79. data/lib/ansible/zwave/openzwave/src/command_classes/SensorMultilevel.h +71 -0
  80. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchAll.cpp +219 -0
  81. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchAll.h +69 -0
  82. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchBinary.cpp +157 -0
  83. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchBinary.h +66 -0
  84. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchMultilevel.cpp +559 -0
  85. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchMultilevel.h +83 -0
  86. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchToggleBinary.cpp +151 -0
  87. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchToggleBinary.h +66 -0
  88. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchToggleMultilevel.cpp +195 -0
  89. data/lib/ansible/zwave/openzwave/src/command_classes/SwitchToggleMultilevel.h +75 -0
  90. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatFanMode.cpp +332 -0
  91. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatFanMode.h +77 -0
  92. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatFanState.cpp +149 -0
  93. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatFanState.h +71 -0
  94. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatMode.cpp +373 -0
  95. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatMode.h +76 -0
  96. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatOperatingState.cpp +147 -0
  97. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatOperatingState.h +71 -0
  98. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatSetpoint.cpp +317 -0
  99. data/lib/ansible/zwave/openzwave/src/command_classes/ThermostatSetpoint.h +73 -0
  100. data/lib/ansible/zwave/openzwave/src/command_classes/Version.cpp +255 -0
  101. data/lib/ansible/zwave/openzwave/src/command_classes/Version.h +71 -0
  102. data/lib/ansible/zwave/openzwave/src/command_classes/WakeUp.cpp +391 -0
  103. data/lib/ansible/zwave/openzwave/src/command_classes/WakeUp.h +85 -0
  104. data/lib/ansible/zwave/openzwave/src/platform/Controller.cpp +68 -0
  105. data/lib/ansible/zwave/openzwave/src/platform/Controller.h +106 -0
  106. data/lib/ansible/zwave/openzwave/src/platform/Event.cpp +102 -0
  107. data/lib/ansible/zwave/openzwave/src/platform/Event.h +91 -0
  108. data/lib/ansible/zwave/openzwave/src/platform/HidController.cpp +539 -0
  109. data/lib/ansible/zwave/openzwave/src/platform/HidController.h +147 -0
  110. data/lib/ansible/zwave/openzwave/src/platform/Log.cpp +310 -0
  111. data/lib/ansible/zwave/openzwave/src/platform/Log.h +184 -0
  112. data/lib/ansible/zwave/openzwave/src/platform/Mutex.cpp +96 -0
  113. data/lib/ansible/zwave/openzwave/src/platform/Mutex.h +88 -0
  114. data/lib/ansible/zwave/openzwave/src/platform/Ref.h +91 -0
  115. data/lib/ansible/zwave/openzwave/src/platform/SerialController.cpp +180 -0
  116. data/lib/ansible/zwave/openzwave/src/platform/SerialController.h +138 -0
  117. data/lib/ansible/zwave/openzwave/src/platform/Stream.cpp +229 -0
  118. data/lib/ansible/zwave/openzwave/src/platform/Stream.h +135 -0
  119. data/lib/ansible/zwave/openzwave/src/platform/Thread.cpp +118 -0
  120. data/lib/ansible/zwave/openzwave/src/platform/Thread.h +101 -0
  121. data/lib/ansible/zwave/openzwave/src/platform/TimeStamp.cpp +92 -0
  122. data/lib/ansible/zwave/openzwave/src/platform/TimeStamp.h +85 -0
  123. data/lib/ansible/zwave/openzwave/src/platform/Wait.cpp +176 -0
  124. data/lib/ansible/zwave/openzwave/src/platform/Wait.h +113 -0
  125. data/lib/ansible/zwave/openzwave/src/platform/unix/EventImpl.cpp +262 -0
  126. data/lib/ansible/zwave/openzwave/src/platform/unix/EventImpl.h +62 -0
  127. data/lib/ansible/zwave/openzwave/src/platform/unix/LogImpl.cpp +304 -0
  128. data/lib/ansible/zwave/openzwave/src/platform/unix/LogImpl.h +70 -0
  129. data/lib/ansible/zwave/openzwave/src/platform/unix/MutexImpl.cpp +136 -0
  130. data/lib/ansible/zwave/openzwave/src/platform/unix/MutexImpl.h +56 -0
  131. data/lib/ansible/zwave/openzwave/src/platform/unix/SerialControllerImpl.cpp +368 -0
  132. data/lib/ansible/zwave/openzwave/src/platform/unix/SerialControllerImpl.h +74 -0
  133. data/lib/ansible/zwave/openzwave/src/platform/unix/ThreadImpl.cpp +181 -0
  134. data/lib/ansible/zwave/openzwave/src/platform/unix/ThreadImpl.h +67 -0
  135. data/lib/ansible/zwave/openzwave/src/platform/unix/TimeStampImpl.cpp +121 -0
  136. data/lib/ansible/zwave/openzwave/src/platform/unix/TimeStampImpl.h +84 -0
  137. data/lib/ansible/zwave/openzwave/src/platform/unix/WaitImpl.cpp +160 -0
  138. data/lib/ansible/zwave/openzwave/src/platform/unix/WaitImpl.h +74 -0
  139. data/lib/ansible/zwave/openzwave/src/platform/windows/EventImpl.cpp +102 -0
  140. data/lib/ansible/zwave/openzwave/src/platform/windows/EventImpl.h +60 -0
  141. data/lib/ansible/zwave/openzwave/src/platform/windows/LogImpl.cpp +302 -0
  142. data/lib/ansible/zwave/openzwave/src/platform/windows/LogImpl.h +71 -0
  143. data/lib/ansible/zwave/openzwave/src/platform/windows/MutexImpl.cpp +114 -0
  144. data/lib/ansible/zwave/openzwave/src/platform/windows/MutexImpl.h +58 -0
  145. data/lib/ansible/zwave/openzwave/src/platform/windows/SerialControllerImpl.cpp +410 -0
  146. data/lib/ansible/zwave/openzwave/src/platform/windows/SerialControllerImpl.h +66 -0
  147. data/lib/ansible/zwave/openzwave/src/platform/windows/ThreadImpl.cpp +158 -0
  148. data/lib/ansible/zwave/openzwave/src/platform/windows/ThreadImpl.h +71 -0
  149. data/lib/ansible/zwave/openzwave/src/platform/windows/TimeStampImpl.cpp +95 -0
  150. data/lib/ansible/zwave/openzwave/src/platform/windows/TimeStampImpl.h +83 -0
  151. data/lib/ansible/zwave/openzwave/src/platform/windows/WaitImpl.cpp +134 -0
  152. data/lib/ansible/zwave/openzwave/src/platform/windows/WaitImpl.h +73 -0
  153. data/lib/ansible/zwave/openzwave/src/value_classes/ValueID.h +283 -0
  154. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_bool.rb +0 -0
  155. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_button.rb +0 -0
  156. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_byte.rb +0 -0
  157. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_decimal.rb +0 -0
  158. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_int.rb +0 -0
  159. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_list.rb +0 -0
  160. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_short.rb +0 -0
  161. data/lib/ansible/zwave/{types → openzwave/types}/valuetype_string.rb +0 -0
  162. data/lib/ansible/zwave/zwave_transceiver.rb +2 -8
  163. data/lib/ansible/zwave/zwave_value.rb +6 -10
  164. metadata +159 -17
  165. data/lib/ansible/zwave/zwave_node.rb +0 -5
@@ -0,0 +1,539 @@
1
+ //-----------------------------------------------------------------------------
2
+ //
3
+ // HidController.h
4
+ //
5
+ // Cross-platform HID port handler
6
+ //
7
+ // Copyright (c) 2010 Jason Frazier <frazierjason@gmail.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 "Msg.h"
29
+ #include "Thread.h"
30
+ #include "Event.h"
31
+ #include "Log.h"
32
+ #include "TimeStamp.h"
33
+ #include "HidController.h"
34
+
35
+ #define CHECK_HIDAPI_RESULT(RESULT, ERRORLABEL) if (RESULT < 0) goto ERRORLABEL
36
+ #define PACKET_BUFFER_LENGTH 256
37
+
38
+ // are these specific to Wayne-Dalton?
39
+ #define FEATURE_REPORT_LENGTH 0x40
40
+ #define INPUT_REPORT_LENGTH 0x5
41
+ #define OUTPUT_REPORT_LENGTH 0x0
42
+
43
+ using namespace OpenZWave;
44
+
45
+ //-----------------------------------------------------------------------------
46
+ // <HidController::HidController>
47
+ // Constructor
48
+ //-----------------------------------------------------------------------------
49
+ HidController::HidController
50
+ (
51
+ ):
52
+ m_hHidController( NULL ),
53
+ m_thread( NULL ),
54
+ m_vendorId( 0x1b5f ), // Wayne Dalton
55
+ m_productId( 0x01 ), // ControlThink ThinkStick
56
+ m_serialNumber( "" ),
57
+ m_hidControllerName( "" ),
58
+ m_bOpen( false )
59
+ {
60
+ }
61
+
62
+ //-----------------------------------------------------------------------------
63
+ // <HidController::~HidController>
64
+ // Destructor
65
+ //-----------------------------------------------------------------------------
66
+ HidController::~HidController
67
+ (
68
+ )
69
+ {
70
+ }
71
+
72
+ //-----------------------------------------------------------------------------
73
+ // <HidController::SetVendorId>
74
+ // Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted.
75
+ //-----------------------------------------------------------------------------
76
+ bool HidController::SetVendorId
77
+ (
78
+ uint32 const _vendorId
79
+ )
80
+ {
81
+ if( m_bOpen )
82
+ {
83
+ return false;
84
+ }
85
+
86
+ m_vendorId = _vendorId;
87
+ return true;
88
+ }
89
+
90
+ //-----------------------------------------------------------------------------
91
+ // <HidController::SetProductId>
92
+ // Set the USB product ID search value. The HID port must be closed for the setting to be accepted.
93
+ //-----------------------------------------------------------------------------
94
+ bool HidController::SetProductId
95
+ (
96
+ uint32 const _productId
97
+ )
98
+ {
99
+ if( m_bOpen )
100
+ {
101
+ return false;
102
+ }
103
+
104
+ m_productId = _productId;
105
+ return true;
106
+ }
107
+
108
+ //-----------------------------------------------------------------------------
109
+ // <HidController::SetSerialNumber>
110
+ // Set the USB serial number search value. The HID port must be closed for the setting to be accepted.
111
+ //-----------------------------------------------------------------------------
112
+ bool HidController::SetSerialNumber
113
+ (
114
+ string const& _serialNumber
115
+ )
116
+ {
117
+ if( m_bOpen )
118
+ {
119
+ return false;
120
+ }
121
+
122
+ m_serialNumber = _serialNumber;
123
+ return true;
124
+ }
125
+
126
+ //-----------------------------------------------------------------------------
127
+ // <HidController::Open>
128
+ // Open and configure a HID port
129
+ //-----------------------------------------------------------------------------
130
+ bool HidController::Open
131
+ (
132
+ string const& _hidControllerName
133
+ )
134
+ {
135
+ if( m_bOpen )
136
+ {
137
+ return false;
138
+ }
139
+
140
+ m_hidControllerName = _hidControllerName;
141
+
142
+ // Try to init the serial port
143
+ if( !Init( 1 ) )
144
+ {
145
+ // Failed. We bail to allow the app a chance to take over, rather than retry
146
+ // automatically. Automatic retries only occur after a successful init.
147
+ return false;
148
+ }
149
+
150
+ m_thread = new Thread( "HidController" );
151
+
152
+ // Start the read thread
153
+ m_thread->Start( ThreadEntryPoint, this );
154
+ return true;
155
+ }
156
+
157
+ //-----------------------------------------------------------------------------
158
+ // <HidController::Close>
159
+ // Close a HID port
160
+ //-----------------------------------------------------------------------------
161
+ bool HidController::Close
162
+ (
163
+ )
164
+ {
165
+ if( m_thread )
166
+ {
167
+ m_thread->Stop();
168
+ m_thread->Release();
169
+ m_thread = NULL;
170
+ }
171
+
172
+ hid_close( m_hHidController );
173
+ m_hHidController = NULL;
174
+
175
+ m_bOpen = false;
176
+ hid_exit();
177
+ return true;
178
+ }
179
+
180
+ //-----------------------------------------------------------------------------
181
+ // <HidController::ThreadEntryPoint>
182
+ // Entry point of the thread for receiving data from the HID port
183
+ //-----------------------------------------------------------------------------
184
+ void HidController::ThreadEntryPoint
185
+ (
186
+ Event* _exitEvent,
187
+ void* _context
188
+ )
189
+ {
190
+ HidController* hc = (HidController*)_context;
191
+ if( hc )
192
+ {
193
+ hc->ThreadProc( _exitEvent );
194
+ }
195
+ }
196
+
197
+ //-----------------------------------------------------------------------------
198
+ // <HidController::ThreadProc>
199
+ // Handle receiving data
200
+ //-----------------------------------------------------------------------------
201
+ void HidController::ThreadProc
202
+ (
203
+ Event* _exitEvent
204
+ )
205
+ {
206
+ uint32 attempts = 0;
207
+ while( true )
208
+ {
209
+ // Init must have been called successfully during Open, so we
210
+ // don't do it again until the end of the loop
211
+ if( m_hHidController )
212
+ {
213
+ // Enter read loop. Call will only return if
214
+ // an exit is requested or an error occurs
215
+ Read();
216
+
217
+ // Reset the attempts, so we get a rapid retry for temporary errors
218
+ attempts = 0;
219
+ }
220
+
221
+ if( attempts < 25 )
222
+ {
223
+ // Retry every 5 seconds for the first two minutes...
224
+ if( Wait::Single( _exitEvent, 5000 ) >= 0 )
225
+ {
226
+ // Exit signalled.
227
+ break;
228
+ }
229
+ }
230
+ else
231
+ {
232
+ // ...retry every 30 seconds after that
233
+ if( Wait::Single( _exitEvent, 30000 ) >= 0 )
234
+ {
235
+ // Exit signalled.
236
+ break;
237
+ }
238
+ }
239
+
240
+ Init( ++attempts );
241
+ }
242
+ }
243
+
244
+ //-----------------------------------------------------------------------------
245
+ // <HidController::Init>
246
+ // Open the HID port
247
+ //-----------------------------------------------------------------------------
248
+ bool HidController::Init
249
+ (
250
+ uint32 const _attempts
251
+ )
252
+ {
253
+ // HIDAPI result
254
+ int hidApiResult;
255
+ const uint8 dataOutEnableZwave[3] = { 0x02, 0x01, 0x04 };
256
+
257
+ hid_init();
258
+ Log::Write( LogLevel_Info, " Open HID port %s", m_hidControllerName.c_str() );
259
+ m_hHidController = hid_open(m_vendorId, m_productId, NULL);
260
+ if (!m_hHidController)
261
+ {
262
+ Log::Write( LogLevel_Error, "Cannot find specified HID port with VID:%04hx and PID:0x%04hx.", m_vendorId, m_productId );
263
+
264
+ // Enumerate connected HIDs for debugging purposes
265
+ // Note: most OS intentionally hide keyboard/mouse devices from HID access
266
+ struct hid_device_info *devices, *currentDevice;
267
+ devices = hid_enumerate(0x0, 0x0);
268
+ currentDevice = devices;
269
+
270
+ Log::Write( LogLevel_Error, "Enumerating connected HIDs:" );
271
+ while (currentDevice)
272
+ {
273
+ Log::Write( LogLevel_Error, "\tVID:%04hx\tPID:0x%04hx\tSN:%ls\tMfg:%ls\tProd:%ls\tPath:%s",
274
+ currentDevice->vendor_id,
275
+ currentDevice->product_id,
276
+ currentDevice->serial_number,
277
+ currentDevice->manufacturer_string,
278
+ currentDevice->product_string,
279
+ currentDevice->path);
280
+ currentDevice = currentDevice->next;
281
+ }
282
+ hid_free_enumeration(devices);
283
+
284
+ goto HidOpenFailure;
285
+ }
286
+
287
+ wchar_t hidInfoString[255];
288
+ hidInfoString[0] = 0x0000;
289
+ Log::Write( LogLevel_Info, " Found HID ZWave controller:");
290
+ Log::Write( LogLevel_Info, " Vendor ID: 0x%04hx", m_vendorId);
291
+ Log::Write( LogLevel_Info, " Product ID: 0x%04hx", m_productId);
292
+
293
+ hidApiResult = hid_get_manufacturer_string(m_hHidController, hidInfoString, 255);
294
+ if (hidApiResult < 0)
295
+ {
296
+ Log::Write( LogLevel_Info, " Manufacturer: <<ERROR READING: 0x%04hx>>", hidApiResult );
297
+ }
298
+ else
299
+ {
300
+ Log::Write( LogLevel_Info, " Manufacturer: %ls", hidInfoString );
301
+ }
302
+
303
+ hidApiResult = hid_get_product_string(m_hHidController, hidInfoString, 255);
304
+ if (hidApiResult < 0)
305
+ {
306
+ Log::Write( LogLevel_Info, " Product name: <<ERROR READING: 0x%04hx>>", hidApiResult );
307
+ }
308
+ else
309
+ {
310
+ Log::Write( LogLevel_Info, " Product name: %ls", hidInfoString );
311
+ }
312
+
313
+ hidApiResult = hid_get_serial_number_string(m_hHidController, hidInfoString, 255);
314
+ if (hidApiResult < 0)
315
+ {
316
+ Log::Write( LogLevel_Warning, "Serial #: <<ERROR READING: 0x%04hx>>", hidApiResult );
317
+ }
318
+ else
319
+ {
320
+ size_t serialLength = wcslen(hidInfoString);
321
+ char* serialHex = new char[serialLength + 1];
322
+ memset(serialHex, 0, serialLength + 1);
323
+ for (size_t i = 0; i < serialLength; ++i)
324
+ {
325
+ snprintf(&serialHex[i], serialLength - i + 1, "%hx", hidInfoString[i] & 0x0f);
326
+ }
327
+ Log::Write( LogLevel_Info, " Serial #: %ls --> %s", hidInfoString, serialHex );
328
+ delete [] serialHex;
329
+ }
330
+ Log::Write( LogLevel_Info, "" );
331
+
332
+ // Turn on ZWave data via a short series of feature reports
333
+ uint8 dataIn[FEATURE_REPORT_LENGTH];
334
+
335
+ // Get Report ID 2
336
+ // Not sure what the result is for, we don't use it so far
337
+ hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn );
338
+ CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure);
339
+
340
+ // Send Report ID 2 - 1 byte "0x04"
341
+ // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx)
342
+ hidApiResult = SendFeatureReport(0x3, dataOutEnableZwave);
343
+ CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure);
344
+
345
+ // Get Report ID 2
346
+ // Not sure what the result is for, we don't use it so far
347
+ hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn );
348
+ CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure);
349
+
350
+ // Ensure that reads for input reports are blocked.
351
+ // Input report data is polled in Wait() to check if there are feature
352
+ // reports waiting to be retrieved that contain ZWave rx packets.
353
+ hidApiResult = hid_set_nonblocking(m_hHidController, 0);
354
+ CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure);
355
+
356
+ // Open successful
357
+ m_bOpen = true;
358
+ return true;
359
+
360
+ HidOpenFailure:
361
+ Log::Write( LogLevel_Error, "Failed to open HID port %s", m_hidControllerName.c_str() );
362
+ const wchar_t* errString = hid_error(m_hHidController);
363
+ Log::Write( LogLevel_Error, "HIDAPI ERROR STRING (if any): %ls", errString);
364
+ hid_close(m_hHidController);
365
+ m_hHidController = NULL;
366
+ return false;
367
+ }
368
+
369
+ //-----------------------------------------------------------------------------
370
+ // <HidController::Read>
371
+ // Read data from the HID port
372
+ //-----------------------------------------------------------------------------
373
+ void HidController::Read
374
+ (
375
+ )
376
+ {
377
+ uint8 buffer[FEATURE_REPORT_LENGTH];
378
+ int bytesRead = 0;
379
+ uint8 inputReport[INPUT_REPORT_LENGTH];
380
+ TimeStamp readTimer;
381
+
382
+ while( true )
383
+ {
384
+ // Rx feature report buffer should contain
385
+ // [0] - 0x05 (rx feature report ID)
386
+ // [1] - length of rx data (or 0x00 and no further bytes if no rx data waiting)
387
+ // [2]... - rx data
388
+ // We poll this waiting for data.
389
+ bytesRead = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x5, buffer);
390
+ CHECK_HIDAPI_RESULT(bytesRead, HidPortError);
391
+ if( bytesRead >= 2 )
392
+ {
393
+
394
+ if( buffer[1] > 0 )
395
+ {
396
+ string tmp = "";
397
+ for (int i = 0; i < buffer[1]; i++)
398
+ {
399
+ char bstr[16];
400
+ snprintf( bstr, sizeof(bstr), "0x%.2x ", buffer[2+i] );
401
+ tmp += bstr;
402
+ }
403
+ Log::Write( LogLevel_Detail, "hid report read=%d ID=%d len=%d %s", bytesRead, buffer[0], buffer[1], tmp.c_str() );
404
+ }
405
+
406
+ if( buffer[1] > 0 )
407
+ {
408
+ Put( &buffer[2], buffer[1] );
409
+ }
410
+ }
411
+ if( readTimer.TimeRemaining() <= 0 )
412
+ {
413
+ // Hang a hid_read to acknowledge receipt. Seems the response is conveying
414
+ // transaction status.
415
+ // Wayne-Dalton input report data is structured as follows (best guess):
416
+ // [0] 0x03 - input report ID
417
+ // [1] 0x01 - ??? never changes
418
+ // [2] 0xNN - if 0x01, no feature reports waiting
419
+ // if 0x02, feature report ID 0x05 is waiting to be retrieved
420
+ // [3,4] 0xNNNN - Number of ZWave messages?
421
+
422
+ int hidApiResult = hid_read( m_hHidController, inputReport, INPUT_REPORT_LENGTH );
423
+ //if( hidApiResult != 0 )
424
+ //{
425
+ // string tmp = "";
426
+ // for( int i = 0; i < INPUT_REPORT_LENGTH; i++ )
427
+ // {
428
+ // char bstr[16];
429
+ // snprintf(bstr, sizeof(bstr), "%02x ", inputReport[i] );
430
+ // tmp += bstr;
431
+ // }
432
+ // Log::Write( LogLevel_Detail, "hid read %d %s", hidApiResult, tmp.c_str() );
433
+ //}
434
+
435
+ if( hidApiResult == -1 )
436
+ {
437
+ const wchar_t* errString = hid_error(m_hHidController);
438
+ Log::Write( LogLevel_Warning, "Error: HID port returned error reading input bytes: 0x%08hx, HIDAPI error string: %ls", hidApiResult, errString );
439
+ }
440
+ readTimer.SetTime( 100 );
441
+ }
442
+ m_thread->Sleep(10);
443
+ }
444
+
445
+ HidPortError:
446
+ Log::Write( LogLevel_Warning, "Error: HID port returned error reading rest of packet: 0x%08hx, HIDAPI error string:", bytesRead );
447
+ Log::Write( LogLevel_Warning, "%ls", hid_error(m_hHidController));
448
+ }
449
+
450
+ //-----------------------------------------------------------------------------
451
+ // <HidController::Write>
452
+ // Send data to the HID port
453
+ //-----------------------------------------------------------------------------
454
+ uint32 HidController::Write
455
+ (
456
+ uint8* _buffer,
457
+ uint32 _length
458
+ )
459
+ {
460
+ if( !m_bOpen )
461
+ {
462
+ //Error
463
+ Log::Write( LogLevel_Warning, "Error: HID port must be opened before writing" );
464
+ return 0;
465
+ }
466
+
467
+ if ( FEATURE_REPORT_LENGTH - 2 < _length)
468
+ {
469
+ //Error
470
+ Log::Write( LogLevel_Info, "Error: Write buffer length %d exceeded feature report data capacity %d", _length, FEATURE_REPORT_LENGTH - 2 );
471
+ return 0;
472
+ }
473
+
474
+ // transmit buffer should be arranged:
475
+ // byte 0 - 0x04 (tx feature report)
476
+ // byte 1 - length of tx data
477
+ // byte 2.... - tx data
478
+ uint8 hidBuffer[FEATURE_REPORT_LENGTH];
479
+ memset(hidBuffer, 0, FEATURE_REPORT_LENGTH);
480
+ hidBuffer[0] = 0x4;
481
+ hidBuffer[1] = (uint8)_length;
482
+ memcpy(&hidBuffer[2], _buffer, _length);
483
+
484
+ Log::Write( LogLevel_Debug, " HidController::Write (sent to controller)" );
485
+ LogData(_buffer, _length, " Write: ");
486
+
487
+ int bytesSent = SendFeatureReport(FEATURE_REPORT_LENGTH, hidBuffer);
488
+ if (bytesSent < 2)
489
+ {
490
+ //Error
491
+ const wchar_t* errString = hid_error(m_hHidController);
492
+ Log::Write( LogLevel_Warning, "Error: HID port returned error sending bytes: 0x%08hx, HIDAPI error string: %ls", bytesSent, errString );
493
+ return 0;
494
+ }
495
+
496
+ return (uint32)bytesSent - 2;
497
+ }
498
+
499
+ //-----------------------------------------------------------------------------
500
+ // <HidController::GetFeatureReport>
501
+ // Read bytes from the specified HID feature report
502
+ //-----------------------------------------------------------------------------
503
+ int HidController::GetFeatureReport
504
+ (
505
+ uint32 _length,
506
+ uint8 _reportId,
507
+ uint8* _buffer
508
+ )
509
+ {
510
+ int result;
511
+ _buffer[0] = _reportId;
512
+ result = hid_get_feature_report(m_hHidController, _buffer, _length);
513
+ if (result < 0)
514
+ {
515
+ Log::Write( LogLevel_Info, "Error: HID GetFeatureReport on ID 0x%hx returned (0x%.8x)", _reportId, result );
516
+ }
517
+ return result;
518
+ }
519
+
520
+ //-----------------------------------------------------------------------------
521
+ // <HidController::SendFeatureReport>
522
+ // Write bytes to the specified HID feature report
523
+ //-----------------------------------------------------------------------------
524
+ int HidController::SendFeatureReport
525
+ (
526
+ uint32 _length,
527
+ const uint8* _data
528
+ )
529
+ {
530
+ int result;
531
+
532
+ result = hid_send_feature_report(m_hHidController, _data, _length);
533
+ if (result < 0)
534
+ {
535
+ Log::Write( LogLevel_Info, "Error: HID SendFeatureReport on ID 0x%hx returned (0x%.8x)", _data[0], result );
536
+ }
537
+ return result;
538
+ }
539
+