Merge branch 'debian' of https://github.com/JSurf/hmcfgusb
authorMichael Gernoth <michael@gernoth.net>
Thu, 16 Jul 2015 20:49:14 +0000 (22:49 +0200)
committerMichael Gernoth <michael@gernoth.net>
Thu, 16 Jul 2015 20:49:14 +0000 (22:49 +0200)
Conflicts:
README.md

README.md
flash-hmcfgusb.c
flash-ota.c
hmcfgusb.c
hmcfgusb.h
hmland.c
hmsniff.c
version.h

index 907d06b59dfd879cc357ad3b9afe8df8f225bdb6..f0ccc78eebcf69a3279c926e01b204d755ced932 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,33 +1,97 @@
-hmcfgusb
-========
-
-github mirror of http://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb
-
-I am not the author of this package, i'm just mirroring it here on github, all credits go to 
-Michael Gernoth http://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb
-
---------------------------------------------------------------------------------------
-
-    This repository contains utilities to use the HM-CFG-USB(2) (HomeMatic USB Konfigurations-Adapter) from ELV on    Linux/Unix by using libusb 1.0.
-    The HM-CFG-USB can be used to send and receive BidCoS-Packets to control HomeMatic home automation devices (like remote controllable sockets, switches, sensors, ...).
-
-    This repository contains, amongst others, an application, which emulates the HomeMatic LAN configuration adapter-protocol to make it possible to use the HM-CFG-USB in Fhem or as a lan configuration tool for the CCU or the HomeMatic windows configuration software.
-
-    Short hmland HowTo:
-    Install prerequisites: apt-get install libusb-1.0-0-dev make gcc
-    Get the current version of this software: hmcfgusb-HEAD-xxxxxxx.tar.gz (xxxxxxx is part of the commit-id. xxxxxxx is just a placeholder for this HowTo, use your value)
-    Extract the archive: tar xzf hmcfgusb-HEAD-xxxxxxx.tar.gz
-    Change into the new directory: cd hmcfgusb-HEAD-xxxxxxx
-    Build the code: make
-    Optional: Install udev-rules so normal users can access the device: sudo cp hmcfgusb.rules /etc/udev/rules.d/
-    Plug in the HM-CFG-USB
-    Run hmland (with debugging the first time, see -h switch): ./hmland -p 1234 -D
-    Configure Fhem to use your new HMLAN device:
-    define hmusb HMLAN 127.0.0.1:1234
-    attr hmusb hmId <hmId>
-    Updating the HM-CFG-USB firmware to version 0.967:
-    Compile the hmcfgusb utilities like in the hmland HowTo above (steps 1 to 7) and stay in the directory
-    Download the new firmware: hmusbif.03c7.enc: wget https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc
-    Make sure that hmland is not running
-    Flash the update to the USB-stick: ./flash-hmcfgusb hmusbif.03c7.enc (You might need to use sudo for this)
-    (Old) Prebuilt package for OpenWRT (ar71xx): hmcfgusb_1_ar71xx.ipk
+This repository contains utilities to use the [HM-CFG-USB(2)][] (HomeMatic USB
+Konfigurations-Adapter) from [ELV][] on Linux/Unix by using [libusb 1.0][].
+
+The HM-CFG-USB can be used to send and receive [BidCoS-Packets][] to control
+[HomeMatic][] home automation devices (like remote controllable sockets,
+switches, sensors, ...).
+
+This repository contains, amongst others, an application, which emulates the
+HomeMatic LAN configuration adapter-protocol to make it possible to use the
+HM-CFG-USB in [Fhem][] or as a lan configuration tool for the [CCU][] or the
+HomeMatic windows configuration software, also supporting devices using
+AES-signing like [KeyMatic][].
+
+[HM-CFG-USB(2)]: http://www.elv.de/homematic-usb-konfigurations-adapter-1.html
+[ELV]: http://www.elv.de/
+[libusb 1.0]: http://www.libusb.org/
+[BidCoS-Packets]: http://homegear.eu/index.php/BidCoS%C2%AE_Packets
+[HomeMatic]: http://www.homematic.com/
+[Fhem]: http://fhem.de/
+[KeyMatic]: http://www.elv.de/homematic-funk-tuerschlossantrieb-keymatic-silber-inkl-funk-handsender.html
+[CCU]: http://www.elv.de/homematic-zentrale-ccu-2.html
+
+### Short hmland HowTo: ###
+
+1.  Install prerequisites:
+    `apt-get install libusb-1.0-0-dev build-essential git`
+2.  Get the current version of this software (choose **one** option):
+    *   Get the current *release*-version as a .tar.gz:
+        1.  Download the latest version from the [releases-directory][].
+            Version 0.100 is used as an example for the following commands.
+        2.  Extract the archive: `tar xzf hmcfgusb-0.100.tar.gz`
+        3.  Change into the new directory: `cd hmcfgusb-0.100`
+    *   Get the current *development*-version via git (can be easily updated with `git pull`):
+        1.  `git clone git://git.zerfleddert.de/hmcfgusb`
+        2.  Change into the new directory: `cd hmcfgusb`
+    *   Get the current *development*-version as an archive:
+        1.  [hmcfgusb-HEAD-xxxxxxx.tar.gz][] (xxxxxxx is part of the commit-id.
+           xxxxxxx is just a placeholder for this HowTo, use your value)
+        2.  Extract the archive: `tar xzf hmcfgusb-HEAD-xxxxxxx.tar.gz`
+        3.  Change into the new directory: `cd hmcfgusb-HEAD-xxxxxxx`
+3.  Build the code: `make`
+4.  Optional: Install udev-rules so normal users can access the device:
+    `sudo cp hmcfgusb.rules /etc/udev/rules.d/`
+5.  Plug in the HM-CFG-USB
+6.  Run hmland (with debugging the first time, see `-h` switch):
+    `./hmland -p 1234 -D`
+7.  Configure Fhem to use your new HMLAN device:  
+    ``define hmusb HMLAN 127.0.0.1:1234``  
+    ``attr hmusb hmId <hmId>``
+
+**Important compatibility information:**
+If older Fhem-versions (before 2015-06-19) or [Homegear][] before 2015-07-01
+is used to connect to hmland, the `-I` switch might be needed to
+impersonate a LAN-interface (this replaces the identity string HM-USB-IF with
+HM-LAN-IF). eQ-3 rfd (CCU and configuration software) works without this switch.
+Software which needs this will not keep a stable connection open to
+hmland without this switch. It was the hardcoded default in versions
+< 0.100.
+
+This incompatibility is needed so connecting software is able to
+differentiate between HM-CFG-LAN and HM-CFG-USB.
+
+[releases-directory]: https://git.zerfleddert.de/hmcfgusb/releases/
+[hmcfgusb-HEAD-xxxxxxx.tar.gz]: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/snapshot/HEAD.tar.gz
+[Homegear]: https://www.homegear.eu/
+
+### Updating the HM-CFG-USB firmware to version 0.967: ###
+
+1.  Compile the hmcfgusb utilities like in the hmland HowTo above
+    (steps 1 to 5) and stay in the directory
+2.  Download the new firmware: [hmusbif.03c7.enc][]:
+    `wget https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc`
+3.  Make sure that hmland is not running
+4.  Flash the update to the USB-stick:
+    `./flash-hmcfgusb hmusbif.03c7.enc` (You might need to use `sudo` for this)
+
+[hmusbif.03c7.enc]: https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc
+
+### Updating HomemMatic devices over the air (OTA) (also for CUL devices): ###
+
+1.  Compile the hmcfgusb utilities like in the hmland HowTo above
+    (steps 1 to 5) and stay in the directory
+2.  Download the new firmware from [eQ-3][], in this example the HM-CC-RT-DN
+    firmware version 1.4
+3.  Extract the tgz-file: `tar xvzf hm_cc_rt_dn_update_V1_4_001_141020.tgz`
+4.  Make sure that hmland is not running
+*   When using the **[HM-CFG-USB(2)][]**, flash the new firmware to the device
+    with serial *KEQ0123456*:  
+     `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456`
+*   When using a **[culfw][]**-based device (**[CUL][]/[COC][]/...**), flash
+    the new firmware to the device with serial *KEQ0123456*:  
+     `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456 -c /dev/ttyACM0`
+
+[eQ-3]: http://www.eq-3.de/downloads.html
+[culfw]: http://culfw.de/culfw.html
+[CUL]: http://busware.de/tiki-index.php?page=CUL
+[COC]: http://busware.de/tiki-index.php?page=COC
index 0f0b9cef707b2b48424942d28b6144bc381d39f1..a9ff876d75557bc8a230910cc3936e1cb83f1324 100644 (file)
@@ -93,11 +93,12 @@ int main(int argc, char **argv)
 
        if (!dev->bootloader) {
                fprintf(stderr, "\nHM-CFG-USB not in bootloader mode, entering bootloader.\n");
-               hmcfgusb_enter_bootloader(dev);
                fprintf(stderr, "\nWaiting for device to reappear...\n");
 
                do {
                        if (dev) {
+                               if (!dev->bootloader)
+                                       hmcfgusb_enter_bootloader(dev);
                                hmcfgusb_close(dev);
                        }
                        sleep(1);
@@ -165,6 +166,7 @@ int main(int argc, char **argv)
        firmware_free(fw);
 
        hmcfgusb_close(dev);
+       hmcfgusb_exit();
 
        return EXIT_SUCCESS;
 }
index 5efd027c148d01070d76e87faab8d9aa5be20bdf..754cc29a8a3bb1f16d12ea6069f058a16640e517 100644 (file)
@@ -453,11 +453,12 @@ int main(int argc, char **argv)
 
                if (!dev.hmcfgusb->bootloader) {
                        printf("HM-CFG-USB not in bootloader mode, entering bootloader.\n");
-                       hmcfgusb_enter_bootloader(dev.hmcfgusb);
                        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);
@@ -466,10 +467,11 @@ int main(int argc, char **argv)
 
                if (dev.hmcfgusb->bootloader) {
                        printf("HM-CFG-USB in bootloader mode, rebooting\n");
-                       hmcfgusb_leave_bootloader(dev.hmcfgusb);
 
                        do {
                                if (dev.hmcfgusb) {
+                                       if (dev.hmcfgusb->bootloader)
+                                               hmcfgusb_leave_bootloader(dev.hmcfgusb);
                                        hmcfgusb_close(dev.hmcfgusb);
                                }
                                sleep(1);
@@ -736,6 +738,7 @@ int main(int argc, char **argv)
        switch(dev.type) {
                case DEVICE_TYPE_HMCFGUSB:
                        hmcfgusb_close(dev.hmcfgusb);
+                       hmcfgusb_exit();
                        break;
                case DEVICE_TYPE_CULFW:
                        culfw_close(dev.culfw);
index 0e118661fa7007397f19c52b647f96299c9c1e22..652eb429c013b9e70ee7283b4c175b50ab4dc4f1 100644 (file)
@@ -58,6 +58,7 @@
 
 static int quit = 0;
 static int debug = 0;
+static int libusb_initialized = 0;
 
 /* Not in all libusb-1.0 versions, so we have to roll our own :-( */
 static char * usb_strerror(int e)
@@ -124,26 +125,33 @@ static libusb_device_handle *hmcfgusb_find(int vid, int pid) {
                        err = libusb_open(dev, &devh);
                        if (err) {
                                fprintf(stderr, "Can't open device: %s\n", usb_strerror(err));
+                               libusb_free_device_list(list, 1);
                                return NULL;
                        }
 
                        err = libusb_detach_kernel_driver(devh, INTERFACE);
                        if ((err != 0) && (err != LIBUSB_ERROR_NOT_FOUND)) {
                                fprintf(stderr, "Can't detach kernel driver: %s\n", usb_strerror(err));
+                               libusb_close(devh);
+                               libusb_free_device_list(list, 1);
                                return NULL;
                        }
 
                        err = libusb_claim_interface(devh, INTERFACE);
                        if ((err != 0)) {
                                fprintf(stderr, "Can't claim interface: %s\n", usb_strerror(err));
+                               libusb_close(devh);
+                               libusb_free_device_list(list, 1);
                                return NULL;
                        }
 
+                       libusb_free_device_list(list, 0);
                        return devh;
                }
 
        }
 
+       libusb_free_device_list(list, 1);
        return NULL;
 }
 
@@ -250,15 +258,11 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer)
 
        if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
                if (transfer->status != LIBUSB_TRANSFER_TIMED_OUT) {
-                       fprintf(stderr, "Interrupt transfer not completed: %s!\n", usb_strerror(transfer->status));
-                       quit = EIO;
+                       if (transfer->status != LIBUSB_TRANSFER_CANCELLED)
+                               fprintf(stderr, "Interrupt transfer not completed: %s!\n", usb_strerror(transfer->status));
 
-                       if (cb_data && cb_data->dev && cb_data->dev->transfer) {
-                               libusb_free_transfer(cb_data->dev->transfer);
-                               cb_data->dev->transfer = NULL;
-                               free(cb_data);
-                       }
-                       return;
+                       quit = EIO;
+                       goto out;
                }
        } else {
                if (cb_data && cb_data->cb) {
@@ -267,14 +271,7 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer)
 
                        if (!cb_data->cb(transfer->buffer, transfer->actual_length, cb_data->data)) {
                                quit = EIO;
-
-                               if (cb_data && cb_data->dev && cb_data->dev->transfer) {
-                                       libusb_free_transfer(cb_data->dev->transfer);
-                                       cb_data->dev->transfer = NULL;
-                                       free(cb_data);
-                               }
-
-                               return;
+                               goto out;
                        }
                } else {
                        hexdump(transfer->buffer, transfer->actual_length, "> ");
@@ -284,8 +281,17 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer)
        err = libusb_submit_transfer(transfer);
        if (err != 0) {
                fprintf(stderr, "Can't re-submit transfer: %s\n", usb_strerror(err));
-               libusb_free_transfer(transfer);
-               cb_data->dev->transfer = NULL;
+               goto out;
+       }
+
+       return;
+
+out:
+       libusb_free_transfer(transfer);
+       if (cb_data) {
+               if (cb_data->dev && cb_data->dev->transfer) {
+                       cb_data->dev->transfer = NULL;
+               }
                free(cb_data);
        }
 }
