Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
235 lines (201 sloc) 6.11 KB
/*
usbrelay: Control USB HID connected electrical relay modules
Copyright (C) 2014 Darryl Bond
Library version
Copyright (C) 2019 Sean Mollet
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <hidapi/hidapi.h>
#include <argp.h>
#include "libusbrelay.h"
#include "usbrelay.h"
#include "gitversion.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static void argp_print_version(FILE *stream, struct argp_state *state)
{
fprintf(stream, "usbrelay %s\n", GITVERSION);
}
void (*argp_program_version_hook)(FILE *stream, struct argp_state *state) = argp_print_version;
const char *argp_program_bug_address =
"https://github.com/darrylb123/usbrelay/issues";
/* Program documentation. */
static char doc[] =
"Control or query USB HID relays."
/* This part of the documentation comes after the options */
"\vWithout ACTION, the actual state of all relays is printed to stdout.\n"
"ACTION can be one of:\n"
"RELID_N=[0|1] to switch the N-th relay off or on\n"
"RELID=NEWID to change relay ID\n"
;
/* A description of the arguments we accept. */
static char args_doc[] = "[ACTION...]";
/* The options we understand. */
static struct argp_option options[] = {
{"debug", 'd', 0, 0, "Produce debugging output" },
{"quiet", 'q', 0, 0, "Be quiet" },
{ 0 }
};
/* Used by ‘main’ to communicate with ‘parse_opt’. */
struct arguments
{
int debug;
int verbose;
};
/* Parse a single option. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
/* Get the ‘input’ argument from ‘argp_parse’, which we
know is a pointer to our arguments structure. */
struct arguments *args = state->input;
switch (key) {
case 'd':
args->debug = 1;
break;
case 'q':
args->verbose = 0;
break;
case ARGP_KEY_NO_ARGS:
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = { options, parse_opt, args_doc, doc };
int main(int argc, char *argv[])
{
struct relay *relays = 0;
int i;
int exit_code = 0;
struct arguments args = {
.debug = 0,
.verbose = 1,
};
/* Parse our arguments; every option seen by ‘parse_opt’ will
be reflected in ‘args’. */
argp_parse (&argp, argc, argv, 0, &optind, &args);
/* allocate the memory for all the relays */
if ((argc - optind) >= 1) {
relays = calloc(argc - optind + 1, sizeof(struct relay)); /* Yeah, I know. Not using the first member */
/* relays is zero-initialized */
}
/* loop through the command line and grab the relay details */
for (i = 0 ; i < (argc - optind); i++) {
char *arg = argv[i + optind];
struct relay *relay = &relays[i];
char *underscore = strchr(arg, '_');
char *equal_sign = strchr(arg, '=');
if (underscore && equal_sign && underscore > equal_sign) { /* e.g. ASDFG=QWERT_1 */
fprintf(stderr, "Invalid relay specification: %s\n",
argv[i + optind]);
exit(1);
}
size_t size;
if (underscore)
size = underscore - arg;
else if (equal_sign)
size = equal_sign - arg;
else
size = strlen(arg);
relay->this_serial = malloc(size + 1);
strncpy(relay->this_serial, arg, size);
/* Parse relay number */
if (underscore)
relay->relay_num = atoi(underscore + 1);
if (equal_sign) {
if (relay->relay_num == 0) { /* command to change the serial - remaining token is the new serial */
strncpy(relay->new_serial, equal_sign + 1,
sizeof(relay->new_serial) - 1);
} else {
if (atoi(equal_sign + 1)) {
relays[i].state = CMD_ON;
} else {
relays[i].state = CMD_OFF;
}
}
}
if (args.debug) {
fprintf(stderr, "Orig: %s, Serial: %s, Relay: %d State: %x\n",
arg, relay->this_serial,
relay->relay_num,
relay->state);
relay->found = 0;
}
}
//Locate and identify attached relay boards
if(args.debug) fprintf(stderr,"Version: %s\n",GITVERSION);
enumerate_relay_boards(getenv("USBID"), args.verbose, args.debug);
/* loop through the supplied command line and try to match the serial */
for (i = 0; i < (argc - optind); i++) {
if (args.debug ) {
fprintf(stderr, "main() arg %d Serial: %s, Relay: %d State: %x \n",
i,relays[i].this_serial,
relays[i].relay_num,
relays[i].state);
}
relay_board *board = find_board(relays[i].this_serial, args.debug );
if (board) {
if (args.debug == 2)
fprintf(stderr, "%d HID Serial: %s ", i, board->serial);
if (relays[i].relay_num == 0) {
if (!relays[i].new_serial[0]) {
fprintf(stderr, "\n \n New serial can't be empty!\n");
} else {
fprintf(stderr, "Setting new serial\n");
set_serial(board->serial,
relays[i].new_serial,args.debug);
}
} else {
if (args.debug)
fprintf(stderr,
"main() operate: %s, Relay: %d State: %x\n",
relays[i].this_serial,
relays[i].relay_num,
relays[i].state);
if (operate_relay(relays[i].this_serial, relays[i].relay_num,relays[i].state,args.debug) < 0)
exit_code++;
relays[i].found = 1;
}
}
}
shutdown();
for (i = 1; i < (argc - optind); i++) {
if (args.debug)
fprintf(stderr,"Serial: %s, Relay: %d State: %x ",
relays[i].this_serial, relays[i].relay_num,
relays[i].state);
if (relays[i].found) {
if (args.debug)
fprintf(stderr, "--- Found\n");
} else {
if (args.debug)
fprintf(stderr, "--- Not Found\n");
exit_code++;
}
}
if (relays) {
for (i = 1; i < (argc - optind) ; i++) {
free(relays[i].this_serial);
}
free(relays);
}
exit(exit_code);
}
You can’t perform that action at this time.