Commit | Line | Data |
---|---|---|
a75e3a5a LOK |
1 | /* |
2 | * This file is part of the libCEC(R) library. | |
3 | * | |
16f47961 | 4 | * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. |
a75e3a5a LOK |
5 | * libCEC(R) is an original work, containing original code. |
6 | * | |
7 | * libCEC(R) is a trademark of Pulse-Eight Limited. | |
8 | * | |
9 | * This program is dual-licensed; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 | * | |
23 | * | |
24 | * Alternatively, you can license this library under a commercial license, | |
25 | * please contact Pulse-Eight Licensing for more information. | |
26 | * | |
27 | * For more information contact: | |
28 | * Pulse-Eight Licensing <license@pulse-eight.com> | |
29 | * http://www.pulse-eight.com/ | |
30 | * http://www.pulse-eight.net/ | |
31 | */ | |
32 | ||
2b44051c | 33 | #include "env.h" |
a75e3a5a | 34 | #include "USBCECAdapterCommands.h" |
2b44051c LOK |
35 | |
36 | #include "USBCECAdapterMessage.h" | |
37 | #include "USBCECAdapterCommunication.h" | |
38 | #include "lib/LibCEC.h" | |
39 | #include "lib/CECProcessor.h" | |
40 | #include "lib/CECTypeUtils.h" | |
41 | #include <stdio.h> | |
a75e3a5a LOK |
42 | |
43 | using namespace CEC; | |
44 | using namespace PLATFORM; | |
45 | ||
004b8382 | 46 | #define LIB_CEC m_comm->m_callback->GetLib() |
0d800fe5 | 47 | #define ToString(p) CCECTypeUtils::ToString(p) |
004b8382 | 48 | |
7c5c5bf4 LOK |
49 | CUSBCECAdapterCommands::CUSBCECAdapterCommands(CUSBCECAdapterCommunication *comm) : |
50 | m_comm(comm), | |
51 | m_bSettingsRetrieved(false), | |
52 | m_bSettingAutoEnabled(false), | |
53 | m_settingCecVersion(CEC_VERSION_UNKNOWN), | |
54 | m_iSettingLAMask(0), | |
b2f56d35 | 55 | m_bNeedsWrite(false), |
a38292a3 | 56 | m_iBuildDate(CEC_FW_BUILD_UNKNOWN), |
2d418322 LOK |
57 | m_bControlledMode(false), |
58 | m_adapterType(P8_ADAPTERTYPE_UNKNOWN) | |
7c5c5bf4 LOK |
59 | { |
60 | m_persistedConfiguration.Clear(); | |
61 | } | |
62 | ||
a75e3a5a LOK |
63 | cec_datapacket CUSBCECAdapterCommands::RequestSetting(cec_adapter_messagecode msgCode) |
64 | { | |
65 | cec_datapacket retVal; | |
66 | retVal.Clear(); | |
67 | ||
68 | CCECAdapterMessage params; | |
69 | CCECAdapterMessage *message = m_comm->SendCommand(msgCode, params); | |
70 | if (message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED) | |
71 | { | |
72 | retVal = message->response; | |
73 | retVal.Shift(2); // shift out start and msgcode | |
74 | retVal.size -= 1; // remove end | |
75 | } | |
c9d15485 | 76 | |
a75e3a5a LOK |
77 | delete message; |
78 | return retVal; | |
79 | } | |
80 | ||
81 | uint16_t CUSBCECAdapterCommands::RequestFirmwareVersion(void) | |
82 | { | |
7c5c5bf4 | 83 | m_persistedConfiguration.iFirmwareVersion = CEC_FW_VERSION_UNKNOWN; |
a75e3a5a LOK |
84 | unsigned int iFwVersionTry(0); |
85 | ||
7c5c5bf4 | 86 | while (m_persistedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN && iFwVersionTry++ < 3) |
a75e3a5a | 87 | { |
b509ba1a | 88 | #ifdef CEC_DEBUGGING |
004b8382 | 89 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting the firmware version"); |
b509ba1a | 90 | #endif |
a75e3a5a LOK |
91 | cec_datapacket response = RequestSetting(MSGCODE_FIRMWARE_VERSION); |
92 | if (response.size == 2) | |
7c5c5bf4 | 93 | m_persistedConfiguration.iFirmwareVersion = (response[0] << 8 | response[1]); |
a75e3a5a LOK |
94 | else |
95 | { | |
daec0320 | 96 | LIB_CEC->AddLog(CEC_LOG_WARNING, "the adapter did not respond with a correct firmware version (try %d, size = %d)", iFwVersionTry, response.size); |
a75e3a5a LOK |
97 | CEvent::Sleep(500); |
98 | } | |
99 | } | |
100 | ||
7c5c5bf4 | 101 | if (m_persistedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) |
a75e3a5a | 102 | { |
004b8382 | 103 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "defaulting to firmware version 1"); |
7c5c5bf4 | 104 | m_persistedConfiguration.iFirmwareVersion = 1; |
a75e3a5a LOK |
105 | } |
106 | ||
431ceea8 LOK |
107 | // firmware versions < 2 don't have an autonomous mode |
108 | if (m_persistedConfiguration.iFirmwareVersion < 2) | |
109 | m_bControlledMode = true; | |
110 | ||
7c5c5bf4 | 111 | return m_persistedConfiguration.iFirmwareVersion; |
a75e3a5a LOK |
112 | } |
113 | ||
7c5c5bf4 | 114 | bool CUSBCECAdapterCommands::RequestSettingAutoEnabled(void) |
a75e3a5a | 115 | { |
b509ba1a | 116 | #ifdef CEC_DEBUGGING |
004b8382 | 117 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting autonomous mode setting"); |
b509ba1a | 118 | #endif |
a75e3a5a LOK |
119 | |
120 | cec_datapacket response = RequestSetting(MSGCODE_GET_AUTO_ENABLED); | |
121 | if (response.size == 1) | |
122 | { | |
7c5c5bf4 | 123 | m_bSettingAutoEnabled = response[0] == 1; |
004b8382 | 124 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted autonomous mode setting: '%s'", m_bSettingAutoEnabled ? "enabled" : "disabled"); |
a75e3a5a LOK |
125 | return true; |
126 | } | |
127 | return false; | |
128 | } | |
129 | ||
7c5c5bf4 | 130 | bool CUSBCECAdapterCommands::RequestSettingCECVersion(void) |
a75e3a5a | 131 | { |
b509ba1a | 132 | #ifdef CEC_DEBUGGING |
004b8382 | 133 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting CEC version setting"); |
b509ba1a | 134 | #endif |
a75e3a5a LOK |
135 | |
136 | cec_datapacket response = RequestSetting(MSGCODE_GET_HDMI_VERSION); | |
137 | if (response.size == 1) | |
138 | { | |
7c5c5bf4 | 139 | m_settingCecVersion = (cec_version)response[0]; |
004b8382 | 140 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted CEC version setting: '%s'", ToString(m_settingCecVersion)); |
a75e3a5a LOK |
141 | return true; |
142 | } | |
143 | return false; | |
144 | } | |
145 | ||
2d418322 LOK |
146 | p8_cec_adapter_type CUSBCECAdapterCommands::RequestAdapterType(void) |
147 | { | |
148 | if (m_adapterType == P8_ADAPTERTYPE_UNKNOWN) | |
149 | { | |
b509ba1a | 150 | #ifdef CEC_DEBUGGING |
2d418322 | 151 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting adapter type"); |
b509ba1a | 152 | #endif |
2d418322 LOK |
153 | |
154 | cec_datapacket response = RequestSetting(MSGCODE_GET_ADAPTER_TYPE); | |
155 | if (response.size == 1) | |
156 | m_adapterType = (p8_cec_adapter_type)response[0]; | |
157 | } | |
158 | return m_adapterType; | |
159 | } | |
160 | ||
b2f56d35 LOK |
161 | uint32_t CUSBCECAdapterCommands::RequestBuildDate(void) |
162 | { | |
d2d1660c | 163 | if (m_iBuildDate == CEC_FW_BUILD_UNKNOWN) |
c37545cf | 164 | { |
b509ba1a | 165 | #ifdef CEC_DEBUGGING |
004b8382 | 166 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting firmware build date"); |
b509ba1a | 167 | #endif |
b2f56d35 | 168 | |
c37545cf LOK |
169 | cec_datapacket response = RequestSetting(MSGCODE_GET_BUILDDATE); |
170 | if (response.size == 4) | |
171 | m_iBuildDate = (uint32_t)response[0] << 24 | (uint32_t)response[1] << 16 | (uint32_t)response[2] << 8 | (uint32_t)response[3]; | |
172 | } | |
173 | return m_iBuildDate; | |
b2f56d35 LOK |
174 | } |
175 | ||
7c5c5bf4 | 176 | bool CUSBCECAdapterCommands::RequestSettingDefaultLogicalAddress(void) |
a75e3a5a | 177 | { |
b509ba1a | 178 | #ifdef CEC_DEBUGGING |
004b8382 | 179 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting default logical address setting"); |
b509ba1a | 180 | #endif |
a75e3a5a LOK |
181 | |
182 | cec_datapacket response = RequestSetting(MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS); | |
183 | if (response.size == 1) | |
184 | { | |
7c5c5bf4 | 185 | m_persistedConfiguration.logicalAddresses.primary = (cec_logical_address)response[0]; |
004b8382 | 186 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted logical address setting: '%s'", ToString(m_persistedConfiguration.logicalAddresses.primary)); |
a75e3a5a LOK |
187 | return true; |
188 | } | |
189 | return false; | |
190 | } | |
191 | ||
7c5c5bf4 | 192 | bool CUSBCECAdapterCommands::RequestSettingDeviceType(void) |
a75e3a5a | 193 | { |
b509ba1a | 194 | #ifdef CEC_DEBUGGING |
004b8382 | 195 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting device type setting"); |
b509ba1a | 196 | #endif |
7c5c5bf4 | 197 | m_persistedConfiguration.deviceTypes.Clear(); |
a75e3a5a LOK |
198 | |
199 | cec_datapacket response = RequestSetting(MSGCODE_GET_DEVICE_TYPE); | |
200 | if (response.size == 1) | |
201 | { | |
7c5c5bf4 | 202 | m_persistedConfiguration.deviceTypes.Add((cec_device_type)response[0]); |
004b8382 | 203 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted device type setting: '%s'", ToString((cec_device_type)response[0])); |
a75e3a5a LOK |
204 | return true; |
205 | } | |
004b8382 | 206 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted device type setting"); |
a75e3a5a LOK |
207 | return false; |
208 | } | |
209 | ||
7c5c5bf4 | 210 | bool CUSBCECAdapterCommands::RequestSettingLogicalAddressMask(void) |
a75e3a5a | 211 | { |
b509ba1a | 212 | #ifdef CEC_DEBUGGING |
004b8382 | 213 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting logical address mask setting"); |
b509ba1a | 214 | #endif |
a75e3a5a LOK |
215 | |
216 | cec_datapacket response = RequestSetting(MSGCODE_GET_LOGICAL_ADDRESS_MASK); | |
217 | if (response.size == 2) | |
218 | { | |
7c5c5bf4 | 219 | m_iSettingLAMask = ((uint16_t)response[0] << 8) | ((uint16_t)response[1]); |
004b8382 | 220 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted logical address mask setting: '%x'", m_iSettingLAMask); |
a75e3a5a LOK |
221 | return true; |
222 | } | |
223 | return false; | |
224 | } | |
225 | ||
7c5c5bf4 | 226 | bool CUSBCECAdapterCommands::RequestSettingOSDName(void) |
a75e3a5a | 227 | { |
b509ba1a | 228 | #ifdef CEC_DEBUGGING |
004b8382 | 229 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting OSD name setting"); |
b509ba1a | 230 | #endif |
a75e3a5a | 231 | |
7c5c5bf4 | 232 | memset(m_persistedConfiguration.strDeviceName, 0, 13); |
a75e3a5a LOK |
233 | cec_datapacket response = RequestSetting(MSGCODE_GET_OSD_NAME); |
234 | if (response.size == 0) | |
7c5c5bf4 | 235 | { |
004b8382 | 236 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted device name setting"); |
a75e3a5a | 237 | return false; |
7c5c5bf4 | 238 | } |
a75e3a5a LOK |
239 | |
240 | char buf[14]; | |
241 | for (uint8_t iPtr = 0; iPtr < response.size && iPtr < 13; iPtr++) | |
242 | buf[iPtr] = (char)response[iPtr]; | |
243 | buf[response.size] = 0; | |
244 | ||
7c5c5bf4 | 245 | snprintf(m_persistedConfiguration.strDeviceName, 13, "%s", buf); |
004b8382 | 246 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted device name setting: '%s'", buf); |
a75e3a5a LOK |
247 | return true; |
248 | } | |
249 | ||
7c5c5bf4 | 250 | bool CUSBCECAdapterCommands::RequestSettingPhysicalAddress(void) |
a75e3a5a | 251 | { |
b509ba1a | 252 | #ifdef CEC_DEBUGGING |
004b8382 | 253 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting physical address setting"); |
b509ba1a | 254 | #endif |
a75e3a5a LOK |
255 | |
256 | cec_datapacket response = RequestSetting(MSGCODE_GET_PHYSICAL_ADDRESS); | |
257 | if (response.size == 2) | |
258 | { | |
7c5c5bf4 | 259 | m_persistedConfiguration.iPhysicalAddress = ((uint16_t)response[0] << 8) | ((uint16_t)response[1]); |
004b8382 | 260 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted physical address setting: '%4x'", m_persistedConfiguration.iPhysicalAddress); |
a75e3a5a LOK |
261 | return true; |
262 | } | |
004b8382 | 263 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted physical address setting"); |
a75e3a5a LOK |
264 | return false; |
265 | } | |
266 | ||
267 | bool CUSBCECAdapterCommands::SetSettingAutoEnabled(bool enabled) | |
268 | { | |
2b44051c | 269 | bool bReturn(false); |
7c5c5bf4 LOK |
270 | |
271 | /* check whether this value was changed */ | |
c8b0c13a LOK |
272 | { |
273 | CLockObject lock(m_mutex); | |
274 | if (m_bSettingAutoEnabled == enabled) | |
275 | return bReturn; | |
276 | m_bNeedsWrite = true; | |
277 | } | |
7c5c5bf4 | 278 | |
004b8382 | 279 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "turning autonomous mode %s", enabled ? "on" : "off"); |
a75e3a5a LOK |
280 | |
281 | CCECAdapterMessage params; | |
282 | params.PushEscaped(enabled ? 1 : 0); | |
283 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_AUTO_ENABLED, params); | |
7c5c5bf4 | 284 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 285 | delete message; |
7c5c5bf4 LOK |
286 | |
287 | if (bReturn) | |
c8b0c13a LOK |
288 | { |
289 | CLockObject lock(m_mutex); | |
7c5c5bf4 | 290 | m_bSettingAutoEnabled = enabled; |
c8b0c13a | 291 | } |
7c5c5bf4 | 292 | |
a75e3a5a LOK |
293 | return bReturn; |
294 | } | |
295 | ||
296 | bool CUSBCECAdapterCommands::SetSettingDeviceType(cec_device_type type) | |
297 | { | |
2b44051c | 298 | bool bReturn(false); |
7c5c5bf4 LOK |
299 | |
300 | /* check whether this value was changed */ | |
c8b0c13a LOK |
301 | { |
302 | CLockObject lock(m_mutex); | |
303 | if (m_persistedConfiguration.deviceTypes.types[0] == type) | |
304 | return bReturn; | |
305 | m_bNeedsWrite = true; | |
306 | } | |
7c5c5bf4 | 307 | |
004b8382 | 308 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the device type to %X (previous: %X)", (uint8_t)type, (uint8_t)m_persistedConfiguration.deviceTypes.types[0]); |
a75e3a5a LOK |
309 | |
310 | CCECAdapterMessage params; | |
311 | params.PushEscaped((uint8_t)type); | |
312 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEVICE_TYPE, params); | |
7c5c5bf4 | 313 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 314 | delete message; |
7c5c5bf4 | 315 | |
c8b0c13a LOK |
316 | if (bReturn) |
317 | { | |
318 | CLockObject lock(m_mutex); | |
319 | m_persistedConfiguration.deviceTypes.types[0] = type; | |
320 | } | |
321 | ||
a75e3a5a LOK |
322 | return bReturn; |
323 | } | |
324 | ||
325 | bool CUSBCECAdapterCommands::SetSettingDefaultLogicalAddress(cec_logical_address address) | |
326 | { | |
2b44051c | 327 | bool bReturn(false); |
7c5c5bf4 LOK |
328 | |
329 | /* check whether this value was changed */ | |
c8b0c13a LOK |
330 | { |
331 | CLockObject lock(m_mutex); | |
332 | if (m_persistedConfiguration.logicalAddresses.primary == address) | |
333 | return bReturn; | |
334 | m_bNeedsWrite = true; | |
335 | } | |
7c5c5bf4 | 336 | |
004b8382 | 337 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the default logical address to %X (previous: %X)", (uint8_t)address, (uint8_t)m_persistedConfiguration.logicalAddresses.primary); |
a75e3a5a LOK |
338 | |
339 | CCECAdapterMessage params; | |
340 | params.PushEscaped((uint8_t)address); | |
341 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS, params); | |
7c5c5bf4 | 342 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 343 | delete message; |
7c5c5bf4 LOK |
344 | |
345 | if (bReturn) | |
c8b0c13a LOK |
346 | { |
347 | CLockObject lock(m_mutex); | |
7c5c5bf4 | 348 | m_persistedConfiguration.logicalAddresses.primary = address; |
c8b0c13a | 349 | } |
7c5c5bf4 | 350 | |
a75e3a5a LOK |
351 | return bReturn; |
352 | } | |
353 | ||
354 | bool CUSBCECAdapterCommands::SetSettingLogicalAddressMask(uint16_t iMask) | |
355 | { | |
2b44051c | 356 | bool bReturn(false); |
7c5c5bf4 LOK |
357 | |
358 | /* check whether this value was changed */ | |
c8b0c13a LOK |
359 | { |
360 | CLockObject lock(m_mutex); | |
361 | if (m_iSettingLAMask == iMask) | |
362 | return bReturn; | |
363 | m_bNeedsWrite = true; | |
364 | } | |
7c5c5bf4 | 365 | |
004b8382 | 366 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the logical address mask to %2X (previous: %2X)", iMask, m_iSettingLAMask); |
a75e3a5a LOK |
367 | |
368 | CCECAdapterMessage params; | |
369 | params.PushEscaped(iMask >> 8); | |
370 | params.PushEscaped((uint8_t)iMask); | |
371 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_LOGICAL_ADDRESS_MASK, params); | |
7c5c5bf4 | 372 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 373 | delete message; |
7c5c5bf4 LOK |
374 | |
375 | if (bReturn) | |
c8b0c13a LOK |
376 | { |
377 | CLockObject lock(m_mutex); | |
7c5c5bf4 | 378 | m_iSettingLAMask = iMask; |
c8b0c13a | 379 | } |
7c5c5bf4 | 380 | |
a75e3a5a LOK |
381 | return bReturn; |
382 | } | |
383 | ||
384 | bool CUSBCECAdapterCommands::SetSettingPhysicalAddress(uint16_t iPhysicalAddress) | |
385 | { | |
2b44051c | 386 | bool bReturn(false); |
7c5c5bf4 LOK |
387 | |
388 | /* check whether this value was changed */ | |
c8b0c13a LOK |
389 | { |
390 | CLockObject lock(m_mutex); | |
391 | if (m_persistedConfiguration.iPhysicalAddress == iPhysicalAddress) | |
392 | return bReturn; | |
393 | m_bNeedsWrite = true; | |
394 | } | |
7c5c5bf4 | 395 | |
004b8382 | 396 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the physical address to %04X (previous: %04X)", iPhysicalAddress, m_persistedConfiguration.iPhysicalAddress); |
a75e3a5a LOK |
397 | |
398 | CCECAdapterMessage params; | |
399 | params.PushEscaped(iPhysicalAddress >> 8); | |
400 | params.PushEscaped((uint8_t)iPhysicalAddress); | |
401 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_PHYSICAL_ADDRESS, params); | |
7c5c5bf4 | 402 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 403 | delete message; |
7c5c5bf4 LOK |
404 | |
405 | if (bReturn) | |
c8b0c13a LOK |
406 | { |
407 | CLockObject lock(m_mutex); | |
7c5c5bf4 | 408 | m_persistedConfiguration.iPhysicalAddress = iPhysicalAddress; |
c8b0c13a | 409 | } |
7c5c5bf4 | 410 | |
a75e3a5a LOK |
411 | return bReturn; |
412 | } | |
413 | ||
414 | bool CUSBCECAdapterCommands::SetSettingCECVersion(cec_version version) | |
415 | { | |
2b44051c | 416 | bool bReturn(false); |
7c5c5bf4 LOK |
417 | |
418 | /* check whether this value was changed */ | |
c8b0c13a LOK |
419 | { |
420 | CLockObject lock(m_mutex); | |
421 | if (m_settingCecVersion == version) | |
422 | return bReturn; | |
423 | m_bNeedsWrite = true; | |
424 | } | |
7c5c5bf4 | 425 | |
004b8382 | 426 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the CEC version to %s (previous: %s)", ToString(version), ToString(m_settingCecVersion)); |
a75e3a5a LOK |
427 | |
428 | CCECAdapterMessage params; | |
429 | params.PushEscaped((uint8_t)version); | |
430 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_HDMI_VERSION, params); | |
7c5c5bf4 | 431 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 432 | delete message; |
7c5c5bf4 LOK |
433 | |
434 | if (bReturn) | |
c8b0c13a LOK |
435 | { |
436 | CLockObject lock(m_mutex); | |
7c5c5bf4 | 437 | m_settingCecVersion = version; |
c8b0c13a | 438 | } |
7c5c5bf4 | 439 | |
a75e3a5a LOK |
440 | return bReturn; |
441 | } | |
442 | ||
443 | bool CUSBCECAdapterCommands::SetSettingOSDName(const char *strOSDName) | |
444 | { | |
2b44051c | 445 | bool bReturn(false); |
7c5c5bf4 LOK |
446 | |
447 | /* check whether this value was changed */ | |
448 | if (!strcmp(m_persistedConfiguration.strDeviceName, strOSDName)) | |
7c5c5bf4 | 449 | return bReturn; |
7c5c5bf4 | 450 | |
004b8382 | 451 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the OSD name to %s (previous: %s)", strOSDName, m_persistedConfiguration.strDeviceName); |
a75e3a5a LOK |
452 | |
453 | CCECAdapterMessage params; | |
454 | for (size_t iPtr = 0; iPtr < strlen(strOSDName); iPtr++) | |
455 | params.PushEscaped(strOSDName[iPtr]); | |
456 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_OSD_NAME, params); | |
7c5c5bf4 | 457 | bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 458 | delete message; |
7c5c5bf4 LOK |
459 | |
460 | if (bReturn) | |
461 | snprintf(m_persistedConfiguration.strDeviceName, 13, "%s", strOSDName); | |
462 | ||
a75e3a5a LOK |
463 | return bReturn; |
464 | } | |
465 | ||
466 | bool CUSBCECAdapterCommands::WriteEEPROM(void) | |
467 | { | |
c8b0c13a LOK |
468 | { |
469 | CLockObject lock(m_mutex); | |
470 | if (!m_bNeedsWrite) | |
471 | return true; | |
472 | } | |
7c5c5bf4 | 473 | |
004b8382 | 474 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "writing settings in the EEPROM"); |
a75e3a5a LOK |
475 | |
476 | CCECAdapterMessage params; | |
477 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_WRITE_EEPROM, params); | |
c8b0c13a | 478 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; |
a75e3a5a | 479 | delete message; |
c8b0c13a LOK |
480 | |
481 | if (bReturn) | |
482 | { | |
483 | CLockObject lock(m_mutex); | |
484 | m_bNeedsWrite = false; | |
485 | } | |
486 | ||
487 | return bReturn; | |
a75e3a5a LOK |
488 | } |
489 | ||
c0152c09 | 490 | bool CUSBCECAdapterCommands::PersistConfiguration(const libcec_configuration &configuration) |
a75e3a5a | 491 | { |
2b44051c | 492 | bool bReturn(false); |
7c5c5bf4 | 493 | if (m_persistedConfiguration.iFirmwareVersion < 2) |
2b44051c | 494 | return bReturn; |
7c5c5bf4 LOK |
495 | |
496 | if (!RequestSettings()) | |
2b44051c LOK |
497 | return bReturn; |
498 | ||
499 | bReturn |= SetSettingAutoEnabled(true); | |
500 | bReturn |= SetSettingDeviceType(CLibCEC::GetType(configuration.logicalAddresses.primary)); | |
501 | bReturn |= SetSettingDefaultLogicalAddress(configuration.logicalAddresses.primary); | |
502 | bReturn |= SetSettingLogicalAddressMask(CLibCEC::GetMaskForType(configuration.logicalAddresses.primary)); | |
503 | bReturn |= SetSettingPhysicalAddress(configuration.iPhysicalAddress); | |
504 | bReturn |= SetSettingCECVersion(configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_0 ? configuration.cecVersion : CEC_VERSION_1_4); | |
505 | bReturn |= SetSettingOSDName(configuration.strDeviceName); | |
a75e3a5a | 506 | |
a75e3a5a LOK |
507 | return bReturn; |
508 | } | |
509 | ||
7c5c5bf4 | 510 | bool CUSBCECAdapterCommands::RequestSettings(void) |
a75e3a5a | 511 | { |
7c5c5bf4 | 512 | if (m_persistedConfiguration.iFirmwareVersion < 2) |
a75e3a5a | 513 | { |
004b8382 | 514 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - firmware version %d does not have any eeprom settings", __FUNCTION__, m_persistedConfiguration.iFirmwareVersion); |
7c5c5bf4 LOK |
515 | // settings can only be persisted with firmware v2+ |
516 | return false; | |
a75e3a5a LOK |
517 | } |
518 | ||
4c70b3b6 | 519 | if (m_bSettingsRetrieved) |
7c5c5bf4 | 520 | return true; |
a75e3a5a | 521 | |
7c5c5bf4 LOK |
522 | bool bReturn(true); |
523 | bReturn &= RequestSettingAutoEnabled(); | |
524 | bReturn &= RequestSettingCECVersion(); | |
525 | bReturn &= RequestSettingDefaultLogicalAddress(); | |
526 | bReturn &= RequestSettingDeviceType(); | |
527 | bReturn &= RequestSettingLogicalAddressMask(); | |
528 | bReturn &= RequestSettingOSDName(); | |
529 | bReturn &= RequestSettingPhysicalAddress(); | |
a75e3a5a LOK |
530 | |
531 | // don't read the following settings: | |
532 | // - auto enabled (always enabled) | |
533 | // - default logical address (autodetected) | |
534 | // - logical address mask (autodetected) | |
535 | // - CEC version (1.3a) | |
536 | ||
537 | // TODO to be added to the firmware: | |
538 | // - base device (4 bits) | |
539 | // - HDMI port number (4 bits) | |
540 | // - TV vendor id (12 bits) | |
541 | // - wake devices (8 bits) | |
542 | // - standby devices (8 bits) | |
543 | // - use TV menu language (1 bit) | |
544 | // - activate source (1 bit) | |
545 | // - power off screensaver (1 bit) | |
546 | // - power off on standby (1 bit) | |
547 | // - send inactive source (1 bit) | |
7c5c5bf4 LOK |
548 | |
549 | m_bSettingsRetrieved = true; | |
550 | ||
a75e3a5a LOK |
551 | return bReturn; |
552 | } | |
553 | ||
c0152c09 | 554 | bool CUSBCECAdapterCommands::GetConfiguration(libcec_configuration &configuration) |
7c5c5bf4 LOK |
555 | { |
556 | // get the settings from the eeprom if needed | |
557 | if (!RequestSettings()) | |
558 | return false; | |
559 | ||
560 | // copy the settings | |
c0152c09 LOK |
561 | configuration.iFirmwareVersion = m_persistedConfiguration.iFirmwareVersion; |
562 | configuration.deviceTypes = m_persistedConfiguration.deviceTypes; | |
563 | configuration.iPhysicalAddress = m_persistedConfiguration.iPhysicalAddress; | |
564 | snprintf(configuration.strDeviceName, 13, "%s", m_persistedConfiguration.strDeviceName); | |
7c5c5bf4 LOK |
565 | |
566 | return true; | |
567 | } | |
568 | ||
a75e3a5a LOK |
569 | bool CUSBCECAdapterCommands::PingAdapter(void) |
570 | { | |
b509ba1a | 571 | #ifdef CEC_DEBUGGING |
004b8382 | 572 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending ping"); |
b509ba1a | 573 | #endif |
a75e3a5a LOK |
574 | |
575 | CCECAdapterMessage params; | |
576 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_PING, params); | |
577 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; | |
578 | delete message; | |
579 | return bReturn; | |
580 | } | |
581 | ||
582 | bool CUSBCECAdapterCommands::SetAckMask(uint16_t iMask) | |
583 | { | |
004b8382 | 584 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting ackmask to %2x", iMask); |
a75e3a5a LOK |
585 | |
586 | CCECAdapterMessage params; | |
587 | params.PushEscaped(iMask >> 8); | |
588 | params.PushEscaped((uint8_t)iMask); | |
589 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_ACK_MASK, params); | |
590 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; | |
591 | delete message; | |
592 | return bReturn; | |
593 | } | |
594 | ||
a582c2bb LOK |
595 | void CUSBCECAdapterCommands::SetActiveSource(bool bSetTo, bool bClientUnregistered) |
596 | { | |
597 | if (bClientUnregistered) return; | |
598 | if (m_persistedConfiguration.iFirmwareVersion >= 3) | |
599 | { | |
600 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "marking the adapter as %s source", bSetTo ? "active" : "inactive"); | |
601 | CCECAdapterMessage params; | |
602 | params.PushEscaped(bSetTo ? 1 : 0); | |
603 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_ACTIVE_SOURCE, params); | |
604 | delete message; | |
605 | } | |
606 | } | |
607 | ||
a75e3a5a LOK |
608 | bool CUSBCECAdapterCommands::StartBootloader(void) |
609 | { | |
004b8382 | 610 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "starting the bootloader"); |
a75e3a5a LOK |
611 | |
612 | CCECAdapterMessage params; | |
613 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_START_BOOTLOADER, params); | |
614 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; | |
615 | delete message; | |
616 | return bReturn; | |
617 | } | |
618 | ||
619 | bool CUSBCECAdapterCommands::SetLineTimeout(uint8_t iTimeout) | |
620 | { | |
004b8382 | 621 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the line timeout to %d", iTimeout); |
a75e3a5a LOK |
622 | CCECAdapterMessage params; |
623 | params.PushEscaped(iTimeout); | |
624 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_TRANSMIT_IDLETIME, params); | |
625 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; | |
626 | delete message; | |
627 | return bReturn; | |
628 | } | |
629 | ||
630 | bool CUSBCECAdapterCommands::SetControlledMode(bool controlled) | |
631 | { | |
a38292a3 LOK |
632 | { |
633 | CLockObject lock(m_mutex); | |
634 | if (m_bControlledMode == controlled) | |
635 | return true; | |
636 | } | |
637 | ||
004b8382 | 638 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "turning controlled mode %s", controlled ? "on" : "off"); |
a75e3a5a LOK |
639 | |
640 | CCECAdapterMessage params; | |
641 | params.PushEscaped(controlled ? 1 : 0); | |
642 | CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_CONTROLLED, params); | |
643 | bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; | |
644 | delete message; | |
a38292a3 LOK |
645 | |
646 | if (bReturn) | |
647 | { | |
648 | CLockObject lock(m_mutex); | |
649 | m_bControlledMode = controlled; | |
650 | } | |
651 | ||
a75e3a5a LOK |
652 | return bReturn; |
653 | } |