@@ -300,18 +306,23 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
        int err;
        int i;
 
-       err = libusb_init(NULL);
-       if (err != 0) {
-               fprintf(stderr, "Can't initialize libusb: %s\n", usb_strerror(err));
-               return NULL;
+       if (!libusb_initialized) {
+               err = libusb_init(NULL);
+               if (err != 0) {
+                       fprintf(stderr, "Can't initialize libusb: %s\n", usb_strerror(err));
+                       return NULL;
+               }
        }
+       libusb_initialized = 1;
 
        devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT);
        if (!devh) {
                devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT_BL);
                if (!devh) {
                        fprintf(stderr, "Can't find/open hmcfgusb!\n");
-                       libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+                       hmcfgusb_exit();
+#endif
                        return NULL;
                }
                bootloader = 1;
@@ -321,7 +332,9 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
        if (!dev) {
                perror("Can't allocate memory for hmcfgusb_dev");
                libusb_close(devh);
-               libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+               hmcfgusb_exit();
+#endif
                return NULL;
        }
 
@@ -335,7 +348,9 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
                perror("Can't allocate memory for hmcfgusb_cb_data");
                free(dev);
                libusb_close(devh);
-               libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+               hmcfgusb_exit();
+#endif
                return NULL;
        }
 
