diff --git a/eismultiplexer.c b/eismultiplexer.c index e83aad97a03e4b6aeae97636062bf5853dba0367..1a0eec7bc59a51096b1a6db93cac7bb3c630dc65 100644 --- a/eismultiplexer.c +++ b/eismultiplexer.c @@ -42,7 +42,7 @@ static void usleep(uint64_t microseconds) nanosleep(&ts, NULL); } -int eismultiplexer_connect(struct eismultiplexer* muliplexer, int serial) +int eismultiplexer_connect(struct eismultiplexer* muliplexer, uint16_t serial) { int ret; muliplexer->priv = malloc(sizeof(*muliplexer->priv)); @@ -52,8 +52,11 @@ int eismultiplexer_connect(struct eismultiplexer* muliplexer, int serial) ret = usbshm_init(muliplexer->priv, NULL, muliplexer); if(ret) return -2; - - ret = usbshm_open(muliplexer->priv, 0xfe17, 0x07dc , NULL); + + unsigned char serialStr[5]; + snprintf((char*)serialStr, sizeof(serialStr), "%04hu", serial); + + ret = usbshm_open(muliplexer->priv, 0xfe17, 0x07dc , serial == 0 ? NULL : serialStr); if(ret) return -3; return 0; @@ -93,7 +96,7 @@ int eismultiplexer_disconnect_channel(struct eismultiplexer* muliplexer, channel channel_t eismultiplexer_get_connected(struct eismultiplexer* muliplexer) { uint8_t buffer[2] = {}; - usbshm_readControlTransferSync(muliplexer->priv, 3, buffer, 1); + usbshm_readControlTransferSync(muliplexer->priv, 3, 0, 0, buffer, 1); return buffer[0]; } @@ -108,7 +111,7 @@ int eismultiplexer_set_led(struct eismultiplexer* muliplexer, bool on) int eismultiplexer_write_eeprom(struct eismultiplexer* muliplexer, uint16_t addr, uint16_t value) { int ret; - while((ret = usbshm_writeControlTransfer(muliplexer->priv, 4, NULL, 0, value, addr)) == USBSHM_ERROR_AGAIN) + while((ret = usbshm_writeControlTransfer(muliplexer->priv, 5, NULL, 0, value, addr)) == USBSHM_ERROR_AGAIN) usleep(1000000); return ret; } @@ -116,7 +119,7 @@ int eismultiplexer_write_eeprom(struct eismultiplexer* muliplexer, uint16_t addr uint16_t eismultiplexer_read_eeprom(struct eismultiplexer* muliplexer, uint16_t addr) { uint8_t buffer[2] = {}; - usbshm_readControlTransferSync(muliplexer->priv, 5, buffer, 2); + usbshm_readControlTransferSync(muliplexer->priv, 4, 0, addr, buffer, 2); return *((uint16_t*)buffer); } diff --git a/eismultiplexer.h b/eismultiplexer.h index 81e103a243d1071ea601877fab1d07cb54d7d3a4..a6a9f7fe5703fbe55c64c50960bfee835fc60227 100644 --- a/eismultiplexer.h +++ b/eismultiplexer.h @@ -63,7 +63,7 @@ struct eismultiplexer { * @param serial The serial number of the device to connect to, or 0 for any * @return 0 on sucess and < 0 on failure */ -int eismultiplexer_connect(struct eismultiplexer* muliplexer, int serial); +int eismultiplexer_connect(struct eismultiplexer* muliplexer, uint16_t serial); /** * @brief Conects the given channel(s) to the common inputs diff --git a/main.c b/main.c index 846676dd86468f3438c6961f179ff58c4be4176c..87c2f58414c2692b0a73d618ad615a55ce9d7844 100644 --- a/main.c +++ b/main.c @@ -29,15 +29,11 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <signal.h> #include "eismultiplexer.h" +#include "options.h" -void print_help(const char* progname) -{ - printf("usage: %s [OPERATION] [CHANNEL] [VALUE]\n", progname); - printf("available operations: connect disconnect clear connect_all get help\n"); -} - -channel_t char_to_channel(char ch) +static channel_t char_to_channel(char ch) { switch(ch) { @@ -74,53 +70,73 @@ channel_t char_to_channel(char ch) } } - -void disconnect(struct eismultiplexer* multiplexer) +static int process_commands(char** commands, size_t command_count, struct eismultiplexer* multiplexer, char* name) { - eismultiplexer_set_led(multiplexer, false); - eismultiplexer_disconnect(multiplexer); -} - - -int main(int argc, char* argv[]) -{ - if(argc < 2 || strcmp(argv[1], "help") == 0) - { - print_help(argv[0]); - return 0; - } - - struct eismultiplexer multiplexer; - - if(eismultiplexer_connect(&multiplexer, 0)) + if(strcmp(commands[0], "clear") == 0) { - printf("Can not connect to EISmultiplexer device\n"); - return 1; + eismultiplexer_disconnect_channel(multiplexer, CHANNEL_NONE); } - - eismultiplexer_set_led(&multiplexer, true); - - if(strcmp(argv[1], "clear") == 0) + else if(strcmp(commands[0], "write") == 0) { - eismultiplexer_disconnect_channel(&multiplexer, CHANNEL_NONE); - } - else if(strcmp(argv[1], "write") == 0) - { - eismultiplexer_write_eeprom(&multiplexer, 0, 42); + if(command_count < 3) + { + printf("Usage %s %s [ADDRESS] [VALUE]\n", name, commands[0]); + return 2; + } + long address = strtol(commands[1], NULL, 10); + long value = strtol(commands[2], NULL, 10); + if(address > UINT16_MAX || address < 0 || value < 0 || value > UINT16_MAX) + { + puts("Value or address is out of range"); + return 2; + } + if(address % 2 == 1) + { + puts("Address must be a even number, 16 bits are written at a time"); + return 2; + } + eismultiplexer_write_eeprom(multiplexer, address, value); } - else if(strcmp(argv[1], "read") == 0) + else if(strcmp(commands[0], "read") == 0) { - uint16_t value = eismultiplexer_read_eeprom(&multiplexer, 0); - printf("0: %u\n", value); + if(command_count < 2) + { + printf("Usage %s %s [ADDRESS] [LENGTH]\n", name, commands[0]); + return 2; + } + long address = strtol(commands[1], NULL, 10); + long length = 2; + if(command_count > 2) + length = strtol(commands[2], NULL, 10); + if(address > UINT16_MAX || address < 0 || length < 0 || length > UINT16_MAX) + { + return 2; + puts("Value or address is out of range"); + } + if(address % 2 == 1) + { + puts("Address must be a even number, 16 bits are read at a time"); + return 2; + } + if(length % 2 == 1) + { + puts("Length must be a even number, 16 bits are read at a time"); + return 2; + } + + for(uint16_t i = address; i - address < length; i+=2) + { + uint16_t value = eismultiplexer_read_eeprom(multiplexer, i); + printf("%u: %u\n", i, value); + } } - else if(strcmp(argv[1], "connect_all") == 0) + else if(strcmp(commands[0], "connect_all") == 0) { - eismultiplexer_connect_channel(&multiplexer, 0xff); + eismultiplexer_connect_channel(multiplexer, 0xff); } - else if(strcmp(argv[1], "get") == 0) + else if(strcmp(commands[0], "get") == 0) { - channel_t channels = eismultiplexer_get_connected(&multiplexer); - printf("%d\n", channels); + channel_t channels = eismultiplexer_get_connected(multiplexer); for(size_t i = 0; i < 7; ++i) { bool connected = channels & (1 << i); @@ -129,41 +145,134 @@ int main(int argc, char* argv[]) } else { - if(argc != 3) + if(command_count != 2) { - printf("Usage %s %s [CHANNEL]\n", argv[0], argv[1]); - disconnect(&multiplexer); + printf("Usage %s %s [CHANNEL]\n", name, commands[0]); return 2; } - channel_t channel = char_to_channel(argv[2][0]); + channel_t channel = char_to_channel(commands[1][0]); if(channel == CHANNEL_NONE) { - printf("%c is not a valid channel\n", argv[2][0]); - disconnect(&multiplexer); + printf("%c is not a valid channel\n", commands[1][0]); return 2; } - if(strcmp(argv[1], "connect") == 0) + if(strcmp(commands[0], "connect") == 0) { - if(eismultiplexer_connect_channel(&multiplexer, channel)) + if(eismultiplexer_connect_channel(multiplexer, channel)) { - printf("could not connect channel %c\n", argv[2][0]); - disconnect(&multiplexer); + printf("could not connect channel %c\n", commands[1][0]); return 3; } } - else if(strcmp(argv[1], "disconnect") == 0) + else if(strcmp(commands[0], "disconnect") == 0) { - if(eismultiplexer_disconnect_channel(&multiplexer, channel)) + if(eismultiplexer_disconnect_channel(multiplexer, channel)) { - printf("could not disconnect channel %c\n", argv[2][0]); - disconnect(&multiplexer); + printf("could not disconnect channel %c\n", commands[1][0]); return 3; } } } - - disconnect(&multiplexer); return 0; } + +enum +{ + INPUT_SUCESS = 0, + INPUT_NO_INPUT, + INPUT_TOO_LONG +}; + +static int get_input(char *prompt, char *buffer, size_t length) +{ + int ch, extra; + + if(prompt != NULL) + { + fputs(prompt, stdout); + fflush(stdout); + } + if(fgets (buffer, length, stdin) == NULL) + return INPUT_NO_INPUT; + + if(buffer[strlen(buffer)-1] != '\n') + { + extra = 0; + while((ch = getchar()) != '\n' && ch != EOF) + extra = 1; + return (extra == 1) ? INPUT_TOO_LONG : INPUT_SUCESS; + } + + buffer[strlen(buffer)-1] = '\0'; + return INPUT_SUCESS; +} + + +int main(int argc, char* argv[]) +{ + struct config config = {}; + argp_parse(&argp, argc, argv, 0, 0, &config); + + if(config.command_count < 1 && !(config.interactive || config.pipe)) + { + printf("A command is required\n"); + return 2; + } + + struct eismultiplexer multiplexer; + if(eismultiplexer_connect(&multiplexer, config.serialSet ? config.serial : 0)) + { + char serialStr[5]; + snprintf(serialStr, sizeof(serialStr), "%04hu", config.serial); + printf("Can not connect to EISmultiplexer device%s%s\n", + config.serialSet ? " with serial " : "", config.serialSet ? serialStr : ""); + return 1; + } + + int ret = 0; + + if(config.interactive || config.pipe) + { + char buffer[256]; + while(true) + { + int ret = get_input(config.pipe ? NULL : "> ", buffer, sizeof(buffer)); + if(ret == INPUT_NO_INPUT) + { + break; + } + else if(ret != INPUT_SUCESS) + { + puts("Invalid command"); + continue; + } + + char* commands[MAX_COMMANDS]; + char* command = strtok(buffer, " \t"); + size_t i = 0; + while(command && i < MAX_COMMANDS) + { + commands[i] = command; + command = strtok(NULL, " \t"); + ++i; + } + + int cmdRet = process_commands(commands, i, &multiplexer, ""); + if(cmdRet == 0) + puts("OK"); + else + printf("ERR %i\n", cmdRet); + } + } + else + { + eismultiplexer_set_led(&multiplexer, true); + ret = process_commands(config.commands, config.command_count, &multiplexer, argv[0]); + eismultiplexer_set_led(&multiplexer, false); + } + + eismultiplexer_disconnect(&multiplexer); + return ret; +} diff --git a/usbshm.c b/usbshm.c index ae2516ec22d0aca852803b8c1a3b8aaa42e46368..81f932ce433569df66e0ffb32c3c549753d30ca2 100644 --- a/usbshm.c +++ b/usbshm.c @@ -59,7 +59,6 @@ void usbshm_distroy(struct usbshm* instance) free(instance->priv->transfer); libusb_close(instance->priv->handle); free(instance->priv->buffer); - free(instance->productName); free(instance->priv); if(--objectCounter == 0) { @@ -94,7 +93,6 @@ int usbshm_init(struct usbshm* instance, void (*dataCallback)(uint8_t request, u instance->priv->buffer = NULL; instance->vendorID = 0; instance->productID = 0; - instance->productName = NULL; instance->dataCallback = dataCallback; instance->user_data = user_data; if(objectCounter == 0) @@ -114,7 +112,7 @@ bool usbshm_ready(struct usbshm* instance) return instance->priv->transfer == NULL; } -int usbshm_open(struct usbshm* instance, int vendorID, int productID, const char* productName) +int usbshm_open(struct usbshm* instance, int vendorID, int productID, const unsigned char* serial) { instance->priv->handle = NULL; pthread_mutex_lock(libusbDataMutex); @@ -130,6 +128,21 @@ int usbshm_open(struct usbshm* instance, int vendorID, int productID, const char if(desc.idVendor == vendorID && desc.idProduct == productID) { errorCode = libusb_open(list[i], &instance->priv->handle) < 0 ? USBSHM_ERROR_ERR : 0; + if(serial) + { + size_t len = strlen((const char*)serial)+1; + unsigned char* buffer = malloc(len); + buffer[0] = '\0'; + libusb_get_string_descriptor_ascii(instance->priv->handle, desc.iSerialNumber, buffer, len); + int cmp = strcmp((const char*)serial, (const char*)buffer); + free(buffer); + if(cmp != 0) + { + libusb_close(instance->priv->handle); + instance->priv->handle = NULL; + continue; + } + } break; } } @@ -145,15 +158,6 @@ int usbshm_open(struct usbshm* instance, int vendorID, int productID, const char { instance->vendorID = vendorID; instance->productID = productID; - if(productName) - { - instance->productName = malloc(strlen(productName)+1); - strcpy(instance->productName, productName); - } - else - { - instance->productName = NULL; - } libusb_set_auto_detach_kernel_driver(instance->priv->handle, true); } else @@ -181,7 +185,7 @@ void usbshm_reset(struct usbshm* instance) void usbshm_reopen(struct usbshm* instance) { libusb_close(instance->priv->handle); - usbshm_open(instance, instance->vendorID, instance->productID, instance->productName); + usbshm_open(instance, instance->vendorID, instance->productID, NULL); } int usbshm_writeControlTransfer(struct usbshm* instance, const uint8_t request, @@ -219,7 +223,7 @@ int usbshm_writeControlTransfer(struct usbshm* instance, const uint8_t request, else return USBSHM_ERROR_AGAIN; } -int usbshm_readControlTransfer(struct usbshm* instance, const uint8_t request, const uint16_t length) +int usbshm_readControlTransfer(struct usbshm* instance, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t length) { if(!usbshm_isOpen(instance)) return USBSHM_ERROR_NOT_CONNECTED; @@ -230,7 +234,7 @@ int usbshm_readControlTransfer(struct usbshm* instance, const uint8_t request, c pthread_mutex_lock(libusbDataMutex); instance->priv->buffer = malloc(length+8); libusb_fill_control_setup(instance->priv->buffer, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, - request, request, request, length); + request, wValue, wIndex, length); instance->priv->transfer = libusb_alloc_transfer(0); libusb_fill_control_transfer(instance->priv->transfer, instance->priv->handle, instance->priv->buffer, &usbshm_transferCallBack, instance, 100); int ret = libusb_submit_transfer(instance->priv->transfer); @@ -265,8 +269,8 @@ static void usbshm_transferCallBack(struct libusb_transfer *transfer) context->priv->transfer = NULL; } -int usbshm_readControlTransferSync(struct usbshm* instance, const uint8_t request, uint8_t* buffer, const uint16_t length) +int usbshm_readControlTransferSync(struct usbshm* instance, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, uint8_t* buffer, const uint16_t length) { return libusb_control_transfer(instance->priv->handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, - request, request, request, buffer, length, 2000); + request, wValue, wIndex, buffer, length, 2000); } diff --git a/usbshm.h b/usbshm.h index add9a7ff34c4da5acfd58ea8228f43be5354a5f3..d03ad2decb928da656653b8042ed295623c9534d 100644 --- a/usbshm.h +++ b/usbshm.h @@ -45,7 +45,6 @@ struct usbshm { struct usbshm_priv* priv; int vendorID; int productID; - char* productName; void* user_data; void (*dataCallback)(uint8_t request, unsigned char* data, size_t length, void* user_data); }; @@ -56,7 +55,7 @@ int usbshm_init(struct usbshm* instance, void (*dataCallback)(uint8_t request, u bool usbshm_ready(struct usbshm* instance); -int usbshm_open(struct usbshm* instance, int vendorID, int productID, const char* productName); +int usbshm_open(struct usbshm* instance, int vendorID, int productID, const unsigned char* serial); bool usbshm_isOpen(struct usbshm* instance); @@ -68,7 +67,7 @@ int usbshm_writeControlTransfer(struct usbshm* instance, const uint8_t request, char* buffer, const uint8_t length, const uint16_t wValue, const uint16_t wIndex); -int usbshm_readControlTransfer(struct usbshm* instance, const uint8_t request, const uint16_t length); +int usbshm_readControlTransfer(struct usbshm* instance, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t length); -int usbshm_readControlTransferSync(struct usbshm* instance, const uint8_t request, uint8_t* buffer, const uint16_t length); +int usbshm_readControlTransferSync(struct usbshm* instance, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, uint8_t* buffer, const uint16_t length);