--- /dev/null
+/*
+ * Control utility for the Solid State Relay module
+ *
+ * (c) 2018 Martin Mares <mj@ucw.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <time.h>
+#include <libusb-1.0/libusb.h>
+
+typedef uint8_t byte;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+struct libusb_context *usb_ctxt;
+struct libusb_device_handle *devh;
+
+static void __attribute__((noreturn)) die(char *msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static inline u32 get_u32_be(const void *p)
+{
+ const byte *c = (const byte *)p;
+ return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
+}
+
+static inline void put_u32_be(void *p, u32 x)
+{
+ byte *c = (byte *)p;
+ c[0] = x >> 24;
+ c[1] = x >> 16;
+ c[2] = x >> 8;
+ c[3] = x;
+}
+
+void open_device(void)
+{
+ int err;
+ libusb_device **devlist;
+ ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist);
+ if (devn < 0)
+ die("Cannot enumerate USB devices: error %d", (int) devn);
+
+ for (ssize_t i=0; i<devn; i++) {
+ struct libusb_device_descriptor desc;
+ libusb_device *dev = devlist[i];
+ if (!libusb_get_device_descriptor(dev, &desc)) {
+ if (desc.idVendor == 0x4242 && desc.idProduct == 0x0002) {
+ printf("Found device at usb%d.%d\n", libusb_get_bus_number(dev), libusb_get_device_address(dev));
+
+ if (err = libusb_open(dev, &devh))
+ die("Cannot open device: error %d", err);
+ libusb_reset_device(devh);
+ if (err = libusb_claim_interface(devh, 0))
+ die("Cannot claim interface: error %d", err);
+
+ libusb_free_device_list(devlist, 1);
+ return;
+ }
+ }
+ }
+
+ libusb_free_device_list(devlist, 1);
+ die("Device not found");
+}
+
+static byte req[64], resp[64];
+
+static int transaction(uint req_len, uint resp_len)
+{
+ int err, transferred;
+ if (err = libusb_bulk_transfer(devh, 0x01, req, req_len, &transferred, 2000))
+ die("Transfer failed: error %d\n", err);
+ // printf("Transferred %d bytes\n", transferred);
+
+ int received;
+ if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000))
+ die("Receive failed: error %d\n", err);
+ // printf("Received %d bytes\n", received);
+
+ if ((uint) received < resp_len)
+ die("Received short packet (%u out of %u bytes)", received, resp_len);
+
+ if (received >= 4) {
+ uint status = get_u32_be(resp);
+ if (status)
+ die("Received error status %08x", status);
+ }
+
+ return received;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: ssr-control [-t] [-s <mask>]\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int get_temp = 0;
+ int set_relays = -1;
+
+ int opt;
+ while ((opt = getopt(argc, argv, "ts:")) >= 0) {
+ switch (opt) {
+ case 't':
+ get_temp = 1;
+ break;
+ case 's':
+ set_relays = atoi(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+ if (optind < argc)
+ usage();
+
+ int err;
+ if (err = libusb_init(&usb_ctxt))
+ die("Cannot initialize libusb: error %d", err);
+ libusb_set_debug(usb_ctxt, 3);
+ open_device();
+
+ if (get_temp) {
+ put_u32_be(req, 2);
+ transaction(8, 8);
+ int t = get_u32_be(resp+4);
+ printf("Temp: %d\n", t);
+ }
+
+ if (set_relays >= 0) {
+ put_u32_be(req, 1);
+ put_u32_be(req+4, set_relays);
+ transaction(8, 4);
+ }
+
+ return 0;
+}