From e98ea2bfdb0dab5fa5b35c0da966eae7f50a6563 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 6 Sep 2011 04:21:36 -0300 Subject: [PATCH] labsw/tool/: basic labsw control utility --- labsw/tool/Makefile | 21 +++++++ labsw/tool/README | 42 +++++++++++++ labsw/tool/labsw.c | 142 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 labsw/tool/Makefile create mode 100644 labsw/tool/README create mode 100644 labsw/tool/labsw.c diff --git a/labsw/tool/Makefile b/labsw/tool/Makefile new file mode 100644 index 0000000..629b9f1 --- /dev/null +++ b/labsw/tool/Makefile @@ -0,0 +1,21 @@ +# +# tool/Makefile - Build the LABSW control tool +# +# Written 2011 by Werner Almesberger +# Copyright 2011 Werner Almesberger +# +# 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. +# + + +F32XBASE = ../../../f32xbase + +MAIN = labsw +OBJS += $(F32XBASE)/lib/usb.o + +include $(F32XBASE)/lib/Makefile.common + +CFLAGS += -I$(F32XBASE)/include -I../fw/include -I../include diff --git a/labsw/tool/README b/labsw/tool/README new file mode 100644 index 0000000..9b02f8b --- /dev/null +++ b/labsw/tool/README @@ -0,0 +1,42 @@ +Lab Switch control utility +-------------------------- + +If invoked without arguments, labsw prints the firmware version and +build date. + +The following commands can be given on the command line: + +ch1=0, ch1=1, ch2=0, ch2=1 + turn the respective channel on or off. Both relay and + opto-coupler are switched. Also enters remote mode. + +query + read the buttons and opto-coupler inputs (rear panel) + +local + exit remote mode + +The Lab Switch starts in local mode, where the CH1/CH2 buttons +toggle the respective channel. The main button turns off both +channels. Local mode is indicated by a green main LED. + +If a channel is set via USB, the Lab Switch enters remote mode, +indicated by a red main LED. In remote mode, the channel buttons +are ignored. Pressing the main button exits remote mode and +turns both channels off. + +The lab switch utility currently lacks the following features: +- access to the rear opto-coupler outputs, +- switching CH1/CH2 relay and opto-coupler independently, +- direct control of LEDs. + +Examples: + +# labsw ch1=1 + +Turns channel 1 on and enters remote mode. + +# labsw ch1=0 ch2=0 local + +Turns channels 1 and 2 off and exits remote mode. This is +equivalent to pressing the main button. diff --git a/labsw/tool/labsw.c b/labsw/tool/labsw.c new file mode 100644 index 0000000..9ba0687 --- /dev/null +++ b/labsw/tool/labsw.c @@ -0,0 +1,142 @@ +/* + * tool/labsw.c - LABSW control tool + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * 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. + */ + + +#include +#include +#include +#include + +#include "f32xbase/usb.h" +#include "labsw/ep0.h" +#include "labsw/usb-id.h" + + +#define FROM_DEV LABSW_FROM_DEV(0) +#define TO_DEV LABSW_TO_DEV(0) + +#define BUF_SIZE 256 + + +static void identify_labsw(usb_dev_handle *dev) +{ + const struct usb_device *device = usb_device(dev); + uint8_t ids[3]; + char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ + int res; + + printf("%04x:%04x ", + device->descriptor.idVendor, device->descriptor.idProduct); + + res = usb_control_msg(dev, FROM_DEV, LABSW_ID, 0, 0, + (char *) ids, sizeof(ids), 1000); + if (res < 0) { + fprintf(stderr, "LABSW_ID: %s\n", usb_strerror()); + exit(1); + } + + printf("protocol %u.%u hw %u\n", ids[0], ids[1], ids[2]); + + res = usb_control_msg(dev, FROM_DEV, LABSW_BUILD, 0, 0, + buf, sizeof(buf), 1000); + if (res < 0) { + fprintf(stderr, "LABSW_BUILD: %s\n", usb_strerror()); + exit(1); + } + buf[res] = 0; + printf("%10s%s\n", "", buf); +} + + +static void set(usb_dev_handle *dev, uint16_t value, uint16_t mask) +{ + int res; + + res = usb_control_msg(dev, TO_DEV, LABSW_SET, value, mask, + NULL, 0, 1000); + if (res < 0) { + fprintf(stderr, "LABSW_SET: %s\n", usb_strerror()); + exit(1); + } +} + + +#define ON_BITS(ch) \ + (LABSW_CH##ch##_RELAY | LABSW_CH##ch##_OPT | LABSW_CH##ch##_R) +#define OFF_BITS(ch) LABSW_CH##ch##_G +#define CHAN_MASK(ch) (ON_BITS(ch) | OFF_BITS(ch)) +#define REMOTE_BITS LABSW_MAIN_R +#define REMOTE_MASK (LABSW_MAIN_R | LABSW_MAIN_G) + + +#define SET_CHAN(ch, on) \ + set(dev, (on ? ON_BITS(ch) : OFF_BITS(ch)) | REMOTE_BITS, \ + CHAN_MASK(ch) | REMOTE_MASK) + + +static void query(usb_dev_handle *dev) +{ + uint8_t buf[2]; + int res; + + res = usb_control_msg(dev, FROM_DEV, LABSW_GET, 0, 0, + (char *) buf, sizeof(buf), 1000); + if (res < 0) { + fprintf(stderr, "LABSW_GET: %s\n", usb_strerror()); + exit(1); + } + if (res != 2) { + fprintf(stderr, "LABSW_GET: expected %u, got %d\n", + (unsigned) sizeof(buf), res); + exit(1); + } + printf("%u %u\n", buf[0], buf[1]); +} + + +int main(int argc, char **argv) +{ + usb_dev_handle *dev; + int i; + + dev = open_usb(USB_VENDOR, USB_PRODUCT); + if (!dev) { + fprintf(stderr, ":-(\n"); + return 1; + } + + if (argc == 1) { + identify_labsw(dev); + return 0; + } + + for (i = 1; i != argc; i++) { + if (!strcmp(argv[i], "ch1=0")) + SET_CHAN(1, 0); + else if (!strcmp(argv[i], "ch1=1")) + SET_CHAN(1, 1); + else if (!strcmp(argv[i], "ch2=0")) + SET_CHAN(2, 0); + else if (!strcmp(argv[i], "ch2=1")) + SET_CHAN(2, 1); + else if (!strcmp(argv[i], "query")) + query(dev); + else if (!strcmp(argv[i], "local")) + set(dev, 0, 0); + else { + fprintf(stderr, "unrecognized command \"%s\"\n", + argv[i]); + exit(1); + } + } + return 0; +}