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