]> git.zerfleddert.de Git - hmcfgusb/blobdiff - flash-ota.c
hmsniff: add two more message types
[hmcfgusb] / flash-ota.c
index f7aabf8d966a74525e517ed3a0ba9fd0e0d2f4ec..7291e173bc6370dada2af02961947f1051ef8958 100644 (file)
@@ -1,6 +1,6 @@
 /* flasher for HomeMatic-devices supporting OTA updates
  *
- * Copyright (c) 2014 Michael Gernoth <michael@gernoth.net>
+ * Copyright (c) 2014-16 Michael Gernoth <michael@gernoth.net>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -51,7 +51,7 @@ extern char *optarg;
 
 uint32_t hmid = 0;
 uint32_t my_hmid = 0;
-char key[16] = {0};
+uint8_t key[16] = {0};
 int32_t kNo = -1;
 
 /* Maximum payloadlen supported by IO */
@@ -177,8 +177,25 @@ static int parse_culfw(uint8_t *buf, int buf_len, void *data)
                                *e = '\0';
                                v = atoi(s);
                                rdata->version |= v;
+
+                               s = e + 1;
+                               e = strchr(s, ' ');
+                               if (!e) {
+                                       break;
+                               }
+                               *e = '\0';
+                               if (!strcmp(s, "a-culfw")) {
+                                       rdata->version = 0xffff;
+                               }
                        }
                        break;
+               case 'E':
+                       {
+                               if (!strncmp((char*)buf, "ERR:CCA", 7)) {
+                                       fprintf(stderr, "CCA didn't complete, too much traffic\n");
+                               }
+                               break;
+                       }
                default:
                        fprintf(stderr, "Unknown response from CUL: %s", buf);
                        return 0;
@@ -270,7 +287,7 @@ int send_hm_message(struct ota_dev *dev, struct recv_data *rdata, uint8_t *msg)
                                }
 
                                if (msg[CTL] & 0x20) {
-                                       int cnt = 3;
+                                       int cnt = 5;
                                        int pfd;
                                        do {
                                                errno = 0;
@@ -283,19 +300,46 @@ int send_hm_message(struct ota_dev *dev, struct recv_data *rdata, uint8_t *msg)
                                                }
                                                if (rdata->message_type == MESSAGE_TYPE_E) {
                                                        if (rdata->message[TYPE] == 0x02) {
-                                                               if (rdata->message[PAYLOAD] == 0x01) {
-                                                                       printf("AES request received but not implemented for culfw!\n");
+                                                               if (rdata->message[PAYLOAD] == 0x04) {
+                                                                       int32_t req_kNo;
+                                                                       uint8_t challenge[6];
+                                                                       uint8_t respbuf[16];
+                                                                       uint8_t *resp;
+
+                                                                       req_kNo = rdata->message[rdata->message[LEN]] / 2;
+                                                                       memcpy(challenge, &(rdata->message[PAYLOAD+1]), 6);
+
+                                                                       if (req_kNo != kNo) {
+                                                                               fprintf(stderr, "AES request for unknown key %d!\n", req_kNo);
+                                                                       } else {
+                                                                               resp = hm_sign(key, challenge, msg, NULL, respbuf);
+                                                                               if (resp) {
+                                                                                       uint8_t rbuf[64];
+
+                                                                                       memset(rbuf, 0, sizeof(rbuf));
+                                                                                       rbuf[MSGID] = rdata->message[MSGID];
+                                                                                       rbuf[CTL] = rdata->message[CTL];
+                                                                                       rbuf[TYPE] = 0x03;
+                                                                                       SET_SRC(rbuf, DST(rdata->message));
+                                                                                       SET_DST(rbuf, SRC(rdata->message));
+                                                                                       memcpy(&(rbuf[PAYLOAD]), resp, 16);
+                                                                                       SET_LEN_FROM_PAYLOADLEN(rbuf, 16);
+
+                                                                                       usleep(110000); /* Determined by a fair dice roll */
+                                                                                       return send_hm_message(dev, rdata, rbuf);
+                                                                               }
+                                                                       }
                                                                } else if (rdata->message[PAYLOAD] >= 0x80 && rdata->message[PAYLOAD] <= 0x8f) {
-                                                                       printf("NACK\n");
+                                                                       fprintf(stderr, "NACK\n");
                                                                } else {        /* ACK or ACKinfo */
                                                                        break;
                                                                }
                                                        } else {
-                                                               printf("Unexpected message received: ");
+                                                               fprintf(stderr, "Unexpected message received: ");
                                                                for (i = 0; i < rdata->message[LEN]; i++) {
-                                                                       printf("%02x", rdata->message[i+1]);
+                                                                       fprintf(stderr, "%02x", rdata->message[i+1]);
                                                                }
-                                                               printf("\n");
+                                                               fprintf(stderr, "\n");
                                                        }
                                                }
                                        } while(cnt--);
@@ -363,12 +407,12 @@ void flash_ota_syntax(char *prog)
        fprintf(stderr, "\t-c device\tenable CUL-mode with CUL at path \"device\"\n");
        fprintf(stderr, "\t-b bps\t\tuse CUL with speed \"bps\" (default: %u)\n", DEFAULT_CUL_BPS);
        fprintf(stderr, "\t-l\t\tlower payloadlen (required for devices with little RAM, e.g. CUL v2 and CUL v4)\n");
+       fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n");
        fprintf(stderr, "\t-h\t\tthis help\n");
        fprintf(stderr, "\nOptional parameters for automatically sending device to bootloader\n");
        fprintf(stderr, "\t-C\t\tHMID of central (3 hex-bytes, no prefix, e.g. ABCDEF)\n");
        fprintf(stderr, "\t-D\t\tHMID of device (3 hex-bytes, no prefix, e.g. 123456)\n");
        fprintf(stderr, "\t-K\t\tKNO:KEY AES key-number and key (hex) separated by colon (Fhem hmKey attribute)\n");
-       fprintf(stderr, "\t\t\tAES is currently not supported when using a culfw-device!\n");
 }
 
 int main(int argc, char **argv)