@@ -352,17 +367,23 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
                free(dev);
                free(cb_data);
                libusb_close(devh);
-               libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+               hmcfgusb_exit();
+#endif
                return NULL;
        }
 
        usb_pfd = libusb_get_pollfds(NULL);
        if (!usb_pfd) {
                fprintf(stderr, "Can't get FDset from libusb!\n");
+               libusb_cancel_transfer(dev->transfer);
+               libusb_handle_events(NULL);
                free(dev);
                free(cb_data);
                libusb_close(devh);
-               libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+               hmcfgusb_exit();
+#endif
                return NULL;
        }
 
@@ -373,10 +394,14 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
        dev->pfd = malloc(dev->n_usb_pfd * sizeof(struct pollfd));
        if (!dev->pfd) {
                perror("Can't allocate memory for poll-fds");
+               libusb_cancel_transfer(dev->transfer);
+               libusb_handle_events(NULL);
                free(dev);
                free(cb_data);
                libusb_close(devh);
-               libusb_exit(NULL);
+#ifdef NEED_LIBUSB_EXIT
+               hmcfgusb_exit();
+#endif
                return NULL;
        }
 
@@ -529,6 +554,7 @@ void hmcfgusb_close(struct hmcfgusb_dev *dev)
 
        if (dev->transfer) {
                libusb_cancel_transfer(dev->transfer);
+               libusb_handle_events(NULL);
        }
 
        err = libusb_release_interface(dev->usb_devh, INTERFACE);
