]> mj.ucw.cz Git - arexx.git/blobdiff - arexxd.c
Clear all librrd errors by calling rrd_clear_error()
[arexx.git] / arexxd.c
index 3baaefd669ca9b168eff4dbedc82018c297204de..0358db145ba9d1d36953c9123f7f71c61918a486 100644 (file)
--- a/arexxd.c
+++ b/arexxd.c
@@ -29,6 +29,7 @@ static int use_syslog;
 static int debug_mode;
 static int debug_packets;
 static int debug_raw_data;
+static int debug_usb;
 static char *log_dir = DEFAULT_LOG_DIR;
 
 static void die(char *fmt, ...)
@@ -140,6 +141,7 @@ static void rrd_point(time_t t, const char *name, double val, char *unit)
                rrd_create(arg_cnt, arg_ptr);
                if (rrd_test_error()) {
                        log_error("rrd_create on %s failed: %s", rr_name, rrd_get_error());
+                       rrd_clear_error();
                        return;
                }
        }
@@ -148,8 +150,10 @@ static void rrd_point(time_t t, const char *name, double val, char *unit)
        arg_push(rr_name);
        arg_push("%d:%f", t, val);
        rrd_update(arg_cnt, arg_ptr);
-       if (rrd_test_error())
+       if (rrd_test_error()) {
                log_error("rrd_update on %s failed: %s", rr_name, rrd_get_error());
+               rrd_clear_error();
+       }
 }
 
 /*** Transforms ***/
@@ -299,6 +303,56 @@ static void raw_point(int t, int id, int raw, int q)
 
 /*** USB interface ***/
 
