X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsigrok.c;h=7e2fa6c1b29ca2990dd5362d4164b69db67bc1df;hb=4058f2aec4638dc5cbfeb67fa683cd9cf1631ef2;hp=6df85394a90dabb76293f1bc8157260ae2cd019b;hpb=31ee0e5282b59f89ac5c9bcaebb993450e45dba1;p=collectd.git diff --git a/src/sigrok.c b/src/sigrok.c index 6df85394..7e2fa6c1 100644 --- a/src/sigrok.c +++ b/src/sigrok.c @@ -36,7 +36,6 @@ static pthread_t sr_thread; static int sr_thread_running = FALSE; GSList *config_devices; -static struct sr_session *session = NULL; static int num_devices; static int loglevel = SR_LOG_WARN; static struct sr_context *sr_ctx; @@ -52,8 +51,8 @@ struct config_device { }; -static int cd_logger(void *cb_data, int msg_loglevel, const char *format, - va_list args) +static int sigrok_log_callback(void*cb_data __attribute__((unused)), + int msg_loglevel, const char *format, va_list args) { char s[512]; @@ -67,41 +66,38 @@ static int cd_logger(void *cb_data, int msg_loglevel, const char *format, static int sigrok_config_device(oconfig_item_t *ci) { - oconfig_item_t *item; struct config_device *cfdev; - int ret, i; - - if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) { - ERROR("Invalid device name."); - return 1; - } + int i; if (!(cfdev = malloc(sizeof(struct config_device)))) { ERROR("malloc() failed."); - return 1; + return -1; + } + memset(cfdev, 0, sizeof(*cfdev)); + if (cf_util_get_string(ci, &cfdev->name)) { + free(cfdev); + WARNING("Invalid device name."); + return -1; } - memset(cfdev, 0, sizeof(struct config_device)); - cf_util_get_string(ci, &cfdev->name); cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL; for (i = 0; i < ci->children_num; i++) { - item = ci->children + i; + oconfig_item_t *item = ci->children + i; if (item->values_num != 1) { - ERROR("Missing value for '%s'.", item->key); - return 1; + free(cfdev); + WARNING("Missing value for '%s'.", item->key); + return -1; } if (!strcasecmp(item->key, "driver")) - ret = cf_util_get_string(item, &cfdev->driver); + cf_util_get_string(item, &cfdev->driver); else if (!strcasecmp(item->key, "conn")) - ret = cf_util_get_string(item, &cfdev->conn); + cf_util_get_string(item, &cfdev->conn); else if (!strcasecmp(item->key, "serialcomm")) - ret = cf_util_get_string(item, &cfdev->serialcomm); + cf_util_get_string(item, &cfdev->serialcomm); else if (!strcasecmp(item->key, "interval")) - ret = cf_util_get_cdtime(item, &cfdev->min_dispatch_interval); - if (ret) { - ERROR("Invalid keyword '%s'.", item->key); - return 1; - } + cf_util_get_cdtime(item, &cfdev->min_dispatch_interval); + else + WARNING("Invalid keyword '%s'.", item->key); } config_devices = g_slist_append(config_devices, cfdev); @@ -111,33 +107,45 @@ static int sigrok_config_device(oconfig_item_t *ci) static int sigrok_config(oconfig_item_t *ci) { - oconfig_item_t *item; int tmp, i; for (i = 0; i < ci->children_num; i++) { - item = ci->children + i; + oconfig_item_t *item = ci->children + i; if (!strcasecmp(item->key, "loglevel")) { if (cf_util_get_int(item, &tmp) || tmp < 0 || tmp > 5) { ERROR("Invalid loglevel"); - return 1; + continue; } loglevel = tmp; - } else if (!strcasecmp(item->key, "Device")) { - if (sigrok_config_device(item) != 0) - return 1; - } else { - ERROR("Invalid keyword '%s'.", item->key); - return 1; - } + } else if (!strcasecmp(item->key, "Device")) + sigrok_config_device(item); + else + WARNING("Invalid keyword '%s'.", item->key); } return 0; } -static void free_drvopts(struct sr_config *src) +static char *sigrok_value_type(const struct sr_datafeed_analog *analog) { - g_variant_unref(src->data); - g_free(src); + char *s; + + if (analog->mq == SR_MQ_VOLTAGE) + s = "voltage"; + else if (analog->mq == SR_MQ_CURRENT) + s = "current"; + else if (analog->mq == SR_MQ_FREQUENCY) + s = "frequency"; + else if (analog->mq == SR_MQ_POWER) + s = "power"; + else if (analog->mq == SR_MQ_TEMPERATURE) + s = "temperature"; + else if (analog->mq == SR_MQ_RELATIVE_HUMIDITY) + s = "humidity"; + else + s = "gauge"; + + return s; } static void sigrok_feed_callback(const struct sr_dev_inst *sdi, @@ -146,15 +154,8 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi, const struct sr_datafeed_analog *analog; struct config_device *cfdev; GSList *l; - value_t *values; + value_t value; value_list_t vl = VALUE_LIST_INIT; - int num_probes, s, p; - - if (packet->type == SR_DF_END) { - /* TODO: try to restart acquisition after a delay? */ - INFO("oops! ended"); - return; - } /* Find this device's configuration. */ cfdev = NULL; @@ -171,47 +172,104 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi, return; } - if (packet->type == SR_DF_ANALOG) { - if (cdtime() - cfdev->last_dispatch < cfdev->min_dispatch_interval) - return; + if (packet->type == SR_DF_END) { + /* TODO: try to restart acquisition after a delay? */ + WARNING("sigrok: acquisition for '%s' ended.", cfdev->name); + return; + } - analog = packet->payload; - num_probes = g_slist_length(analog->probes); - if (!(values = malloc(sizeof(value_t) * num_probes))) { - ERROR("malloc() failed."); - return; - } - for (s = 0; s < analog->num_samples; s++) { - for (p = 0; p < num_probes; p++) { - values[s + p].gauge = analog->data[s + p]; - } - } - vl.values = values; - vl.values_len = num_probes; - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); - sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin)); - ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), - "%s", cfdev->name); - sstrncpy(vl.type, "gauge", sizeof(vl.type)); - plugin_dispatch_values(&vl); - - cfdev->last_dispatch = cdtime(); + if (packet->type != SR_DF_ANALOG) + return; + + if (cdtime() - cfdev->last_dispatch < cfdev->min_dispatch_interval) + return; + + /* Ignore all but the first sample on the first probe. */ + analog = packet->payload; + value.gauge = analog->data[0]; + vl.values = &value; + vl.values_len = 1; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin)); + ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), + "%s", cfdev->name); + sstrncpy(vl.type, sigrok_value_type(analog), sizeof(vl.type)); + plugin_dispatch_values(&vl); + + cfdev->last_dispatch = cdtime(); + +} + +static void free_drvopts(struct sr_config *src) +{ + g_variant_unref(src->data); + g_free(src); +} + +static int sigrok_init_driver(struct config_device *cfdev, + struct sr_dev_driver *drv) +{ + struct sr_config *src; + GSList *devlist, *drvopts; + char hwident[512]; + + if (sr_driver_init(sr_ctx, drv) != SR_OK) + /* Error was logged by libsigrok. */ + return -1; + + drvopts = NULL; + if (cfdev->conn) { + if (!(src = malloc(sizeof(struct sr_config)))) + return -1; + src->key = SR_CONF_CONN; + src->data = g_variant_new_string(cfdev->conn); + drvopts = g_slist_append(drvopts, src); + } + if (cfdev->serialcomm) { + if (!(src = malloc(sizeof(struct sr_config)))) + return -1; + src->key = SR_CONF_SERIALCOMM; + src->data = g_variant_new_string(cfdev->serialcomm); + drvopts = g_slist_append(drvopts, src); + } + devlist = sr_driver_scan(drv, drvopts); + g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts); + if (!devlist) { + /* Not an error, but the user should know about it. */ + WARNING("No device found for '%s'.", cfdev->name); + return 0; + } + + if (g_slist_length(devlist) > 1) { + INFO("sigrok: %d sigrok devices for device entry '%s': must be 1.", + g_slist_length(devlist), cfdev->name); + return -1; } + cfdev->sdi = devlist->data; + g_slist_free(devlist); + ssnprintf(hwident, sizeof(hwident), "%s %s %s", + cfdev->sdi->vendor ? cfdev->sdi->vendor : "", + cfdev->sdi->model ? cfdev->sdi->model : "", + cfdev->sdi->version ? cfdev->sdi->version : ""); + INFO("sigrok: Device '%s' is a %s", cfdev->name, hwident); + + if (sr_dev_open(cfdev->sdi) != SR_OK) + return -1; + + if (sr_session_dev_add(cfdev->sdi) != SR_OK) + return -1; + return 1; } -static void *thread_init(void *arg __attribute__((unused))) +static void *sigrok_read_thread(void *arg __attribute__((unused))) { struct sr_dev_driver *drv, **drvlist; - struct sr_config *src; - GSList *devlist, *drvopts, *l; + GSList *l; struct config_device *cfdev; int ret, i; - char hwident[512]; - - (void)arg; - sr_log_callback_set(cd_logger, NULL); + sr_log_callback_set(sigrok_log_callback, NULL); sr_log_loglevel_set(loglevel); if ((ret = sr_init(&sr_ctx)) != SR_OK) { @@ -219,7 +277,7 @@ static void *thread_init(void *arg __attribute__((unused))) return NULL; } - if (!(session = sr_session_new())) + if (!sr_session_new()) return NULL; num_devices = 0; @@ -238,50 +296,11 @@ static void *thread_init(void *arg __attribute__((unused))) return NULL; } - if (sr_driver_init(sr_ctx, drv) != SR_OK) - return NULL; - - drvopts = NULL; - if (cfdev->conn) { - if (!(src = malloc(sizeof(struct sr_config)))) - return NULL; - src->key = SR_CONF_CONN; - src->data = g_variant_new_string(cfdev->conn); - drvopts = g_slist_append(drvopts, src); - } - if (cfdev->serialcomm) { - if (!(src = malloc(sizeof(struct sr_config)))) - return NULL; - src->key = SR_CONF_SERIALCOMM; - src->data = g_variant_new_string(cfdev->serialcomm); - drvopts = g_slist_append(drvopts, src); - } - devlist = sr_driver_scan(drv, drvopts); - g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts); - if (!devlist) - /* No devices found for this driver. */ - continue; - - if (g_slist_length(devlist) > 1) { - INFO("sigrok: %d sigrok devices for device entry '%s': must be 1.", - g_slist_length(devlist), cfdev->name); - return NULL; - } - cfdev->sdi = devlist->data; - g_slist_free(devlist); - ssnprintf(hwident, sizeof(hwident), "%s %s %s", - cfdev->sdi->vendor ? cfdev->sdi->vendor : "", - cfdev->sdi->model ? cfdev->sdi->model : "", - cfdev->sdi->version ? cfdev->sdi->version : ""); - INFO("sigrok: Device '%s' is a %s.", cfdev->name, hwident); - - if (sr_dev_open(cfdev->sdi) != SR_OK) - return NULL; - - if (sr_session_dev_add(cfdev->sdi) != SR_OK) + if ((ret = sigrok_init_driver(cfdev, drv)) < 0) + /* Error was already logged. */ return NULL; - num_devices++; + num_devices += ret; } if (num_devices > 0) { @@ -319,7 +338,8 @@ static int sigrok_init(void) return -1; } - if ((status = plugin_thread_create(&sr_thread, NULL, thread_init, NULL)) != 0) { + if ((status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread, + NULL)) != 0) { ERROR("sigrok: Failed to create thread: %s.", strerror(status)); return -1; }