1 /*
2 * vim:tw=80:ai:tabstop=4:softtabstop=4:shiftwidth=4:expandtab
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * (C) Copyright Phil Dibowitz 2007
19 * (C) Copyright Kevin Timmerman 2007
20 */
21
22 /*
23 * This file is entry points into libconcord.
24 * - phil Sat Aug 18 22:49:48 PDT 2007
25 */
26
27 #include <stdio.h>
28 #include <string>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <zip.h>
33 #include <list>
34 #include <unistd.h>
35 #include <vector>
36 #include "libconcord.h"
37 #include "lc_internal.h"
38 #include "remote.h"
39 #include "binaryfile.h"
40 #include "hid.h"
41 #include "usblan.h"
42 #include "web.h"
43 #include "protocol.h"
44 #include "time.h"
45 #include "operationfile.h"
46
47 #define ZWAVE_HID_PID_MIN 0xC112
48 #define ZWAVE_HID_PID_MAX 0xC115
49
50 // Certain remotes (e.g., 900) take longer to reboot, so extend wait time.
51 #define MAX_WAIT_FOR_BOOT 10
52 #define WAIT_FOR_BOOT_SLEEP 5
53
54 static class CRemoteBase *rmt;
55 static class OperationFile *of;
56 static struct TRemoteInfo ri;
57 static struct THIDINFO hid_info;
58 static struct THarmonyTime rtime;
59
60 /*
61 * BEGIN ACCESSORS
62 */
get_mfg()63 const char *get_mfg()
64 {
65 return ri.model->mfg;
66 }
67
get_model()68 const char *get_model()
69 {
70 return ri.model->model;
71 }
72
get_codename()73 const char *get_codename()
74 {
75 return (ri.model->code_name) ? ri.model->code_name : (char *)"";
76 }
77
get_skin()78 int get_skin()
79 {
80 return ri.skin;
81 }
82
get_fw_ver_maj()83 int get_fw_ver_maj()
84 {
85 return ri.fw_ver_major;
86 }
87
get_fw_ver_min()88 int get_fw_ver_min()
89 {
90 return ri.fw_ver_minor;
91 }
92
get_fw_type()93 int get_fw_type()
94 {
95 return ri.fw_type;
96 }
97
get_hw_ver_maj()98 int get_hw_ver_maj()
99 {
100 return ri.hw_ver_major;
101 }
102
get_hw_ver_min()103 int get_hw_ver_min()
104 {
105 return ri.hw_ver_minor;
106 }
107
get_hw_ver_mic()108 int get_hw_ver_mic()
109 {
110 return ri.hw_ver_micro;
111 }
112
get_flash_size()113 int get_flash_size()
114 {
115 return ri.flash->size;
116 }
117
get_flash_mfg()118 int get_flash_mfg()
119 {
120 return ri.flash_mfg;
121 }
122
get_flash_id()123 int get_flash_id()
124 {
125 return ri.flash_id;
126 }
127
get_flash_part_num()128 const char *get_flash_part_num()
129 {
130 return ri.flash->part;
131 }
132
get_arch()133 int get_arch()
134 {
135 return ri.architecture;
136 }
137
get_proto()138 int get_proto()
139 {
140 return ri.protocol;
141 }
142
get_hid_mfg_str()143 const char *get_hid_mfg_str()
144 {
145 return hid_info.mfg.c_str();
146 }
147
get_hid_prod_str()148 const char *get_hid_prod_str()
149 {
150 return hid_info.prod.c_str();
151 }
152
get_hid_irl()153 int get_hid_irl()
154 {
155 return hid_info.irl;
156 }
157
get_hid_orl()158 int get_hid_orl()
159 {
160 return hid_info.orl;
161 }
162
get_hid_frl()163 int get_hid_frl()
164 {
165 return hid_info.frl;
166 }
167
get_usb_vid()168 int get_usb_vid()
169 {
170 return hid_info.vid;
171 }
172
get_usb_pid()173 int get_usb_pid()
174 {
175 return hid_info.pid;
176 }
177
get_usb_bcd()178 int get_usb_bcd()
179 {
180 return hid_info.ver;
181 }
182
get_serial(int p)183 char *get_serial(int p)
184 {
185 switch (p) {
186 case 1:
187 return ri.serial1;
188 break;
189 case 2:
190 return ri.serial2;
191 break;
192 case 3:
193 return ri.serial3;
194 break;
195 }
196
197 return (char *)"";
198 }
199
get_config_bytes_used()200 int get_config_bytes_used()
201 {
202 return ri.config_bytes_used;
203 }
204
get_config_bytes_total()205 int get_config_bytes_total()
206 {
207 return ri.max_config_size;
208 }
209
is_z_remote()210 int is_z_remote()
211 {
212 /* should this be in the remoteinfo struct? */
213 return rmt->IsZRemote() ? 1 : 0;
214 }
215
is_usbnet_remote()216 int is_usbnet_remote()
217 {
218 return rmt->IsUSBNet() ? 1 : 0;
219 }
220
is_mh_remote()221 int is_mh_remote()
222 {
223 return rmt->IsMHRemote() ? 1 : 0;
224 }
225
is_mh_pid(unsigned int pid)226 int is_mh_pid(unsigned int pid)
227 {
228 switch (pid) {
229 case 0xC124: /* Harmony 300 */
230 case 0xC125: /* Harmony 200 */
231 case 0xC126: /* Harmony Link */
232 case 0xC129: /* Harmony Hub */
233 case 0xC12B: /* Harmony Touch/Ultimate */
234 return 1;
235 default:
236 return 0;
237 }
238 }
239
get_time_second()240 int get_time_second()
241 {
242 return rtime.second;
243 }
244
get_time_minute()245 int get_time_minute()
246 {
247 return rtime.minute;
248 }
249
get_time_hour()250 int get_time_hour()
251 {
252 return rtime.hour;
253 }
254
get_time_day()255 int get_time_day()
256 {
257 return rtime.day;
258 }
259
get_time_dow()260 int get_time_dow()
261 {
262 return rtime.dow;
263 }
264
get_time_month()265 int get_time_month()
266 {
267 return rtime.month;
268 }
269
get_time_year()270 int get_time_year()
271 {
272 return rtime.year;
273 }
274
get_time_utc_offset()275 int get_time_utc_offset()
276 {
277 return rtime.utc_offset;
278 }
279
get_time_timezone()280 const char *get_time_timezone()
281 {
282 return rtime.timezone.c_str();
283 }
284
285
286 /*
287 * PUBLIC HELPER FUNCTIONS
288 */
289
lc_strerror(int err)290 const char *lc_strerror(int err)
291 {
292 switch (err) {
293 case LC_ERROR:
294 return "Unknown error";
295 break;
296
297 case LC_ERROR_INVALID_DATA_FROM_REMOTE:
298 return "Invalid data received from remote";
299 break;
300
301 case LC_ERROR_READ:
302 return "Error while reading from the remote";
303 break;
304
305 case LC_ERROR_WRITE:
306 return "Error while writing to the remote";
307 break;
308
309 case LC_ERROR_INVALIDATE:
310 return
311 "Error while asking the remote to invalidate it's flash";
312 break;
313
314 case LC_ERROR_ERASE:
315 return "Error while erasing flash";
316 break;
317
318 case LC_ERROR_VERIFY:
319 return "Error while verifying flash";
320 break;
321
322 case LC_ERROR_POST:
323 return "Error sending post data to Harmony website";
324 break;
325
326 case LC_ERROR_GET_TIME:
327 return "Error getting time from remote";
328 break;
329
330 case LC_ERROR_SET_TIME:
331 return "Error setting time on the remote";
332 break;
333
334 case LC_ERROR_CONNECT:
335 return "Error connecting or finding the remote\nNOTE: \
336 if you recently plugged in your remote and you have a newer remote, you\nmay \
337 need to wait a few additional seconds for your remote to be fully connected.";
338 break;
339
340 case LC_ERROR_OS:
341 return "OS-level error";
342 break;
343
344 case LC_ERROR_OS_FILE:
345 return "OS-level error related to file operations";
346 break;
347
348 case LC_ERROR_OS_NET:
349 return "OS-level error related to network operations";
350 break;
351
352 case LC_ERROR_UNSUPP:
353 return
354 "Model or configuration or operation unsupported";
355 break;
356
357 case LC_ERROR_INVALID_CONFIG:
358 return
359 "The configuration present on the remote is invalid";
360 break;
361
362 case LC_ERROR_IR_OVERFLOW:
363 return
364 "Received IR signal is too long - release key earlier";
365 break;
366 }
367
368 return "Unknown error";
369 }
370
delete_blob(uint8_t * ptr)371 void delete_blob(uint8_t *ptr)
372 {
373 delete[] ptr;
374 }
375
lc_cb_stage_str(int stage)376 const char *lc_cb_stage_str(int stage)
377 {
378 switch (stage) {
379 case LC_CB_STAGE_GET_IDENTITY:
380 return "Requesting identity";
381 break;
382
383 case LC_CB_STAGE_INITIALIZE_UPDATE:
384 return "Initializing update";
385 break;
386
387 case LC_CB_STAGE_INVALIDATE_FLASH:
388 return "Invalidating flash";
389 break;
390
391 case LC_CB_STAGE_ERASE_FLASH:
392 return "Erasing flash";
393 break;
394
395 case LC_CB_STAGE_WRITE_CONFIG:
396 return "Writing config";
397 break;
398
399 case LC_CB_STAGE_VERIFY_CONFIG:
400 return "Verifying config";
401 break;
402
403 case LC_CB_STAGE_FINALIZE_UPDATE:
404 return "Finalizing update";
405 break;
406
407 case LC_CB_STAGE_READ_CONFIG:
408 return "Reading config";
409 break;
410
411 case LC_CB_STAGE_WRITE_FIRMWARE:
412 return "Writing firmware";
413 break;
414
415 case LC_CB_STAGE_READ_FIRMWARE:
416 return "Reading firmware";
417 break;
418
419 case LC_CB_STAGE_READ_SAFEMODE:
420 return "Reading safemode fw";
421 break;
422
423 case LC_CB_STAGE_RESET:
424 return "Rebooting remote";
425 break;
426
427 case LC_CB_STAGE_SET_TIME:
428 return "Setting time";
429 break;
430
431 case LC_CB_STAGE_HTTP:
432 return "Contacting website";
433 break;
434
435 case LC_CB_STAGE_LEARN:
436 return "Learning IR code";
437 break;
438 }
439
440 return "(Unknown)";
441 }
442
443 /*
444 * Wrapper around the OperationFile class.
445 */
read_and_parse_file(char * filename,int * type)446 int read_and_parse_file(char *filename, int *type)
447 {
448 of = new OperationFile;
449 return of->ReadAndParseOpFile(filename, type);
450 }
451
delete_opfile_obj()452 void delete_opfile_obj()
453 {
454 if (of)
455 delete of;
456 }
457
458 /*
459 * PRIVATE HELPER FUNCTIONS
460 */
461
_is_fw_update_supported(int direct)462 int _is_fw_update_supported(int direct)
463 {
464 /*
465 * If we don't have a fw_base, then we don't support fw updates
466 * in anyway (direct or live).
467 *
468 * If we're in 'live' mode, then we need to make sure we we have a
469 * fw_up_base (we know we have a fw_base from previous portion of if),
470 * to know we're capable of doing it.
471 *
472 * Also, only allow architectures where we've figured out the
473 * structure of the initial magic bytes.
474 */
475 if (is_z_remote()) {
476 return 0;
477 }
478
479 if (ri.arch->firmware_base == 0
480 || (!direct && ri.arch->firmware_update_base == 0)
481 || (ri.arch->firmware_4847_offset == 0)) {
482 return 0;
483 }
484
485 return 1;
486 }
487
_write_fw_to_remote(uint8_t * in,uint32_t size,uint32_t addr,lc_callback cb,void * cb_arg,uint32_t cb_stage)488 int _write_fw_to_remote(uint8_t *in, uint32_t size, uint32_t addr,
489 lc_callback cb, void *cb_arg, uint32_t cb_stage)
490 {
491 int err = 0;
492
493 if ((err = rmt->WriteFlash(addr, size, in, ri.protocol, cb, cb_arg,
494 cb_stage))) {
495 return LC_ERROR_WRITE;
496 }
497 return 0;
498 }
499
_read_fw_from_remote(uint8_t * & out,uint32_t size,uint32_t addr,lc_callback cb,void * cb_arg,uint32_t cb_stage)500 int _read_fw_from_remote(uint8_t *&out, uint32_t size, uint32_t addr,
501 lc_callback cb, void *cb_arg, uint32_t cb_stage)
502 {
503 out = new uint8_t[size];
504 int err = 0;
505
506 if (!cb_arg) {
507 cb_arg = (void *)true;
508 }
509
510 if ((err = rmt->ReadFlash(addr, size, out, ri.protocol, false, cb, cb_arg,
511 cb_stage))) {
512 return LC_ERROR_READ;
513 }
514
515 return 0;
516 }
517
518 /*
519 * Fix the magic bytes of the firmware binaries...
520 *
521 * The first few bytes of the firmware file we receive from the
522 * website will be blanked out (0xFF), and we need to fill them
523 * by calculating appropriate content.
524 *
525 * So why don't we always do this? If the user has a dump from us,
526 * it already has the right initial bytes... and if somehow the
527 * firmware on the device is messed up, we don't want to ignore
528 * that useful data in the file.
529 *
530 * So we only overwrite the initial bytes if they are missing.
531 * For most users, that will be all the time.
532 *
533 * - Phil Dibowitz Tue Mar 11 23:17:53 PDT 2008
534 */
_fix_magic_bytes(uint8_t * in,uint32_t size)535 int _fix_magic_bytes(uint8_t *in, uint32_t size)
536 {
537 if (size < (ri.arch->firmware_4847_offset + 2)) {
538 return LC_ERROR;
539 }
540
541 if (in[0] == 0xFF && in[1] == 0xFF) {
542 /*
543 * There are "always" two bytes at some location that
544 * contain 0x48 and 0x47.
545 *
546 * Note: For some arch's (10 currently) we haven't
547 * investigated where these go, hence the check for
548 * a valid location in _is_fw_update_supported.
549 *
550 * Note: Arch 2 may be an exception to rule, and needs
551 * more investigation.
552 */
553 in[ri.arch->firmware_4847_offset] = 0x48;
554 in[ri.arch->firmware_4847_offset + 1] = 0x47;
555
556 /*
557 * The first 2 bytes are a simple 16-bit checksum, computed
558 * beginning at the location of the hard-coded 0x48/0x47
559 * bytes through the end of the firmware.
560 */
561 uint8_t suma = 0x21;
562 uint8_t sumb = 0x43;
563 for (
564 uint32_t index = ri.arch->firmware_4847_offset;
565 index < FIRMWARE_MAX_SIZE;
566 index += 2
567 ) {
568 suma ^= in[index];
569 sumb ^= in[index + 1];
570 }
571 in[0] = suma;
572 in[1] = sumb;
573 }
574
575 return 0;
576 }
577
578
579 /*
580 * Support helpers - needs to be below private helpers above.
581 * ZERO IS YES!!
582 */
is_config_dump_supported()583 int is_config_dump_supported()
584 {
585 return 0;
586 }
587
is_config_update_supported()588 int is_config_update_supported()
589 {
590 return 0;
591 }
592
is_fw_dump_supported()593 int is_fw_dump_supported()
594 {
595 return is_z_remote() ? LC_ERROR_UNSUPP: 0;
596 }
597
is_fw_update_supported(int direct)598 int is_fw_update_supported(int direct)
599 {
600 /*
601 * Currently firmware upgrades are only available certain remotes.
602 */
603 if (_is_fw_update_supported(direct)) {
604 return 0;
605 } else {
606 return LC_ERROR_UNSUPP;
607 }
608 }
609
_report_stages(lc_callback cb,void * cb_arg,int num,const uint32_t * stages)610 void _report_stages(lc_callback cb, void *cb_arg, int num,
611 const uint32_t *stages)
612 {
613 cb(LC_CB_STAGE_NUM_STAGES, num, 0, 0, 0, cb_arg, stages);
614 }
615
616 static const uint32_t update_configuration_hid_stages[]={
617 LC_CB_STAGE_INITIALIZE_UPDATE,
618 LC_CB_STAGE_INVALIDATE_FLASH,
619 LC_CB_STAGE_ERASE_FLASH,
620 LC_CB_STAGE_WRITE_CONFIG,
621 LC_CB_STAGE_VERIFY_CONFIG,
622 };
623 static const int update_configuration_hid_num_stages = 5;
624
625 static const uint32_t update_configuration_zwave_mh_stages[]={
626 LC_CB_STAGE_INITIALIZE_UPDATE,
627 LC_CB_STAGE_WRITE_CONFIG,
628 LC_CB_STAGE_FINALIZE_UPDATE,
629 };
630 static const int update_configuration_zwave_mh_num_stages = 3;
631
632 static const uint32_t update_firmware_hid_stages[]={
633 LC_CB_STAGE_INITIALIZE_UPDATE,
634 LC_CB_STAGE_INVALIDATE_FLASH,
635 LC_CB_STAGE_ERASE_FLASH,
636 LC_CB_STAGE_WRITE_FIRMWARE,
637 LC_CB_STAGE_FINALIZE_UPDATE,
638 };
639 static const int update_firmware_hid_num_stages = 5;
640
641 static const uint32_t update_firmware_hid_direct_stages[]={
642 LC_CB_STAGE_INVALIDATE_FLASH,
643 LC_CB_STAGE_ERASE_FLASH,
644 LC_CB_STAGE_WRITE_FIRMWARE,
645 };
646 static const int update_firmware_hid_direct_num_stages = 3;
647
_get_update_config_stages(int noreset)648 std::vector<uint32_t> _get_update_config_stages(int noreset)
649 {
650 std::vector<uint32_t> stages;
651 uint32_t *base_stages;
652 int num_base_stages;
653
654 if (is_z_remote() || is_mh_remote()) {
655 base_stages = (uint32_t*)update_configuration_zwave_mh_stages;
656 num_base_stages = update_configuration_zwave_mh_num_stages;
657 } else {
658 base_stages = (uint32_t*)update_configuration_hid_stages;
659 num_base_stages = update_configuration_hid_num_stages;
660 }
661
662 for (int i = 0; i < num_base_stages; i++)
663 stages.push_back(base_stages[i]);
664
665 if (!noreset && !(is_z_remote() && !is_usbnet_remote()))
666 stages.push_back(LC_CB_STAGE_RESET);
667
668 stages.push_back(LC_CB_STAGE_SET_TIME);
669
670 return stages;
671 }
672
_get_update_firmware_stages(int noreset,int direct)673 std::vector<uint32_t> _get_update_firmware_stages(int noreset, int direct)
674 {
675 std::vector<uint32_t> stages;
676 uint32_t *base_stages;
677 int num_base_stages;
678
679 if (direct) {
680 base_stages = (uint32_t*)update_firmware_hid_direct_stages;
681 num_base_stages = update_firmware_hid_direct_num_stages;
682 } else {
683 base_stages = (uint32_t*)update_firmware_hid_stages;
684 num_base_stages = update_firmware_hid_num_stages;
685 }
686
687 for (int i = 0; i < num_base_stages; i++)
688 stages.push_back(base_stages[i]);
689
690 if (!noreset && !(is_z_remote() && !is_usbnet_remote()))
691 stages.push_back(LC_CB_STAGE_RESET);
692
693 stages.push_back(LC_CB_STAGE_SET_TIME);
694
695 return stages;
696 }
697
698 /*
699 * GENERAL REMOTE STUFF
700 */
init_concord()701 int init_concord()
702 {
703 int err;
704 rmt = NULL;
705
706 #ifdef _WIN32
707 // Initialize WinSock
708 WSADATA wsainfo;
709 int error = WSAStartup(1*256 + 1, &wsainfo);
710 if (error) {
711 debug("WSAStartup() Error: %i", error);
712 return LC_ERROR_OS_NET;
713 }
714 #endif
715
716 if (InitUSB()) {
717 debug("InitUSB failed");
718 return LC_ERROR_OS;
719 }
720
721 if ((err = FindRemote(hid_info))) {
722 hid_info.pid = 0;
723
724 if ((err = FindUsbLanRemote())) {
725 return LC_ERROR_CONNECT;
726 }
727
728 rmt = new CRemoteZ_USBNET;
729 }
730
731 /*
732 * If hid_info is defined AND pid is 0XC11F, we found something
733 * via HID that's a 1000... that REALLY shouldn't even be possible
734 * but this'll catch that.
735 */
736 if (hid_info.pid == 0xC11F) {
737 return LC_ERROR_INVALID_DATA_FROM_REMOTE;
738 }
739
740 if (!rmt) {
741 if (hid_info.pid >= ZWAVE_HID_PID_MIN &&
742 hid_info.pid <= ZWAVE_HID_PID_MAX) {
743 // 890, Monstor, etc.
744 rmt = new CRemoteZ_HID;
745 } else if (is_mh_pid(hid_info.pid)) {
746 rmt = new CRemoteMH;
747 } else {
748 rmt = new CRemote;
749 /*
750 * Send a "reset USB" command before sending any other
751 * commands. Seems to be required for the Harmony One;
752 * otherwise, the first communication attempt fails.
753 * The official software seems to do this for most
754 * remotes.
755 */
756 rmt->Reset(COMMAND_RESET_USB);
757 }
758 }
759
760 return 0;
761 }
762
deinit_concord()763 int deinit_concord()
764 {
765 ShutdownUSB();
766 if (rmt)
767 delete rmt;
768 return 0;
769 }
770
_get_identity(lc_callback cb,void * cb_arg,uint32_t cb_stage)771 int _get_identity(lc_callback cb, void *cb_arg, uint32_t cb_stage)
772 {
773 if ((rmt->GetIdentity(ri, hid_info, cb, cb_arg, cb_stage))) {
774 return LC_ERROR;
775 }
776
777 /* Do some sanity checking */
778 if (ri.flash->size == 0) {
779 return LC_ERROR_INVALID_CONFIG;
780 }
781
782 if (ri.arch == NULL || ri.arch->cookie == 0) {
783 return LC_ERROR_INVALID_CONFIG;
784 }
785
786 if (!ri.valid_config) {
787 return LC_ERROR_INVALID_CONFIG;
788 }
789
790 return 0;
791 }
792
get_identity(lc_callback cb,void * cb_arg)793 int get_identity(lc_callback cb, void *cb_arg)
794 {
795 _report_stages(cb, cb_arg, 1, NULL);
796 return _get_identity(cb, cb_arg, LC_CB_STAGE_GET_IDENTITY);
797 }
798
reset_remote(lc_callback cb,void * cb_arg)799 int reset_remote(lc_callback cb, void *cb_arg)
800 {
801 int err;
802 int secs = 0;
803 const int max_secs = MAX_WAIT_FOR_BOOT * WAIT_FOR_BOOT_SLEEP;
804
805 if ((err = rmt->Reset(COMMAND_RESET_DEVICE)))
806 return err;
807
808 deinit_concord();
809 for (int i = 0; i < MAX_WAIT_FOR_BOOT; i++) {
810 for (int j = 0; j < WAIT_FOR_BOOT_SLEEP; j++) {
811 if (cb)
812 cb(LC_CB_STAGE_RESET, secs, secs, max_secs,
813 LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
814 sleep(1);
815 secs++;
816 }
817 err = init_concord();
818 if (err == 0) {
819 err = _get_identity(NULL, NULL, 0);
820 /*
821 * On remotes where firmware upgrades are not "direct",
822 * the config gets erased as part of the firmware
823 * update. Thus, the config could be invalid if we are
824 * resetting after a firmware upgrade, and we don't
825 * want to treat this as an error.
826 */
827 if ((err == 0) || (err == LC_ERROR_INVALID_CONFIG)) {
828 err = 0;
829 break;
830 }
831 deinit_concord();
832 }
833 }
834
835 if (err != 0)
836 return err;
837
838 if (cb)
839 cb(LC_CB_STAGE_RESET, max_secs, max_secs, max_secs,
840 LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
841
842 return 0;
843 }
844
845 /* FIXME: This should almost certainly be rolled into prep_config() */
_invalidate_flash(lc_callback cb,void * cb_arg,uint32_t cb_stage)846 int _invalidate_flash(lc_callback cb, void *cb_arg, uint32_t cb_stage)
847 {
848 int err = 0;
849
850 if ((err = rmt->InvalidateFlash(cb, cb_arg, cb_stage)))
851 return LC_ERROR_INVALIDATE;
852
853 return 0;
854 }
855
invalidate_flash(lc_callback cb,void * cb_arg)856 int invalidate_flash(lc_callback cb, void *cb_arg)
857 {
858 return _invalidate_flash(cb, cb_arg, LC_CB_STAGE_INVALIDATE_FLASH);
859 }
860
post_preconfig(lc_callback cb,void * cb_arg)861 int post_preconfig(lc_callback cb, void *cb_arg)
862 {
863 int err;
864 if (cb)
865 cb(LC_CB_STAGE_HTTP, 0, 0, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
866
867 if ((err = Post(of->GetXml(), of->GetXmlSize(), "POSTOPTIONS", ri, true)))
868 return err;
869
870 if (cb)
871 cb(LC_CB_STAGE_HTTP, 1, 1, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
872
873 return 0;
874 }
875
post_postfirmware(lc_callback cb,void * cb_arg)876 int post_postfirmware(lc_callback cb, void *cb_arg)
877 {
878 int err;
879 if (cb)
880 cb(LC_CB_STAGE_HTTP, 0, 0, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg,
881 NULL);
882
883 if ((err = Post(of->GetXml(), of->GetXmlSize(), "COMPLETEPOSTOPTIONS", ri,
884 false)))
885 return err;
886
887 if (cb)
888 cb(LC_CB_STAGE_HTTP, 1, 1, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg,
889 NULL);
890 return 0;
891 }
892
post_postconfig(lc_callback cb,void * cb_arg)893 int post_postconfig(lc_callback cb, void *cb_arg)
894 {
895 int err;
896 if (cb)
897 cb(LC_CB_STAGE_HTTP, 0, 0, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
898
899 if ((err = Post(of->GetXml(), of->GetXmlSize(), "COMPLETEPOSTOPTIONS", ri,
900 true, false, is_z_remote() ? true : false, NULL, NULL)))
901 return err;
902
903 if (cb)
904 cb(LC_CB_STAGE_HTTP, 1, 1, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
905
906 return 0;
907 }
908
post_connect_test_success(lc_callback cb,void * cb_arg)909 int post_connect_test_success(lc_callback cb, void *cb_arg)
910 {
911 /*
912 * If we arrived, we can talk to the remote - so if it's
913 * just a connectivity test, tell the site we succeeded
914 */
915
916 /*
917 * For some reason, on arch 9, the site sends a file missing
918 * one cookie value, so we need to tell Post() to add it in.
919 * Note that it ONLY does this for the connectivity test...
920 */
921 int err;
922 bool add_cookiekeyval = false;
923 if (ri.architecture == 9) {
924 add_cookiekeyval = true;
925 }
926
927 if (cb)
928 cb(LC_CB_STAGE_HTTP, 0, 0, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
929
930 if ((err = Post(of->GetXml(), of->GetXmlSize(), "POSTOPTIONS", ri, true,
931 add_cookiekeyval)))
932 return err;
933
934 if (cb)
935 cb(LC_CB_STAGE_HTTP, 1, 1, 1, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
936
937 return 0;
938 }
939
get_time()940 int get_time()
941 {
942 int err;
943 if ((err = rmt->GetTime(ri, rtime)))
944 return LC_ERROR_GET_TIME;
945
946 return 0;
947 }
948
_set_time(lc_callback cb,void * cb_arg)949 int _set_time(lc_callback cb, void *cb_arg)
950 {
951 const time_t t = time(NULL);
952 struct tm *lt = localtime(&t);
953
954 if (cb)
955 cb(LC_CB_STAGE_SET_TIME, 0, 1, 2, LC_CB_COUNTER_TYPE_STEPS, cb_arg,
956 NULL);
957
958 rtime.second = lt->tm_sec;
959 rtime.minute = lt->tm_min;
960 rtime.hour = lt->tm_hour;
961 rtime.day = lt->tm_mday;
962 rtime.dow = lt->tm_wday;
963 rtime.month = lt->tm_mon + 1;
964 rtime.year = lt->tm_year + 1900;
965 rtime.utc_offset = 0;
966 rtime.timezone = "";
967
968 int err = rmt->SetTime(ri, rtime);
969 if (err != 0) {
970 return err;
971 }
972 if (cb)
973 cb(LC_CB_STAGE_SET_TIME, 1, 2, 2, LC_CB_COUNTER_TYPE_STEPS, cb_arg,
974 NULL);
975
976 return 0;
977 }
978
set_time(lc_callback cb,void * cb_arg)979 int set_time(lc_callback cb, void *cb_arg)
980 {
981 _report_stages(cb, cb_arg, 1, NULL);
982 return _set_time(cb, cb_arg);
983 }
984
985
986 /*
987 * CONFIG-RELATED
988 */
989
read_config_from_remote(uint8_t ** out,uint32_t * size,lc_callback cb,void * cb_arg)990 int read_config_from_remote(uint8_t **out, uint32_t *size, lc_callback cb,
991 void *cb_arg)
992 {
993 int err = 0;
994
995 if (!ri.valid_config) {
996 return LC_ERROR_INVALID_CONFIG;
997 }
998
999 if (!cb_arg) {
1000 cb_arg = (void *)true;
1001 }
1002
1003 // For zwave-hid remotes, need to read the config once to get the size
1004 // For usbnet we do this in GetIdentity, but for hid it takes too long
1005 if (is_z_remote() && !is_usbnet_remote()) {
1006 if ((err = ((CRemoteZ_HID*)rmt)->ReadRegion(
1007 REGION_USER_CONFIG, ri.config_bytes_used, NULL, cb,
1008 cb_arg, LC_CB_STAGE_READ_CONFIG))) {
1009 return err;
1010 }
1011 }
1012
1013 *size = ri.config_bytes_used;
1014 *out = new uint8_t[*size];
1015
1016 if ((err = rmt->ReadFlash(ri.arch->config_base, *size, *out, ri.protocol,
1017 false, cb, cb_arg, LC_CB_STAGE_READ_CONFIG))) {
1018 return LC_ERROR_READ;
1019 }
1020
1021 return 0;
1022 }
1023
_write_config_to_remote(lc_callback cb,void * cb_arg,uint32_t cb_stage)1024 int _write_config_to_remote(lc_callback cb, void *cb_arg, uint32_t cb_stage)
1025 {
1026 int err = 0;
1027
1028 if (!cb_arg) {
1029 cb_arg = (void *)true;
1030 }
1031
1032 if (is_z_remote() || is_mh_remote()) {
1033 if ((err = rmt->UpdateConfig(of->GetDataSize(), of->GetData(), cb,
1034 cb_arg, cb_stage, of->GetXmlSize(),
1035 of->GetXml())))
1036 return LC_ERROR_WRITE;
1037 } else {
1038 if ((err = rmt->WriteFlash(ri.arch->config_base, of->GetDataSize(),
1039 of->GetData(), ri.protocol, cb, cb_arg,
1040 cb_stage)))
1041 return LC_ERROR_WRITE;
1042 }
1043
1044 return 0;
1045 }
1046
1047 /*
1048 * When MH configs are read from the remote, sometimes the remote returns extra
1049 * data after the end of the config file proper. This function searches for
1050 * the sequence of bytes that indicates the end of the config and returns the
1051 * real length of the config that should be written out to disk. Note that in
1052 * some cases (Harmony 300), the remote does not return the EOF bytes, so we
1053 * manually add them ourselves (see ReadFlash() in remote_mh.cpp).
1054 */
_mh_get_config_len(uint8_t * in,uint32_t size)1055 uint32_t _mh_get_config_len(uint8_t *in, uint32_t size)
1056 {
1057 for (uint32_t i = 0; (i + 3) < size; i++) {
1058 if (!memcmp(&in[i], MH_EOF_BYTES, 4)) {
1059 return i + 4;
1060 }
1061 }
1062 debug("Failed to find MH config EOF sequence");
1063 return 0;
1064 }
1065
_mh_write_config_to_file(uint8_t * in,uint32_t size,char * file_name)1066 int _mh_write_config_to_file(uint8_t *in, uint32_t size, char *file_name)
1067 {
1068 int zip_err;
1069 struct zip *zip = zip_open(file_name, ZIP_CREATE | ZIP_EXCL, &zip_err);
1070 if (!zip) {
1071 if (zip_err == ZIP_ER_EXISTS) {
1072 printf("Error: file %s already exists\n", file_name);
1073 } else {
1074 char error_str[100];
1075 zip_error_to_str(error_str, 100, zip_err, errno);
1076 debug("Failed to create zip file %s (%s)", file_name, error_str);
1077 }
1078 return LC_ERROR_OS_FILE;
1079 }
1080 int index;
1081
1082 // Write XML
1083 extern const char *mh_config_header;
1084 // 100 is arbitrary - it should be plenty to hold the snprintf data below
1085 int xml_buffer_len = strlen(mh_config_header) + 100;
1086 char xml_buffer[xml_buffer_len];
1087 uint16_t checksum = mh_get_checksum(in, size);
1088 int xml_len = snprintf(xml_buffer, xml_buffer_len, mh_config_header,
1089 size, size - 6, checksum, ri.skin);
1090 if (xml_len >= xml_buffer_len) {
1091 debug("Error, XML buffer length exceeded");
1092 return LC_ERROR;
1093 }
1094 struct zip_source *xml = zip_source_buffer(zip, xml_buffer, xml_len, 0);
1095 if (!xml) {
1096 debug("Failed to create zip_source_buffer for XML file");
1097 return LC_ERROR_OS_FILE;
1098 }
1099 index = zip_add(zip, "Description.xml", xml);
1100 if (index == -1) {
1101 debug("Error writing XML to zip file");
1102 zip_source_free(xml);
1103 return LC_ERROR_OS_FILE;
1104 }
1105
1106 // Write EzHex file
1107 struct zip_source *ezhex = zip_source_buffer(zip, in, size, 0);
1108 if (!ezhex) {
1109 debug("Failed to create zip_source_buffer for EzHex file");
1110 return LC_ERROR_OS_FILE;
1111 }
1112 index = zip_add(zip, "Result.EzHex", ezhex);
1113 if (index == -1) {
1114 debug("Error writing EzHex to zip file");
1115 zip_source_free(ezhex);
1116 return LC_ERROR_OS_FILE;
1117 }
1118
1119 if (zip_close(zip) != 0) {
1120 debug("Error closing zip file");
1121 return LC_ERROR_OS_FILE;
1122 }
1123
1124 return 0;
1125 }
1126
write_config_to_remote(lc_callback cb,void * cb_arg)1127 int write_config_to_remote(lc_callback cb, void *cb_arg)
1128 {
1129 return _write_config_to_remote(cb, cb_arg, LC_CB_STAGE_WRITE_CONFIG);
1130 }
1131
write_config_to_file(uint8_t * in,uint32_t size,char * file_name,int binary)1132 int write_config_to_file(uint8_t *in, uint32_t size, char *file_name,
1133 int binary)
1134 {
1135 // If this is an MH remote, need to find the real end of the binary
1136 if (is_mh_remote()) {
1137 size = _mh_get_config_len(in, size);
1138 ri.config_bytes_used = size;
1139 }
1140
1141 // If this is an MH remote, need to write out zip file with XML/binary
1142 if (!binary && is_mh_remote()) {
1143 return _mh_write_config_to_file(in, size, file_name);
1144 }
1145
1146 binaryoutfile of;
1147
1148 if (of.open(file_name) != 0) {
1149 debug("Failed to open %s", file_name);
1150 return LC_ERROR_OS_FILE;
1151 }
1152
1153 if (!binary) {
1154 uint32_t u = size;
1155 uint8_t chk = 0x69;
1156 uint8_t *pc = in;
1157 while (u--)
1158 chk ^= *pc++;
1159
1160 /*
1161 * Build XML
1162 * FIXME: Abstract this.
1163 */
1164 extern const char *config_header;
1165 char *ch = new char[strlen(config_header) + 200];
1166 const int chlen = sprintf(
1167 ch, config_header, ri.protocol, ri.skin, ri.flash_mfg, ri.flash_id,
1168 ri.hw_ver_major, ri.hw_ver_minor, ri.fw_type, ri.protocol, ri.skin,
1169 ri.flash_mfg, ri.flash_id, ri.hw_ver_major, ri.hw_ver_minor,
1170 ri.fw_type, ri.config_bytes_used, chk);
1171 of.write(reinterpret_cast<uint8_t*>(ch), chlen);
1172 free(ch);
1173 }
1174
1175 of.write(in, ri.config_bytes_used);
1176
1177 if (of.close() != 0) {
1178 debug("Failed to close %s", file_name);
1179 return LC_ERROR_OS_FILE;
1180 }
1181
1182 return 0;
1183 }
1184
_verify_remote_config(lc_callback cb,void * cb_arg,uint32_t cb_stage)1185 int _verify_remote_config(lc_callback cb, void *cb_arg, uint32_t cb_stage)
1186 {
1187 int err = 0;
1188
1189 if ((err = rmt->ReadFlash(ri.arch->config_base, of->GetDataSize(),
1190 of->GetData(), ri.protocol, true, cb, cb_arg,
1191 cb_stage))) {
1192 return LC_ERROR_VERIFY;
1193 }
1194
1195 return 0;
1196 }
1197
verify_remote_config(lc_callback cb,void * cb_arg)1198 int verify_remote_config(lc_callback cb, void *cb_arg)
1199 {
1200 return _verify_remote_config(cb, cb_arg, LC_CB_STAGE_VERIFY_CONFIG);
1201 }
1202
_prep_config(lc_callback cb,void * cb_arg,uint32_t cb_stage)1203 int _prep_config(lc_callback cb, void *cb_arg, uint32_t cb_stage)
1204 {
1205 int err = 0;
1206
1207 if ((err = rmt->PrepConfig(ri, cb, cb_arg, cb_stage))) {
1208 return LC_ERROR;
1209 }
1210
1211 return 0;
1212 }
1213
prep_config(lc_callback cb,void * cb_arg)1214 int prep_config(lc_callback cb, void *cb_arg)
1215 {
1216 return _prep_config(cb, cb_arg, LC_CB_STAGE_INITIALIZE_UPDATE);
1217 }
1218
_finish_config(lc_callback cb,void * cb_arg,uint32_t cb_stage)1219 int _finish_config(lc_callback cb, void *cb_arg, uint32_t cb_stage)
1220 {
1221 int err = 0;
1222
1223 if ((err = rmt->FinishConfig(ri))) {
1224 return LC_ERROR;
1225 }
1226
1227 return 0;
1228 }
1229
finish_config(lc_callback cb,void * cb_arg)1230 int finish_config(lc_callback cb, void *cb_arg)
1231 {
1232 return _finish_config(cb, cb_arg, LC_CB_STAGE_FINALIZE_UPDATE);
1233 }
1234
_erase_config(lc_callback cb,void * cb_arg,uint32_t cb_stage)1235 int _erase_config(lc_callback cb, void *cb_arg, uint32_t cb_stage)
1236 {
1237 int err = 0;
1238
1239 if ((err = rmt->EraseFlash(ri.arch->config_base, of->GetDataSize(),
1240 ri, cb, cb_arg, cb_stage))) {
1241 return LC_ERROR_ERASE;
1242 }
1243
1244 return 0;
1245 }
1246
erase_config(lc_callback cb,void * cb_arg)1247 int erase_config(lc_callback cb, void *cb_arg)
1248 {
1249 return _erase_config(cb, cb_arg, LC_CB_STAGE_ERASE_FLASH);
1250 }
1251
_update_configuration_zwave(lc_callback cb,void * cb_arg)1252 int _update_configuration_zwave(lc_callback cb, void *cb_arg)
1253 {
1254 int err;
1255
1256 if ((err = _write_config_to_remote(cb, cb_arg, 0))) {
1257 return err;
1258 }
1259
1260 return 0;
1261 }
1262
_update_configuration_mh(lc_callback cb,void * cb_arg)1263 int _update_configuration_mh(lc_callback cb, void *cb_arg)
1264 {
1265 int err;
1266
1267 if ((err = _write_config_to_remote(cb, cb_arg, 0))) {
1268 return err;
1269 }
1270
1271 return 0;
1272 }
1273
_update_configuration_hid(lc_callback cb,void * cb_arg)1274 int _update_configuration_hid(lc_callback cb, void *cb_arg) {
1275 int err;
1276
1277 if ((err = prep_config(cb, cb_arg))) {
1278 return err;
1279 }
1280
1281 /*
1282 * We must invalidate flash before we erase and write so that
1283 * nothing will attempt to reference it while we're working.
1284 */
1285 if ((err = invalidate_flash(cb, cb_arg))) {
1286 return err;
1287 }
1288
1289 /*
1290 * Flash can be changed to 0, but not back to 1, so you must
1291 * erase the flash (to 1) in order to write the flash.
1292 */
1293 if ((err = erase_config(cb, cb_arg))) {
1294 return err;
1295 }
1296
1297 if ((err = write_config_to_remote(cb, cb_arg))) {
1298 return err;
1299 }
1300
1301 if ((err = verify_remote_config(cb, cb_arg))) {
1302 return err;
1303 }
1304
1305 if ((err = finish_config(cb, cb_arg))) {
1306 return err;
1307 }
1308
1309 return 0;
1310 }
1311
update_configuration(lc_callback cb,void * cb_arg,int noreset)1312 int update_configuration(lc_callback cb, void *cb_arg, int noreset)
1313 {
1314 int err;
1315
1316 std::vector<uint32_t> stages = _get_update_config_stages(noreset);
1317 _report_stages(cb, cb_arg, stages.size(), &stages[0]);
1318
1319 if (is_z_remote()) {
1320 err = _update_configuration_zwave(cb, cb_arg);
1321 } else if (is_mh_remote()) {
1322 err = _update_configuration_mh(cb, cb_arg);
1323 } else {
1324 err = _update_configuration_hid(cb, cb_arg);
1325 }
1326
1327 if (err != 0)
1328 return err;
1329
1330 // If reset is enabled (!noreset), we do reset, except that
1331 // zwave-hid (is_z_remote() && !is_usbnet_remote()) doesn't need it.
1332 // thus...
1333 if (!noreset && !(is_z_remote() && !is_usbnet_remote()))
1334 if ((err = reset_remote(cb, cb_arg)))
1335 return err;
1336
1337 if ((err = _set_time(cb, cb_arg)))
1338 return err;
1339
1340 return 0;
1341 }
1342
1343
1344 /*
1345 * SAFEMODE FIRMWARE RELATED
1346 */
1347
erase_safemode(lc_callback cb,void * cb_arg)1348 int erase_safemode(lc_callback cb, void *cb_arg)
1349 {
1350 int err = 0;
1351
1352 if ((err = rmt->EraseFlash(ri.arch->flash_base, FIRMWARE_MAX_SIZE, ri,
1353 cb, cb_arg))) {
1354 return LC_ERROR_ERASE;
1355 }
1356
1357 return 0;
1358 }
1359
read_safemode_from_remote(uint8_t ** out,uint32_t * size,lc_callback cb,void * cb_arg)1360 int read_safemode_from_remote(uint8_t **out, uint32_t *size, lc_callback cb,
1361 void *cb_arg)
1362 {
1363 *size = FIRMWARE_MAX_SIZE;
1364 return _read_fw_from_remote(*out, *size, ri.arch->flash_base, cb,
1365 cb_arg, LC_CB_STAGE_READ_SAFEMODE);
1366 }
1367
write_safemode_to_file(uint8_t * in,uint32_t size,char * file_name)1368 int write_safemode_to_file(uint8_t *in, uint32_t size, char *file_name)
1369 {
1370 binaryoutfile of;
1371
1372 if (of.open(file_name) != 0) {
1373 return LC_ERROR_OS_FILE;
1374 }
1375
1376 of.write(in, size);
1377
1378 if (of.close() != 0) {
1379 return LC_ERROR_OS_FILE;
1380 }
1381
1382 return 0;
1383 }
1384
1385
1386 /*
1387 * FIRMWARE RELATED
1388 */
1389
is_config_safe_after_fw()1390 int is_config_safe_after_fw()
1391 {
1392 /*
1393 * For some remotes, firmware updates wipes out the config. The
1394 * user code needs to be able to determine this so they can tell
1395 * the user and/or update the config.
1396 */
1397 if (ri.arch->firmware_update_base == ri.arch->config_base) {
1398 return LC_ERROR;
1399 } else {
1400 return 0;
1401 }
1402 }
1403
prep_firmware(lc_callback cb,void * cb_arg)1404 int prep_firmware(lc_callback cb, void *cb_arg)
1405 {
1406 int err = 0;
1407
1408 if ((err = rmt->PrepFirmware(ri, cb, cb_arg,
1409 LC_CB_STAGE_INITIALIZE_UPDATE))) {
1410 return LC_ERROR;
1411 }
1412
1413 return 0;
1414 }
1415
finish_firmware(lc_callback cb,void * cb_arg)1416 int finish_firmware(lc_callback cb, void *cb_arg)
1417 {
1418 int err = 0;
1419
1420 if ((err = rmt->FinishFirmware(ri, cb, cb_arg,
1421 LC_CB_STAGE_FINALIZE_UPDATE))) {
1422 return LC_ERROR;
1423 }
1424
1425 return 0;
1426 }
1427
_erase_firmware(int direct,lc_callback cb,void * cb_arg,uint32_t cb_stage)1428 int _erase_firmware(int direct, lc_callback cb, void *cb_arg, uint32_t cb_stage)
1429 {
1430 int err = 0;
1431
1432 uint32_t addr = ri.arch->firmware_update_base;
1433 if (direct) {
1434 debug("Writing direct");
1435 addr = ri.arch->firmware_base;
1436 }
1437
1438 if ((err = rmt->EraseFlash(addr, FIRMWARE_MAX_SIZE, ri, cb, cb_arg,
1439 cb_stage))) {
1440 return LC_ERROR_ERASE;
1441 }
1442
1443 return 0;
1444 }
1445
erase_firmware(int direct,lc_callback cb,void * cb_arg)1446 int erase_firmware(int direct, lc_callback cb, void *cb_arg)
1447 {
1448 return _erase_firmware(direct, cb, cb_arg, LC_CB_STAGE_ERASE_FLASH);
1449 }
1450
read_firmware_from_remote(uint8_t ** out,uint32_t * size,lc_callback cb,void * cb_arg)1451 int read_firmware_from_remote(uint8_t **out, uint32_t *size, lc_callback cb,
1452 void *cb_arg)
1453 {
1454 *size = FIRMWARE_MAX_SIZE;
1455 return _read_fw_from_remote(*out, *size, ri.arch->firmware_base, cb,
1456 cb_arg, LC_CB_STAGE_READ_FIRMWARE);
1457 }
1458
_write_firmware_to_remote(int direct,lc_callback cb,void * cb_arg,uint32_t cb_stage)1459 int _write_firmware_to_remote(int direct, lc_callback cb, void *cb_arg,
1460 uint32_t cb_stage)
1461 {
1462 uint32_t addr = ri.arch->firmware_update_base;
1463 int err = 0;
1464
1465 if (of->GetDataSize() > FIRMWARE_MAX_SIZE) {
1466 return LC_ERROR;
1467 }
1468
1469 if (direct) {
1470 debug("Writing direct");
1471 addr = ri.arch->firmware_base;
1472 }
1473
1474 if ((err = _fix_magic_bytes(of->GetData(), of->GetDataSize()))) {
1475 return LC_ERROR_READ;
1476 }
1477
1478 return _write_fw_to_remote(of->GetData(), of->GetDataSize(), addr, cb,
1479 cb_arg, cb_stage);
1480 }
1481
write_firmware_to_remote(int direct,lc_callback cb,void * cb_arg)1482 int write_firmware_to_remote(int direct, lc_callback cb, void *cb_arg)
1483 {
1484 return _write_firmware_to_remote(direct, cb, cb_arg,
1485 LC_CB_STAGE_WRITE_FIRMWARE);
1486 }
1487
write_firmware_to_file(uint8_t * in,uint32_t size,char * file_name,int binary)1488 int write_firmware_to_file(uint8_t *in, uint32_t size, char *file_name,
1489 int binary)
1490 {
1491 binaryoutfile of;
1492 if (of.open(file_name) != 0) {
1493 return LC_ERROR_OS_FILE;
1494 }
1495
1496 if (binary) {
1497 of.write(in, size);
1498 } else {
1499 #ifdef _DEBUG
1500 /// todo: file header
1501 uint16_t *pw =
1502 reinterpret_cast<uint16_t*>(in);
1503
1504 /*
1505 * Calculate checksum
1506 */
1507 uint16_t wc = 0x4321;
1508 uint32_t n = 32*1024;
1509 while (n--)
1510 wc ^= *pw++;
1511 debug("Checksum: %04X", wc);
1512 #endif
1513
1514 uint8_t *pf = in;
1515 const uint8_t *fwend = in + size;
1516 of.write("<INFORMATION>\n");
1517 of.write("\t<PHASE>\n");
1518 of.write("\t\t<TYPE>Firmware_Main</TYPE>\n");
1519 of.write("\t\t<DATAS>\n");
1520 do {
1521 of.write("\t\t\t<DATA>");
1522 char hex[16];
1523 uint32_t u = 32;
1524 if (u > size) {
1525 u = size;
1526 }
1527 while (u--) {
1528 // convert to hex
1529 sprintf(hex, "%02X", *pf++);
1530 of.write(hex);
1531 size--;
1532 }
1533 of.write("</DATA>\n");
1534 } while (pf < fwend);
1535 of.write("\t\t</DATAS>\n");
1536 of.write("\t</PHASE>\n");
1537 of.write("</INFORMATION>\n");
1538 }
1539
1540 if (of.close() != 0) {
1541 return LC_ERROR_OS_FILE;
1542 }
1543
1544 return 0;
1545 }
1546
update_firmware(lc_callback cb,void * cb_arg,int noreset,int direct)1547 int update_firmware(lc_callback cb, void *cb_arg, int noreset, int direct)
1548 {
1549 int err;
1550
1551 if (!_is_fw_update_supported(direct)) {
1552 return LC_ERROR_UNSUPP;
1553 }
1554
1555 vector<uint32_t> stages = _get_update_firmware_stages(noreset, direct);
1556 _report_stages(cb, cb_arg, stages.size(), &stages[0]);
1557
1558 if (!direct) {
1559 if ((err = prep_firmware(cb, cb_arg)))
1560 return err;
1561 }
1562
1563 if ((err = invalidate_flash(cb, cb_arg)))
1564 return err;
1565
1566 if ((err = erase_firmware(direct, cb, cb_arg)))
1567 return err;
1568
1569 if ((err = write_firmware_to_remote(direct, cb, cb_arg)))
1570 return err;
1571
1572 if (!direct) {
1573 if ((err = finish_firmware(cb, cb_arg)))
1574 return err;
1575 }
1576
1577 if (!noreset)
1578 if ((err = reset_remote(cb, cb_arg)))
1579 return err;
1580
1581 if ((err = _set_time(cb, cb_arg)))
1582 return err;
1583
1584 return 0;
1585 }
1586
1587
1588 /*
1589 * IR stuff
1590 */
1591
1592 /*
1593 * List of key names to be learned is passed in section INPUTPARMS
1594 * as e.g.:
1595 * <PARAMETER><KEY>KeyName</KEY><VALUE>PowerToggle</VALUE></PARAMETER>
1596 * First of these is repeated in section PARAMETERS, so we must
1597 * concentrate on INPUTPARMS to avoid duplication.
1598 */
1599
1600 /*
1601 * locate the INPUTPARMS section in *data:
1602 */
_init_key_scan(uint8_t * data,uint32_t size,uint8_t ** inputparams_start,uint8_t ** inputparams_end)1603 int _init_key_scan(uint8_t *data, uint32_t size, uint8_t **inputparams_start,
1604 uint8_t **inputparams_end)
1605 {
1606 int err;
1607
1608 /* locating start tag "<INPUTPARMS>" */
1609 err = GetTag("INPUTPARMS", data, size, *inputparams_start);
1610 if (err == 0) {
1611 /* locating end tag "</INPUTPARMS>" */
1612 err = GetTag("/INPUTPARMS", *inputparams_start,
1613 size - (*inputparams_start - data), *inputparams_end);
1614 }
1615 return err;
1616 }
1617
_next_key_name(uint8_t ** start,uint8_t * inputparams_end,string * keyname)1618 int _next_key_name(uint8_t **start, uint8_t *inputparams_end, string *keyname)
1619 {
1620 int err;
1621 /*
1622 * to be really paranoid, we would have to narrow the search range
1623 * further down to next <PARAMETER>...</PARAMETER>, but IMHO it
1624 * should be safe to assume that Logitech always sends sane files:
1625 */
1626 do {
1627 err = GetTag("KEY", *start, (inputparams_end - *start), *start,
1628 keyname);
1629 if (err != 0) {
1630 return err;
1631 }
1632 } while (*keyname != "KeyName");
1633
1634 err = GetTag("VALUE", *start, (inputparams_end - *start),
1635 *start, keyname);
1636
1637 if (err == 0) {
1638 /* found next key name : */
1639 debug("Key Name: %s\n", (*keyname).c_str());
1640 }
1641 return err;
1642 }
1643
1644
get_key_names(char *** key_names,uint32_t * key_names_length)1645 int get_key_names(char ***key_names, uint32_t *key_names_length)
1646 {
1647 using namespace std;
1648 uint8_t *cursor = of->GetXml();
1649 uint8_t *inputparams_end;
1650 uint32_t key_index = 0;
1651 list<string> key_list;
1652 string key_name;
1653
1654 if ((key_names == NULL) || (key_names_length == NULL)) {
1655 return LC_ERROR;
1656 }
1657 /* setup data scanning, locating start and end of keynames section: */
1658 if (_init_key_scan(of->GetXml(), of->GetXmlSize(), &cursor,
1659 &inputparams_end) != 0) {
1660 return LC_ERROR;
1661 }
1662
1663 /* scan for key names and append found names to list: */
1664 while (_next_key_name(&cursor, inputparams_end, &key_name) == 0) {
1665 key_list.push_back(key_name);
1666 }
1667
1668 if (key_list.size() == 0) {
1669 return LC_ERROR;
1670 }
1671
1672 *key_names_length = key_list.size();
1673 *key_names = new char*[*key_names_length];
1674
1675 /* copy list of found names to allocated buffer: */
1676 for (
1677 list<string>::const_iterator cursor = key_list.begin();
1678 cursor != key_list.end();
1679 ++cursor
1680 ) {
1681 (*key_names)[key_index++] = strdup((*cursor).c_str());
1682 }
1683 /* C++ should take care of key_name and key_list deallocation */
1684 return 0;
1685 }
1686
1687 /*
1688 * Free memory allocated by get_key_names:
1689 */
delete_key_names(char ** key_names,uint32_t key_names_length)1690 void delete_key_names(char **key_names, uint32_t key_names_length)
1691 {
1692 uint32_t key_count = 0;
1693 if (key_names != NULL) {
1694 for (key_count = 0; key_count < key_names_length; key_count++) {
1695 free(key_names[key_count]);
1696 /* allocated by strdup -> free() */
1697 }
1698 delete[](key_names); /* allocated by new[] -> delete[] */
1699 }
1700 }
1701
1702 /*
1703 * Fill ir_data with IR code learned from other remote
1704 * via Harmony IR receiver.
1705 * Returns 0 for success, error code for failure.
1706 */
learn_from_remote(uint32_t * carrier_clock,uint32_t ** ir_signal,uint32_t * ir_signal_length,lc_callback cb,void * cb_arg)1707 int learn_from_remote(uint32_t *carrier_clock, uint32_t **ir_signal,
1708 uint32_t *ir_signal_length, lc_callback cb, void *cb_arg)
1709 {
1710 if (rmt == NULL){
1711 return LC_ERROR_CONNECT;
1712 }
1713 if ((carrier_clock == NULL) || (ir_signal == NULL)
1714 || (ir_signal_length == NULL)) {
1715 /* nothing to write to: */
1716 return LC_ERROR;
1717 }
1718
1719 /* try to learn code via Harmony from original remote: */
1720 return rmt->LearnIR(carrier_clock, ir_signal, ir_signal_length, cb, cb_arg,
1721 LC_CB_STAGE_LEARN);
1722 }
1723
1724 /*
1725 * Free memory allocated by learn_from_remote:
1726 */
delete_ir_signal(uint32_t * ir_signal)1727 void delete_ir_signal(uint32_t *ir_signal)
1728 {
1729 delete[] ir_signal; /* allocated by new[] -> delete[] */
1730 }
1731
1732 /*
1733 * Fill encoded_signal with IR code encoded to Logitech
1734 * posting string format.
1735 * Returns 0 for success, error code in case of failure.
1736 */
encode_for_posting(uint32_t carrier_clock,uint32_t * ir_signal,uint32_t ir_signal_length,char ** encoded_signal)1737 int encode_for_posting(uint32_t carrier_clock, uint32_t *ir_signal,
1738 uint32_t ir_signal_length, char **encoded_signal)
1739 {
1740 int err = 0;
1741 string encoded;
1742 if (ir_signal == NULL || ir_signal_length == 0 || encoded_signal == NULL) {
1743 return LC_ERROR; /* cannot do anything without */
1744 }
1745 err = encode_ir_signal(carrier_clock, ir_signal, ir_signal_length,
1746 &encoded);
1747 if (err == 0) {
1748 debug("Learned code: %s", encoded.c_str());
1749 *encoded_signal = strdup(encoded.c_str());
1750 }
1751 return err;
1752 }
1753
1754 /*
1755 * Free memory allocated by encode_for_posting:
1756 */
delete_encoded_signal(char * encoded_signal)1757 void delete_encoded_signal(char *encoded_signal)
1758 {
1759 free(encoded_signal); /* allocated by strdup -> free() */
1760 }
1761
1762 /*
1763 * Post encoded IR-code with key_name and additional
1764 * information from XML data[size] to Logitech.
1765 * Returns 0 for success, error code for failure.
1766 */
post_new_code(char * key_name,char * encoded_signal,lc_callback cb,void * cb_arg)1767 int post_new_code(char *key_name, char *encoded_signal, lc_callback cb,
1768 void *cb_arg)
1769 {
1770 int err;
1771 string learn_key, learn_seq;
1772
1773 if (cb)
1774 cb(LC_CB_STAGE_HTTP, 0, 0, 2, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
1775
1776 if (key_name == NULL || encoded_signal == NULL) {
1777 return LC_ERROR_POST; /* cannot do anything without */
1778 }
1779
1780 learn_key = key_name;
1781 learn_seq = encoded_signal;
1782
1783 if (cb)
1784 cb(LC_CB_STAGE_HTTP, 1, 1, 2, LC_CB_COUNTER_TYPE_STEPS, cb_arg, NULL);
1785
1786 if ((err = Post(of->GetXml(), of->GetXmlSize(), "POSTOPTIONS", ri, true,
1787 false, false, &learn_seq, &learn_key)))
1788 return err;
1789
1790 if (cb)
1791 cb(LC_CB_STAGE_HTTP, 2, 2, 2, LC_CB_COUNTER_TYPE_STEPS, cb_arg,
1792 NULL);
1793
1794 return 0;
1795 }
1796
1797 /*
1798 * Special structures and methods for the Harmony Link
1799 */
1800 /*
1801 * Given a buffer holding key-value pairs of the form
1802 *
1803 * key1,val1
1804 * key2,val2
1805 *
1806 * Will find the key passed in and copy the value on the other side of the
1807 * comma into dest.
1808 */
mh_get_value(char * buffer,const char * key,char * dest)1809 void mh_get_value(char *buffer, const char *key, char *dest)
1810 {
1811 char *start = NULL;
1812 char *end = NULL;
1813 int len;
1814 std::string key_str(key);
1815 key_str += ",";
1816 start = strstr(buffer, key_str.c_str());
1817 if (start) {
1818 start += key_str.length();
1819 end = strstr(start, "\n");
1820 if (end) {
1821 len = end - start;
1822 if (len >= MH_STRING_LENGTH)
1823 start = NULL;
1824 }
1825 }
1826 if (start && end)
1827 strncpy(dest, start, len);
1828 }
1829
mh_get_cfg_properties(struct mh_cfg_properties * properties)1830 int mh_get_cfg_properties(struct mh_cfg_properties *properties)
1831 {
1832 if (!is_mh_remote())
1833 return LC_ERROR;
1834
1835 int err;
1836 int buflen = 5000;
1837 char buffer[buflen];
1838 uint32_t data_read;
1839 if ((err = rmt->ReadFile("/cfg/properties", (uint8_t*)buffer, buflen,
1840 &data_read, 0x00, NULL, NULL, 0)))
1841 return err;
1842
1843 mh_get_value(buffer, "host_name", properties->host_name);
1844 mh_get_value(buffer, "account_email", properties->email);
1845 mh_get_value(buffer, "discovery_service_link", properties->service_link);
1846
1847 return 0;
1848 }
1849
mh_set_cfg_properties(const struct mh_cfg_properties * properties)1850 int mh_set_cfg_properties(const struct mh_cfg_properties *properties)
1851 {
1852 if (!is_mh_remote())
1853 return LC_ERROR;
1854
1855 int err;
1856 std::string str_buffer;
1857 str_buffer += "host_name,";
1858 str_buffer += properties->host_name;
1859 str_buffer += "\n";
1860 str_buffer += "account_email,";
1861 str_buffer += properties->email;
1862 str_buffer += "\n";
1863 str_buffer += "discovery_service_link,";
1864 str_buffer += properties->service_link;
1865 str_buffer += "\n";
1866
1867 err = rmt->WriteFile("/cfg/properties", (uint8_t*)str_buffer.c_str(),
1868 strlen(str_buffer.c_str()));
1869 return err;
1870 }
1871
mh_get_wifi_networks(struct mh_wifi_networks * networks)1872 int mh_get_wifi_networks(struct mh_wifi_networks *networks)
1873 {
1874 if (!is_mh_remote())
1875 return LC_ERROR;
1876
1877 int err;
1878 int buflen = 5000;
1879 char buffer[buflen];
1880 uint32_t data_read;
1881 if ((err = rmt->ReadFile("/sys/wifi/networks", (uint8_t*)buffer, buflen,
1882 &data_read, 0x00, NULL, NULL, 0)))
1883 return err;
1884
1885 char *buf_ptr = buffer;
1886 int i = 0;
1887 while (strstr(buf_ptr, "item,") && (i < MH_MAX_WIFI_NETWORKS)) {
1888 mh_get_value(buf_ptr, "ssid", networks->network[i].ssid);
1889 mh_get_value(buf_ptr, "signal_strength",
1890 networks->network[i].signal_strength);
1891 mh_get_value(buf_ptr, "channel", networks->network[i].channel);
1892 mh_get_value(buf_ptr, "encryption", networks->network[i].encryption);
1893 buf_ptr = strstr(buf_ptr, "encryption,");
1894 if (buf_ptr)
1895 buf_ptr = strstr(buf_ptr, "\n");
1896 i++;
1897 }
1898
1899 return 0;
1900 }
1901
mh_get_wifi_config(struct mh_wifi_config * config)1902 int mh_get_wifi_config(struct mh_wifi_config *config)
1903 {
1904 if (!is_mh_remote())
1905 return LC_ERROR;
1906
1907 int err;
1908 int buflen = 5000;
1909 char buffer[buflen];
1910 uint32_t data_read;
1911 if ((err = rmt->ReadFile("/sys/wifi/connect", (uint8_t*)buffer, buflen,
1912 &data_read, 0x00, NULL, NULL, 0)))
1913 return err;
1914
1915 mh_get_value(buffer, "ssid", config->ssid);
1916 mh_get_value(buffer, "encryption", config->encryption);
1917 mh_get_value(buffer, "password", config->password);
1918 mh_get_value(buffer, "connect_status", config->connect_status);
1919 mh_get_value(buffer, "error_code", config->error_code);
1920
1921 return 0;
1922 }
1923
mh_set_wifi_config(const struct mh_wifi_config * config)1924 int mh_set_wifi_config(const struct mh_wifi_config *config)
1925 {
1926 if (!is_mh_remote())
1927 return LC_ERROR;
1928
1929 int err;
1930 std::string str_buffer;
1931 str_buffer += "ssid,";
1932 str_buffer += config->ssid;
1933 str_buffer += "\n";
1934 str_buffer += "encryption,";
1935 str_buffer += config->encryption;
1936 str_buffer += "\n";
1937 str_buffer += "user,\n"; /* not sure what this is - appears unused */
1938 str_buffer += "password,";
1939 str_buffer += config->password;
1940 str_buffer += "\n";
1941
1942 err = rmt->WriteFile("/sys/wifi/connect", (uint8_t*)str_buffer.c_str(),
1943 strlen(str_buffer.c_str()));
1944 return err;
1945 }
1946
mh_get_serial()1947 const char *mh_get_serial()
1948 {
1949 return ri.mh_serial.c_str();
1950 }
1951
mh_read_file(const char * filename,uint8_t * buffer,const uint32_t buflen,uint32_t * data_read)1952 int mh_read_file(const char *filename, uint8_t *buffer, const uint32_t buflen,
1953 uint32_t *data_read)
1954 {
1955 if (!is_mh_remote())
1956 return LC_ERROR;
1957 return rmt->ReadFile(filename, buffer, buflen, data_read, 0x00, NULL, NULL,
1958 0);
1959 }
1960
mh_write_file(const char * filename,uint8_t * buffer,const uint32_t buflen)1961 int mh_write_file(const char *filename, uint8_t *buffer, const uint32_t buflen)
1962 {
1963 if (!is_mh_remote())
1964 return LC_ERROR;
1965 return rmt->WriteFile(filename, buffer, buflen);
1966 }
1967
1968 /*
1969 * PRIVATE-SHARED INTERNAL FUNCTIONS
1970 * These are functions used by the whole library but are NOT part of the API
1971 * and probably should be somewhere else...
1972 */
1973
report_net_error(const char * msg)1974 void report_net_error(const char *msg)
1975 {
1976 #ifdef _WIN32
1977 debug("Net error: %s failed with error %i", msg, WSAGetLastError());
1978 #else
1979 debug("Net error: %s failed with error %s", msg, strerror(errno));
1980 #endif
1981 }
1982