@@ -537,10 +563,19 @@ void hmcfgusb_close(struct hmcfgusb_dev *dev)
        }
 
        libusb_close(dev->usb_devh);
+#ifdef NEED_LIBUSB_EXIT
+       hmcfgusb_exit();
+#endif
        free(dev->pfd);
        free(dev);
+}
 
-       libusb_exit(NULL);
+void hmcfgusb_exit(void)
+{
+       if (libusb_initialized) {
+               libusb_exit(NULL);
+               libusb_initialized = 0;
+       }
 }
 
 void hmcfgusb_set_debug(int d)
index 8172622b30f4ed4763a0432c1ca129bd953914e2..7bfc53dd53bf1667df348a017b1cadc0faed05eb 100644 (file)
@@ -41,4 +41,5 @@ int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout);
 void hmcfgusb_enter_bootloader(struct hmcfgusb_dev *dev);
 void hmcfgusb_leave_bootloader(struct hmcfgusb_dev *dev);
 void hmcfgusb_close(struct hmcfgusb_dev *dev);
+void hmcfgusb_exit(void);
 void hmcfgusb_set_debug(int d);
index 6b89ece6a56d76d3f69ed8daba597ee369743517..f1f0e3dcf88595ca9b310057539e1eb5638f2d38 100644 (file)
--- a/hmland.c
+++ b/hmland.c
@@ -1,6 +1,6 @@
 /* HM-CFG-LAN emulation for HM-CFG-USB
  *
- * Copyright (c) 2013 Michael Gernoth <michael@gernoth.net>
+ * Copyright (c) 2013-15 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
 #define PID_FILE "/var/run/hmland.pid"
 
 #define DEFAULT_REBOOT_SECONDS 86400
+#define LAN_READ_CHUNK_SIZE    2048
+/* Don't allow remote clients to consume all of our memory */
+#define LAN_MAX_LINE_LENGTH    4096
+#define LAN_MAX_BUF_LENGTH     1048576
 
 extern char *optarg;
 
