add the ability to select a specific device via serial number
add a interactive mode add a batch mode
This commit is contained in:
parent
e43ef91f85
commit
c7603f54c4
|
@ -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));
|
||||
|
@ -53,7 +53,10 @@ int eismultiplexer_connect(struct eismultiplexer* muliplexer, int serial)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
233
main.c
233
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)
|
||||
if(strcmp(commands[0], "clear") == 0)
|
||||
{
|
||||
print_help(argv[0]);
|
||||
return 0;
|
||||
eismultiplexer_disconnect_channel(multiplexer, CHANNEL_NONE);
|
||||
}
|
||||
else if(strcmp(commands[0], "write") == 0)
|
||||
{
|
||||
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(commands[0], "read") == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
struct eismultiplexer multiplexer;
|
||||
|
||||
if(eismultiplexer_connect(&multiplexer, 0))
|
||||
{
|
||||
printf("Can not connect to EISmultiplexer device\n");
|
||||
return 1;
|
||||
for(uint16_t i = address; i - address < length; i+=2)
|
||||
{
|
||||
uint16_t value = eismultiplexer_read_eeprom(multiplexer, i);
|
||||
printf("%u: %u\n", i, value);
|
||||
}
|
||||
}
|
||||
|
||||
eismultiplexer_set_led(&multiplexer, true);
|
||||
|
||||
if(strcmp(argv[1], "clear") == 0)
|
||||
else if(strcmp(commands[0], "connect_all") == 0)
|
||||
{
|
||||
eismultiplexer_disconnect_channel(&multiplexer, CHANNEL_NONE);
|
||||
eismultiplexer_connect_channel(multiplexer, 0xff);
|
||||
}
|
||||
else if(strcmp(argv[1], "write") == 0)
|
||||
else if(strcmp(commands[0], "get") == 0)
|
||||
{
|
||||
eismultiplexer_write_eeprom(&multiplexer, 0, 42);
|
||||
}
|
||||
else if(strcmp(argv[1], "read") == 0)
|
||||
{
|
||||
uint16_t value = eismultiplexer_read_eeprom(&multiplexer, 0);
|
||||
printf("0: %u\n", value);
|
||||
}
|
||||
else if(strcmp(argv[1], "connect_all") == 0)
|
||||
{
|
||||
eismultiplexer_connect_channel(&multiplexer, 0xff);
|
||||
}
|
||||
else if(strcmp(argv[1], "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;
|
||||
}
|
||||
|
|
38
usbshm.c
38
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);
|
||||
}
|
||||
|
|
7
usbshm.h
7
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue