-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
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);
firmware_free(fw);
hmcfgusb_close(dev);
+ hmcfgusb_exit();
return EXIT_SUCCESS;
}
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);
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);
switch(dev.type) {
case DEVICE_TYPE_HMCFGUSB:
hmcfgusb_close(dev.hmcfgusb);
+ hmcfgusb_exit();
break;
case DEVICE_TYPE_CULFW:
culfw_close(dev.culfw);
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)
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;
}
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) {
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, "> ");
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);
}
}
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;
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;
}
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;
}
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;
}
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;
}
if (dev->transfer) {
libusb_cancel_transfer(dev->transfer);
+ libusb_handle_events(NULL);
}
err = libusb_release_interface(dev->usb_devh, INTERFACE);
}
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)
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);
/* 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;
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;
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;
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)
exit(EXIT_FAILURE);
}
- impersonate_hmlanif = 1;
-
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) {
perror("Can't open socket");
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,
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");
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;
case 'd':
flags |= FLAG_DAEMON;
break;
+ case 'I':
+ impersonate_hmlanif = 1;
+ break;
case 'i':
interactive = 1;
break;
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 ':':
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]);
}
hmcfgusb_close(dev);
} while (!quit);
+ hmcfgusb_exit();
+
return EXIT_SUCCESS;
}
-#define VERSION "0.097-git"
+#define VERSION "0.101-git"