@@ -58,6 +62,8 @@ static int reboot_seconds = 0;
 static int reboot_at_hour = -1;
 static int reboot_at_minute = -1;
 static int reboot_set = 0;
+static uint8_t *lan_read_buf = NULL;
+static int lan_read_buflen = 0;
 
 struct queued_rx {
        char *rx;
@@ -283,7 +289,12 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data)
                        format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 3, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE);
                        format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 3, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE);
                        format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 4, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE);
-                       format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 2, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE | FLAG_NL);
+                       if (version < 0x03c7) {
+                               format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 2, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE | FLAG_NL);
+                       } else {
+                               format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 2, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE);
+                               format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 1, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE | FLAG_NL);
+                       }
 
                        if (!reboot_set) {
                                int new_reboot_seconds;
@@ -398,72 +409,98 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data)
        return 1;
 }
 
-static int hmlan_parse_in(int fd, void *data)
+static int hmlan_parse_one(uint8_t *cmd, int last, void *data)
 {
        struct hmcfgusb_dev *dev = data;
-       uint8_t buf[1025];
        uint8_t out[0x40]; //FIXME!!!
        uint8_t *outpos;
-       uint8_t *inpos;
-       int i;
-       int last;
-       int r;
+       uint8_t *inpos = cmd;
 
-       memset(buf, 0, sizeof(buf));
+       outpos = out;
 
-       r = read(fd, buf, sizeof(buf)-1);
-       if (r > 0) {
-               uint8_t *inend = buf + r;
+       if (last == 0)
+               return 1;
 
-               inpos = buf;
+       write_log((char*)cmd, last,  "LAN > ");
+
+       memset(out, 0, sizeof(out));
+       *outpos++ = *inpos++;
+
+       switch(*cmd) {
+               case 'S':
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE);
+                       break;
+               case 'Y':
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE);
+                       break;
+               case '+':
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0);
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE);
+               default:
+                       parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_IGNORE_COMMAS);
+                       break;
+       }
 
