X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/blobdiff_plain/cd45e4af020e8ceb85a448227669b03a05f493da..5aa2bb3eb67f181638ac7c0243beba7974e2b0b0:/hmsniff.c diff --git a/hmsniff.c b/hmsniff.c index 70e2412..2ffb9e1 100644 --- a/hmsniff.c +++ b/hmsniff.c @@ -1,6 +1,6 @@ /* HM-sniffer for HM-CFG-USB * - * Copyright (c) 2013-15 Michael Gernoth + * Copyright (c) 2013-16 Michael Gernoth * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -36,11 +36,13 @@ #include "version.h" #include "hexdump.h" #include "hmcfgusb.h" +#include "hmuartlgw.h" +#include "hm.h" static int verbose = 0; /* See HMConfig.pm */ -char *hm_message_types(uint8_t type, uint8_t subtype) +const char *hm_message_types(uint8_t type, uint8_t subtype) { switch(type) { case 0x00: @@ -89,15 +91,28 @@ char *hm_message_types(uint8_t type, uint8_t subtype) case 0x53: return "Water sensor"; break; + case 0x54: + return "Gas sensor"; + break; case 0x58: return "Climate event"; break; case 0x5a: return "Thermal control"; break; + case 0x5e: + case 0x5f: + return "Power event"; + break; case 0x70: return "Weather event"; break; + case 0xca: + return "Firmware"; + break; + case 0xcb: + return "Rf configuration"; + break; default: return "?"; break; @@ -151,6 +166,7 @@ static void dissect_hm(uint8_t *buf, int len) } else { if (!(count++ % 20)) printf(" LL NR FL CM sender recvr payload\n"); + printf("%s.%03ld: %02X %02X %02X %02X %02X%02X%02X %02X%02X%02X ", ts, tv.tv_usec/1000, buf[0], buf[1], buf[2], buf[3], @@ -189,6 +205,7 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) break; case 'R': case 'I': + case 'G': break; default: hexdump(buf, buf_len, "Unknown> "); @@ -198,10 +215,40 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) return 1; } +static int parse_hmuartlgw(enum hmuartlgw_dst dst, uint8_t *buf, int buf_len, void *data) +{ + if (dst == HMUARTLGW_OS) { + if ((buf[0] != HMUARTLGW_OS_ACK) || + (buf[1] != 0x01)) { + hexdump(buf, buf_len, "OS> "); + } + return 0; + } + + if (dst != HMUARTLGW_APP) { + return 0; + } + + switch(buf[0]) { + case HMUARTLGW_APP_RECV: + buf[3] = buf_len - 4; + dissect_hm(buf + 3, buf_len - 3); + case HMUARTLGW_APP_ACK: + break; + default: + hexdump(buf, buf_len, "Unknown> "); + } + + return 1; +} + void hmsniff_syntax(char *prog) { fprintf(stderr, "Syntax: %s options\n\n", prog); fprintf(stderr, "Possible options:\n"); + fprintf(stderr, "\t-f\t\tfast (100k/firmware update) mode\n"); + fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n"); + fprintf(stderr, "\t-U device\tuse HM-MOD-UART on given device\n"); fprintf(stderr, "\t-v\t\tverbose mode\n"); fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); @@ -209,19 +256,35 @@ void hmsniff_syntax(char *prog) int main(int argc, char **argv) { - struct hmcfgusb_dev *dev; + struct hm_dev dev = { 0 }; struct recv_data rdata; + char *serial = NULL; + char *uart = NULL; int quit = 0; + int speed = 10; + uint8_t buf[32]; int opt; - while((opt = getopt(argc, argv, "vV")) != -1) { + dev.type = DEVICE_TYPE_HMCFGUSB; + + while((opt = getopt(argc, argv, "fS:U:vV")) != -1) { switch (opt) { + case 'f': + speed = 100; + break; + case 'S': + serial = optarg; + break; + case 'U': + uart = optarg; + dev.type = DEVICE_TYPE_HMUARTLGW; + break; case 'v': verbose = 1; break; case 'V': printf("hmsniff " VERSION "\n"); - printf("Copyright (c) 2013-15 Michael Gernoth\n\n"); + printf("Copyright (c) 2013-16 Michael Gernoth\n\n"); exit(EXIT_SUCCESS); case 'h': case ':': @@ -233,53 +296,109 @@ int main(int argc, char **argv) } } - hmcfgusb_set_debug(0); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + hmcfgusb_set_debug(0); + } else { + hmuartlgw_set_debug(0); + } do { memset(&rdata, 0, sizeof(rdata)); rdata.wrong_hmid = 0; - dev = hmcfgusb_init(parse_hmcfgusb, &rdata); - if (!dev) { - fprintf(stderr, "Can't initialize HM-CFG-USB, retrying in 1s...\n"); - sleep(1); - continue; - } - printf("HM-CFG-USB opened!\n"); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + dev.hmcfgusb = hmcfgusb_init(parse_hmcfgusb, &rdata, serial); + if (!dev.hmcfgusb) { + fprintf(stderr, "Can't initialize HM-CFG-USB, retrying in 1s...\n"); + sleep(1); + continue; + } + printf("HM-CFG-USB opened!\n"); - hmcfgusb_send_null_frame(dev, 1); - hmcfgusb_send(dev, (unsigned char*)"K", 1, 1); + hmcfgusb_send_null_frame(dev.hmcfgusb, 1); + hmcfgusb_send(dev.hmcfgusb, (unsigned char*)"K", 1, 1); + + hmcfgusb_send_null_frame(dev.hmcfgusb, 1); + buf[0] = 'G'; + buf[1] = speed; + hmcfgusb_send(dev.hmcfgusb, buf, 2, 1); + } else { + dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata, 1); + if (!dev.hmuartlgw) { + fprintf(stderr, "Can't initialize HM-MOD-UART!\n"); + exit(1); + } + printf("HM-MOD-UART opened!\n"); + + buf[0] = HMUARTLGW_APP_SET_HMID; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + hmuartlgw_send(dev.hmuartlgw, buf, 4, HMUARTLGW_APP); + do { hmuartlgw_poll(dev.hmuartlgw, 500); } while (errno != ETIMEDOUT); + if (speed == 100) { + buf[0] = HMUARTLGW_OS_UPDATE_MODE; + buf[1] = 0xe9; + buf[2] = 0xca; + hmuartlgw_send(dev.hmuartlgw, buf, 3, HMUARTLGW_OS); + } else { + buf[0] = HMUARTLGW_OS_NORMAL_MODE; + hmuartlgw_send(dev.hmuartlgw, buf, 1, HMUARTLGW_OS); + } + } while(!quit) { int fd; if (rdata.wrong_hmid) { printf("changing hmId to 000000, this might reboot the device!\n"); - hmcfgusb_send(dev, (unsigned char*)"A\00\00\00", 4, 1); - rdata.wrong_hmid = 0; - hmcfgusb_send(dev, (unsigned char*)"K", 1, 1); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + hmcfgusb_send(dev.hmcfgusb, (unsigned char*)"A\00\00\00", 4, 1); + rdata.wrong_hmid = 0; + hmcfgusb_send(dev.hmcfgusb, (unsigned char*)"K", 1, 1); + } else { + buf[0] = HMUARTLGW_APP_SET_HMID; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + hmuartlgw_send(dev.hmuartlgw, buf, 4, HMUARTLGW_APP); + } + } + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + fd = hmcfgusb_poll(dev.hmcfgusb, 1000); + } else { + fd = hmuartlgw_poll(dev.hmuartlgw, 60000); } - fd = hmcfgusb_poll(dev, 1000); if (fd >= 0) { fprintf(stderr, "activity on unknown fd %d!\n", fd); continue; } else if (fd == -1) { if (errno) { if (errno != ETIMEDOUT) { - perror("hmcfgusb_poll"); + perror("hmsniff_poll"); break; } else { /* periodically wakeup the device */ - hmcfgusb_send_null_frame(dev, 1); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + hmcfgusb_send_null_frame(dev.hmcfgusb, 1); + } } } } } - hmcfgusb_close(dev); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + if (dev.hmcfgusb) + hmcfgusb_close(dev.hmcfgusb); + } else { + if (dev.hmuartlgw) + hmuartlgw_close(dev.hmuartlgw); + } } while (!quit); - hmcfgusb_exit(); + if (dev.type == DEVICE_TYPE_HMCFGUSB) { + hmcfgusb_exit(); + } return EXIT_SUCCESS; }