X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fsigrok.c;h=8a325fe9f07006d4e68526696bde2ed954ffedc2;hp=400645538d7d842f5d47f422f1347a2be5d7112d;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=3d74a63ae43c1786eb9b966e2209c24c5643dae8 diff --git a/src/sigrok.c b/src/sigrok.c index 40064553..8a325fe9 100644 --- a/src/sigrok.c +++ b/src/sigrok.c @@ -44,357 +44,336 @@ static int loglevel = SR_LOG_WARN; static struct sr_context *sr_ctx; struct config_device { - char *name; - char *driver; - char *conn; - char *serialcomm; - struct sr_dev_inst *sdi; - cdtime_t min_dispatch_interval; - cdtime_t last_dispatch; + char *name; + char *driver; + char *conn; + char *serialcomm; + struct sr_dev_inst *sdi; + cdtime_t min_dispatch_interval; + cdtime_t last_dispatch; }; +static int sigrok_log_callback(void *cb_data __attribute__((unused)), + int msg_loglevel, const char *format, + va_list args) { + char s[512]; -static int sigrok_log_callback(void*cb_data __attribute__((unused)), - int msg_loglevel, const char *format, va_list args) -{ - char s[512]; + if (msg_loglevel <= loglevel) { + vsnprintf(s, 512, format, args); + plugin_log(LOG_INFO, "sigrok plugin: %s", s); + } - if (msg_loglevel <= loglevel) { - vsnprintf(s, 512, format, args); - plugin_log(LOG_INFO, "sigrok plugin: %s", s); - } - - return 0; + return 0; } -static int sigrok_config_device(oconfig_item_t *ci) -{ - struct config_device *cfdev; - - if (!(cfdev = calloc(1, sizeof(*cfdev)))) { - ERROR("sigrok plugin: calloc failed."); - return -1; - } - if (cf_util_get_string(ci, &cfdev->name)) { - free(cfdev); - WARNING("sigrok plugin: Invalid device name."); - return -1; - } - cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL; - - for (int i = 0; i < ci->children_num; i++) { - oconfig_item_t *item = ci->children + i; - if (!strcasecmp(item->key, "driver")) - cf_util_get_string(item, &cfdev->driver); - else if (!strcasecmp(item->key, "conn")) - cf_util_get_string(item, &cfdev->conn); - else if (!strcasecmp(item->key, "serialcomm")) - cf_util_get_string(item, &cfdev->serialcomm); - else if (!strcasecmp(item->key, "minimuminterval")) - cf_util_get_cdtime(item, &cfdev->min_dispatch_interval); - else - WARNING("sigrok plugin: Invalid keyword \"%s\".", - item->key); - } - - config_devices = g_slist_append(config_devices, cfdev); - - return 0; +static int sigrok_config_device(oconfig_item_t *ci) { + struct config_device *cfdev; + + if (!(cfdev = calloc(1, sizeof(*cfdev)))) { + ERROR("sigrok plugin: calloc failed."); + return -1; + } + if (cf_util_get_string(ci, &cfdev->name)) { + free(cfdev); + WARNING("sigrok plugin: Invalid device name."); + return -1; + } + cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL; + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *item = ci->children + i; + if (!strcasecmp(item->key, "driver")) + cf_util_get_string(item, &cfdev->driver); + else if (!strcasecmp(item->key, "conn")) + cf_util_get_string(item, &cfdev->conn); + else if (!strcasecmp(item->key, "serialcomm")) + cf_util_get_string(item, &cfdev->serialcomm); + else if (!strcasecmp(item->key, "minimuminterval")) + cf_util_get_cdtime(item, &cfdev->min_dispatch_interval); + else + WARNING("sigrok plugin: Invalid keyword \"%s\".", item->key); + } + + config_devices = g_slist_append(config_devices, cfdev); + + return 0; } -static int sigrok_config(oconfig_item_t *ci) -{ - for (int i = 0; i < ci->children_num; i++) { - oconfig_item_t *item = ci->children + i; - if (strcasecmp("LogLevel", item->key) == 0) { - int status; - int tmp = -1; - - status = cf_util_get_int (item, &tmp); - if (status != 0) - continue; - else if ((tmp < 0) || (tmp > 5)) { - ERROR ("sigrok plugin: The \"LogLevel\" " - "configuration option expects " - "an integer between 0 and 5 " - "(inclusive); you provided %i.", - tmp); - continue; - } - loglevel = tmp; - } else if (!strcasecmp(item->key, "Device")) - sigrok_config_device(item); - else - WARNING("sigrok plugin: Invalid keyword \"%s\".", - item->key); - } - - return 0; +static int sigrok_config(oconfig_item_t *ci) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *item = ci->children + i; + if (strcasecmp("LogLevel", item->key) == 0) { + int status; + int tmp = -1; + + status = cf_util_get_int(item, &tmp); + if (status != 0) + continue; + else if ((tmp < 0) || (tmp > 5)) { + ERROR("sigrok plugin: The \"LogLevel\" " + "configuration option expects " + "an integer between 0 and 5 " + "(inclusive); you provided %i.", + tmp); + continue; + } + loglevel = tmp; + } else if (!strcasecmp(item->key, "Device")) + sigrok_config_device(item); + else + WARNING("sigrok plugin: Invalid keyword \"%s\".", item->key); + } + + return 0; } -static const char *sigrok_value_type(const struct sr_datafeed_analog *analog) -{ - const 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 if (analog->mq == SR_MQ_SOUND_PRESSURE_LEVEL) - s = "spl"; - else - s = "gauge"; - - return s; +static const char *sigrok_value_type(const struct sr_datafeed_analog *analog) { + const 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 if (analog->mq == SR_MQ_SOUND_PRESSURE_LEVEL) + s = "spl"; + else + s = "gauge"; + + return s; } static void sigrok_feed_callback(const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, void *cb_data) -{ - const struct sr_datafeed_analog *analog; - struct config_device *cfdev; - value_t value; - value_list_t vl = VALUE_LIST_INIT; - - /* Find this device's configuration. */ - cfdev = NULL; - for (GSList *l = config_devices; l; l = l->next) { - cfdev = l->data; - if (cfdev->sdi == sdi) { - /* Found it. */ - break; - } - cfdev = NULL; - } - - if (!cfdev) { - ERROR("sigrok plugin: Received data from driver \"%s\" but " - "can't find a configuration / device matching " - "it.", sdi->driver->name); - return; - } - - if (packet->type == SR_DF_END) { - /* TODO: try to restart acquisition after a delay? */ - WARNING("sigrok plugin: acquisition for \"%s\" ended.", - cfdev->name); - return; - } - - if (packet->type != SR_DF_ANALOG) - return; - - if ((cfdev->min_dispatch_interval != 0) - && ((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(); + const struct sr_datafeed_packet *packet, + void *cb_data) { + const struct sr_datafeed_analog *analog; + struct config_device *cfdev; + value_list_t vl = VALUE_LIST_INIT; + + /* Find this device's configuration. */ + cfdev = NULL; + for (GSList *l = config_devices; l; l = l->next) { + cfdev = l->data; + if (cfdev->sdi == sdi) { + /* Found it. */ + break; + } + cfdev = NULL; + } + + if (!cfdev) { + ERROR("sigrok plugin: Received data from driver \"%s\" but " + "can't find a configuration / device matching " + "it.", + sdi->driver->name); + return; + } + + if (packet->type == SR_DF_END) { + /* TODO: try to restart acquisition after a delay? */ + WARNING("sigrok plugin: acquisition for \"%s\" ended.", cfdev->name); + return; + } + + if (packet->type != SR_DF_ANALOG) + return; + + if ((cfdev->min_dispatch_interval != 0) && + ((cdtime() - cfdev->last_dispatch) < cfdev->min_dispatch_interval)) + return; + + /* Ignore all but the first sample on the first probe. */ + analog = packet->payload; + vl.values = &(value_t){.gauge = analog->data[0]}; + vl.values_len = 1; + sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, cfdev->name, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, sigrok_value_type(analog), sizeof(vl.type)); + + plugin_dispatch_values(&vl); + cfdev->last_dispatch = cdtime(); } -static void sigrok_free_drvopts(struct sr_config *src) -{ - g_variant_unref(src->data); - g_free(src); +static void sigrok_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(*src)))) - 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(*src)))) - 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)sigrok_free_drvopts); - if (!devlist) { - /* Not an error, but the user should know about it. */ - WARNING("sigrok plugin: No device found for \"%s\".", - cfdev->name); - return 0; - } - - if (g_slist_length(devlist) > 1) { - INFO("sigrok plugin: %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 plugin: 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; + 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(*src)))) + 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(*src)))) + 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)sigrok_free_drvopts); + if (!devlist) { + /* Not an error, but the user should know about it. */ + WARNING("sigrok plugin: No device found for \"%s\".", cfdev->name); + return 0; + } + + if (g_slist_length(devlist) > 1) { + INFO("sigrok plugin: %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); + snprintf(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 plugin: 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 *sigrok_read_thread(void *arg __attribute__((unused))) -{ - struct sr_dev_driver *drv, **drvlist; - GSList *l; - struct config_device *cfdev; - int ret, i; - - sr_log_callback_set(sigrok_log_callback, NULL); - sr_log_loglevel_set(loglevel); - - if ((ret = sr_init(&sr_ctx)) != SR_OK) { - ERROR("sigrok plugin: Failed to initialize libsigrok: %s.", - sr_strerror(ret)); - return NULL; - } - - if (!sr_session_new()) - return NULL; - - num_devices = 0; - drvlist = sr_driver_list(); - for (l = config_devices; l; l = l->next) { - cfdev = l->data; - drv = NULL; - for (i = 0; drvlist[i]; i++) { - if (!strcmp(drvlist[i]->name, cfdev->driver)) { - drv = drvlist[i]; - break; - } - } - if (!drv) { - ERROR("sigrok plugin: Unknown driver \"%s\".", - cfdev->driver); - return NULL; - } - - if ((ret = sigrok_init_driver(cfdev, drv)) < 0) - /* Error was already logged. */ - return NULL; - - num_devices += ret; - } - - if (num_devices > 0) { - /* Do this only when we're sure there's hardware to talk to. */ - if (sr_session_datafeed_callback_add(sigrok_feed_callback, NULL) - != SR_OK) - return NULL; - - /* Start acquisition on all devices. */ - if (sr_session_start() != SR_OK) - return NULL; - - /* Main loop, runs forever. */ - sr_session_run(); - - sr_session_stop(); - sr_session_dev_remove_all(); - } - - sr_session_destroy(); - - sr_exit(sr_ctx); - - pthread_exit(NULL); - sr_thread_running = FALSE; - - return NULL; +static void *sigrok_read_thread(void *arg __attribute__((unused))) { + struct sr_dev_driver *drv, **drvlist; + GSList *l; + struct config_device *cfdev; + int ret, i; + + sr_log_callback_set(sigrok_log_callback, NULL); + sr_log_loglevel_set(loglevel); + + if ((ret = sr_init(&sr_ctx)) != SR_OK) { + ERROR("sigrok plugin: Failed to initialize libsigrok: %s.", + sr_strerror(ret)); + return NULL; + } + + if (!sr_session_new()) + return NULL; + + num_devices = 0; + drvlist = sr_driver_list(); + for (l = config_devices; l; l = l->next) { + cfdev = l->data; + drv = NULL; + for (i = 0; drvlist[i]; i++) { + if (!strcmp(drvlist[i]->name, cfdev->driver)) { + drv = drvlist[i]; + break; + } + } + if (!drv) { + ERROR("sigrok plugin: Unknown driver \"%s\".", cfdev->driver); + return NULL; + } + + if ((ret = sigrok_init_driver(cfdev, drv)) < 0) + /* Error was already logged. */ + return NULL; + + num_devices += ret; + } + + if (num_devices > 0) { + /* Do this only when we're sure there's hardware to talk to. */ + if (sr_session_datafeed_callback_add(sigrok_feed_callback, NULL) != SR_OK) + return NULL; + + /* Start acquisition on all devices. */ + if (sr_session_start() != SR_OK) + return NULL; + + /* Main loop, runs forever. */ + sr_session_run(); + + sr_session_stop(); + sr_session_dev_remove_all(); + } + + sr_session_destroy(); + + sr_exit(sr_ctx); + + pthread_exit(NULL); + sr_thread_running = FALSE; + + return NULL; } -static int sigrok_init(void) -{ - int status; - - if (sr_thread_running) { - ERROR("sigrok plugin: Thread already running."); - return -1; - } - - status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread, - NULL); - if (status != 0) - { - char errbuf[1024]; - ERROR("sigrok plugin: Failed to create thread: %s.", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - sr_thread_running = TRUE; - - return 0; +static int sigrok_init(void) { + int status; + + if (sr_thread_running) { + ERROR("sigrok plugin: Thread already running."); + return -1; + } + + status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread, NULL, + "sigrok read"); + if (status != 0) { + char errbuf[1024]; + ERROR("sigrok plugin: Failed to create thread: %s.", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + sr_thread_running = TRUE; + + return 0; } -static int sigrok_shutdown(void) -{ - struct config_device *cfdev; - GSList *l; - - if (sr_thread_running) { - pthread_cancel(sr_thread); - pthread_join(sr_thread, NULL); - } - - for (l = config_devices; l; l = l->next) { - cfdev = l->data; - free(cfdev->name); - free(cfdev->driver); - free(cfdev->conn); - free(cfdev->serialcomm); - free(cfdev); - } - g_slist_free(config_devices); - - return 0; +static int sigrok_shutdown(void) { + struct config_device *cfdev; + GSList *l; + + if (sr_thread_running) { + pthread_cancel(sr_thread); + pthread_join(sr_thread, NULL); + } + + for (l = config_devices; l; l = l->next) { + cfdev = l->data; + free(cfdev->name); + free(cfdev->driver); + free(cfdev->conn); + free(cfdev->serialcomm); + free(cfdev); + } + g_slist_free(config_devices); + + return 0; } -void module_register(void) -{ - plugin_register_complex_config("sigrok", sigrok_config); - plugin_register_init("sigrok", sigrok_init); - plugin_register_shutdown("sigrok", sigrok_shutdown); +void module_register(void) { + plugin_register_complex_config("sigrok", sigrok_config); + plugin_register_init("sigrok", sigrok_init); + plugin_register_shutdown("sigrok", sigrok_shutdown); }