X-Git-Url: https://git.ao2.it/visomat-utils.git/blobdiff_plain/91d0c4148bdb1fca33062b80b669e3c9e00c8030..6d26d073abb2eed23a21d87058b8d6eb0e8d2112:/src/visomat-data-downloader.c diff --git a/src/visomat-data-downloader.c b/src/visomat-data-downloader.c index a91ee43..c2b8590 100644 --- a/src/visomat-data-downloader.c +++ b/src/visomat-data-downloader.c @@ -21,19 +21,21 @@ #include #include +#include #include #include #include +#define VISOMAT_DEVICE_VID 0x1247 +#define VISOMAT_DEVICE_PID 0x00f8 +#define VISOMAT_CONFIGURATION 1 +#define VISOMAT_INTERFACE 1 +#define VISOMAT_EP_IN 0x82 +#define VISOMAT_EP_OUT 0x03 + #define STX 0x02 #define ETX 0x03 -#define DEVICE_VID 0x1247 -#define DEVICE_PID 0x00f8 - -#define EP_IN 0x82 -#define EP_OUT 0x03 - #define BASE_YEAR 2000 typedef enum { @@ -117,7 +119,7 @@ static void print_record_csv_compat(struct datetime *d, struct pressure *p) printf("\n"); } -/* TODO separate better decoding data from printing it */ +/* TODO: it would be better to separate decoding data from printing it */ static int decode_eeprom(unsigned char *buffer, unsigned int len, unsigned int user_mask) @@ -224,7 +226,7 @@ static int send_command(libusb_device_handle *dev, visomat_command cmd) request[4] = ETX; transferred = 0; - ret = libusb_bulk_transfer(dev, EP_OUT, request, sizeof(request), &transferred, 0); + ret = libusb_bulk_transfer(dev, VISOMAT_EP_OUT, request, sizeof(request), &transferred, 0); if (ret != 0 || transferred != sizeof(request)) { fprintf(stderr, "Error: sending request: %d (%s)\ttransferred: %d (expected %zu)\n", ret, libusb_error_name(ret), transferred, sizeof(request)); @@ -247,7 +249,7 @@ static int get_response(libusb_device_handle *dev, unsigned int j; transferred = 0; - ret = libusb_bulk_transfer(dev, EP_IN, response, sizeof(response), &transferred, 5000); + ret = libusb_bulk_transfer(dev, VISOMAT_EP_IN, response, sizeof(response), &transferred, 5000); if (ret != 0) { fprintf(stderr, "Error getting response: %d (%s)\ttransferred: %d (expected %zu)\n", ret, libusb_error_name(ret), transferred, sizeof(response)); @@ -315,30 +317,89 @@ int main(void) { int ret; libusb_device_handle *dev; + int current_configuration; + + ret = libusb_init(NULL); + if (ret < 0) { + fprintf(stderr, "libusb_init failed: %s\n", + libusb_error_name(ret)); + goto out; + } - libusb_init(NULL); libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO); - dev = libusb_open_device_with_vid_pid(NULL, DEVICE_VID, DEVICE_PID); + dev = libusb_open_device_with_vid_pid(NULL, + VISOMAT_DEVICE_VID, + VISOMAT_DEVICE_PID); if (dev == NULL) { - fprintf(stderr, "Couldn't open device.\n"); - ret = -ENODEV; + fprintf(stderr, "libusb_open failed: %s\n", strerror(errno)); + ret = -errno; goto out_libusb_exit; } - libusb_set_configuration(dev, 1); - libusb_detach_kernel_driver(dev, 1); - libusb_claim_interface(dev, 1); + current_configuration = -1; + ret = libusb_get_configuration(dev, ¤t_configuration); + if (ret < 0) { + fprintf(stderr, "libusb_get_configuration failed: %s\n", + libusb_error_name(ret)); + goto out_libusb_close; + } + + if (current_configuration != VISOMAT_CONFIGURATION) { + ret = libusb_set_configuration(dev, VISOMAT_CONFIGURATION); + if (ret < 0) { + fprintf(stderr, "libusb_set_configuration failed: %s\n", + libusb_error_name(ret)); + fprintf(stderr, "Cannot set configuration %hhu\n", + VISOMAT_CONFIGURATION); + goto out_libusb_close; + } + } + + libusb_set_auto_detach_kernel_driver(dev, 1); + + ret = libusb_claim_interface(dev, VISOMAT_INTERFACE); + if (ret < 0) { + fprintf(stderr, "libusb_claim_interface failed: %s\n", + libusb_error_name(ret)); + fprintf(stderr, "Cannot claim interface %hhu\n", + VISOMAT_INTERFACE); + goto out_libusb_close; + } + + /* Checking that the configuration has not changed, as suggested in + * http://libusb.sourceforge.net/api-1.0/caveats.html + */ + current_configuration = -1; + ret = libusb_get_configuration(dev, ¤t_configuration); + if (ret < 0) { + fprintf(stderr, "libusb_get_configuration after claim failed: %s\n", + libusb_error_name(ret)); + goto out_libusb_release_interface; + } + + if (current_configuration != VISOMAT_CONFIGURATION) { + fprintf(stderr, "libusb configuration changed (expected: %hhu, current: %hhu\n", + VISOMAT_CONFIGURATION, current_configuration); + ret = -EINVAL; + goto out_libusb_release_interface; + } ret = visomat_get_datetime(dev); if (ret < 0) - goto out; + goto out_libusb_release_interface; ret = visomat_dump_eeprom(dev, 0x01 | 0x02); + if (ret < 0) + goto out_libusb_release_interface; -out: +out_libusb_release_interface: + libusb_release_interface(dev, VISOMAT_INTERFACE); +out_libusb_close: libusb_close(dev); + dev = NULL; out_libusb_exit: libusb_exit(NULL); +out: return ret; }