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