+
+               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);
+               }