+
+ if (rdata.version < 0x013a) {
+ fprintf(stderr, "\nThis version does _not_ support firmware upgrade mode, you need at least 1.58!\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (uart) {
+ uint32_t new_hmid = my_hmid;
+
+ hmuartlgw_set_debug(debug);
+
+ dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata, 1);
+ if (!dev.hmuartlgw) {
+ fprintf(stderr, "Can't initialize HM-MOD-UART\n");
+ exit(EXIT_FAILURE);
+ }
+ dev.type = DEVICE_TYPE_HMUARTLGW;
+
+ out[0] = HMUARTLGW_APP_GET_HMID;
+ send_wait_hmuartlgw(&dev, &rdata, out, 1, HMUARTLGW_APP, HMUARTLGW_STATE_GET_HMID, HMUARTLGW_STATE_ACK_APP);
+
+ out[0] = HMUARTLGW_OS_GET_FIRMWARE;
+ send_wait_hmuartlgw(&dev, &rdata, out, 1, HMUARTLGW_OS, HMUARTLGW_STATE_GET_FIRMWARE, HMUARTLGW_STATE_DONE);
+
+ out[0] = HMUARTLGW_OS_GET_CREDITS;
+ send_wait_hmuartlgw(&dev, &rdata, out, 1, HMUARTLGW_OS, HMUARTLGW_STATE_GET_CREDITS, HMUARTLGW_STATE_DONE);
+
+ printf("HM-MOD-UART firmware version: %u.%u.%u, used credits: %u%%\n",
+ rdata.uartlgw_version[0],
+ rdata.uartlgw_version[1],
+ rdata.uartlgw_version[2],
+ rdata.credits);
+
+ if (rdata.credits >= 40) {
+ printf("\nRebooting HM-MOD-UART to avoid running out of credits\n");
+
+ hmuartlgw_enter_bootloader(dev.hmuartlgw);
+ hmuartlgw_enter_app(dev.hmuartlgw);
+ }
+
+ printf("\nHM-MOD-UART opened\n\n");
+
+ if (new_hmid && (my_hmid != new_hmid)) {
+ printf("Changing hmid from %06x to %06x\n", my_hmid, new_hmid);
+
+ out[0] = HMUARTLGW_APP_SET_HMID;
+ out[1] = (new_hmid >> 16) & 0xff;
+ out[2] = (new_hmid >> 8) & 0xff;
+ out[3] = new_hmid & 0xff;
+ send_wait_hmuartlgw(&dev, &rdata, out, 4, HMUARTLGW_APP, HMUARTLGW_STATE_WAIT_APP, HMUARTLGW_STATE_ACK_APP);
+
+ my_hmid = new_hmid;
+ }
+
+ if (kNo > 0) {
+ printf("Setting AES-key\n");
+
+ memset(out, 0, sizeof(out));
+ out[0] = HMUARTLGW_APP_SET_CURRENT_KEY;
+ memcpy(&(out[1]), key, 16);
+ out[17] = kNo;
+ send_wait_hmuartlgw(&dev, &rdata, out, 18, HMUARTLGW_APP, HMUARTLGW_STATE_WAIT_APP, HMUARTLGW_STATE_ACK_APP);
+
+ memset(out, 0, sizeof(out));
+ out[0] = HMUARTLGW_APP_SET_OLD_KEY;
+ memcpy(&(out[1]), key, 16);
+ out[17] = kNo;
+ send_wait_hmuartlgw(&dev, &rdata, out, 18, HMUARTLGW_APP, HMUARTLGW_STATE_WAIT_APP, HMUARTLGW_STATE_ACK_APP);
+ }
+ } else {
+ uint32_t new_hmid = my_hmid;
+
+ hmcfgusb_set_debug(debug);
+
+ dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial);
+ if (!dev.hmcfgusb) {
+ fprintf(stderr, "Can't initialize HM-CFG-USB\n");
+ exit(EXIT_FAILURE);
+ }
+ dev.type = DEVICE_TYPE_HMCFGUSB;
+
+ memset(out, 0, sizeof(out));
+ out[0] = 'K';
+ hmcfgusb_send(dev.hmcfgusb, out, sizeof(out), 1);
+
+ while (1) {
+ errno = 0;
+ pfd = hmcfgusb_poll(dev.hmcfgusb, 1000);
+ if ((pfd < 0) && errno) {
+ if (errno != ETIMEDOUT) {
+ perror("\n\nhmcfgusb_poll");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (rdata.version)
+ break;
+ }
+
+ if (rdata.version < 0x3c7) {
+ fprintf(stderr, "HM-CFG-USB firmware too low: %u < 967\n", rdata.version);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("HM-CFG-USB firmware version: %u, used credits: %u%%\n", rdata.version, rdata.credits);
+
+ if (rdata.credits >= 40) {
+ printf("\nRebooting HM-CFG-USB to avoid running out of credits\n\n");
+
+ if (!dev.hmcfgusb->bootloader) {
+ printf("HM-CFG-USB not in bootloader mode, entering bootloader.\n");
+ printf("Waiting for device to reappear...\n");
+
+ do {
+ if (dev.hmcfgusb) {
+ if (!dev.hmcfgusb->bootloader)
+ hmcfgusb_enter_bootloader(dev.hmcfgusb);
+ hmcfgusb_close(dev.hmcfgusb);
+ }
+ sleep(1);
+ } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial)) == NULL) || (!dev.hmcfgusb->bootloader));
+ }
+
+ if (dev.hmcfgusb->bootloader) {
+ printf("HM-CFG-USB in bootloader mode, rebooting\n");
+
+ do {
+ if (dev.hmcfgusb) {
+ if (dev.hmcfgusb->bootloader)
+ hmcfgusb_leave_bootloader(dev.hmcfgusb);
+ hmcfgusb_close(dev.hmcfgusb);
+ }
+ sleep(1);
+ } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial)) == NULL) || (dev.hmcfgusb->bootloader));
+ }
+ }
+
+ printf("\n\nHM-CFG-USB opened\n\n");
+
+ if (new_hmid && (my_hmid != new_hmid)) {
+ printf("Changing hmid from %06x to %06x\n", my_hmid, new_hmid);
+
+ memset(out, 0, sizeof(out));
+ out[0] = 'A';
+ out[1] = (new_hmid >> 16) & 0xff;
+ out[2] = (new_hmid >> 8) & 0xff;
+ out[3] = new_hmid & 0xff;
+
+ hmcfgusb_send(dev.hmcfgusb, out, sizeof(out), 1);
+
+ my_hmid = new_hmid;
+ }
+
+ if (kNo > 0) {
+ printf("Setting AES-key\n");
+
+ memset(out, 0, sizeof(out));
+ out[0] = 'Y';
+ out[1] = 0x01;
+ out[2] = kNo;
+ out[3] = sizeof(key);
+ memcpy(&(out[4]), key, sizeof(key));
+ hmcfgusb_send(dev.hmcfgusb, out, sizeof(out), 1);
+
+ memset(out, 0, sizeof(out));
+ out[0] = 'Y';
+ out[1] = 0x02;
+ out[2] = 0x00;
+ out[3] = 0x00;
+ hmcfgusb_send(dev.hmcfgusb, out, sizeof(out), 1);
+
+ memset(out, 0, sizeof(out));
+ out[0] = 'Y';
+ out[1] = 0x03;
+ out[2] = 0x00;
+ out[3] = 0x00;
+ hmcfgusb_send(dev.hmcfgusb, out, sizeof(out), 1);
+ }