+ if (culfw_dev) {
+ printf("Opening culfw-device at path %s with speed %u\n", culfw_dev, bps);
+ dev.culfw = culfw_init(culfw_dev, bps, parse_culfw, &rdata);
+ if (!dev.culfw) {
+ fprintf(stderr, "Can't initialize CUL at %s with rate %u\n", culfw_dev, bps);
+ exit(EXIT_FAILURE);
+ }
+ dev.type = DEVICE_TYPE_CULFW;
+
+ printf("Requesting firmware version\n");
+ culfw_send(dev.culfw, "\r\n", 2);
+ culfw_flush(dev.culfw);
+
+ while (1) {
+ culfw_send(dev.culfw, "V\r\n", 3);
+
+ errno = 0;
+ pfd = culfw_poll(dev.culfw, 1000);
+ if ((pfd < 0) && errno) {
+ if (errno != ETIMEDOUT) {
+ perror("\n\nhmcfgusb_poll");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (rdata.version)
+ break;
+ }
+
+ printf("culfw-device firmware version: ");
+ if (rdata.version != 0xffff) {
+ printf("%u.%02u\n",
+ (rdata.version >> 8) & 0xff,
+ rdata.version & 0xff);
+ } else {
+ if (rdata.is_TSCUL) {
+ culfw_send(dev.culfw, "At1\r\n", 5); // tsculfw: try switch on timestamp protocol
+ printf("tsculfw\n");
+ culfw_flush(dev.culfw);
+ culfw_send(dev.culfw, "ApTiMeStAmP\r\n", 13); // tsculfw: send ping to get credits info
+ pfd = culfw_poll(dev.culfw, 1000);
+ if ((pfd < 0) && errno) {
+ if (errno != ETIMEDOUT) {
+ perror("\n\nhmcfgusb_poll");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (rdata.credits) { // tsculfw: maximum credits available?
+ fprintf(stderr, "\n\ntsculfw does not report full credits, try again later\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (kNo > 0) {
+ char keybuf[64] = { 0 };
+ int i;
+
+ printf("Setting AES-key\n");
+ snprintf(keybuf, sizeof(keybuf) - 1, "Ak%02x", kNo - 1);
+
+ for (i = 0; i < 16; i++) {
+ keybuf[4 + (i * 2)] = nibble_to_ascii((key[i] >> 4) & 0xf);
+ keybuf[4 + (i * 2) + 1] = nibble_to_ascii(key[i] & 0xf);
+ }
+ keybuf[4 + (i * 2) ] = '\r';
+ keybuf[4 + (i * 2) + 1] = '\n';
+ culfw_send(dev.culfw, keybuf, strlen(keybuf)); // tsculfw: send ping to get credits info
+ pfd = culfw_poll(dev.culfw, 1000);
+ if ((pfd < 0) && errno) {
+ if (errno != ETIMEDOUT) {
+ perror("\n\nhmcfgusb_poll");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+ else {
+ printf("a-culfw\n");
+ }
+ }
+
+ 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);
+ }