cec: send a feature abort again for all unhandled commands, removed statics, refactor...
[deb_libcec.git] / src / lib / adapter / USBCECAdapterCommunication.cpp
CommitLineData
a8f0bd18
LOK
1/*
2 * This file is part of the libCEC(R) library.
3 *
b492c10e 4 * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
a8f0bd18
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
7bb4ed43 33#include "USBCECAdapterCommunication.h"
a75e3a5a
LOK
34#include "USBCECAdapterCommands.h"
35#include "USBCECAdapterMessageQueue.h"
ba65909d
LOK
36#include "../platform/sockets/serialport.h"
37#include "../platform/util/timeutils.h"
5477a250 38#include "../LibCEC.h"
7bb4ed43 39#include "../CECProcessor.h"
a8f0bd18
LOK
40
41using namespace std;
42using namespace CEC;
f00ff009 43using namespace PLATFORM;
a8f0bd18 44
ae54110f
LOK
45#define CEC_ADAPTER_PING_TIMEOUT 15000
46
5daed059
LOK
47// firmware version 2
48#define CEC_LATEST_ADAPTER_FW_VERSION 2
49// firmware date Thu Apr 26 20:14:49 2012 +0000
50#define CEC_LATEST_ADAPTER_FW_DATE 0x4F99ACB9
51
004b8382
LOK
52#define LIB_CEC m_callback->GetLib()
53
b32ffd87 54CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCallback *callback, const char *strPort, uint16_t iBaudRate /* = CEC_SERIAL_DEFAULT_BAUDRATE */) :
a75e3a5a 55 IAdapterCommunication(callback),
12027dbe 56 m_port(NULL),
1fc16cfd 57 m_iLineTimeout(0),
a75e3a5a 58 m_lastPollDestination(CECDEVICE_UNKNOWN),
56e53c14 59 m_bInitialised(false),
a75e3a5a
LOK
60 m_pingThread(NULL),
61 m_commands(NULL),
004b8382
LOK
62 m_adapterMessageQueue(NULL),
63 m_iAckMask(0xFFFF)
a8f0bd18 64{
d2d1660c 65 for (unsigned int iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
4164923b 66 m_bWaitingForAck[iPtr] = false;
089f0e9d 67 m_port = new CSerialPort(strPort, iBaudRate);
a8f0bd18
LOK
68}
69
a75e3a5a 70CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void)
a8f0bd18 71{
a75e3a5a
LOK
72 Close();
73 delete m_commands;
74 delete m_adapterMessageQueue;
e4a53f8e 75 delete m_port;
efed01e1 76}
a8f0bd18 77
b32ffd87 78bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */, bool bSkipChecks /* = false */, bool bStartListening /* = true */)
efed01e1 79{
a75e3a5a 80 bool bConnectionOpened(false);
2c780401 81 {
efed01e1
LOK
82 CLockObject lock(m_mutex);
83
a75e3a5a 84 /* we need the port settings here */
efed01e1
LOK
85 if (!m_port)
86 {
004b8382 87 LIB_CEC->AddLog(CEC_LOG_ERROR, "port is NULL");
a75e3a5a 88 return bConnectionOpened;
efed01e1
LOK
89 }
90
a75e3a5a 91 /* return true when the port is already open */
efed01e1
LOK
92 if (IsOpen())
93 {
004b8382 94 LIB_CEC->AddLog(CEC_LOG_WARNING, "port is already open");
efed01e1
LOK
95 return true;
96 }
97
a75e3a5a
LOK
98 /* adapter commands */
99 if (!m_commands)
100 m_commands = new CUSBCECAdapterCommands(this);
101
102 if (!m_adapterMessageQueue)
a8559e01 103 {
a75e3a5a 104 m_adapterMessageQueue = new CCECAdapterMessageQueue(this);
a8559e01
LOK
105 m_adapterMessageQueue->CreateThread();
106 }
a75e3a5a
LOK
107
108 /* try to open the connection */
efed01e1 109 CStdString strError;
a75e3a5a
LOK
110 CTimeout timeout(iTimeoutMs);
111 while (!bConnectionOpened && timeout.TimeLeft() > 0)
efed01e1 112 {
a75e3a5a 113 if ((bConnectionOpened = m_port->Open(timeout.TimeLeft())) == false)
efed01e1
LOK
114 {
115 strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str());
116 Sleep(250);
efed01e1 117 }
a75e3a5a 118 /* and retry every 250ms until the timeout passed */
efed01e1
LOK
119 }
120
a75e3a5a
LOK
121 /* return false when we couldn't connect */
122 if (!bConnectionOpened)
efed01e1 123 {
004b8382 124 LIB_CEC->AddLog(CEC_LOG_ERROR, strError);
efed01e1
LOK
125 return false;
126 }
127
004b8382 128 LIB_CEC->AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
a75e3a5a 129 ClearInputBytes();
2c780401 130 }
a8f0bd18 131
a75e3a5a 132 if (!CreateThread())
a8f0bd18 133 {
a75e3a5a 134 bConnectionOpened = false;
004b8382 135 LIB_CEC->AddLog(CEC_LOG_ERROR, "could not create a communication thread");
a75e3a5a
LOK
136 }
137 else if (!bSkipChecks && !CheckAdapter())
138 {
139 bConnectionOpened = false;
004b8382 140 LIB_CEC->AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks");
befa3a23 141 }
f80cd208 142 else if (bStartListening)
befa3a23 143 {
a75e3a5a
LOK
144 /* start a ping thread, that will ping the adapter every 15 seconds
145 if it doesn't receive any ping for 30 seconds, it'll switch to auto mode */
56e53c14 146 m_pingThread = new CAdapterPingThread(this, CEC_ADAPTER_PING_TIMEOUT);
a75e3a5a 147 if (m_pingThread->CreateThread())
efed01e1 148 {
a75e3a5a 149 bConnectionOpened = true;
efed01e1
LOK
150 }
151 else
152 {
a75e3a5a 153 bConnectionOpened = false;
004b8382 154 LIB_CEC->AddLog(CEC_LOG_ERROR, "could not create a ping thread");
efed01e1 155 }
a8f0bd18 156 }
a75e3a5a
LOK
157
158 if (!bConnectionOpened || !bStartListening)
159 StopThread(0);
a8f0bd18 160
a75e3a5a 161 return bConnectionOpened;
a8f0bd18
LOK
162}
163
7bb4ed43 164void CUSBCECAdapterCommunication::Close(void)
a8f0bd18 165{
0b714871
LOK
166 /* stop the reader thread */
167 StopThread(0);
168
169 CLockObject lock(m_mutex);
170
a75e3a5a 171 /* set the ackmask to 0 before closing the connection */
0b714871 172 if (IsRunning() && m_port->IsOpen() && m_port->GetErrorNumber() == 0)
a75e3a5a 173 {
004b8382 174 LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - closing the connection", __FUNCTION__);
a75e3a5a
LOK
175 SetAckMask(0);
176 if (m_commands->GetFirmwareVersion() >= 2)
177 SetControlledMode(false);
178 }
179
a8559e01
LOK
180 m_adapterMessageQueue->Clear();
181
a75e3a5a 182 /* stop and delete the ping thread */
56e53c14
LOK
183 if (m_pingThread)
184 m_pingThread->StopThread(0);
185 delete m_pingThread;
186 m_pingThread = NULL;
a8f0bd18 187
a75e3a5a 188 /* close and delete the com port connection */
e4a53f8e
LOK
189 if (m_port)
190 m_port->Close();
0b714871
LOK
191
192 libcec_parameter param;
004b8382 193 LIB_CEC->Alert(CEC_ALERT_CONNECTION_LOST, param);
a8f0bd18
LOK
194}
195
33dd87a9 196cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout)
7bb4ed43
LOK
197{
198 cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
9f68cc28
LOK
199 if (!IsRunning())
200 return retVal;
7bb4ed43 201
33dd87a9 202 CCECAdapterMessage *output = new CCECAdapterMessage(data, iLineTimeout);
7bb4ed43 203
a75e3a5a
LOK
204 /* mark as waiting for an ack from the destination */
205 MarkAsWaiting(data.destination);
4164923b 206
a75e3a5a 207 /* send the message */
33dd87a9 208 bRetry = (!m_adapterMessageQueue->Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0;
a8559e01 209 if (bRetry)
33dd87a9 210 Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
7bb4ed43
LOK
211 retVal = output->state;
212
213 delete output;
214 return retVal;
215}
216
a75e3a5a 217void *CUSBCECAdapterCommunication::Process(void)
3c53ac93 218{
a75e3a5a 219 CCECAdapterMessage msg;
004b8382 220 LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread started");
5dcf9f25 221
a75e3a5a 222 while (!IsStopped())
5dcf9f25 223 {
a75e3a5a
LOK
224 /* read from the serial port */
225 if (!ReadFromDevice(50, 5))
226 break;
227
228 /* TODO sleep 5 ms so other threads can get a lock */
229 Sleep(5);
5dcf9f25
LOK
230 }
231
a75e3a5a 232 m_adapterMessageQueue->Clear();
004b8382 233 LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread ended");
a75e3a5a 234 return NULL;
a8f0bd18
LOK
235}
236
a75e3a5a 237bool CUSBCECAdapterCommunication::HandlePoll(const CCECAdapterMessage &msg)
a8f0bd18 238{
a75e3a5a
LOK
239 bool bIsError(msg.IsError());
240 cec_adapter_messagecode messageCode(msg.Message());
241 CLockObject lock(m_mutex);
9f68cc28 242
a75e3a5a 243 if (messageCode == MSGCODE_FRAME_START && msg.IsACK())
a8f0bd18 244 {
a75e3a5a
LOK
245 m_lastPollDestination = msg.Destination();
246 if (msg.Destination() < CECDEVICE_BROADCAST)
a8f0bd18 247 {
a75e3a5a
LOK
248 if (!m_bWaitingForAck[msg.Destination()] && !msg.IsEOM())
249 {
250 if (m_callback)
251 m_callback->HandlePoll(msg.Initiator(), msg.Destination());
252 }
253 else
254 m_bWaitingForAck[msg.Destination()] = false;
a8f0bd18 255 }
7bb4ed43 256 }
a75e3a5a 257 else if (messageCode == MSGCODE_RECEIVE_FAILED)
7bb4ed43 258 {
a75e3a5a
LOK
259 /* hack to suppress warnings when an LG is polling */
260 if (m_lastPollDestination != CECDEVICE_UNKNOWN)
261 bIsError = m_callback->HandleReceiveFailed(m_lastPollDestination);
7bb4ed43 262 }
a8f0bd18 263
a75e3a5a 264 return bIsError;
a8f0bd18 265}
2abe74eb 266
a75e3a5a 267void CUSBCECAdapterCommunication::MarkAsWaiting(const cec_logical_address dest)
2abe74eb 268{
a75e3a5a
LOK
269 /* mark as waiting for an ack from the destination */
270 if (dest < CECDEVICE_BROADCAST)
7bb4ed43 271 {
a75e3a5a
LOK
272 CLockObject lock(m_mutex);
273 m_bWaitingForAck[dest] = true;
7bb4ed43 274 }
7bb4ed43
LOK
275}
276
b32ffd87 277void CUSBCECAdapterCommunication::ClearInputBytes(uint32_t iTimeout /* = CEC_CLEAR_INPUT_DEFAULT_WAIT */)
1fc16cfd 278{
a75e3a5a
LOK
279 CTimeout timeout(iTimeout);
280 uint8_t buff[1024];
281 ssize_t iBytesRead(0);
a4d657c7 282 bool bGotMsgEnd(true);
1fc16cfd 283
a75e3a5a 284 while (timeout.TimeLeft() > 0 && ((iBytesRead = m_port->Read(buff, 1024, 5)) > 0 || !bGotMsgEnd))
1fc16cfd 285 {
a4d657c7 286 bGotMsgEnd = false;
a75e3a5a
LOK
287 /* if something was received, wait for MSGEND */
288 for (ssize_t iPtr = 0; iPtr < iBytesRead; iPtr++)
289 bGotMsgEnd = buff[iPtr] == MSGEND;
1fc16cfd 290 }
1fc16cfd
LOK
291}
292
7bb4ed43 293bool CUSBCECAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
a171d2fd 294{
16459df9 295 bool bReturn(true);
a75e3a5a 296 bool bChanged(false);
089f0e9d 297
a75e3a5a 298 /* only send the command if the timeout changed */
089f0e9d 299 {
a75e3a5a
LOK
300 CLockObject lock(m_mutex);
301 bChanged = (m_iLineTimeout != iTimeout);
302 m_iLineTimeout = iTimeout;
089f0e9d
LOK
303 }
304
a75e3a5a
LOK
305 if (bChanged)
306 bReturn = m_commands->SetLineTimeout(iTimeout);
a171d2fd 307
a75e3a5a 308 return bReturn;
f9e01dac
LOK
309}
310
a75e3a5a 311bool CUSBCECAdapterCommunication::WriteToDevice(CCECAdapterMessage *message)
5dcf9f25 312{
a75e3a5a
LOK
313 CLockObject adapterLock(m_mutex);
314 if (!m_port->IsOpen())
315 {
004b8382 316 LIB_CEC->AddLog(CEC_LOG_DEBUG, "error writing command '%s' to serial port '%s': the connection is closed", CCECAdapterMessage::ToString(message->Message()), m_port->GetName().c_str());
a75e3a5a
LOK
317 message->state = ADAPTER_MESSAGE_STATE_ERROR;
318 return false;
319 }
5dcf9f25 320
a75e3a5a
LOK
321 /* write the message */
322 if (m_port->Write(message->packet.data, message->Size()) != (ssize_t) message->Size())
323 {
004b8382 324 LIB_CEC->AddLog(CEC_LOG_DEBUG, "error writing command '%s' to serial port '%s': %s", CCECAdapterMessage::ToString(message->Message()), m_port->GetName().c_str(), m_port->GetError().c_str());
a75e3a5a 325 message->state = ADAPTER_MESSAGE_STATE_ERROR;
a8559e01 326 Close();
cb4ee028 327 return false;
a75e3a5a 328 }
cb4ee028 329
004b8382 330 LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' sent", message->IsTranmission() ? "CEC transmission" : CCECAdapterMessage::ToString(message->Message()));
a75e3a5a
LOK
331 message->state = ADAPTER_MESSAGE_STATE_SENT;
332 return true;
c214d197 333}
b057edad 334
a75e3a5a 335bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize /* = 256 */)
12a36be9 336{
a75e3a5a
LOK
337 ssize_t iBytesRead(0);
338 uint8_t buff[256];
339 if (iSize > 256)
340 iSize = 256;
12a36be9 341
a75e3a5a 342 /* read from the serial port */
12a36be9 343 {
a75e3a5a 344 CLockObject lock(m_mutex);
0b714871 345 if (!m_port || !m_port->IsOpen())
a75e3a5a 346 return false;
a8559e01 347
a75e3a5a 348 iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
a8559e01
LOK
349
350 if (m_port->GetErrorNumber())
351 {
004b8382 352 LIB_CEC->AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
a8559e01
LOK
353 m_port->Close();
354 return false;
355 }
12a36be9
LOK
356 }
357
a75e3a5a 358 if (iBytesRead < 0 || iBytesRead > 256)
a75e3a5a 359 return false;
a75e3a5a 360 else if (iBytesRead > 0)
12a36be9 361 {
a75e3a5a
LOK
362 /* add the data to the current frame */
363 m_adapterMessageQueue->AddData(buff, iBytesRead);
12a36be9
LOK
364 }
365
a75e3a5a 366 return true;
b057edad
BL
367}
368
a75e3a5a 369CCECAdapterMessage *CUSBCECAdapterCommunication::SendCommand(cec_adapter_messagecode msgCode, CCECAdapterMessage &params, bool bIsRetry /* = false */)
c214d197 370{
a75e3a5a
LOK
371 if (!m_port || !m_port->IsOpen() ||
372 !m_adapterMessageQueue)
373 return NULL;
c214d197 374
a75e3a5a
LOK
375 /* create the adapter message for this command */
376 CCECAdapterMessage *output = new CCECAdapterMessage;
377 output->PushBack(MSGSTART);
378 output->PushEscaped((uint8_t)msgCode);
379 output->Append(params);
380 output->PushBack(MSGEND);
12a36be9 381
a75e3a5a
LOK
382 /* write the command */
383 if (!m_adapterMessageQueue->Write(output))
12a36be9 384 {
0b714871
LOK
385 if (output->state == ADAPTER_MESSAGE_STATE_ERROR)
386 Close();
a75e3a5a 387 return output;
12a36be9 388 }
a75e3a5a 389 else
12a36be9 390 {
ee090252
LOK
391 if (!bIsRetry && output->Reply() == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED &&
392 msgCode != MSGCODE_GET_BUILDDATE /* same messagecode value had a different meaning in older fw builds */)
a75e3a5a
LOK
393 {
394 /* if the controller reported that the command was rejected, and we didn't send the command
395 to set controlled mode, then the controller probably switched to auto mode. set controlled
396 mode and retry */
004b8382 397 LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting controlled mode and retrying");
a75e3a5a
LOK
398 delete output;
399 if (SetControlledMode(true))
400 return SendCommand(msgCode, params, true);
401 }
12a36be9 402 }
12a36be9 403
a75e3a5a 404 return output;
c214d197
LOK
405}
406
b32ffd87 407bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
12a36be9 408{
a75e3a5a
LOK
409 bool bReturn(false);
410 CTimeout timeout(iTimeoutMs > 0 ? iTimeoutMs : CEC_DEFAULT_TRANSMIT_WAIT);
12a36be9 411
a75e3a5a
LOK
412 /* try to ping the adapter */
413 bool bPinged(false);
414 unsigned iPingTry(0);
415 while (timeout.TimeLeft() > 0 && (bPinged = PingAdapter()) == false)
12a36be9 416 {
004b8382 417 LIB_CEC->AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry);
a75e3a5a 418 CEvent::Sleep(500);
12a36be9 419 }
c214d197 420
a75e3a5a
LOK
421 /* try to read the firmware version */
422 if (bPinged && timeout.TimeLeft() > 0 && m_commands->RequestFirmwareVersion() >= 2)
12a36be9 423 {
a75e3a5a
LOK
424 /* try to set controlled mode for v2+ firmwares */
425 unsigned iControlledTry(0);
426 bool bControlled(false);
427 while (timeout.TimeLeft() > 0 && (bControlled = SetControlledMode(true)) == false)
428 {
004b8382 429 LIB_CEC->AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry);
a75e3a5a
LOK
430 CEvent::Sleep(500);
431 }
432 bReturn = bControlled;
12a36be9 433 }
a75e3a5a
LOK
434 else
435 bReturn = true;
c214d197 436
baabc020
LOK
437 /* try to read the build date */
438 m_commands->RequestBuildDate();
439
a75e3a5a
LOK
440 SetInitialised(bReturn);
441 return bReturn;
c214d197
LOK
442}
443
a75e3a5a 444bool CUSBCECAdapterCommunication::IsOpen(void)
12a36be9 445{
a75e3a5a
LOK
446 /* thread is not being stopped, the port is open and the thread is running */
447 return !IsStopped() && m_port->IsOpen() && IsRunning();
12a36be9
LOK
448}
449
a75e3a5a 450CStdString CUSBCECAdapterCommunication::GetError(void) const
c214d197 451{
a75e3a5a 452 return m_port->GetError();
c214d197
LOK
453}
454
a75e3a5a 455void CUSBCECAdapterCommunication::SetInitialised(bool bSetTo /* = true */)
12a36be9
LOK
456{
457 CLockObject lock(m_mutex);
a75e3a5a 458 m_bInitialised = bSetTo;
12a36be9
LOK
459}
460
a75e3a5a 461bool CUSBCECAdapterCommunication::IsInitialised(void)
c214d197
LOK
462{
463 CLockObject lock(m_mutex);
a75e3a5a 464 return m_bInitialised;
c214d197
LOK
465}
466
a75e3a5a 467bool CUSBCECAdapterCommunication::StartBootloader(void)
12a36be9 468{
55c75e6e
LOK
469 if (m_port->IsOpen() && m_commands->StartBootloader())
470 {
471 Close();
472 return true;
473 }
474 return false;
12a36be9
LOK
475}
476
a75e3a5a 477bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask)
13fd6a66 478{
004b8382
LOK
479 if (m_iAckMask == iMask)
480 return true;
481
482 if (m_port && m_port->IsOpen() && m_commands->SetAckMask(iMask))
483 {
484 m_iAckMask = iMask;
485 return true;
486 }
487
488 return false;
489}
490
491uint16_t CUSBCECAdapterCommunication::GetAckMask(void)
492{
493 return m_iAckMask;
13fd6a66 494}
ef7696f5 495
a75e3a5a 496bool CUSBCECAdapterCommunication::PingAdapter(void)
6729ac71 497{
0b714871 498 return m_port->IsOpen() ? m_commands->PingAdapter() : false;
6729ac71
LOK
499}
500
a75e3a5a 501uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void)
ef7696f5 502{
a75e3a5a 503 return m_commands->GetFirmwareVersion();
ef7696f5
LOK
504}
505
b2f56d35
LOK
506uint32_t CUSBCECAdapterCommunication::GetFirmwareBuildDate(void)
507{
508 return m_commands->RequestBuildDate();
509}
510
5daed059
LOK
511bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void)
512{
513 return GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION &&
514 GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE;
515}
516
a75e3a5a 517bool CUSBCECAdapterCommunication::PersistConfiguration(libcec_configuration *configuration)
ef7696f5 518{
0b714871 519 return m_port->IsOpen() ? m_commands->PersistConfiguration(configuration) : false;
ef7696f5
LOK
520}
521
a75e3a5a 522bool CUSBCECAdapterCommunication::GetConfiguration(libcec_configuration *configuration)
ef7696f5 523{
0b714871 524 return m_port->IsOpen() ? m_commands->GetConfiguration(configuration) : false;
ef7696f5
LOK
525}
526
cba904a6
LOK
527CStdString CUSBCECAdapterCommunication::GetPortName(void)
528{
a75e3a5a 529 return m_port->GetName();
c9c282a4 530}
d4db0c6f 531
a75e3a5a 532bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled)
d4db0c6f 533{
0b714871 534 return m_port->IsOpen() ? m_commands->SetControlledMode(controlled) : false;
d4db0c6f 535}
56e53c14
LOK
536
537void *CAdapterPingThread::Process(void)
538{
539 while (!IsStopped())
540 {
541 if (m_timeout.TimeLeft() == 0)
542 {
a75e3a5a 543 /* reinit the timeout */
56e53c14 544 m_timeout.Init(CEC_ADAPTER_PING_TIMEOUT);
a75e3a5a
LOK
545
546 /* send a ping to the adapter */
547 bool bPinged(false);
548 int iFailedCounter(0);
549 while (!bPinged && iFailedCounter < 3)
550 {
551 if (!m_com->PingAdapter())
552 {
b32ffd87
LOK
553 /* sleep and retry */
554 Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
a75e3a5a
LOK
555 ++iFailedCounter;
556 }
557 else
558 {
559 bPinged = true;
560 }
561 }
562
563 if (iFailedCounter == 3)
564 {
565 /* failed to ping the adapter 3 times in a row. something must be wrong with the connection */
004b8382 566 m_com->LIB_CEC->AddLog(CEC_LOG_ERROR, "failed to ping the adapter 3 times in a row. closing the connection.");
a75e3a5a
LOK
567 m_com->StopThread(false);
568 break;
569 }
56e53c14
LOK
570 }
571
572 Sleep(500);
573 }
574 return NULL;
575}