]> mj.ucw.cz Git - arexx.git/blobdiff - arexxd.c
Clear all librrd errors by calling rrd_clear_error()
[arexx.git] / arexxd.c
index 80d37556f032e4b66d7cad5d62e1a6661a4f0c1a..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 ***/
@@ -168,6 +172,9 @@ static double correct_point(int id, double val, const char **name)
                case 10415:
                        *name = "ursarium";
                        return val - 0.93;
+               case 10707:
+                       *name = "balcony";
+                       return val - 0.71;
                case 19246:
                        *name = "catarium";
                        return val + 0.49;
@@ -175,7 +182,7 @@ static double correct_point(int id, double val, const char **name)
                        *name = "catarium-rh";
                        return val;
                case 12133:
-                       *name = "balcony";
+                       *name = "outside";
                        return val + 0.44;
                default:
                        return val;
@@ -296,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;
@@ -311,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);
@@ -334,6 +393,8 @@ failed:
 
 static void release_device(void)
 {
+       libusb_release_interface(devh, 0);
+       libusb_reset_device(devh);
        libusb_close(devh);
        devh = NULL;
 }
@@ -362,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;
@@ -375,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;
@@ -483,6 +544,7 @@ static void set_clock(void)
 
 /*** Main ***/
 
+static sigset_t term_sigs;
 static volatile sig_atomic_t want_shutdown;
 
 static void sigterm_handler(int sig __attribute__((unused)))
@@ -490,6 +552,14 @@ static void sigterm_handler(int sig __attribute__((unused)))
        want_shutdown = 1;
 }
 
+static void interruptible_msleep(int ms)
+{
+       sigprocmask(SIG_UNBLOCK, &term_sigs, NULL);
+       struct timespec ts = { .tv_sec = ms/1000, .tv_nsec = (ms%1000) * 1000000 };
+       nanosleep(&ts, NULL);
+       sigprocmask(SIG_BLOCK, &term_sigs, NULL);
+}
+
 static const struct option long_options[] = {
        { "debug",              0, NULL, 'd' },
        { "log-dir",            1, NULL, 'l' },
@@ -508,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);
 }
@@ -515,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++;
@@ -529,6 +600,9 @@ int main(int argc, char **argv)
                        case 'r':
                                debug_raw_data++;
                                break;
+                       case 'u':
+                               debug_usb++;
+                               break;
                        default:
                                usage();
                }
@@ -538,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)
@@ -563,7 +638,6 @@ int main(int argc, char **argv)
        sigaction(SIGTERM, &sa, NULL);
        sigaction(SIGINT, &sa, NULL);
 
-       sigset_t term_sigs;
        sigemptyset(&term_sigs);
        sigaddset(&term_sigs, SIGTERM);
        sigaddset(&term_sigs, SIGINT);
@@ -576,7 +650,7 @@ int main(int argc, char **argv)
                                inited = 1;
                                log_error("Data logger not connected, waiting until it appears");
                        }
-                       sleep(30);
+                       interruptible_msleep(30000);
                        continue;
                }
                log_info("Listening");
@@ -608,17 +682,17 @@ int main(int argc, char **argv)
                        want_sleep = 1;
                        if (err > 0 && parse_packet(reply))
                                want_sleep = 0;
-                       sigprocmask(SIG_UNBLOCK, &term_sigs, NULL);
                        if (want_sleep) {
-                               sleep(4);
+                               interruptible_msleep(4000);
                                want_stats = 1;
-                       }
-                       sigprocmask(SIG_BLOCK, &term_sigs, NULL);
+                       } else
+                               interruptible_msleep(5);
                }
 
                log_info("Disconnecting data logger");
                release_device();
                inited = 0;
+               interruptible_msleep(10000);
        }
 
        log_info("Terminated");