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