]> git.defcon.no Git - hm-trp-tool/blob - configurator.cpp
I forgot, all source needs README and licensing
[hm-trp-tool] / configurator.cpp
1 #include "configurator.h"
2 #include "ui_creator.h"
3 #include <QBoxLayout>
4 #include <QVBoxLayout>
5 #include <QHBoxLayout>
6 #include <QLabel>
7 #include <QMessageBox>
8
9 #include <unistd.h>
10 #include <termios.h> /* Terminal I/O support */
11 #include <errno.h> /* Error number definitions */
12 #include <fcntl.h> /* File descriptor manipulation */
13 #include <stdio.h>
14 #include <errno.h>
15
16 #ifndef CBUFFER_SIZE
17 #define CBUFFER_SIZE 32
18 #endif
19
20 const int count_devtype = 4;
21 const char* dev_name[4] = {
22 "HM-TRP-433",
23 "HM-TRP-470",
24 "HM-TRP-868",
25 "HM-TRP-915"
26 };
27
28 const uint32_t freq_min[4] = {
29 414 * 1e6,
30 450 * 1e6,
31 849 * 1e6,
32 895 * 1e6
33 };
34 const uint32_t freq_max[4] = {
35 454 * 1e6,
36 490 * 1e6,
37 889 * 1e6,
38 935 * 1e6
39 };
40 const uint32_t freq_default[4] = {
41 434 * 1e6,
42 470 * 1e6,
43 869 * 1e6,
44 915 * 1e6
45 };
46
47 const int count_recv_bw = 12;
48 // Values selected somewhat randomly...
49 const int recv_bw[12] = {
50 30,
51 50,
52 75,
53 90,
54 105,
55 120,
56 150,
57 175,
58 200,
59 250,
60 300,
61 620
62 };
63
64 const int count_freq_dev = 10;
65 // Values selected somewhat randomly...
66 const int freq_dev[10] = { // Values as kHz ..
67 10,
68 20,
69 35,
70 50,
71 55,
72 80,
73 110,
74 120,
75 145,
76 160
77 };
78
79 const int count_powerlevel = 8;
80 const int powerlevel[8] = { 1, 2, 5, 8, 11, 14, 17, 20 };
81
82 const int count_rates = 9;
83 const int port_rate_value[9] = {
84 1200,
85 1800,
86 2400,
87 4800,
88 9600,
89 19200,
90 38400,
91 57600,
92 115200
93 };
94
95 const int port_rates[9] = {
96 B1200,
97 B1800,
98 B2400,
99 B4800,
100 B9600,
101 B19200,
102 B38400,
103 B57600,
104 B115200
105 };
106
107 const char cmd_reset[3] = { 0xAA, 0xFA, 0xF0 };
108 const char cmd_config[3] = { 0xAA, 0xFA, 0xE1 };
109 const char cmd_frequency[3] = { 0xAA, 0xFA, 0xD2 };
110 const char cmd_air_rate[3] = { 0xAA, 0xFA, 0xC3 };
111 const char cmd_bw[3] = { 0xAA, 0xFA, 0xB4 };
112 const char cmd_deviation[3] = { 0xAA, 0xFA, 0xA5 };
113 const char cmd_power[3] = { 0xAA, 0xFA, 0x96 };
114 const char cmd_uart_rate[3] = { 0xAA, 0xFA, 0x1E };
115 const char cmd_RSSI[3] = { 0xAA, 0xFA, 0x87 };
116 const char cmd_SNR[3] = { 0xAA, 0xFA, 0x78 };
117
118 int Configurator::write_uint32_t ( int f, uint32_t v )
119 {
120 int i;
121 unsigned char buf[4];
122 v = __bswap_32(v);
123 for ( i = 0; i < 4; i++ )
124 buf[i] = (v>>(8*i) & 0xff );
125
126 return write( f, buf, 4 );
127 }
128
129 int Configurator::write_uint16_t ( int f, uint16_t v )
130 {
131 int i;
132 unsigned char buf[2];
133 v = __bswap_16(v);
134 for ( i = 0; i < 2; i++ )
135 buf[i] = (v>>(8*i) & 0xff );
136
137 return write( f, buf, 2 );
138 }
139
140 int Configurator::write_uint8_t ( int f, uint8_t v )
141 {
142 return write( f, &v, 1 );
143 }
144
145 int Configurator::write_cmd ( int f, const char* buf )
146 {
147 return write( f, buf, 3 ); // Send the command to the device
148 }
149
150 int Configurator::read_config ( int fd, config_t * config )
151 {
152
153 unsigned char buf[CBUFFER_SIZE];
154 int res;
155
156 res = write_cmd( fd, cmd_config ); // Send the command to the device
157 if ( res < 0 ) return(-1); // and die on failure..
158
159 //int i = 0;
160 uint8_t* tmp_config = (uint8_t*)config;
161 do {
162 bzero(buf, CBUFFER_SIZE);
163 res = read( fd, buf, 1 );
164
165 if ( res )
166 {
167 *tmp_config++ = (uint8_t)buf[0];
168 // Make sure wo don't overflow the config struct.
169 if ( (uint8_t*)tmp_config > ((uint8_t*)config+sizeof(config_t)) ) return(-2);
170 }
171
172 } while ( res > 0 );
173
174 if ( res < 0 )
175 {
176 return -1;
177 }
178
179 if ( config->freq )
180 {
181 config->freq = __bswap_32( config->freq );
182 config->air_rate = __bswap_32( config->air_rate );
183 config->bw = __bswap_16( config->bw );
184 config->uart_rate = __bswap_32( config->uart_rate );
185 return 1;
186 }
187
188 return 0; // No errors, but no valid config
189 }
190
191 int Configurator::read_ok ( int fd )
192 {
193 unsigned char ok[5];
194 int i = 0;
195 unsigned char c;
196 bzero(ok, 5);
197
198 while( (read( fd, &c, 1 ) > 0 ) && ( i < 4) ) ok[i++] = c;
199 if ( strcmp( (const char*)ok, "OK\r\n" ) == 0 ) return 1;
200 return 0;
201 }
202
203
204 int Configurator::open_port ( const char* device, int rate )
205 {
206 int f;
207 struct termios tio;
208
209 f = open ( device, O_RDWR | O_NOCTTY ); // Not using O_NDELAY, that caused ERR11: temp unavail.
210 if ( f < 0 )
211 {
212 return(-1);
213 }
214
215 tio.c_cflag = rate;
216
217 // 8 bits, local mode, read enabled
218 tio.c_cflag |= CS8 | CLOCAL | CREAD;
219
220 // no flow-control,
221 tio.c_cflag &= ~CRTSCTS;
222
223 // no parity
224 tio.c_iflag = IGNPAR;
225
226 tio.c_oflag = 0;
227 tio.c_lflag = 0; // Non-canonical read, no other options.
228 tio.c_cc[VMIN] = 0; // Disable minimum characters for read
229 tio.c_cc[VTIME] = 5; // Wait for a max of 0.5 second
230
231 tcsetattr(f,TCSANOW,&tio); // Apply this now.
232
233 tcflush(f, TCIOFLUSH); // the serial input buffer.
234
235 return f;
236 }
237
238
239 Configurator::Configurator(QWidget *parent) :
240 QMainWindow(parent),
241 ui(new Ui::Configurator)
242 {
243
244 ui->setupUi(this);
245
246 config = (config_t*)malloc(sizeof(config_t));
247 bzero(config, sizeof(config_t));
248 connect(ui->serialPort, SIGNAL(returnPressed()), this, SLOT(on_readButton_clicked()));
249
250 }
251
252 Configurator::~Configurator()
253 {
254 delete ui;
255 }
256
257 void Configurator::on_readButton_clicked()
258 {
259 ui->statusBar->showMessage("Looking for device...");
260
261 ui->serialPort->setFocus();
262
263 ui->readButton->setEnabled(false);
264 ui->writeButton->setEnabled(false);
265 ui->defaultsButton->setEnabled(false);
266 update();
267 repaint();
268 QCoreApplication::processEvents();
269
270
271 QByteArray byteArray = (ui->serialPort->text()).toLocal8Bit();
272 const char* device = byteArray.constData();
273
274 bzero(config, sizeof(config_t));
275
276 for ( int r = 0; r <= count_rates; r++ )
277 {
278 cur_rate_i = port_rates[r];
279 int fd = open_port( device, cur_rate_i );
280 if ( fd < 0 )
281 {
282 ui->statusBar->showMessage( QString("Failed to open port: ") + QString ( strerror( errno )) );
283 ui->readButton->setEnabled(true);
284 return;
285 }
286
287 if ( read_config(fd, config) < 0 )
288 {
289 ui->statusBar->showMessage( QString("Failed to read config: ") + QString ( strerror( errno )) );
290 ui->readButton->setEnabled(true);
291 return;
292 }
293 if ( read_config( fd, config ) == 1 )
294 {
295 ui->statusBar->showMessage( QString("Found device at ") + QString().setNum( port_rate_value[r] ) );
296 printf("Read Verify-rate: %d\n", cur_rate_i);
297
298 if ( (config->air_rate < (uint32_t)port_rates[0]) ||
299 (config->uart_rate < (uint32_t)port_rates[0]) ||
300 (config->bw < (uint16_t)recv_bw[0] ) ||
301 (config->deviation < (uint8_t)freq_dev[0] ) )
302 {
303 QMessageBox::critical(this, QString("Power cycle device!"),
304 QString("The data returned by the connected ") + QString( dev_name[dev_model] ) + QString(" is invalid.\nPlease power-cycle your device by e.g. disconnecting\nand reconnectingbefore proceeding.")
305 );
306 }
307
308 printf("Freq %d \n", config->freq );
309 printf("Air rate %d \n", config->air_rate );
310 printf("Deviation %d \n", config->deviation );
311 printf("TX Power %d \n", config->power );
312 printf("BW %d \n", config->bw );
313 printf("UART rate %d \n", config->uart_rate );
314
315 ui->curRate->setText( QString().setNum( port_rate_value[r] ) );
316
317 for ( int i = 0; i < count_devtype; i++ )
318 {
319 if ( (config->freq >= freq_min[i]) &&
320 (config->freq <= freq_max[i]))
321 { dev_model = i; break; }
322 }
323
324 ui->devType->setText( QString( dev_name[dev_model] ) );
325
326 ui->airRate->clear();
327 for ( int i = 0; i < count_rates; i++ )
328 ui->airRate->insertItem(i, QString().setNum( port_rate_value[i] ) );
329
330 ui->uartRate->clear();
331 for ( int i = 0; i < count_rates; i++ )
332 ui->uartRate->insertItem(i, QString().setNum( port_rate_value[i] ) );
333
334 ui->recvBandwidth->clear();
335 for ( int i = 0; i < count_recv_bw; i++ )
336 ui->recvBandwidth->insertItem(i, QString().setNum( recv_bw[i] ) );
337
338 ui->freqDeviation->clear();
339 for ( int i = 0; i < count_freq_dev; i++ )
340 ui->freqDeviation->insertItem(i, QString().setNum( freq_dev[i] ) );
341
342 ui->powerLevel->clear();
343 for ( int i = 0; i < count_powerlevel; i++ )
344 ui->powerLevel->insertItem(i, QString().setNum( powerlevel[i] ) );
345
346 for ( int i = 0; i < count_rates; i++ )
347 if ( config->air_rate == (uint32_t)port_rate_value[i] )
348 ui->airRate->setCurrentIndex(i);
349
350 for ( int i = 0; i < count_rates; i++ )
351 if ( config->uart_rate == (uint32_t)port_rate_value[i] )
352 ui->uartRate->setCurrentIndex(i);
353
354 for ( int i = 0; i < count_recv_bw; i++ )
355 if ( config->bw == (uint16_t)recv_bw[i] )
356 ui->recvBandwidth->setCurrentIndex(i);
357
358 for ( int i = 0; i < count_freq_dev; i++ )
359 if ( config->deviation == (uint8_t)freq_dev[i] )
360 ui->freqDeviation->setCurrentIndex(i);
361
362 for ( int i = 0; i < count_powerlevel; i++ )
363 if ( powerlevel[config->power] == (uint8_t)powerlevel[i] )
364 ui->powerLevel->setCurrentIndex(i);
365
366 ui->frequency->setText( QString().setNum( config->freq/1000 ) );
367
368 ui->readButton->setEnabled(true);
369 ui->writeButton->setEnabled(true);
370 ui->defaultsButton->setEnabled(true);
371
372 ::close(fd);
373 return;
374 }
375 ::close(fd);
376 }
377
378 ui->statusBar->showMessage( QString("Unable to locate device!"), 10000);
379 QMessageBox::critical(this, QString("Unable to locate device"),
380 QString("Could not find a connected HM-TRP.\nPlease verify that the CONFIG pin is jumpered LOW,\nand power-cycle your device by e.g. disconnecting\nand reconnecting before proceeding.")
381 );
382
383 ui->readButton->setEnabled(true);
384
385 }
386
387
388 void Configurator::on_writeButton_clicked()
389 {
390
391 ui->serialPort->setFocus();
392 ui->statusBar->showMessage( QString("Writing settings to device ...") );
393
394 ui->readButton->setEnabled(false);
395 ui->writeButton->setEnabled(false);
396 ui->defaultsButton->setEnabled(false);
397 update();
398 repaint();
399 QCoreApplication::processEvents();
400
401 QByteArray byteArray = (ui->serialPort->text()).toLocal8Bit();
402 const char* device = byteArray.constData();
403
404 int fd = open_port( device, cur_rate_i );
405 if ( fd < 0 )
406 {
407 ui->statusBar->showMessage( QString("Failed to open port: ") + QString ( strerror( errno )) );
408 ui->readButton->setEnabled(true);
409 return;
410 }
411
412 if ( read_config(fd, config) != 1 )
413 {
414 ui->statusBar->showMessage( QString("Failed to verify device config: ") + QString ( strerror( errno )) );
415 ui->readButton->setEnabled(true);
416 return;
417 }
418
419 uint32_t freq = (ui->frequency->text()).toInt() * 1000;
420 if (
421
422 ( freq < (uint32_t)freq_min[dev_model] ) ||
423 ( freq > (uint32_t)freq_max[dev_model] ) )
424 {
425 QMessageBox::critical(this, QString("Invalid frequency"),
426 QString("The given frequency is outside of the permitted range\n") +
427 QString("Device type ") + QString( dev_name[dev_model] ) + QString(" permits frequencies\n") +
428 QString("from ") + QString().setNum( freq_min[dev_model]/1000) + QString("kHz to ") + QString().setNum( freq_max[dev_model]/1000) + QString("kHz.")
429 );
430 return;
431 }
432
433 config->air_rate = ui->airRate->currentText().toInt();
434 config->bw = ui->recvBandwidth->currentText().toInt();
435 config->deviation = ui->freqDeviation->currentText().toInt();
436 config->freq = freq;
437 config->uart_rate = ui->uartRate->currentText().toInt();
438
439
440
441
442 for ( int i = 0; i < count_powerlevel; i++ )
443 {
444
445 if ( ui->powerLevel->currentText().toInt() == powerlevel[i] )
446 {
447 config->power = i;
448 break;
449 }
450 }
451
452 printf("After config changes:");
453 printf("Freq %d \n", config->freq );
454 printf("Air rate %d \n", config->air_rate );
455 printf("Deviation %d \n", config->deviation );
456 printf("TX Power %d \n", config->power );
457 printf("BW %d \n", config->bw );
458 printf("UART rate %d \n", config->uart_rate );
459
460 write_cmd( fd, cmd_frequency );
461 write_uint32_t( fd, config->freq );
462 if ( !read_ok( fd ) )
463 return errorStatus("Failed to set frequency");
464
465 write_cmd( fd, cmd_air_rate );
466 write_uint32_t( fd, config->air_rate );
467 if ( !read_ok( fd ) )
468 return errorStatus("Failed to set air data rate");
469
470 write_cmd( fd, cmd_bw );
471 write_uint16_t( fd, config->bw );
472 if ( !read_ok( fd ) )
473 return errorStatus("Failed to set recieve bandwidth");
474
475 write_cmd( fd, cmd_deviation );
476 write_uint8_t( fd, config->deviation );
477 if ( !read_ok( fd ) )
478 return errorStatus("Failed to set frequency deviation");
479
480 write_cmd( fd, cmd_power );
481 write_uint8_t( fd, config->power );
482 if ( !read_ok( fd ) )
483 return errorStatus("Failed to set transmit power");
484
485 write_cmd( fd, cmd_uart_rate );
486 write_uint32_t( fd, config->uart_rate );
487 read_ok( fd ); // Clear buffer.
488
489 ::close(fd);
490
491 on_readButton_clicked();
492
493 }
494
495 void Configurator::on_defaultsButton_clicked()
496 {
497
498 ui->serialPort->setFocus();
499
500 ui->readButton->setEnabled(false);
501 ui->writeButton->setEnabled(false);
502 ui->defaultsButton->setEnabled(false);
503 update();
504 repaint();
505 QCoreApplication::processEvents();
506
507 QByteArray byteArray = (ui->serialPort->text()).toLocal8Bit();
508 const char* device = byteArray.constData();
509
510 int fd = open_port( device, cur_rate_i );
511 if ( fd < 0 )
512 {
513 ui->statusBar->showMessage( QString("Failed to open port: ") + QString ( strerror( errno )) );
514 ui->readButton->setEnabled(true);
515 return;
516 }
517
518 if ( read_config(fd, config) != 1 )
519 {
520 ui->statusBar->showMessage( QString("Failed to verify device config: ") + QString ( strerror( errno )) );
521 ui->readButton->setEnabled(true);
522 return;
523 }
524 write_cmd( fd, cmd_reset );
525 ::close(fd);
526
527 QMessageBox::critical(this, QString("Power cycle device!"),
528 QString("The reset command has been sent to the ") + QString( dev_name[dev_model] ) + QString(".\nPlease power-cycle your device by e.g. disconnecting\nand reconnectingbefore proceeding.")
529 );
530
531 on_readButton_clicked();
532
533 }
534
535 void Configurator::errorStatus(QString message)
536 {
537 ui->statusBar->showMessage( message );
538 ui->readButton->setEnabled(true);
539 ui->writeButton->setEnabled(true);
540 ui->defaultsButton->setEnabled(true);
541 }