-               while (inpos < inend) {
-                       uint8_t *instart = inpos;
+       hmcfgusb_send(dev, out, sizeof(out), 1);
 
-                       if ((*inpos == '\r') || (*inpos == '\n')) {
-                               inpos++;
-                               continue;
-                       }
-                       
-                       outpos = out;
+       return 1;
+}
 
-                       last = inend - inpos;
+static int hmlan_parse_in(int fd, void *data)
+{
+       uint8_t *newbuf;
+       int r;
+       int i;
 
-                       for (i = 0; i < last; i++) {
-                               if ((inpos[i] == '\r') || (inpos[i] == '\n')) {
-                                       last = i;
+       newbuf = realloc(lan_read_buf, lan_read_buflen + LAN_READ_CHUNK_SIZE);
+       if (!newbuf) {
+               perror("realloc");
+               return 0;
+       }
+       lan_read_buf = newbuf;
+       r = read(fd, lan_read_buf + lan_read_buflen, LAN_READ_CHUNK_SIZE);
+       if (r > 0) {
+               lan_read_buflen += r;
+               if (lan_read_buflen > LAN_MAX_BUF_LENGTH) {
+                       if (verbose)
+                               printf("Our buffer is bigger than %d bytes (%d bytes), closing connection!\n", LAN_MAX_BUF_LENGTH, lan_read_buflen);
+                       return -1;
+               }
+               while(lan_read_buflen > 0) {
+                       int found = 0;
+
+                       for (i = 0; i < lan_read_buflen; i++) {
+                               if ((lan_read_buf[i] == '\r') || (lan_read_buf[i] == '\n')) {
+                                       if (i > 0)
+                                               hmlan_parse_one(lan_read_buf, i, data);
+                                       memmove(lan_read_buf, lan_read_buf + i + 1, lan_read_buflen - (i + 1));
+                                       lan_read_buflen -= (i + 1);
+                                       found = 1;
                                        break;
                                }
+                               if (i > LAN_MAX_LINE_LENGTH) {
+                                       if (verbose)
+                                               printf("Client sent more than %d bytes without newline, closing connection!\n", LAN_MAX_LINE_LENGTH);
+                                       return -1;
+                               }
                        }
-
-                       if (last == 0)
-                               continue;
-
-                       write_log((char*)instart, last,  "LAN > ");
-
-                       memset(out, 0, sizeof(out));
-                       *outpos++ = *inpos++;
-
-                       switch(*instart) {
-                               case 'S':
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE);
-                                       break;
-                               case 'Y':
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0);
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE);
-                                       break;
-                               default:
-                                       parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_IGNORE_COMMAS);
-                                       break;
+                       if (!found)
+                               break;
+                       newbuf = realloc(lan_read_buf, lan_read_buflen);
+                       if (lan_read_buflen && !newbuf) {
+                               perror("realloc");
+                               return 0;
                        }
-
-                       hmcfgusb_send(dev, out, sizeof(out), 1);
+                       lan_read_buf = newbuf;
                }
        } else if (r < 0) {
                if (errno != ECONNRESET)
@@ -686,8 +723,6 @@ static int socket_server(char *iface, int port, int flags)
                exit(EXIT_FAILURE);
        }
 
