From: Michael Gernoth <michael@gernoth.net>
Date: Sun, 13 Sep 2015 15:17:44 +0000 (+0200)
Subject: hmcfgusb: add possibility to use a specific HM-CFG-USB with -S
X-Git-Tag: v0.102~5
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/commitdiff_plain/f51714bea4af46dd81d3ed97acffea57201f108f?ds=inline;hp=bcc4286832802319feb44be923b82cdfa8670610

hmcfgusb: add possibility to use a specific HM-CFG-USB with -S

This makes it possible to connect multiple HM-CFG-USB-devices to a
machine and run multiple instances of hmland, update the firmware
of a specific HM-CFG-USB or use a specific device for OTA updates.
---

diff --git a/flash-hmcfgusb.c b/flash-hmcfgusb.c
index a9ff876..7f296de 100644
--- a/flash-hmcfgusb.c
+++ b/flash-hmcfgusb.c
@@ -1,6 +1,6 @@
 /* flasher for HM-CFG-USB
  *
- * Copyright (c) 2013-14 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
@@ -56,6 +56,15 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data)
 	return 1;
 }
 
+void flash_hmcfgusb_syntax(char *prog)
+{
+	fprintf(stderr, "Syntax: %s [options] filename.enc\n\n", prog);
+	fprintf(stderr, "Possible options:\n");
+	fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n");
+	fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n");
+
+}
+
 int main(int argc, char **argv)
 {
 	const char twiddlie[] = { '-', '\\', '|', '/' };
@@ -63,21 +72,45 @@ int main(int argc, char **argv)
 	struct recv_data rdata;
 	uint16_t len;
 	struct firmware *fw;
+	char *serial = "ABC";
+	char *filename = NULL;
 	int block;
 	int pfd;
+	int opt;
 	int debug = 0;
 
-	printf("HM-CFG-USB flasher version " VERSION "\n\n");
+	while((opt = getopt(argc, argv, "S:V")) != -1) {
+		switch (opt) {
+			case 'S':
+				serial = optarg;
+				break;
+			case 'V':
+				printf("flash-hmcfgusb " VERSION "\n");
+				printf("Copyright (c) 2013-15 Michael Gernoth\n\n");
+				exit(EXIT_SUCCESS);
+			case 'h':
+			case ':':
+			case '?':
+			default:
+				flash_hmcfgusb_syntax(argv[0]);
+				exit(EXIT_FAILURE);
+				break;
+		}
+	}
 
-	if (argc != 2) {
-		if (argc == 1)
-			fprintf(stderr, "Missing firmware filename!\n\n");
+	if (optind == argc - 1) {
+		filename = argv[optind];
+	}
+
+	printf("HM-CFG-USB flasher version " VERSION "\n\n");
 
-		fprintf(stderr, "Syntax: %s hmusbif.enc\n\n", argv[0]);
+	if (!filename) {
+		fprintf(stderr, "Missing firmware filename!\n\n");
+		flash_hmcfgusb_syntax(argv[0]);
 		exit(EXIT_FAILURE);
 	}
 
-	fw = firmware_read_firmware(argv[1], debug);
+	fw = firmware_read_firmware(filename, debug);
 	if (!fw)
 		exit(EXIT_FAILURE);
 
@@ -85,7 +118,7 @@ int main(int argc, char **argv)
 
 	memset(&rdata, 0, sizeof(rdata));
 
-	dev = hmcfgusb_init(parse_hmcfgusb, &rdata);
+	dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial);
 	if (!dev) {
 		fprintf(stderr, "Can't initialize HM-CFG-USB\n");
 		exit(EXIT_FAILURE);
@@ -102,7 +135,7 @@ int main(int argc, char **argv)
 				hmcfgusb_close(dev);
 			}
 			sleep(1);
-		} while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL) || (!dev->bootloader));
+		} while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial)) == NULL) || (!dev->bootloader));
 	}
 
 	printf("\nHM-CFG-USB opened.\n\n");
diff --git a/flash-ota.c b/flash-ota.c
index a93446f..22f98ce 100644
--- a/flash-ota.c
+++ b/flash-ota.c
@@ -406,6 +406,7 @@ 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");
@@ -429,6 +430,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;
@@ -440,7 +442,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);
@@ -494,6 +496,9 @@ int main(int argc, char **argv)
 					endptr += 2;
 				}
 				break;
+			case 'S':
+				hmcfgusb_serial = optarg;
+				break;
 			case 'h':
 			case ':':
 			case '?':
@@ -563,7 +568,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);
@@ -608,7 +613,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) {
@@ -621,7 +626,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));
 			}
 		}
 
diff --git a/hmcfgusb.c b/hmcfgusb.c
index 652eb42..c82613f 100644
--- a/hmcfgusb.c
+++ b/hmcfgusb.c
@@ -99,7 +99,7 @@ static char * usb_strerror(int e)
 	return unknerr;
 }
 
-static libusb_device_handle *hmcfgusb_find(int vid, int pid) {
+static libusb_device_handle *hmcfgusb_find(int vid, int pid, char *serial) {
 	libusb_device_handle *devh = NULL;
 	libusb_device **list;
 	ssize_t cnt;
@@ -129,6 +129,26 @@ static libusb_device_handle *hmcfgusb_find(int vid, int pid) {
 				return NULL;
 			}
 
+			if (serial) {
+				if (desc.iSerialNumber > 0) {
+					uint8_t devSerial[256];
+					err = libusb_get_string_descriptor_ascii(devh, desc.iSerialNumber, devSerial, sizeof(devSerial));
+					if (err < 0) {
+						fprintf(stderr, "Can't read serial-number: %s\n", usb_strerror(err));
+						libusb_close(devh);
+						libusb_free_device_list(list, 1);
+						return NULL;
+					}
+					if (strcmp((char*)devSerial, (char*)serial)) {
+						libusb_close(devh);
+						continue;
+					}
+				} else {
+					libusb_close(devh);
+					continue;
+				}
+			}
+
 			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));
@@ -296,7 +316,7 @@ out:
 	}
 }
 
-struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
+struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data, char *serial)
 {
 	libusb_device_handle *devh = NULL;
 	const struct libusb_pollfd **usb_pfd = NULL;
@@ -315,11 +335,15 @@ struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data)
 	}
 	libusb_initialized = 1;
 
-	devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT);
+	devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT, serial);
 	if (!devh) {
-		devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT_BL);
+		devh = hmcfgusb_find(ID_VENDOR, ID_PRODUCT_BL, serial);
 		if (!devh) {
-			fprintf(stderr, "Can't find/open hmcfgusb!\n");
+			if (serial) {
+				fprintf(stderr, "Can't find/open HM-CFG-USB with serial %s!\n", serial);
+			} else {
+				fprintf(stderr, "Can't find/open HM-CFG-USB!\n");
+			}
 #ifdef NEED_LIBUSB_EXIT
 			hmcfgusb_exit();
 #endif
diff --git a/hmcfgusb.h b/hmcfgusb.h
index 7bfc53d..de94f23 100644
--- a/hmcfgusb.h
+++ b/hmcfgusb.h
@@ -35,7 +35,7 @@ struct hmcfgusb_dev {
 
 int hmcfgusb_send(struct hmcfgusb_dev *usbdev, unsigned char* send_data, int len, int done);
 int hmcfgusb_send_null_frame(struct hmcfgusb_dev *usbdev, int silent);
-struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data);
+struct hmcfgusb_dev *hmcfgusb_init(hmcfgusb_cb_fn cb, void *data, char *serial);
 int hmcfgusb_add_pfd(struct hmcfgusb_dev *dev, int fd, short events);
 int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout);
 void hmcfgusb_enter_bootloader(struct hmcfgusb_dev *dev);
diff --git a/hmland.c b/hmland.c
index f0b07f2..8e5d6da 100644
--- a/hmland.c
+++ b/hmland.c
@@ -65,6 +65,7 @@ static int reboot_at_minute = -1;
 static int reboot_set = 0;
 static uint8_t *lan_read_buf = NULL;
 static int lan_read_buflen = 0;
+static char *serial = NULL;
 
 struct queued_rx {
 	char *rx;
@@ -505,7 +506,7 @@ static int comm(int fd_in, int fd_out, int master_socket, int flags)
 
 	hmcfgusb_set_debug(debug);
 
-	dev = hmcfgusb_init(hmlan_format_out, &fd_out);
+	dev = hmcfgusb_init(hmlan_format_out, &fd_out, serial);
 	if (!dev) {
 		fprintf(stderr, "Can't initialize HM-CFG-USB!\n");
 		return 0;
@@ -808,6 +809,7 @@ void hmlan_syntax(char *prog)
 	fprintf(stderr, "\t-p n\t\tlisten on port n (default: 1000)\n");
 	fprintf(stderr, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u if FW < 0.967, 0 otherwise)\n", DEFAULT_REBOOT_SECONDS);
 	fprintf(stderr, "\t   hh:mm\treboot HM-CFG-USB daily at hh:mm\n");
+	fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial (for multiple hmland instances)\n");
 	fprintf(stderr, "\t-v\t\tverbose mode\n");
 	fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n");
 
@@ -822,7 +824,7 @@ int main(int argc, char **argv)
 	char *ep;
 	int opt;
 	
-	while((opt = getopt(argc, argv, "DdhIiPp:Rr:l:L:vV")) != -1) {
+	while((opt = getopt(argc, argv, "DdhIiPp:Rr:l:L:S:vV")) != -1) {
 		switch (opt) {
 			case 'D':
 				debug = 1;
@@ -880,6 +882,9 @@ int main(int argc, char **argv)
 					exit(EXIT_FAILURE);
 				}
 				break;
+			case 'S':
+				serial = optarg;
+				break;
 			case 'v':
 				verbose = 1;
 				break;
diff --git a/hmsniff.c b/hmsniff.c
index f341044..9b59e2f 100644
--- a/hmsniff.c
+++ b/hmsniff.c
@@ -214,6 +214,7 @@ 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-v\t\tverbose mode\n");
 	fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n");
 
@@ -223,16 +224,20 @@ int main(int argc, char **argv)
 {
 	struct hmcfgusb_dev *dev;
 	struct recv_data rdata;
+	char *serial = NULL;
 	int quit = 0;
 	int speed = 10;
 	uint8_t speed_buf[2];
 	int opt;
 
-	while((opt = getopt(argc, argv, "fvV")) != -1) {
+	while((opt = getopt(argc, argv, "fS:vV")) != -1) {
 		switch (opt) {
 			case 'f':
 				speed = 100;
 				break;
+			case 'S':
+				serial = optarg;
+				break;
 			case 'v':
 				verbose = 1;
 				break;
@@ -256,7 +261,7 @@ int main(int argc, char **argv)
 		memset(&rdata, 0, sizeof(rdata));
 		rdata.wrong_hmid = 0;
 
-		dev = hmcfgusb_init(parse_hmcfgusb, &rdata);
+		dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial);
 		if (!dev) {
 			fprintf(stderr, "Can't initialize HM-CFG-USB, retrying in 1s...\n");
 			sleep(1);