cec: fixed abi
[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;
c30acafa 193 param.paramData = NULL; param.paramType = CEC_PARAMETER_TYPE_UNKOWN;
004b8382 194 LIB_CEC->Alert(CEC_ALERT_CONNECTION_LOST, param);
a8f0bd18
LOK
195}
196
33dd87a9 197cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout)
7bb4ed43
LOK
198{
199 cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
9f68cc28
LOK
200 if (!IsRunning())
201 return retVal;
7bb4ed43 202
33dd87a9 203 CCECAdapterMessage *output = new CCECAdapterMessage(data, iLineTimeout);
7bb4ed43 204
a75e3a5a
LOK
205 /* mark as waiting for an ack from the destination */
206 MarkAsWaiting(data.destination);
4164923b 207
a75e3a5a 208 /* send the message */
33dd87a9 209 bRetry = (!m_adapterMessageQueue->Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0;
a8559e01 210 if (bRetry)
33dd87a9 211 Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
7bb4ed43
LOK
212 retVal = output->state;
213
214 delete output;
215 return retVal;
216}
217
a75e3a5a 218void *CUSBCECAdapterCommunication::Process(void)
3c53ac93 219{
a75e3a5a 220 CCECAdapterMessage msg;
004b8382 221 LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread started");
5dcf9f25 222
a75e3a5a 223 while (!IsStopped())
5dcf9f25 224 {
a75e3a5a
LOK
225 /* read from the serial port */
226 if (!ReadFromDevice(50, 5))
227 break;
228
229 /* TODO sleep 5 ms so other threads can get a lock */
230 Sleep(5);
5dcf9f25
LOK
231 }
232
a75e3a5a 233 m_adapterMessageQueue->Clear();
004b8382 234 LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread ended");
a75e3a5a 235 return NULL;
a8f0bd18
LOK
236}
237
a75e3a5a 238bool CUSBCECAdapterCommunication::HandlePoll(const CCECAdapterMessage &msg)
a8f0bd18 239{
a75e3a5a
LOK
240 bool bIsError(msg.IsError());
241 cec_adapter_messagecode messageCode(msg.Message());
242 CLockObject lock(m_mutex);
9f68cc28 243
a75e3a5a 244 if (messageCode == MSGCODE_FRAME_START && msg.IsACK())
a8f0bd18 245 {
a75e3a5a
LOK
246 m_lastPollDestination = msg.Destination();
247 if (msg.Destination() < CECDEVICE_BROADCAST)
a8f0bd18 248 {
a75e3a5a
LOK
249 if (!m_bWaitingForAck[msg.Destination()] && !msg.IsEOM())
250 {
251 if (m_callback)
252 m_callback->HandlePoll(msg.Initiator(), msg.Destination());
253 }
254 else
255 m_bWaitingForAck[msg.Destination()] = false;
a8f0bd18 256 }
7bb4ed43 257 }
a75e3a5a 258 else if (messageCode == MSGCODE_RECEIVE_FAILED)
7bb4ed43 259 {
a75e3a5a
LOK
260 /* hack to suppress warnings when an LG is polling */
261 if (m_lastPollDestination != CECDEVICE_UNKNOWN)
262 bIsError = m_callback->HandleReceiveFailed(m_lastPollDestination);
7bb4ed43 263 }
a8f0bd18 264
a75e3a5a 265 return bIsError;
a8f0bd18 266}
2abe74eb 267
a75e3a5a 268void CUSBCECAdapterCommunication::MarkAsWaiting(const cec_logical_address dest)
2abe74eb 269{
a75e3a5a
LOK
270 /* mark as waiting for an ack from the destination */
271 if (dest < CECDEVICE_BROADCAST)
7bb4ed43 272 {
a75e3a5a
LOK
273 CLockObject lock(m_mutex);
274 m_bWaitingForAck[dest] = true;
7bb4ed43 275 }
7bb4ed43
LOK
276}
277
b32ffd87 278void CUSBCECAdapterCommunication::ClearInputBytes(uint32_t iTimeout /* = CEC_CLEAR_INPUT_DEFAULT_WAIT */)
1fc16cfd 279{
a75e3a5a
LOK
280 CTimeout timeout(iTimeout);
281 uint8_t buff[1024];
282 ssize_t iBytesRead(0);
a4d657c7 283 bool bGotMsgEnd(true);
1fc16cfd 284
a75e3a5a 285 while (timeout.TimeLeft() > 0 && ((iBytesRead = m_port->Read(buff, 1024, 5)) > 0 || !bGotMsgEnd))
1fc16cfd 286 {
a4d657c7 287 bGotMsgEnd = false;
a75e3a5a
LOK
288 /* if something was received, wait for MSGEND */
289 for (ssize_t iPtr = 0; iPtr < iBytesRead; iPtr++)
290 bGotMsgEnd = buff[iPtr] == MSGEND;
1fc16cfd 291 }
1fc16cfd
LOK
292}
293
7bb4ed43 294bool CUSBCECAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
a171d2fd 295{
16459df9 296 bool bReturn(true);
a75e3a5a 297 bool bChanged(false);
089f0e9d 298
a75e3a5a 299 /* only send the command if the timeout changed */
089f0e9d 300 {
a75e3a5a
LOK
301 CLockObject lock(m_mutex);
302 bChanged = (m_iLineTimeout != iTimeout);
303 m_iLineTimeout = iTimeout;
089f0e9d
LOK
304 }
305
a75e3a5a
LOK
306 if (bChanged)
307 bReturn = m_commands->SetLineTimeout(iTimeout);
a171d2fd 308
a75e3a5a 309 return bReturn;
f9e01dac
LOK
310}
311
a75e3a5a 312bool CUSBCECAdapterCommunication::WriteToDevice(CCECAdapterMessage *message)
5dcf9f25 313{
a75e3a5a
LOK
314 CLockObject adapterLock(m_mutex);
315 if (!m_port->IsOpen())
316 {
004b8382 317 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
318 message->state = ADAPTER_MESSAGE_STATE_ERROR;
319 return false;
320 }
5dcf9f25 321
a75e3a5a
LOK
322 /* write the message */
323 if (m_port->Write(message->packet.data, message->Size()) != (ssize_t) message->Size())
324 {
004b8382 325 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 326 message->state = ADAPTER_MESSAGE_STATE_ERROR;
a8559e01 327 Close();
cb4ee028 328 return false;
a75e3a5a 329 }
cb4ee028 330
004b8382 331 LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' sent", message->IsTranmission() ? "CEC transmission" : CCECAdapterMessage::ToString(message->Message()));
a75e3a5a
LOK
332 message->state = ADAPTER_MESSAGE_STATE_SENT;
333 return true;
c214d197 334}
b057edad 335
a75e3a5a 336bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize /* = 256 */)
12a36be9 337{
a75e3a5a
LOK
338 ssize_t iBytesRead(0);
339 uint8_t buff[256];
340 if (iSize > 256)
341 iSize = 256;
12a36be9 342
a75e3a5a 343 /* read from the serial port */
12a36be9 344 {
a75e3a5a 345 CLockObject lock(m_mutex);
0b714871 346 if (!m_port || !m_port->IsOpen())
a75e3a5a 347 return false;
a8559e01 348
a75e3a5a 349 iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
a8559e01
LOK
350
351 if (m_port->GetErrorNumber())
352 {
004b8382 353 LIB_CEC->AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
a8559e01
LOK
354 m_port->Close();
355 return false;
356 }
12a36be9
LOK
357 }
358
a75e3a5a 359 if (iBytesRead < 0 || iBytesRead > 256)
a75e3a5a 360 return false;
a75e3a5a 361 else if (iBytesRead > 0)
12a36be9 362 {
a75e3a5a
LOK
363 /* add the data to the current frame */
364 m_adapterMessageQueue->AddData(buff, iBytesRead);
12a36be9
LOK
365 }
366
a75e3a5a 367 return true;
b057edad
BL
368}
369
a75e3a5a 370CCECAdapterMessage *CUSBCECAdapterCommunication::SendCommand(cec_adapter_messagecode msgCode, CCECAdapterMessage &params, bool bIsRetry /* = false */)
c214d197 371{
a75e3a5a
LOK
372 if (!m_port || !m_port->IsOpen() ||
373 !m_adapterMessageQueue)
374 return NULL;
c214d197 375
a75e3a5a
LOK
376 /* create the adapter message for this command */
377 CCECAdapterMessage *output = new CCECAdapterMessage;
378 output->PushBack(MSGSTART);
379 output->PushEscaped((uint8_t)msgCode);
380 output->Append(params);
381 output->PushBack(MSGEND);
12a36be9 382
a75e3a5a
LOK
383 /* write the command */
384 if (!m_adapterMessageQueue->Write(output))
12a36be9 385 {
0b714871
LOK
386 if (output->state == ADAPTER_MESSAGE_STATE_ERROR)
387 Close();
a75e3a5a 388 return output;
12a36be9 389 }
a75e3a5a 390 else
12a36be9 391 {
ee090252
LOK
392 if (!bIsRetry && output->Reply() == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED &&
393 msgCode != MSGCODE_GET_BUILDDATE /* same messagecode value had a different meaning in older fw builds */)
a75e3a5a
LOK
394 {
395 /* if the controller reported that the command was rejected, and we didn't send the command
396 to set controlled mode, then the controller probably switched to auto mode. set controlled
397 mode and retry */
004b8382 398 LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting controlled mode and retrying");
a75e3a5a
LOK
399 delete output;
400 if (SetControlledMode(true))
401 return SendCommand(msgCode, params, true);
402 }
12a36be9 403 }
12a36be9 404
a75e3a5a 405 return output;
c214d197
LOK
406}
407
b32ffd87 408bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
12a36be9 409{
a75e3a5a
LOK
410 bool bReturn(false);
411 CTimeout timeout(iTimeoutMs > 0 ? iTimeoutMs : CEC_DEFAULT_TRANSMIT_WAIT);
12a36be9 412
a75e3a5a
LOK
413 /* try to ping the adapter */
414 bool bPinged(false);
415 unsigned iPingTry(0);
416 while (timeout.TimeLeft() > 0 && (bPinged = PingAdapter()) == false)
12a36be9 417 {
004b8382 418 LIB_CEC->AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry);
a75e3a5a 419 CEvent::Sleep(500);
12a36be9 420 }
c214d197 421
a75e3a5a
LOK
422 /* try to read the firmware version */
423 if (bPinged && timeout.TimeLeft() > 0 && m_commands->RequestFirmwareVersion() >= 2)
12a36be9 424 {
a75e3a5a
LOK
425 /* try to set controlled mode for v2+ firmwares */
426 unsigned iControlledTry(0);
427 bool bControlled(false);
428 while (timeout.TimeLeft() > 0 && (bControlled = SetControlledMode(true)) == false)
429 {
004b8382 430 LIB_CEC->AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry);
a75e3a5a
LOK
431 CEvent::Sleep(500);
432 }
433 bReturn = bControlled;
12a36be9 434 }
a75e3a5a
LOK
435 else
436 bReturn = true;
c214d197 437
baabc020
LOK
438 /* try to read the build date */
439 m_commands->RequestBuildDate();
440
a75e3a5a
LOK
441 SetInitialised(bReturn);
442 return bReturn;
c214d197
LOK
443}
444
a75e3a5a 445bool CUSBCECAdapterCommunication::IsOpen(void)
12a36be9 446{
a75e3a5a
LOK
447 /* thread is not being stopped, the port is open and the thread is running */
448 return !IsStopped() && m_port->IsOpen() && IsRunning();
12a36be9
LOK
449}
450
a75e3a5a 451CStdString CUSBCECAdapterCommunication::GetError(void) const
c214d197 452{
a75e3a5a 453 return m_port->GetError();
c214d197
LOK
454}
455
a75e3a5a 456void CUSBCECAdapterCommunication::SetInitialised(bool bSetTo /* = true */)
12a36be9
LOK
457{
458 CLockObject lock(m_mutex);
a75e3a5a 459 m_bInitialised = bSetTo;
12a36be9
LOK
460}
461
a75e3a5a 462bool CUSBCECAdapterCommunication::IsInitialised(void)
c214d197
LOK
463{
464 CLockObject lock(m_mutex);
a75e3a5a 465 return m_bInitialised;
c214d197
LOK
466}
467
a75e3a5a 468bool CUSBCECAdapterCommunication::StartBootloader(void)
12a36be9 469{
55c75e6e
LOK
470 if (m_port->IsOpen() && m_commands->StartBootloader())
471 {
472 Close();
473 return true;
474 }
475 return false;
12a36be9
LOK
476}
477
a75e3a5a 478bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask)
13fd6a66 479{
004b8382
LOK
480 if (m_iAckMask == iMask)
481 return true;
482
483 if (m_port && m_port->IsOpen() && m_commands->SetAckMask(iMask))
484 {
485 m_iAckMask = iMask;
486 return true;
487 }
488
489 return false;
490}
491
492uint16_t CUSBCECAdapterCommunication::GetAckMask(void)
493{
494 return m_iAckMask;
13fd6a66 495}
ef7696f5 496
a75e3a5a 497bool CUSBCECAdapterCommunication::PingAdapter(void)
6729ac71 498{
0b714871 499 return m_port->IsOpen() ? m_commands->PingAdapter() : false;
6729ac71
LOK
500}
501
a75e3a5a 502uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void)
ef7696f5 503{
a75e3a5a 504 return m_commands->GetFirmwareVersion();
ef7696f5
LOK
505}
506
b2f56d35
LOK
507uint32_t CUSBCECAdapterCommunication::GetFirmwareBuildDate(void)
508{
509 return m_commands->RequestBuildDate();
510}
511
5daed059
LOK
512bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void)
513{
514 return GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION &&
515 GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE;
516}
517
a75e3a5a 518bool CUSBCECAdapterCommunication::PersistConfiguration(libcec_configuration *configuration)
ef7696f5 519{
0b714871 520 return m_port->IsOpen() ? m_commands->PersistConfiguration(configuration) : false;
ef7696f5
LOK
521}
522
a75e3a5a 523bool CUSBCECAdapterCommunication::GetConfiguration(libcec_configuration *configuration)
ef7696f5 524{
0b714871 525 return m_port->IsOpen() ? m_commands->GetConfiguration(configuration) : false;
ef7696f5
LOK
526}
527
cba904a6
LOK
528CStdString CUSBCECAdapterCommunication::GetPortName(void)
529{
a75e3a5a 530 return m_port->GetName();
c9c282a4 531}
d4db0c6f 532
a75e3a5a 533bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled)
d4db0c6f 534{
0b714871 535 return m_port->IsOpen() ? m_commands->SetControlledMode(controlled) : false;
d4db0c6f 536}
56e53c14
LOK
537
538void *CAdapterPingThread::Process(void)
539{
540 while (!IsStopped())
541 {
542 if (m_timeout.TimeLeft() == 0)
543 {
a75e3a5a 544 /* reinit the timeout */
56e53c14 545 m_timeout.Init(CEC_ADAPTER_PING_TIMEOUT);
a75e3a5a
LOK
546
547 /* send a ping to the adapter */
548 bool bPinged(false);
549 int iFailedCounter(0);
550 while (!bPinged && iFailedCounter < 3)
551 {
552 if (!m_com->PingAdapter())
553 {
b32ffd87
LOK
554 /* sleep and retry */
555 Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
a75e3a5a
LOK
556 ++iFailedCounter;
557 }
558 else
559 {
560 bPinged = true;
561 }
562 }
563
564 if (iFailedCounter == 3)
565 {
566 /* failed to ping the adapter 3 times in a row. something must be wrong with the connection */
004b8382 567 m_com->LIB_CEC->AddLog(CEC_LOG_ERROR, "failed to ping the adapter 3 times in a row. closing the connection.");
a75e3a5a
LOK
568 m_com->StopThread(false);
569 break;
570 }
56e53c14
LOK
571 }
572
573 Sleep(500);
574 }
575 return NULL;
576}