X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/blobdiff_plain/6262005e88c7c9edff4c0f962ca338ffb2a299fb..920d34e08c728c4e56f80fad26bc8f81f044f674:/hmsniff.c diff --git a/hmsniff.c b/hmsniff.c index 1936d5b..89e2e82 100644 --- a/hmsniff.c +++ b/hmsniff.c @@ -1,6 +1,6 @@ /* HM-sniffer for HM-CFG-USB * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2013-15 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 @@ -29,14 +29,18 @@ #include #include #include +#include #include #include +#include "version.h" #include "hexdump.h" #include "hmcfgusb.h" +static int verbose = 0; + /* See HMConfig.pm */ -char *hm_message_types(uint8_t type) +char *hm_message_types(uint8_t type, uint8_t subtype) { switch(type) { case 0x00: @@ -46,13 +50,20 @@ char *hm_message_types(uint8_t type) return "Configuration"; break; case 0x02: - return "Acknowledge"; + if (subtype >= 0x80 && subtype <= 0x8f) { + return "NACK"; + } else if (subtype == 0x01) { + return "ACKinfo"; + } else if (subtype == 0x04) { + return "AESrequest"; + } + return "ACK"; break; case 0x03: - return "AES"; + return "AESreply"; break; case 0x04: - return "AES-Key"; + return "AESkey"; break; case 0x10: return "Information"; @@ -81,6 +92,12 @@ char *hm_message_types(uint8_t type) case 0x58: return "Climate event"; break; + case 0x5a: + return "Thermal control"; + break; + case 0x5e: + return "Power event"; + break; case 0x70: return "Weather event"; break; @@ -95,43 +112,60 @@ static void dissect_hm(uint8_t *buf, int len) struct timeval tv; struct tm *tmp; char ts[32]; + static int count = 0; int i; gettimeofday(&tv, NULL); tmp = localtime(&tv.tv_sec); memset(ts, 0, sizeof(ts)); strftime(ts, sizeof(ts)-1, "%Y-%m-%d %H:%M:%S", tmp); - printf("%s.%06ld: ", ts, tv.tv_usec); - for (i = 0; i < len; i++) { - printf("%02X", buf[i]); - } - printf("\n"); - printf("Packet information:\n"); - printf("\tLength: %u\n", buf[0]); - printf("\tMessage ID: %u\n", buf[1]); - printf("\tSender: %02x%02x%02x\n", buf[4], buf[5], buf[6]); - printf("\tReceiver: %02x%02x%02x\n", buf[7], buf[8], buf[9]); - printf("\tControl Byte: 0x%02x\n", buf[2]); - printf("\t\tFlags: "); - if (buf[2] & (1 << 0)) printf("WAKEUP "); - if (buf[2] & (1 << 1)) printf("WAKEMEUP "); - if (buf[2] & (1 << 2)) printf("CFG "); - if (buf[2] & (1 << 3)) printf("? "); - if (buf[2] & (1 << 4)) printf("BURST "); - if (buf[2] & (1 << 5)) printf("BIDI "); - if (buf[2] & (1 << 6)) printf("RPTED "); - if (buf[2] & (1 << 7)) printf("RPTEN "); - printf("\n"); - printf("\tMessage type: %s (0x%02x)\n", hm_message_types(buf[3]), buf[3]); - printf("\tMesage: "); - for (i = 10; i < len; i++) { - printf("%02X", buf[i]); - } - printf("\n"); + if (verbose) { + printf("%s.%06ld: ", ts, tv.tv_usec); + + for (i = 0; i < len; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + printf("Packet information:\n"); + printf("\tLength: %u\n", buf[0]); + printf("\tMessage ID: %u\n", buf[1]); + printf("\tSender: %02x%02x%02x\n", buf[4], buf[5], buf[6]); + printf("\tReceiver: %02x%02x%02x\n", buf[7], buf[8], buf[9]); + printf("\tControl Byte: 0x%02x\n", buf[2]); + printf("\t\tFlags: "); + if (buf[2] & (1 << 0)) printf("WAKEUP "); + if (buf[2] & (1 << 1)) printf("WAKEMEUP "); + if (buf[2] & (1 << 2)) printf("CFG "); + if (buf[2] & (1 << 3)) printf("? "); + if (buf[2] & (1 << 4)) printf("BURST "); + if (buf[2] & (1 << 5)) printf("BIDI "); + if (buf[2] & (1 << 6)) printf("RPTED "); + if (buf[2] & (1 << 7)) printf("RPTEN "); + printf("\n"); + printf("\tMessage type: %s (0x%02x 0x%02x)\n", hm_message_types(buf[3], buf[10]), buf[3], buf[10]); + printf("\tMessage: "); + for (i = 10; i < len; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + + printf("\n"); + } else { + if (!(count++ % 20)) + printf(" LL NR FL CM sender recvr payload\n"); - printf("\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], + buf[4], buf[5], buf[6], + buf[7], buf[8], buf[9]); + for (i = 10; i < len; i++) { + printf("%02X", buf[i]); + } + printf("%s(%s)\n", (i>10)?" ":"", hm_message_types(buf[3], buf[10])); + } } struct recv_data { @@ -168,11 +202,40 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) return 1; } +void hmsniff_syntax(char *prog) +{ + fprintf(stderr, "Syntax: %s options\n\n", prog); + fprintf(stderr, "Possible options:\n"); + fprintf(stderr, "\t-v\t\tverbose mode\n"); + fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); + +} + int main(int argc, char **argv) { struct hmcfgusb_dev *dev; struct recv_data rdata; int quit = 0; + int opt; + + while((opt = getopt(argc, argv, "vV")) != -1) { + switch (opt) { + case 'v': + verbose = 1; + break; + case 'V': + printf("hmsniff " VERSION "\n"); + printf("Copyright (c) 2013-15 Michael Gernoth\n\n"); + exit(EXIT_SUCCESS); + case 'h': + case ':': + case '?': + default: + hmsniff_syntax(argv[0]); + exit(EXIT_FAILURE); + break; + } + } hmcfgusb_set_debug(0); @@ -200,17 +263,19 @@ int main(int argc, char **argv) rdata.wrong_hmid = 0; hmcfgusb_send(dev, (unsigned char*)"K", 1, 1); } - fd = hmcfgusb_poll(dev, 1); + fd = hmcfgusb_poll(dev, 1000); if (fd >= 0) { fprintf(stderr, "activity on unknown fd %d!\n", fd); continue; } else if (fd == -1) { if (errno) { - perror("hmcfgusb_poll"); - break; - } else { - /* periodically wakeup the device */ - hmcfgusb_send_null_frame(dev, 1); + if (errno != ETIMEDOUT) { + perror("hmcfgusb_poll"); + break; + } else { + /* periodically wakeup the device */ + hmcfgusb_send_null_frame(dev, 1); + } } } } @@ -218,5 +283,7 @@ int main(int argc, char **argv) hmcfgusb_close(dev); } while (!quit); + hmcfgusb_exit(); + return EXIT_SUCCESS; }