static int hw_cleanup(void) { GSList *l; struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; int ret = SR_OK; if (!(drvc = di->priv)) return SR_OK; /* Properly close and free all devices. */ for (l = drvc->instances; l; l = l->next) { if (!(sdi = l->data)) { /* Log error, but continue cleaning up the rest. */ sr_err("%s: sdi was NULL, continuing", __func__); ret = SR_ERR_BUG; continue; } if (!(devc = sdi->priv)) { /* Log error, but continue cleaning up the rest. */ sr_err("%s: sdi->priv was NULL, continuing", __func__); ret = SR_ERR_BUG; continue; } hw_dev_close(sdi); sr_serial_dev_inst_free(devc->serial); sr_dev_inst_free(sdi); } g_slist_free(drvc->instances); drvc->instances = NULL; return ret; }
/* Properly close and free all devices. */ static int clear_instances(int dmm) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; GSList *l; struct sr_dev_driver *di; di = dmms[dmm].di; if (!(drvc = di->priv)) return SR_OK; drvc = di->priv; for (l = drvc->instances; l; l = l->next) { if (!(sdi = l->data)) continue; if (!(devc = sdi->priv)) continue; sr_serial_dev_inst_free(devc->serial); sr_dev_inst_free(sdi); } g_slist_free(drvc->instances); drvc->instances = NULL; return SR_OK; }
/** * Standard driver dev_clear() helper. * * Clear driver, this means, close all instances. * * This function can be used to implement the dev_clear() driver API * callback. dev_close() is called before every sr_dev_inst is cleared. * * The only limitation is driver-specific device contexts (sdi->priv). * These are freed, but any dynamic allocation within structs stored * there cannot be freed. * * @param driver The driver which will have its instances released. * @param clear_private If not NULL, this points to a function called * with sdi->priv as argument. The function can then clear any device * instance-specific resources kept there. It must also clear the struct * pointed to by sdi->priv. * * @return SR_OK on success. */ SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver, std_dev_clear_callback clear_private) { struct drv_context *drvc; struct sr_dev_inst *sdi; GSList *l; int ret; if (!(drvc = driver->context)) /* Driver was never initialized, nothing to do. */ return SR_OK; ret = SR_OK; for (l = drvc->instances; l; l = l->next) { if (!(sdi = l->data)) { ret = SR_ERR_BUG; continue; } if (driver->dev_close) driver->dev_close(sdi); if (sdi->conn) { #ifdef HAVE_LIBSERIALPORT if (sdi->inst_type == SR_INST_SERIAL) sr_serial_dev_inst_free(sdi->conn); #endif #ifdef HAVE_LIBUSB_1_0 if (sdi->inst_type == SR_INST_USB) sr_usb_dev_inst_free(sdi->conn); #endif if (sdi->inst_type == SR_INST_SCPI) sr_scpi_free(sdi->conn); if (sdi->inst_type == SR_INST_MODBUS) sr_modbus_free(sdi->conn); } if (clear_private) /* The helper function is responsible for freeing * its own sdi->priv! */ clear_private(sdi->priv); else g_free(sdi->priv); sr_dev_inst_free(sdi); } g_slist_free(drvc->instances); drvc->instances = NULL; return ret; }
/* * Standard driver dev_clear() helper. * * This function can be used to implement the dev_clear() driver API * callback. dev_close() is called before every sr_dev_inst is cleared. * * The only limitation is driver-specific device contexts (sdi->priv). * These are freed, but any dynamic allocation within structs stored * there cannot be freed. * * @param driver The driver which will have its instances released. * @param clear_private If not NULL, this points to a function called * with sdi->priv as argument. The function can then clear any device * instance-specific resources kept there. It must also clear the struct * pointed to by sdi->priv. * * @return SR_OK on success. */ SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver, std_dev_clear_t clear_private) { struct drv_context *drvc; struct sr_dev_inst *sdi; GSList *l; int ret; if (!(drvc = driver->priv)) /* Driver was never initialized, nothing to do. */ return SR_OK; ret = SR_OK; for (l = drvc->instances; l; l = l->next) { if (!(sdi = l->data)) { ret = SR_ERR_BUG; continue; } if (driver->dev_close) driver->dev_close(sdi); if (sdi->conn) { #if HAVE_LIBSERIALPORT if (sdi->inst_type == SR_INST_SERIAL) sr_serial_dev_inst_free(sdi->conn); #endif #if HAVE_LIBUSB_1_0 if (sdi->inst_type == SR_INST_USB) sr_usb_dev_inst_free(sdi->conn); #endif if (sdi->inst_type == SR_INST_USBTMC) sr_usbtmc_dev_inst_free(sdi->conn); } if (clear_private) clear_private(sdi->priv); else g_free(sdi->priv); sr_dev_inst_free(sdi); } g_slist_free(drvc->instances); drvc->instances = NULL; return ret; }
static int hw_cleanup(void) { GSList *l; struct sr_dev_inst *sdi; struct context *ctx; /* Properly close and free all devices. */ for (l = genericdmm_dev_insts; l; l = l->next) { if (!(sdi = l->data)) { /* Log error, but continue cleaning up the rest. */ sr_err("genericdmm: sdi was NULL, continuing."); continue; } if (!(ctx = sdi->priv)) { /* Log error, but continue cleaning up the rest. */ sr_err("genericdmm: sdi->priv was NULL, continuing."); continue; } if (ctx->profile) { switch (ctx->profile->transport) { case DMM_TRANSPORT_USBHID: /* TODO */ break; case DMM_TRANSPORT_SERIAL: if (ctx->serial && ctx->serial->fd != -1) serial_close(ctx->serial->fd); sr_serial_dev_inst_free(ctx->serial); break; } } sr_dev_inst_free(sdi); } g_slist_free(genericdmm_dev_insts); genericdmm_dev_insts = NULL; if (genericdmm_usb_context) libusb_exit(genericdmm_usb_context); return SR_OK; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { int i, model_id; struct drv_context *drvc; struct dev_context *devc; struct sr_dev_inst *sdi; struct sr_config *src; GSList *devices, *l; const char *conn, *serialcomm; struct sr_serial_dev_inst *serial; char reply[50], **tokens, *dummy; drvc = di->context; drvc->instances = NULL; devices = NULL; conn = NULL; serialcomm = NULL; devc = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; default: sr_err("Unknown option %d, skipping.", src->key); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = "9600/8n1"; serial = sr_serial_dev_inst_new(conn, serialcomm); if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; serial_flush(serial); sr_info("Probing serial port %s.", conn); /* Get the device model. */ memset(&reply, 0, sizeof(reply)); if ((hcs_send_cmd(serial, "GMOD\r") < 0) || (hcs_read_reply(serial, 2, reply, sizeof(reply)) < 0)) return NULL; tokens = g_strsplit((const gchar *)&reply, "\r", 2); model_id = -1; for (i = 0; models[i].id != NULL; i++) { if (!strcmp(models[i].id, tokens[0])) model_id = i; } if (model_id < 0) { sr_err("Unknown model ID '%s' detected, aborting.", tokens[0]); g_strfreev(tokens); return NULL; } g_strfreev(tokens); /* Init device instance, etc. */ sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup("Manson"); sdi->model = g_strdup(models[model_id].name); sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->driver = di; sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "CH1"); devc = g_malloc0(sizeof(struct dev_context)); sr_sw_limits_init(&devc->limits); devc->model = &models[model_id]; sdi->priv = devc; /* Get current voltage, current, status. */ if ((hcs_send_cmd(serial, "GETD\r") < 0) || (hcs_read_reply(serial, 2, reply, sizeof(reply)) < 0)) goto exit_err; tokens = g_strsplit((const gchar *)&reply, "\r", 2); if (hcs_parse_volt_curr_mode(sdi, tokens) < 0) { g_strfreev(tokens); goto exit_err; } g_strfreev(tokens); /* Get max. voltage and current. */ if ((hcs_send_cmd(serial, "GMAX\r") < 0) || (hcs_read_reply(serial, 2, reply, sizeof(reply)) < 0)) goto exit_err; tokens = g_strsplit((const gchar *)&reply, "\r", 2); devc->current_max_device = g_strtod(&tokens[0][3], &dummy) * devc->model->current[2]; tokens[0][3] = '\0'; devc->voltage_max_device = g_strtod(tokens[0], &dummy) * devc->model->voltage[2]; g_strfreev(tokens); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; exit_err: sr_dev_inst_free(sdi); g_free(devc); return NULL; }
/** * Scan for Metrahit 2x in a bidirectional mode using Gossen Metrawatt * 'BD 232' interface. */ static GSList *scan_2x_bd232(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_serial_dev_inst *serial; GSList *l, *devices; const char *conn, *serialcomm; int cnt, byte; gint64 timeout_us; sdi = NULL; devc = NULL; conn = serialcomm = NULL; devices = NULL; drvc = di->context; drvc->instances = NULL; sr_spew("scan_2x_bd232() called!"); for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM_2X; serial = sr_serial_dev_inst_new(conn, serialcomm); if (serial_open(serial, SERIAL_RDWR) != SR_OK) goto exit_err; devc = g_malloc0(sizeof(struct dev_context)); sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_GMC); sdi->priv = devc; /* Send message 03 "Query multimeter version and status" */ sdi->conn = serial; if (req_stat14(sdi, TRUE) != SR_OK) goto exit_err; /* Wait for reply from device(s) for up to 2s. */ timeout_us = g_get_monotonic_time() + (2 * 1000 * 1000); while (timeout_us > g_get_monotonic_time()) { /* Receive reply (14 bytes) */ devc->buflen = 0; for (cnt = 0; cnt < GMC_REPLY_SIZE; cnt++) { byte = read_byte(serial, timeout_us); if (byte != -1) devc->buf[devc->buflen++] = (byte & MASK_6BITS); } if (devc->buflen != GMC_REPLY_SIZE) continue; devc->addr = devc->buf[0]; process_msg14(sdi); devc->buflen = 0; if (devc->model != METRAHIT_NONE) { sr_spew("%s %s detected!", VENDOR_GMC, gmc_model_str(devc->model)); devc->elapsed_msec = g_timer_new(); sdi->model = g_strdup(gmc_model_str(devc->model)); sdi->version = g_strdup_printf("Firmware %d.%d", devc->fw_ver_maj, devc->fw_ver_min); sdi->conn = serial; sdi->priv = devc; sdi->driver = di; sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1"); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); devc = g_malloc0(sizeof(struct dev_context)); sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_GMC); } }; /* Free last alloc if no device found */ if (devc->model == METRAHIT_NONE) { g_free(devc); sr_dev_inst_free(sdi); } return devices; exit_err: sr_info("scan_2x_bd232(): Error!"); if (serial) sr_serial_dev_inst_free(serial); g_free(devc); if (sdi) sr_dev_inst_free(sdi); return NULL; }
/** * Scan for Metrahit 1x and Metrahit 2x in send mode using Gossen Metrawatt * 'RS232' interface. * * The older 1x models use 8192 baud and the newer 2x 9600 baud. * The DMM usually sends up to about 20 messages per second. However, depending * on configuration and measurement mode the intervals can be much larger and * then the detection might not work. */ static GSList *scan_1x_2x_rs232(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_serial_dev_inst *serial; GSList *l, *devices; const char *conn, *serialcomm; enum model model; gboolean serialcomm_given; devices = NULL; drvc = di->context; drvc->instances = NULL; conn = serialcomm = NULL; serialcomm_given = FALSE; sr_spew("scan_1x_2x_rs232() called!"); for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); serialcomm_given = TRUE; break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM_2X_RS232; serial = sr_serial_dev_inst_new(conn, serialcomm); if (serial_open(serial, SERIAL_RDWR) != SR_OK) { sr_serial_dev_inst_free(serial); return NULL; } serial_flush(serial); model = scan_model_sm(serial); /* * If detection failed and no user-supplied parameters, * try second baud rate. */ if ((model == METRAHIT_NONE) && !serialcomm_given) { serialcomm = SERIALCOMM_1X_RS232; g_free(serial->serialcomm); serial->serialcomm = g_strdup(serialcomm); if (serial_set_paramstr(serial, serialcomm) == SR_OK) { serial_flush(serial); model = scan_model_sm(serial); } } if (model != METRAHIT_NONE) { sr_spew("%s %s detected!", VENDOR_GMC, gmc_model_str(model)); sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_GMC); sdi->model = g_strdup(gmc_model_str(model)); devc = g_malloc0(sizeof(struct dev_context)); devc->model = model; devc->limit_samples = 0; devc->limit_msec = 0; devc->num_samples = 0; devc->elapsed_msec = g_timer_new(); devc->settings_ok = FALSE; sdi->conn = serial; sdi->priv = devc; sdi->driver = di; sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1"); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } return devices; }
static void scpi_serial_free(void *priv) { struct scpi_serial *sscpi = priv; sr_serial_dev_inst_free(sscpi->serial); }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct drv_context *drvc; struct dev_context *devc; GSList *devices, *l; struct sr_dev_inst *sdi; struct sr_config *src; const char *conn, *serialcomm; struct sr_serial_dev_inst *serial; char reply[50]; int i, model_id; unsigned int len; devices = NULL; conn = NULL; serialcomm = NULL; drvc = di->context; drvc->instances = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; default: sr_err("Unknown option %d, skipping.", src->key); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = "9600/8n1"; serial = sr_serial_dev_inst_new(conn, serialcomm); if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; serial_flush(serial); /* Get the device model. */ len = 0; for (i = 0; models[i].id; i++) { if (strlen(models[i].id) > len) len = strlen(models[i].id); } memset(&reply, 0, sizeof(reply)); sr_dbg("Want max %d bytes.", len); if ((korad_kdxxxxp_send_cmd(serial, "*IDN?") < 0)) return NULL; /* i is used here for debug purposes only. */ if ((i = korad_kdxxxxp_read_chars(serial, len, reply)) < 0) return NULL; sr_dbg("Received: %d, %s", i, reply); model_id = -1; for (i = 0; models[i].id; i++) { if (!strcmp(models[i].id, reply)) model_id = i; } if (model_id < 0) { sr_err("Unknown model ID '%s' detected, aborting.", reply); return NULL; } sr_dbg("Found: %s %s", models[model_id].vendor, models[model_id].name); /* Init device instance, etc. */ sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(models[model_id].vendor); sdi->model = g_strdup(models[model_id].name); sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->driver = di; sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "CH1"); devc = g_malloc0(sizeof(struct dev_context)); devc->model = &models[model_id]; devc->reply[5] = 0; devc->req_sent_at = 0; sdi->priv = devc; /* Get current status of device. */ if (korad_kdxxxxp_get_all_values(serial, devc) < 0) goto exit_err; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; exit_err: sr_dev_inst_free(sdi); g_free(devc); sr_dbg("Scan failed."); return NULL; }
static GSList *scan(GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_channel *ch; struct sr_serial_dev_inst *serial; GSList *l, *devices; int len, i; const char *conn, *serialcomm; char *buf, **tokens; drvc = di->priv; drvc->instances = NULL; devices = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM; if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; serial_flush(serial); if (serial_write_blocking(serial, "*IDN?\r\n", 7, SERIAL_WRITE_TIMEOUT_MS) < 7) { sr_err("Unable to send identification string."); return NULL; } len = 128; if (!(buf = g_try_malloc(len))) { sr_err("Serial buffer malloc failed."); return NULL; } serial_readline(serial, &buf, &len, 250); if (!len) return NULL; tokens = g_strsplit(buf, ",", 4); if (!strcmp("Agilent Technologies", tokens[0]) && tokens[1] && tokens[2] && tokens[3]) { for (i = 0; supported_agdmm[i].model; i++) { if (strcmp(supported_agdmm[i].modelname, tokens[1])) continue; sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup("Agilent"); sdi->model = g_strdup(tokens[1]); sdi->version = g_strdup(tokens[3]); devc = g_malloc0(sizeof(struct dev_context)); devc->profile = &supported_agdmm[i]; devc->cur_mq = -1; sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->priv = devc; sdi->driver = di; ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"); sdi->channels = g_slist_append(sdi->channels, ch); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); break; } } g_strfreev(tokens); g_free(buf); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }
static GSList *scan(GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_probe *probe; struct sr_serial_dev_inst *serial; GSList *l, *devices; int len, i; const char *conn, *serialcomm; char *buf, **tokens; drvc = di->priv; drvc->instances = NULL; devices = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM; if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) return NULL; serial_flush(serial); if (serial_write(serial, "*IDN?\r\n", 7) == -1) { sr_err("Unable to send identification string: %s.", strerror(errno)); return NULL; } len = 128; if (!(buf = g_try_malloc(len))) { sr_err("Serial buffer malloc failed."); return NULL; } serial_readline(serial, &buf, &len, 150); if (!len) return NULL; tokens = g_strsplit(buf, ",", 4); if (!strcmp("Agilent Technologies", tokens[0]) && tokens[1] && tokens[2] && tokens[3]) { for (i = 0; supported_agdmm[i].model; i++) { if (strcmp(supported_agdmm[i].modelname, tokens[1])) continue; if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, tokens[0], tokens[1], tokens[3]))) return NULL; if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { sr_err("Device context malloc failed."); return NULL; } devc->profile = &supported_agdmm[i]; devc->cur_mq = -1; sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->priv = devc; sdi->driver = di; if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1"))) return NULL; sdi->probes = g_slist_append(sdi->probes, probe); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); break; } } g_strfreev(tokens); g_free(buf); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }
static GSList *fluke_scan(const char *conn, const char *serialcomm) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_channel *ch; struct sr_serial_dev_inst *serial; GSList *devices; int retry, len, i, s; char buf[128], *b, **tokens; if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; drvc = di->priv; b = buf; retry = 0; devices = NULL; /* We'll try the discovery sequence three times in case the device * is not in an idle state when we send ID. */ while (!devices && retry < 3) { retry++; serial_flush(serial); if (serial_write_blocking(serial, "ID\r", 3, SERIAL_WRITE_TIMEOUT_MS) < 0) { sr_err("Unable to send ID string"); continue; } /* Response is first a CMD_ACK byte (ASCII '0' for OK, * or '1' to signify an error. */ len = 128; serial_readline(serial, &b, &len, 150); if (len != 1) continue; if (buf[0] != '0') continue; /* If CMD_ACK was OK, ID string follows. */ len = 128; serial_readline(serial, &b, &len, 850); if (len < 10) continue; if (strcspn(buf, ",") < 15) /* Looks like it's comma-separated. */ tokens = g_strsplit(buf, ",", 3); else /* Fluke 199B, at least, uses semicolon. */ tokens = g_strsplit(buf, ";", 3); if (!strncmp("FLUKE", tokens[0], 5) && tokens[1] && tokens[2]) { for (i = 0; supported_flukedmm[i].model; i++) { if (strcmp(supported_flukedmm[i].modelname, tokens[0] + 6)) continue; /* Skip leading spaces in version number. */ for (s = 0; tokens[1][s] == ' '; s++); sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup("Fluke"); sdi->model = g_strdup(tokens[0] + 6); sdi->version = g_strdup(tokens[1] + s); devc = g_malloc0(sizeof(struct dev_context)); devc->profile = &supported_flukedmm[i]; sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->priv = devc; sdi->driver = di; ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"); sdi->channels = g_slist_append(sdi->channels, ch); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); break; } } g_strfreev(tokens); if (devices) /* Found one. */ break; } serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }
static int probe_port(const char *port, GSList **devices) { struct dev_context *devc; struct sr_dev_inst *sdi; struct sr_serial_dev_inst *serial; struct sr_probe *probe; unsigned int i; int len, num_tokens; gboolean matched, has_digital; const char *manufacturer, *model, *version; char buf[256]; gchar **tokens, *channel_name; *devices = NULL; if (!(serial = sr_serial_dev_inst_new(port, NULL))) return SR_ERR_MALLOC; if (serial_open(serial, SERIAL_RDWR) != SR_OK) return SR_ERR; len = serial_write(serial, "*IDN?", 5); len = serial_read(serial, buf, sizeof(buf)); if (serial_close(serial) != SR_OK) return SR_ERR; sr_serial_dev_inst_free(serial); if (len == 0) return SR_ERR_NA; buf[len] = 0; tokens = g_strsplit(buf, ",", 0); sr_dbg("response: %s [%s]", port, buf); for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++); if (num_tokens < 4) { g_strfreev(tokens); return SR_ERR_NA; } manufacturer = tokens[0]; model = tokens[1]; version = tokens[3]; if (strcmp(manufacturer, "Rigol Technologies")) { g_strfreev(tokens); return SR_ERR_NA; } matched = has_digital = FALSE; for (i = 0; i < ARRAY_SIZE(supported_models); i++) { if (!strcmp(model, supported_models[i])) { matched = TRUE; has_digital = g_str_has_suffix(model, "D"); break; } } if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, manufacturer, model, version))) { g_strfreev(tokens); return SR_ERR_NA; } g_strfreev(tokens); if (!(sdi->conn = sr_serial_dev_inst_new(port, NULL))) return SR_ERR_MALLOC; sdi->driver = di; sdi->inst_type = SR_INST_SERIAL; if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) return SR_ERR_MALLOC; devc->limit_frames = 0; devc->has_digital = has_digital; for (i = 0; i < 2; i++) { if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, i == 0 ? "CH1" : "CH2"))) return SR_ERR_MALLOC; sdi->probes = g_slist_append(sdi->probes, probe); } if (devc->has_digital) { for (i = 0; i < 16; i++) { if (!(channel_name = g_strdup_printf("D%d", i))) return SR_ERR_MALLOC; probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name); g_free(channel_name); if (!probe) return SR_ERR_MALLOC; sdi->probes = g_slist_append(sdi->probes, probe); } } sdi->priv = devc; *devices = g_slist_append(NULL, sdi); return SR_OK; }
static GSList *scan(GSList *options, int modelid) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_channel *ch; struct sr_channel_group *cg; struct sr_serial_dev_inst *serial; GSList *l, *devices; struct pps_model *model; uint8_t packet[PACKET_SIZE]; unsigned int i; int ret; const char *conn, *serialcomm; char channel[10]; devices = NULL; drvc = di->priv; drvc->instances = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM; if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) return NULL; serial_flush(serial); /* This is how the vendor software channels for hardware. */ memset(packet, 0, PACKET_SIZE); packet[0] = 0xaa; packet[1] = 0xaa; if (serial_write(serial, packet, PACKET_SIZE) == -1) { sr_err("Unable to write while probing for hardware: %s", strerror(errno)); return NULL; } /* The device responds with a 24-byte packet when it receives a packet. * At 9600 baud, 300ms is long enough for it to have arrived. */ g_usleep(300 * 1000); memset(packet, 0, PACKET_SIZE); if ((ret = serial_read_nonblocking(serial, packet, PACKET_SIZE)) < 0) { sr_err("Unable to read while probing for hardware: %s", strerror(errno)); return NULL; } if (ret != PACKET_SIZE || packet[0] != 0xaa || packet[1] != 0xaa) { /* Doesn't look like an Atten PPS. */ return NULL; } model = NULL; for (i = 0; i < ARRAY_SIZE(models); i++) { if (models[i].modelid == modelid) { model = &models[i]; break; } } if (!model) { sr_err("Unknown modelid %d", modelid); return NULL; } sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Atten", model->name, NULL); sdi->driver = di; sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; for (i = 0; i < MAX_CHANNELS; i++) { snprintf(channel, 10, "CH%d", i + 1); ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, channel); sdi->channels = g_slist_append(sdi->channels, ch); cg = g_malloc(sizeof(struct sr_channel_group)); cg->name = g_strdup(channel); cg->channels = g_slist_append(NULL, ch); cg->priv = NULL; sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); } devc = g_malloc0(sizeof(struct dev_context)); devc->model = model; devc->config = g_malloc0(sizeof(struct per_channel_config) * model->num_channels); sdi->priv = devc; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_serial_dev_inst *serial; struct sr_channel_group *cg; struct sr_channel *ch; GSList *l, *devices; int ret, len; const char *conn, *serialcomm; char buf[100]; char *bufptr; double version; devices = NULL; drvc = di->context; drvc->instances = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM; serial = sr_serial_dev_inst_new(conn, serialcomm); if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; serial_flush(serial); if (serial_write_blocking(serial, CMD_VERSION, strlen(CMD_VERSION), serial_timeout(serial, strlen(CMD_VERSION))) < (int)strlen(CMD_VERSION)) { sr_dbg("Unable to write while probing for hardware."); serial_close(serial); return NULL; } memset(buf, 0, sizeof(buf)); bufptr = buf; len = sizeof(buf); ret = serial_readline(serial, &bufptr, &len, 3000); if (ret < 0 || len < 9 || strncmp((const char *)&buf, "version ", 8)) { sr_dbg("Unable to probe version number."); serial_close(serial); return NULL; } version = g_ascii_strtod(buf + 8, NULL); if (version < 1.10) { sr_info("Firmware >= 1.10 required (got %1.2f).", version); serial_close(serial); return NULL; } sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_ACTIVE; sdi->vendor = g_strdup("Arachnid Labs"); sdi->model = g_strdup("Re:load Pro"); sdi->version = g_strdup(buf + 8); sdi->driver = &arachnid_labs_re_load_pro_driver_info; sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; cg = g_malloc0(sizeof(struct sr_channel_group)); cg->name = g_strdup("1"); sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V"); cg->channels = g_slist_append(cg->channels, ch); ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "I"); cg->channels = g_slist_append(cg->channels, ch); devc = g_malloc0(sizeof(struct dev_context)); sdi->priv = devc; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }
static GSList *scan(GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_config *src; struct sr_probe *probe; struct sr_serial_dev_inst *serial; GSList *l, *devices; int len, cnt; const char *conn, *serialcomm; char *buf; char fmttype[10]; char req[10]; int auxtype; devices = NULL; drvc = di->priv; drvc->instances = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; } } if (!conn) return NULL; if (!serialcomm) serialcomm = SERIALCOMM; if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) return NULL; serial_flush(serial); if (!(buf = g_try_malloc(BUF_MAX))) { sr_err("Serial buffer malloc failed."); return NULL; } snprintf(req, sizeof(req), "%s\r\n", nmadmm_requests[NMADMM_REQ_IDN].req_str); for (cnt = 0; cnt < 7; cnt++) { if (serial_write(serial, req, strlen(req)) == -1) { sr_err("Unable to send identification request: %d %s.", errno, strerror(errno)); return NULL; } len = BUF_MAX; serial_readline(serial, &buf, &len, 1500); if (!len) continue; buf[BUF_MAX - 1] = '\0'; /* Match ID string, e.g. "1834 065 V1.06,IF V1.02" (DM950) */ if (g_regex_match_simple("^1834 [^,]*,IF V*", (char *)buf, 0, 0)) { auxtype = xgittoint(buf[7]); // TODO: Will this work with non-DM950? snprintf(fmttype, sizeof(fmttype), "DM9%d0", auxtype); sr_spew("Norma %s DMM %s detected!", fmttype, &buf[9]); if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Norma", fmttype, buf + 9))) return NULL; if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { sr_err("Device context malloc failed."); return NULL; } devc->type = auxtype; devc->version = g_strdup(&buf[9]); devc->elapsed_msec = g_timer_new(); sdi->conn = serial; sdi->priv = devc; sdi->driver = di; if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1"))) return NULL; sdi->probes = g_slist_append(sdi->probes, probe); drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); break; } /* * The interface of the DM9x0 contains a cap that needs to * charge for up to 10s before the interface works, if not * powered externally. Therefore wait a little to improve * chances. */ if (cnt == 3) { sr_info("Waiting 5s to allow interface to settle."); g_usleep(5 * 1000 * 1000); } } g_free(buf); serial_close(serial); if (!devices) sr_serial_dev_inst_free(serial); return devices; }