@@ -387,6 +431,7 @@ int main(int argc, char **argv)
        uint8_t msgid = 0x1;
        uint16_t len;
        struct firmware *fw;
+       char *hmcfgusb_serial = NULL;
        int block;
        int pfd;
        int debug = 0;
@@ -398,7 +443,7 @@ int main(int argc, char **argv)
 
        printf("HomeMatic OTA flasher version " VERSION "\n\n");
 
-       while((opt = getopt(argc, argv, "b:c:f:hls:C:D:K:")) != -1) {
+       while((opt = getopt(argc, argv, "b:c:f:hls:C:D:K:S:")) != -1) {
                switch (opt) {
                        case 'b':
                                bps = atoi(optarg);
@@ -452,6 +497,9 @@ int main(int argc, char **argv)
                                        endptr += 2;
                                }
                                break;
+                       case 'S':
+                               hmcfgusb_serial = optarg;
+                               break;
                        case 'h':
                        case ':':
                        case '?':
@@ -476,12 +524,6 @@ int main(int argc, char **argv)
        memset(&dev, 0, sizeof(struct ota_dev));
 
        if (culfw_dev) {
-               if (kNo != -1) {
-                       fprintf(stderr, "\nAES currently not supported with culfw-device!\n");
-                       flash_ota_syntax(argv[0]);
-                       exit(EXIT_FAILURE);
-               }
-
                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) {
@@ -509,9 +551,14 @@ int main(int argc, char **argv)
                                break;
                }
 
-               printf("culfw-device firmware version: %u.%02u\n", 
-                       (rdata.version >> 8) & 0xff,
-                       rdata.version & 0xff);
+               printf("culfw-device firmware version: ");
+               if (rdata.version != 0xffff) {
+                       printf("%u.%02u\n",
+                               (rdata.version >> 8) & 0xff,
+                               rdata.version & 0xff);
+               } 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");
@@ -522,7 +569,7 @@ int main(int argc, char **argv)
 
                hmcfgusb_set_debug(debug);
 
-               dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata);
+               dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial);
                if (!dev.hmcfgusb) {
                        fprintf(stderr, "Can't initialize HM-CFG-USB\n");
                        exit(EXIT_FAILURE);
@@ -567,7 +614,7 @@ int main(int argc, char **argv)
                                                hmcfgusb_close(dev.hmcfgusb);
                                        }
                                        sleep(1);
-                               } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL) || (!dev.hmcfgusb->bootloader));
+                               } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial)) == NULL) || (!dev.hmcfgusb->bootloader));
                        }
 
                        if (dev.hmcfgusb->bootloader) {
@@ -580,7 +627,7 @@ int main(int argc, char **argv)
                                                hmcfgusb_close(dev.hmcfgusb);
                                        }
                                        sleep(1);
-                               } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL) || (dev.hmcfgusb->bootloader));
+                               } while (((dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, hmcfgusb_serial)) == NULL) || (dev.hmcfgusb->bootloader));
                        }
                }
 
@@ -634,7 +681,6 @@ int main(int argc, char **argv)
 
        if (hmid && my_hmid) {
                printf("Sending device with hmid %06x to bootloader\n", hmid);
-               out[MSGID] = msgid++;
                out[CTL] = 0x30;
                out[TYPE] = 0x11;
                SET_SRC(out, my_hmid);
@@ -644,6 +690,7 @@ int main(int argc, char **argv)
 
                cnt = 3;
                do {
+                       out[MSGID] = msgid++;
                        if (send_hm_message(&dev, &rdata, out)) {
                                break;
                        }
Impressum, Datenschutz