+static int rx_endpoint, tx_endpoint;
+
+static int parse_descriptors(libusb_device *dev)
+{
+       int err;
+       struct libusb_config_descriptor *desc;
+
+       if (err = libusb_get_active_config_descriptor(dev, &desc)) {
+               log_error("libusb_get_config_descriptor failed: error %d", err);
+               return 0;
+       }
+       if (desc->bNumInterfaces != 1) {
+               log_error("Unexpected number of interfaces: %d", desc->bNumInterfaces);
+               goto failed;
+       }
+
+       const struct libusb_interface *iface = &desc->interface[0];
+       if (iface->num_altsetting != 1) {
+               log_error("Unexpected number of alternate interface settings: %d", iface->num_altsetting);
+               goto failed;
+       }
+
+       const struct libusb_interface_descriptor *ifd = &iface->altsetting[0];
+       if (ifd->bNumEndpoints != 2) {
+               log_error("Unexpected number of endpoints: %d", ifd->bNumEndpoints);
+               goto failed;
+       }
+
+       rx_endpoint = tx_endpoint = -1;
+       for (int i=0; i<2; i++) {
+               const struct libusb_endpoint_descriptor *epd = &ifd->endpoint[i];
+               if (epd->bEndpointAddress & 0x80)
+                       rx_endpoint = epd->bEndpointAddress;
+               else
+                       tx_endpoint = epd->bEndpointAddress;
+       }
+       if (rx_endpoint < 0 || tx_endpoint < 0) {
+               log_error("Failed to identify endpoints");
+               goto failed;
+       }
+
+       log_pkt("Found endpoints: rx==%02x tx=%02x\n", rx_endpoint, tx_endpoint);
+       libusb_free_config_descriptor(desc);
+       return 1;
+
+failed:
+       libusb_free_config_descriptor(desc);
+       return 0;
+}
+
 static int find_device(void)
 {
        libusb_device **devlist;
@@ -314,6 +368,8 @@ static int find_device(void)
                if (!libusb_get_device_descriptor(dev, &desc)) {
                        if (desc.idVendor == 0x0451 && desc.idProduct == 0x3211) {
                                log_info("Arexx data logger found at usb%d.%d", libusb_get_bus_number(dev), libusb_get_device_address(dev));
+                               if (!parse_descriptors(dev))
+                                       continue;
                                int err;
                                if (err = libusb_open(dev, &devh)) {
                                        log_error("libusb_open() failed: error %d", err);
@@ -337,6 +393,8 @@ failed:
 
 static void release_device(void)
 {
+       libusb_release_interface(devh, 0);
+       libusb_reset_device(devh);
        libusb_close(devh);
        devh = NULL;
 }
@@ -365,7 +423,7 @@ static int send_and_receive(byte *req, byte *reply)
        }
 
        int err, transferred;
-       if (err = libusb_bulk_transfer(devh, 0x01, req, 64, &transferred, 200)) {
+       if (err = libusb_bulk_transfer(devh, tx_endpoint, req, 64, &transferred, 200)) {
                if (err == LIBUSB_ERROR_TIMEOUT) {
                        log_pkt(">> xmit timed out\n");
                        return 0;
@@ -378,7 +436,7 @@ static int send_and_receive(byte *req, byte *reply)
                log_pkt(">> xmit %d bytes\n", transferred);
                dump_packet(req);
        }
-       if (err = libusb_bulk_transfer(devh, 0x81, reply, 64, &transferred, 200)) {
+       if (err = libusb_bulk_transfer(devh, rx_endpoint, reply, 64, &transferred, 200)) {
                if (err == LIBUSB_ERROR_TIMEOUT) {
                        log_pkt("<< recv timed out\n");
                        return 0;
@@ -494,10 +552,11 @@ static void sigterm_handler(int sig __attribute__((unused)))
        want_shutdown = 1;
 }
 
-static void interruptible_sleep(int seconds)
+static void interruptible_msleep(int ms)
 {
        sigprocmask(SIG_UNBLOCK, &term_sigs, NULL);
-       sleep(seconds);
+       struct timespec ts = { .tv_sec = ms/1000, .tv_nsec = (ms%1000) * 1000000 };
+       nanosleep(&ts, NULL);
        sigprocmask(SIG_BLOCK, &term_sigs, NULL);
 }
 
@@ -519,6 +578,7 @@ Options:\n\
 -l, --log-dir=<dir>    Directory where all received data should be stored\n\
 -p, --debug-packets    Log all packets sent and received\n\
 -r, --debug-raw                Log conversion from raw values\n\
+-u, --debug-usb                Enable libusb debug messages (to stdout/stderr)\n\
 ");
        exit(1);
 }
@@ -526,7 +586,7 @@ Options:\n\
 int main(int argc, char **argv)
 {
        int opt;
-       while ((opt = getopt_long(argc, argv, "dl:pr", long_options, NULL)) >= 0)
+       while ((opt = getopt_long(argc, argv, "dl:pru", long_options, NULL)) >= 0)
                switch (opt) {
                        case 'd':
                                debug_mode++;
@@ -540,6 +600,9 @@ int main(int argc, char **argv)
                        case 'r':
                                debug_raw_data++;
                                break;
+                       case 'u':
+                               debug_usb++;
+                               break;
                        default:
                                usage();
                }
@@ -549,7 +612,8 @@ int main(int argc, char **argv)
        int err;
        if (err = libusb_init(&usb_ctxt))
                die("Cannot initialize libusb: error %d", err);
-       // libusb_set_debug(usb_ctxt, 3);
+       if (debug_usb)
+               libusb_set_debug(usb_ctxt, 3);
 
        if (!debug_mode) {
                if (chdir(log_dir) < 0)
@@ -586,7 +650,7 @@ int main(int argc, char **argv)
                                inited = 1;
                                log_error("Data logger not connected, waiting until it appears");
                        }
-                       interruptible_sleep(30);
+                       interruptible_msleep(30000);
                        continue;
                }
                log_info("Listening");
@@ -619,15 +683,16 @@ int main(int argc, char **argv)
                        if (err > 0 && parse_packet(reply))
                                want_sleep = 0;
                        if (want_sleep) {
-                               interruptible_sleep(4);
+                               interruptible_msleep(4000);
                                want_stats = 1;
-                       }
+                       } else
+                               interruptible_msleep(5);
                }
 
                log_info("Disconnecting data logger");
                release_device();
                inited = 0;
-               interruptible_sleep(10);
+               interruptible_msleep(10000);
        }
 
        log_info("Terminated");