-       impersonate_hmlanif = 1;
-
        sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sock == -1) {
                perror("Can't open socket");
@@ -750,6 +785,11 @@ static int socket_server(char *iface, int port, int flags)
                shutdown(client, SHUT_RDWR);
                close(client);
 
+               if (lan_read_buf)
+                       free(lan_read_buf);
+               lan_read_buf = NULL;
+               lan_read_buflen = 0;
+
                write_log(NULL, 0, "Connection to %d.%d.%d.%d closed!\n",
                                (client_addr & 0xff000000) >> 24,
                                (client_addr & 0x00ff0000) >> 16,
@@ -776,6 +816,7 @@ void hmlan_syntax(char *prog)
        fprintf(stderr, "\t-D\t\tdebug mode\n");
        fprintf(stderr, "\t-d\t\tdaemon mode\n");
        fprintf(stderr, "\t-h\t\tthis help\n");
+       fprintf(stderr, "\t-I\t\tpretend to be HM-LAN-IF for compatibility with client-software (previous default)\n");
        fprintf(stderr, "\t-i\t\tinteractive mode (connect HM-CFG-USB to terminal)\n");
        fprintf(stderr, "\t-l ip\t\tlisten on given IP address only (for example 127.0.0.1)\n");
        fprintf(stderr, "\t-L logfile\tlog network-communication to logfile\n");
@@ -797,7 +838,7 @@ int main(int argc, char **argv)
        char *ep;
        int opt;
        
-       while((opt = getopt(argc, argv, "DdhiPp:Rr:l:L:vV")) != -1) {
+       while((opt = getopt(argc, argv, "DdhIiPp:Rr:l:L:vV")) != -1) {
                switch (opt) {
                        case 'D':
                                debug = 1;
@@ -806,6 +847,9 @@ int main(int argc, char **argv)
                        case 'd':
                                flags |= FLAG_DAEMON;
                                break;
+                       case 'I':
+                               impersonate_hmlanif = 1;
+                               break;
                        case 'i':
                                interactive = 1;
                                break;
@@ -857,7 +901,7 @@ int main(int argc, char **argv)
                                break;
                        case 'V':
                                printf("hmland " VERSION "\n");
-                               printf("Copyright (c) 2013 Michael Gernoth\n\n");
+                               printf("Copyright (c) 2013-15 Michael Gernoth\n\n");
                                exit(EXIT_SUCCESS);
                        case 'h':
                        case ':':
index a3cbe7a244ffd96304018b7e5a383a68bee62f13..1f5d889a0fff7f7874f07ab54317beb847336a72 100644 (file)
--- a/hmsniff.c
+++ b/hmsniff.c
@@ -125,7 +125,7 @@ static void dissect_hm(uint8_t *buf, int len)
        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: ");
+       printf("\tMessage: ");
        for (i = 10; i < len; i++) {
                printf("%02X", buf[i]);
        }
@@ -221,5 +221,7 @@ int main(int argc, char **argv)
                hmcfgusb_close(dev);
        } while (!quit);
 
+       hmcfgusb_exit();
+
        return EXIT_SUCCESS;
 }
index 0680b904cd4e79eb6feab19ae552273f57db7003..bec36aff1387ceccc0ffce80d6679520fcf64a32 100644 (file)
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
-#define VERSION        "0.097-git"
+#define VERSION        "0.101-git"
Impressum, Datenschutz