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