cec: don't stop waiting for MSGCODE_COMMAND_ACCEPTED when another command was received
[deb_libcec.git] / src / testclient / main.cpp
CommitLineData
abbca718
LOK
1/*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011 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 "../../include/CECExports.h"
b9187cc6 34#include "../lib/platform/threads.h"
abbca718
LOK
35#include "../lib/util/StdString.h"
36#include <cstdio>
37#include <fcntl.h>
38#include <iostream>
39#include <string>
b9187cc6 40#include <sstream>
abbca718
LOK
41
42using namespace CEC;
43using namespace std;
44
25701fa6 45#define CEC_TEST_CLIENT_VERSION 5
abbca718 46
b9187cc6 47
8bca69de 48inline bool HexStrToInt(const std::string& data, uint8_t& value)
b9187cc6 49{
8bca69de
LOK
50 int iTmp(0);
51 if (sscanf(data.c_str(), "%x", &iTmp) == 1)
52 {
53 if (iTmp > 256)
54 value = 255;
55 else if (iTmp < 0)
56 value = 0;
57 else
58 value = (uint8_t) iTmp;
b9187cc6 59
8bca69de
LOK
60 return true;
61 }
62
63 return false;
64}
b9187cc6
LOK
65
66//get the first word (separated by whitespace) from string data and place that in word
67//then remove that word from string data
68bool GetWord(string& data, string& word)
69{
70 stringstream datastream(data);
71 string end;
72
73 datastream >> word;
74 if (datastream.fail())
75 {
76 data.clear();
77 return false;
78 }
79
80 size_t pos = data.find(word) + word.length();
81
82 if (pos >= data.length())
83 {
84 data.clear();
85 return true;
86 }
87
88 data = data.substr(pos);
89
90 datastream.clear();
91 datastream.str(data);
92
93 datastream >> end;
94 if (datastream.fail())
95 data.clear();
96
97 return true;
98}
99
2abe74eb 100void flush_log(ICECAdapter *cecParser)
abbca718
LOK
101{
102 cec_log_message message;
103 while (cecParser && cecParser->GetNextLogMessage(&message))
104 {
105 switch (message.level)
106 {
107 case CEC_LOG_ERROR:
25701fa6 108 cout << "ERROR: " << message.message << endl;
abbca718
LOK
109 break;
110 case CEC_LOG_WARNING:
25701fa6 111 cout << "WARNING: " << message.message << endl;
abbca718
LOK
112 break;
113 case CEC_LOG_NOTICE:
25701fa6 114 cout << "NOTICE: " << message.message << endl;
abbca718
LOK
115 break;
116 case CEC_LOG_DEBUG:
25701fa6 117 cout << "DEBUG: " << message.message << endl;
abbca718
LOK
118 break;
119 }
120 }
121}
122
2abe74eb 123void list_devices(ICECAdapter *parser)
abbca718 124{
25701fa6
LOK
125 cec_adapter *devices = new cec_adapter[10];
126 uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
abbca718
LOK
127 if (iDevicesFound <= 0)
128 {
25701fa6 129 cout << "Found devices: NONE" << endl;
abbca718
LOK
130 }
131 else
132 {
25701fa6
LOK
133 CStdString strLog;
134 strLog.Format("Found devices: %d", iDevicesFound);
135 cout << strLog.c_str() << endl;
136 for (unsigned int iDevicePtr = 0; iDevicePtr < iDevicesFound; iDevicePtr++)
abbca718
LOK
137 {
138 CStdString strDevice;
25701fa6 139 strDevice.Format("device: %d\npath: %s\ncom port: %s", iDevicePtr + 1, devices[iDevicePtr].path, devices[iDevicePtr].comm);
abbca718
LOK
140 cout << endl << strDevice.c_str() << endl;
141 }
142 }
143}
144
145void show_help(const char* strExec)
146{
147 cout << endl <<
148 strExec << " {-h|--help|-l|--list-devices|[COM PORT]}" << endl <<
149 endl <<
150 "parameters:" << endl <<
151 "\t-h --help Shows this help text" << endl <<
152 "\t-l --list-devices List all devices on this system" << endl <<
825ddb96
LOK
153 "\t[COM PORT] The com port to connect to. If no COM port is given, the client tries to connect to the first device that is detected" << endl <<
154 endl <<
155 "Type 'h' or 'help' and press enter after starting the client to display all available commands" << endl;
156}
157
158void show_console_help(void)
159{
160 cout << endl <<
161 "================================================================================" << endl <<
162 "Available commands:" << endl <<
163 endl <<
164 "tx {bytes} transfer bytes over the CEC line." << endl <<
165 "[tx 40 00 FF 11 22 33] sends bytes 0x40 0x00 0xFF 0x11 0x22 0x33" << endl <<
166 endl <<
825ddb96
LOK
167 "la {logical_address} change the logical address of the CEC adapter." << endl <<
168 "[la 4] logical address 4" << endl <<
169 endl <<
170 "[ping] send a ping command to the CEC adapter." << endl <<
171 "[bl] to let the adapter enter the bootloader, to upgrade the flash rom." << endl <<
172 "[h] or [help] show this help." << endl <<
173 "[q] or [quit] to quit the CEC test client and switch off all connected CEC devices." << endl <<
174 "================================================================================" << endl;
abbca718
LOK
175}
176
177int main (int argc, char *argv[])
178{
d54c6c91 179 ICECAdapter *parser = LoadLibCec("CECTester");
abbca718
LOK
180 if (!parser && parser->GetMinVersion() > CEC_TEST_CLIENT_VERSION)
181 {
182 cout << "Unable to create parser. Is libcec.dll present?" << endl;
183 return 1;
184 }
185 CStdString strLog;
186 strLog.Format("CEC Parser created - libcec version %d", parser->GetLibVersion());
187 cout << strLog.c_str() << endl;
188
189 //make stdin non-blocking
190#ifndef __WINDOWS__
191 int flags = fcntl(0, F_GETFL, 0);
192 flags |= O_NONBLOCK;
193 fcntl(0, F_SETFL, flags);
194#endif
195
196 string strPort;
197 if (argc < 2)
198 {
199 cout << "no serial port given. trying autodetect: ";
25701fa6
LOK
200 cec_adapter devices[10];
201 uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
abbca718
LOK
202 if (iDevicesFound <= 0)
203 {
204 cout << "FAILED" << endl;
205 UnloadLibCec(parser);
206 return 1;
207 }
208 else
209 {
210 cout << endl << " path: " << devices[0].path << endl <<
211 " com port: " << devices[0].comm << endl << endl;
212 strPort = devices[0].comm;
213 }
214 }
215 else if (!strcmp(argv[1], "--list-devices") || !strcmp(argv[1], "-l"))
216 {
217 list_devices(parser);
218 UnloadLibCec(parser);
219 return 0;
220 }
221 else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))
222 {
223 show_help(argv[0]);
224 return 0;
225 }
226 else
227 {
228 strPort = argv[1];
229 }
230
231 if (!parser->Open(strPort.c_str()))
232 {
233 cout << "unable to open the device on port " << strPort << endl;
234 flush_log(parser);
235 UnloadLibCec(parser);
236 return 1;
237 }
238
239 cout << "cec device opened" << endl;
abbca718 240
8829d291 241 parser->PowerOnDevices(CECDEVICE_TV);
abbca718
LOK
242 flush_log(parser);
243
244 parser->SetActiveView();
245 flush_log(parser);
246
247 bool bContinue(true);
248 cout << "waiting for input" << endl;
249 while (bContinue)
250 {
251 flush_log(parser);
252
253 string input;
254 getline(cin, input);
255 cin.clear();
256
257 if (!input.empty())
258 {
259 string command;
260 if (GetWord(input, command))
261 {
262 if (command == "tx")
263 {
264 string strvalue;
8bca69de 265 uint8_t ivalue;
25701fa6
LOK
266 cec_frame bytes;
267 bytes.clear();
268
abbca718
LOK
269 while (GetWord(input, strvalue) && HexStrToInt(strvalue, ivalue))
270 bytes.push_back(ivalue);
271
272 parser->Transmit(bytes);
273 }
6dfe9213
LOK
274 else if (command == "la")
275 {
276 string strvalue;
6dfe9213
LOK
277 if (GetWord(input, strvalue))
278 {
279 parser->SetLogicalAddress((cec_logical_address) atoi(strvalue.c_str()));
abbca718
LOK
280 }
281 }
282 else if (command == "ping")
283 {
2abe74eb 284 parser->PingAdapter();
abbca718
LOK
285 }
286 else if (command == "bl")
287 {
288 parser->StartBootloader();
289 }
12027dbe
LOK
290 else if (command == "r")
291 {
25701fa6 292 cout << "closing the connection" << endl;
12027dbe 293 parser->Close();
25701fa6
LOK
294 flush_log(parser);
295
296 cout << "opening a new connection" << endl;
12027dbe 297 parser->Open(strPort.c_str());
25701fa6
LOK
298 flush_log(parser);
299
300 cout << "setting active view" << endl;
12027dbe
LOK
301 parser->SetActiveView();
302 }
825ddb96
LOK
303 else if (command == "h" || command == "help")
304 {
305 show_console_help();
306 }
abbca718
LOK
307 else if (command == "q" || command == "quit")
308 {
309 bContinue = false;
310 }
311 }
312 if (bContinue)
313 cout << "waiting for input" << endl;
314 }
315 CCondition::Sleep(50);
316 }
317
2abe74eb 318 parser->StandbyDevices(CECDEVICE_BROADCAST);
5f39c4d8 319 parser->Close();
abbca718
LOK
320 flush_log(parser);
321 UnloadLibCec(parser);
322 return 0;
323}