cec: fixed compilation warnings
[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"
ba65909d
LOK
34#include "../platform/sockets/serialport.h"
35#include "../platform/util/timeutils.h"
5477a250 36#include "../LibCEC.h"
7bb4ed43 37#include "../CECProcessor.h"
a8f0bd18
LOK
38
39using namespace std;
40using namespace CEC;
f00ff009 41using namespace PLATFORM;
a8f0bd18 42
7bb4ed43 43CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) :
12027dbe 44 m_port(NULL),
a171d2fd 45 m_processor(processor),
1fc16cfd 46 m_iLineTimeout(0),
7bb4ed43
LOK
47 m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN),
48 m_lastInitiator(CECDEVICE_UNKNOWN),
49 m_bNextIsEscaped(false),
50 m_bGotStart(false)
a8f0bd18 51{
99666519 52 m_port = new PLATFORM::CSerialPort(strPort, iBaudRate);
a8f0bd18
LOK
53}
54
7bb4ed43 55CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void)
a8f0bd18 56{
12027dbe 57 Close();
a8f0bd18
LOK
58}
59
b1f94db1 60bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */)
a8f0bd18 61{
7b494bea
LOK
62 uint64_t iNow = GetTimeMs();
63 uint64_t iTimeout = iNow + iTimeoutMs;
64
f00ff009 65 CLockObject lock(m_mutex);
7b494bea 66
13fd6a66
LOK
67 if (!m_port)
68 {
5477a250 69 CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL");
a8f0bd18 70 return false;
13fd6a66
LOK
71 }
72
73 if (IsOpen())
74 {
5477a250 75 CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open");
7b494bea 76 return true;
13fd6a66 77 }
a8f0bd18 78
b1f94db1 79 m_callback = cb;
7b494bea
LOK
80 CStdString strError;
81 bool bConnected(false);
82 while (!bConnected && iNow < iTimeout)
83 {
99666519 84 if ((bConnected = m_port->Open(iTimeout)) == false)
7b494bea 85 {
99666519 86 strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str());
7b494bea
LOK
87 Sleep(250);
88 iNow = GetTimeMs();
89 }
90 }
91
92 if (!bConnected)
a8f0bd18 93 {
5477a250 94 CLibCEC::AddLog(CEC_LOG_ERROR, strError);
a8f0bd18
LOK
95 return false;
96 }
97
2c780401 98 CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
a8f0bd18
LOK
99
100 //clear any input bytes
2c780401
LOK
101 uint8_t buff[1024];
102 while (m_port->Read(buff, 1024, 100) > 0)
103 {
104 CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
105 Sleep(250);
106 }
a8f0bd18 107
828682d3 108 if (CreateThread())
a8f0bd18 109 {
5477a250 110 CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started");
a8f0bd18
LOK
111 return true;
112 }
113 else
114 {
5477a250 115 CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread");
a8f0bd18
LOK
116 }
117
118 return false;
119}
120
7bb4ed43 121void CUSBCECAdapterCommunication::Close(void)
a8f0bd18 122{
f00ff009 123 CLockObject lock(m_mutex);
d5bffd3c 124 m_rcvCondition.Broadcast();
b9eea66d 125 StopThread();
a8f0bd18
LOK
126}
127
7bb4ed43 128void *CUSBCECAdapterCommunication::Process(void)
a8f0bd18 129{
b1f94db1 130 cec_command command;
13fd6a66 131 while (!IsStopped())
a8f0bd18 132 {
9e1cfa5c 133 ReadFromDevice(50);
b1f94db1
LOK
134
135 /* push the next command to the callback method if there is one */
136 if (m_callback && Read(command, 0))
137 m_callback->OnCommandReceived(command);
138
c02980af 139 Sleep(5);
3c53ac93 140 WriteNextCommand();
a8f0bd18
LOK
141 }
142
ef7696f5 143 CCECAdapterMessage *msg(NULL);
a0878ee3
LOK
144 if (m_outBuffer.Pop(msg))
145 msg->condition.Broadcast();
146
9f9c8c82
LOK
147 if (m_port)
148 {
149 delete m_port;
150 m_port = NULL;
151 }
152
a8f0bd18
LOK
153 return NULL;
154}
155
7bb4ed43
LOK
156cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, uint8_t iMaxTries, uint8_t iLineTimeout /* = 3 */, uint8_t iRetryLineTimeout /* = 3 */)
157{
158 cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
159
160 CCECAdapterMessage *output = new CCECAdapterMessage(data);
161
162 /* set the number of retries */
163 if (data.opcode == CEC_OPCODE_NONE) //TODO
164 output->maxTries = 1;
165 else if (data.initiator != CECDEVICE_BROADCAST)
166 output->maxTries = iMaxTries;
167
168 output->lineTimeout = iLineTimeout;
169 output->retryTimeout = iRetryLineTimeout;
170 output->tries = 0;
171
172 bool bRetry(true);
173 while (bRetry && ++output->tries < output->maxTries)
174 {
175 bRetry = (!Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0;
176 if (bRetry)
177 Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
178 }
179 retVal = output->state;
180
181 delete output;
182 return retVal;
183}
184
185bool CUSBCECAdapterCommunication::Write(CCECAdapterMessage *data)
3c53ac93 186{
5dcf9f25
LOK
187 CLockObject lock(data->mutex);
188 data->state = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
3c53ac93 189 m_outBuffer.Push(data);
5dcf9f25
LOK
190 data->condition.Wait(data->mutex);
191
b1f94db1
LOK
192 if ((data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT_ACKED) ||
193 (!data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT))
5dcf9f25 194 {
b1f94db1
LOK
195 CLibCEC::AddLog(CEC_LOG_DEBUG, "command was not %s", data->state == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED ? "acked" : "sent");
196 return false;
5dcf9f25
LOK
197 }
198
b1f94db1 199 return true;
a8f0bd18
LOK
200}
201
7bb4ed43 202bool CUSBCECAdapterCommunication::Read(cec_command &command, uint32_t iTimeout)
a8f0bd18 203{
7bb4ed43
LOK
204 CCECAdapterMessage msg;
205 if (Read(msg, iTimeout))
a8f0bd18 206 {
7bb4ed43 207 if (ParseMessage(msg))
a8f0bd18 208 {
7bb4ed43
LOK
209 command = m_currentframe;
210 m_currentframe.Clear();
211 return true;
a8f0bd18 212 }
7bb4ed43
LOK
213 }
214 return false;
215}
a8f0bd18 216
7bb4ed43
LOK
217bool CUSBCECAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout)
218{
219 CLockObject lock(m_mutex);
a8f0bd18 220
7bb4ed43
LOK
221 msg.Clear();
222 CCECAdapterMessage *buf(NULL);
a8f0bd18 223
7bb4ed43
LOK
224 if (!m_inBuffer.Pop(buf))
225 {
b1f94db1 226 if (iTimeout == 0 || !m_rcvCondition.Wait(m_mutex, iTimeout))
7bb4ed43
LOK
227 return false;
228 m_inBuffer.Pop(buf);
229 }
0e31a62c 230
7bb4ed43
LOK
231 if (buf)
232 {
233 msg.packet = buf->packet;
234 msg.state = msg.state = ADAPTER_MESSAGE_STATE_INCOMING;
235 delete buf;
236 return true;
237 }
238 return false;
a8f0bd18
LOK
239}
240
7bb4ed43 241CStdString CUSBCECAdapterCommunication::GetError(void) const
a8f0bd18 242{
ba65909d
LOK
243 CStdString strError;
244 strError = m_port->GetError();
245 return strError;
a8f0bd18 246}
2abe74eb 247
7bb4ed43 248bool CUSBCECAdapterCommunication::StartBootloader(void)
2abe74eb 249{
28352a04 250 bool bReturn(false);
2abe74eb 251 if (!IsRunning())
28352a04 252 return bReturn;
2abe74eb 253
5477a250 254 CLibCEC::AddLog(CEC_LOG_DEBUG, "starting the bootloader");
28352a04 255 CCECAdapterMessage *output = new CCECAdapterMessage;
25701fa6 256
ef7696f5
LOK
257 output->PushBack(MSGSTART);
258 output->PushEscaped(MSGCODE_START_BOOTLOADER);
259 output->PushBack(MSGEND);
5dcf9f25 260 output->isTransmission = false;
71c4a2f5 261 output->expectControllerAck = false;
2abe74eb 262
5dcf9f25 263 if ((bReturn = Write(output)) == false)
5477a250 264 CLibCEC::AddLog(CEC_LOG_ERROR, "could not start the bootloader");
28352a04
LOK
265 delete output;
266
267 return bReturn;
2abe74eb
LOK
268}
269
7bb4ed43 270bool CUSBCECAdapterCommunication::PingAdapter(void)
2abe74eb 271{
28352a04 272 bool bReturn(false);
2abe74eb 273 if (!IsRunning())
28352a04 274 return bReturn;
2abe74eb 275
5477a250 276 CLibCEC::AddLog(CEC_LOG_DEBUG, "sending ping");
28352a04 277 CCECAdapterMessage *output = new CCECAdapterMessage;
25701fa6 278
ef7696f5
LOK
279 output->PushBack(MSGSTART);
280 output->PushEscaped(MSGCODE_PING);
281 output->PushBack(MSGEND);
5dcf9f25 282 output->isTransmission = false;
2abe74eb 283
5dcf9f25 284 if ((bReturn = Write(output)) == false)
5477a250 285 CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter");
28352a04
LOK
286 delete output;
287
288 return bReturn;
2abe74eb 289}
13fd6a66 290
7bb4ed43
LOK
291bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg)
292{
293 bool bEom(false);
294 bool bIsError(msg.IsError());
295
296 if (msg.IsEmpty())
297 return bEom;
298
299 switch(msg.Message())
300 {
301 case MSGCODE_FRAME_START:
302 {
303 m_currentframe.Clear();
304 if (msg.Size() >= 2)
305 {
306 m_currentframe.initiator = msg.Initiator();
307 m_currentframe.destination = msg.Destination();
308 m_currentframe.ack = msg.IsACK();
309 m_currentframe.eom = msg.IsEOM();
310 }
311 if (m_currentframe.ack == 0x1)
312 {
313 m_lastInitiator = m_currentframe.initiator;
314 m_processor->HandlePoll(m_currentframe.initiator, m_currentframe.destination);
315 }
316 }
317 break;
318 case MSGCODE_RECEIVE_FAILED:
319 {
320 m_currentframe.Clear();
321 if (m_lastInitiator != CECDEVICE_UNKNOWN)
322 bIsError = m_processor->HandleReceiveFailed(m_lastInitiator);
323 }
324 break;
325 case MSGCODE_FRAME_DATA:
326 {
327 if (msg.Size() >= 2)
328 {
329 m_currentframe.PushBack(msg[1]);
330 m_currentframe.eom = msg.IsEOM();
331 }
332 bEom = msg.IsEOM();
333 }
334 break;
335 default:
336 break;
337 }
338
339 CLibCEC::AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
340 return bEom;
341}
342
343uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void)
1fc16cfd
LOK
344{
345 uint16_t iReturn(m_iFirmwareVersion);
346 if (!IsRunning())
347 return iReturn;
348
349 if (iReturn == CEC_FW_VERSION_UNKNOWN)
350 {
5477a250 351 CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
1fc16cfd
LOK
352 CCECAdapterMessage *output = new CCECAdapterMessage;
353
354 output->PushBack(MSGSTART);
355 output->PushEscaped(MSGCODE_FIRMWARE_VERSION);
356 output->PushBack(MSGEND);
357 output->isTransmission = false;
358 output->expectControllerAck = false;
359
b1f94db1 360 bool bWriteOk = Write(output);
1fc16cfd 361 delete output;
b1f94db1
LOK
362 if (!bWriteOk)
363 {
364 CLibCEC::AddLog(CEC_LOG_ERROR, "could not request the firmware version");
365 }
1fc16cfd
LOK
366 else
367 {
b1f94db1
LOK
368 ReadFromDevice(CEC_DEFAULT_TRANSMIT_WAIT, 5 /* start + msgcode + 2 bytes for fw version + end */);
369 CCECAdapterMessage input;
370 if (!Read(input, 0) || input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3)
371 CLibCEC::AddLog(CEC_LOG_ERROR, "no or invalid firmware version (size = %d, message = %d)", input.Size(), input.Message());
372 else
373 {
374 m_iFirmwareVersion = (input[1] << 8 | input[2]);
375 iReturn = m_iFirmwareVersion;
376 }
1fc16cfd
LOK
377 }
378 }
379
380 return iReturn;
381}
382
7bb4ed43 383bool CUSBCECAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
a171d2fd 384{
7bb4ed43
LOK
385 m_iLineTimeout = iTimeout;
386 return true;
387 //TODO
388// bool bReturn(m_iLineTimeout != iTimeout);
389//
390// if (!bReturn)
391// {
392// CCECAdapterMessage *output = new CCECAdapterMessage;
393//
394// output->PushBack(MSGSTART);
395// output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME);
396// output->PushEscaped(iTimeout);
397// output->PushBack(MSGEND);
398// output->isTransmission = false;
399//
400// if ((bReturn = Write(output)) == false)
401// CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime");
402// delete output;
403// }
404//
405// return bReturn;
a171d2fd
LOK
406}
407
7bb4ed43 408bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask)
5dcf9f25
LOK
409{
410 bool bReturn(false);
bca69ca1 411 CLibCEC::AddLog(CEC_LOG_DEBUG, "setting ackmask to %2x", iMask);
5dcf9f25
LOK
412
413 CCECAdapterMessage *output = new CCECAdapterMessage;
414
415 output->PushBack(MSGSTART);
416 output->PushEscaped(MSGCODE_SET_ACK_MASK);
417 output->PushEscaped(iMask >> 8);
418 output->PushEscaped((uint8_t)iMask);
419 output->PushBack(MSGEND);
420 output->isTransmission = false;
421
422 if ((bReturn = Write(output)) == false)
5477a250 423 CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the ackmask");
5dcf9f25
LOK
424 delete output;
425
426 return bReturn;
427}
428
b057edad
BL
429
430bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled)
431{
432 bool bReturn(false);
bca69ca1 433 CLibCEC::AddLog(CEC_LOG_DEBUG, "turning controlled mode %s", controlled ? "on" : "off");
b057edad
BL
434
435 CCECAdapterMessage *output = new CCECAdapterMessage;
436
437 output->PushBack(MSGSTART);
438 output->PushEscaped(MSGCODE_SET_CONTROLLED);
439 output->PushEscaped(controlled);
440 output->PushBack(MSGEND);
441 output->isTransmission = false;
442
443 if ((bReturn = Write(output)) == false)
444 CLibCEC::AddLog(CEC_LOG_ERROR, "could not set controlled mode");
445 delete output;
446
447 return bReturn;
448}
449
7bb4ed43 450bool CUSBCECAdapterCommunication::IsOpen(void)
13fd6a66 451{
b9eea66d 452 return !IsStopped() && m_port->IsOpen() && IsRunning();
13fd6a66 453}
ef7696f5 454
7bb4ed43 455bool CUSBCECAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
6729ac71
LOK
456{
457 bool bError(false);
458 bool bTransmitSucceeded(false);
b2f0b1ab 459 uint8_t iPacketsLeft(message.Size() / 4);
6729ac71
LOK
460
461 int64_t iNow = GetTimeMs();
b1f94db1 462 int64_t iTargetTime = iNow + (message.transmit_timeout <= 5 ? CEC_DEFAULT_TRANSMIT_WAIT : message.transmit_timeout);
6729ac71 463
b1f94db1 464 while (!bTransmitSucceeded && !bError && iNow < iTargetTime)
6729ac71 465 {
b1f94db1 466 ReadFromDevice(50);
6729ac71 467 CCECAdapterMessage msg;
b1f94db1 468 if (!Read(msg, 0))
6729ac71
LOK
469 {
470 iNow = GetTimeMs();
471 continue;
472 }
473
474 if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK())
475 {
476 m_processor->HandlePoll(msg.Initiator(), msg.Destination());
7bb4ed43 477 m_lastInitiator = msg.Initiator();
6729ac71
LOK
478 iNow = GetTimeMs();
479 continue;
480 }
481
482 if (msg.Message() == MSGCODE_RECEIVE_FAILED &&
7bb4ed43
LOK
483 m_lastInitiator != CECDEVICE_UNKNOWN &&
484 m_processor->HandleReceiveFailed(m_lastInitiator))
6729ac71
LOK
485 {
486 iNow = GetTimeMs();
487 continue;
488 }
489
490 bError = msg.IsError();
491 if (bError)
492 {
b2f0b1ab 493 message.reply = msg.Message();
5477a250 494 CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
6729ac71
LOK
495 }
496 else
497 {
498 switch(msg.Message())
499 {
500 case MSGCODE_COMMAND_ACCEPTED:
5477a250 501 CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
6729ac71
LOK
502 if (iPacketsLeft > 0)
503 iPacketsLeft--;
b2f0b1ab 504 if (!message.isTransmission && iPacketsLeft == 0)
5dcf9f25 505 bTransmitSucceeded = true;
6729ac71
LOK
506 break;
507 case MSGCODE_TRANSMIT_SUCCEEDED:
5477a250 508 CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
6729ac71
LOK
509 bTransmitSucceeded = (iPacketsLeft == 0);
510 bError = !bTransmitSucceeded;
b2f0b1ab 511 message.reply = MSGCODE_TRANSMIT_SUCCEEDED;
6729ac71
LOK
512 break;
513 default:
514 // ignore other data while waiting
515 break;
516 }
517
518 iNow = GetTimeMs();
519 }
520 }
521
b1f94db1
LOK
522 message.state = bTransmitSucceeded && !bError ?
523 ADAPTER_MESSAGE_STATE_SENT_ACKED :
524 ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
525
6729ac71
LOK
526 return bTransmitSucceeded && !bError;
527}
528
7bb4ed43 529void CUSBCECAdapterCommunication::AddData(uint8_t *data, size_t iLen)
ef7696f5
LOK
530{
531 CLockObject lock(m_mutex);
99666519 532 for (size_t iPtr = 0; iPtr < iLen; iPtr++)
7bb4ed43
LOK
533 {
534 if (!m_bGotStart)
535 {
536 if (data[iPtr] == MSGSTART)
537 m_bGotStart = true;
538 }
539 else if (data[iPtr] == MSGSTART) //we found a msgstart before msgend, this is not right, remove
540 {
541 if (m_currentAdapterMessage.Size() > 0)
542 CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
543 m_currentAdapterMessage.Clear();
544 m_bGotStart = true;
545 }
546 else if (data[iPtr] == MSGEND)
547 {
548 CCECAdapterMessage *newMessage = new CCECAdapterMessage;
549 newMessage->packet = m_currentAdapterMessage.packet;
550 m_inBuffer.Push(newMessage);
551 m_currentAdapterMessage.Clear();
552 m_bGotStart = false;
553 m_bNextIsEscaped = false;
554 m_rcvCondition.Signal();
555 }
556 else if (m_bNextIsEscaped)
557 {
558 m_currentAdapterMessage.PushBack(data[iPtr] + (uint8_t)ESCOFFSET);
559 m_bNextIsEscaped = false;
560 }
561 else if (data[iPtr] == MSGESC)
562 {
563 m_bNextIsEscaped = true;
564 }
565 else
566 {
567 m_currentAdapterMessage.PushBack(data[iPtr]);
568 }
569 }
ef7696f5
LOK
570}
571
b1f94db1 572bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize /* = 256 */)
ef7696f5 573{
99666519
LOK
574 ssize_t iBytesRead;
575 uint8_t buff[256];
ef7696f5
LOK
576 if (!m_port)
577 return false;
b1f94db1
LOK
578 if (iSize > 256)
579 iSize = 256;
ef7696f5 580
1fc16cfd 581 CLockObject lock(m_mutex);
b1f94db1 582 iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
ef7696f5
LOK
583 if (iBytesRead < 0 || iBytesRead > 256)
584 {
99666519 585 CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
ef7696f5
LOK
586 return false;
587 }
588 else if (iBytesRead > 0)
99666519
LOK
589 {
590 AddData(buff, iBytesRead);
591 }
ef7696f5
LOK
592
593 return iBytesRead > 0;
594}
595
7bb4ed43 596void CUSBCECAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
ef7696f5 597{
1fc16cfd 598 CLockObject adapterLock(m_mutex);
ef7696f5 599 CLockObject lock(msg->mutex);
7bb4ed43
LOK
600 if (msg->tries == 1)
601 SetLineTimeout(msg->lineTimeout);
602 else
603 SetLineTimeout(msg->retryTimeout);
604
99666519 605 if (m_port->Write(msg->packet.data, msg->Size()) != (ssize_t) msg->Size())
ef7696f5 606 {
b74fd339 607 CLibCEC::AddLog(CEC_LOG_ERROR, "error writing to serial port: %s", m_port->GetError().c_str());
ef7696f5
LOK
608 msg->state = ADAPTER_MESSAGE_STATE_ERROR;
609 }
610 else
611 {
5477a250 612 CLibCEC::AddLog(CEC_LOG_DEBUG, "command sent");
ef7696f5 613 msg->state = ADAPTER_MESSAGE_STATE_SENT;
b1f94db1
LOK
614
615 if (msg->expectControllerAck)
616 {
617 if (!WaitForAck(*msg))
618 CLibCEC::AddLog(CEC_LOG_DEBUG, "did not receive ack");
619 }
ef7696f5
LOK
620 }
621 msg->condition.Signal();
622}
623
7bb4ed43 624void CUSBCECAdapterCommunication::WriteNextCommand(void)
ef7696f5
LOK
625{
626 CCECAdapterMessage *msg(NULL);
627 if (m_outBuffer.Pop(msg))
628 SendMessageToAdapter(msg);
629}