static int nma_send_req(const struct sr_dev_inst *sdi, int req, char *params) { struct sr_serial_dev_inst *serial; struct dev_context *devc; char buf[NMADMM_BUFSIZE]; int len; if (!sdi || !(serial = sdi->conn) || !(devc = sdi->priv)) return SR_ERR_BUG; len = snprintf(buf, sizeof(buf), "%s%s\r\n", nmadmm_requests[req].req_str, params ? params : ""); sr_spew("Sending request: '%s'.", buf); devc->last_req = req; devc->last_req_pending = TRUE; if (serial_write_blocking(serial, buf, len, serial_timeout(serial, len)) < 0) { sr_err("Unable to send request."); devc->last_req_pending = FALSE; return SR_ERR; } devc->req_sent_at = g_get_monotonic_time(); return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { int ret; struct dev_context *devc; struct sr_serial_dev_inst *serial; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; devc = sdi->priv; serial = sdi->conn; /* Send the 'monitor <ms>' command (doesn't have a reply). */ if ((ret = serial_write_blocking(serial, CMD_MONITOR, strlen(CMD_MONITOR), serial_timeout(serial, strlen(CMD_MONITOR)))) < (int)strlen(CMD_MONITOR)) { sr_err("Unable to send 'monitor' command: %d.", ret); return SR_ERR; } /* Poll every 100ms, or whenever some data comes in. */ serial_source_add(sdi->session, serial, G_IO_IN, 100, reloadpro_receive_data, (void *)sdi); sr_sw_limits_acquisition_start(&devc->limits); std_session_send_df_header(sdi); memset(devc->buf, 0, RELOADPRO_BUFSIZE); devc->buflen = 0; return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_serial_dev_inst *serial; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; if (!(devc = sdi->priv)) { sr_err("sdi->priv was NULL."); return SR_ERR_BUG; } devc->cb_data = cb_data; /* Send header packet to the session bus. */ std_session_send_df_header(cb_data, LOG_PREFIX); /* Poll every 100ms, or whenever some data comes in. */ serial = sdi->conn; serial_source_add(sdi->session, serial, G_IO_IN, 50, fluke_receive_data, (void *)sdi); if (serial_write_blocking(serial, "QM\r", 3, SERIAL_WRITE_TIMEOUT_MS) < 0) { sr_err("Unable to send QM."); return SR_ERR; } devc->cmd_sent_at = g_get_monotonic_time() / 1000; devc->expect_response = TRUE; return SR_OK; }
/** * Send command with parameter. * * @param[in] cmd Command * @param[in] param Parameter (0..999, depending on command). * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid argument. * @retval SR_ERR Error. */ SR_PRIV int send_msg1(const struct sr_dev_inst *sdi, char cmd, int param) { struct sr_serial_dev_inst *serial; char buf[5]; if (!sdi || !(serial = sdi->conn)) return SR_ERR_ARG; snprintf(buf, sizeof(buf), "%c%03d", cmd, param); buf[4] = '\r'; sr_spew("send_msg1(): %c%c%c%c\\r", buf[0], buf[1], buf[2], buf[3]); if (serial_write_blocking(serial, buf, sizeof(buf), serial_timeout(serial, sizeof(buf))) < (int)sizeof(buf)) { sr_err("Write error for cmd=%c", cmd); return SR_ERR; } /* * Wait 50ms to ensure that the device does not swallow any of the * following commands. */ g_usleep(50 * 1000); return SR_OK; }
static int mic_send(struct sr_serial_dev_inst *serial, const char *cmd) { int ret; if ((ret = serial_write_blocking(serial, cmd, strlen(cmd), serial_timeout(serial, strlen(cmd)))) < 0) { sr_err("Error sending '%s' command: %d.", cmd, ret); return SR_ERR; } return SR_OK; }
SR_PRIV int fluke_receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_serial_dev_inst *serial; int len; int64_t now, elapsed; (void)fd; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; serial = sdi->conn; if (revents == G_IO_IN) { /* Serial data arrived. */ while (FLUKEDMM_BUFSIZE - devc->buflen - 1 > 0) { len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1); if (len < 1) break; devc->buflen++; *(devc->buf + devc->buflen) = '\0'; if (*(devc->buf + devc->buflen - 1) == '\r') { *(devc->buf + --devc->buflen) = '\0'; handle_line(sdi); break; } } } if (sr_sw_limits_check(&devc->limits)) { sdi->driver->dev_acquisition_stop(sdi); return TRUE; } now = g_get_monotonic_time() / 1000; elapsed = now - devc->cmd_sent_at; /* Send query command at poll_period interval, or after 1 second * has elapsed. This will make it easier to recover from any * out-of-sync or temporary disconnect issues. */ if ((devc->expect_response == FALSE && elapsed > devc->profile->poll_period) || elapsed > devc->profile->timeout) { if (serial_write_blocking(serial, "QM\r", 3, SERIAL_WRITE_TIMEOUT_MS) < 0) sr_err("Unable to send QM."); devc->cmd_sent_at = now; devc->expect_response = TRUE; } return TRUE; }
static int scpi_serial_send(void *priv, const char *command) { int result; struct scpi_serial *sscpi = priv; struct sr_serial_dev_inst *serial = sscpi->serial; result = serial_write_blocking(serial, command, strlen(command), 0); if (result < 0) { sr_err("Error while sending SCPI command: '%s'.", command); return SR_ERR; } sr_spew("Successfully sent SCPI command: '%s'.", command); return SR_OK; }
/** Send command to device with va_list. */ SR_PRIV int lps_send_va(struct sr_serial_dev_inst *serial, const char *fmt, va_list args) { int retc; char auxfmt[LINELEN_MAX]; char buf[LINELEN_MAX]; snprintf(auxfmt, sizeof(auxfmt), "%s\r\n", fmt); vsnprintf(buf, sizeof(buf), auxfmt, args); sr_spew("lps_send_va: \"%s\"", buf); retc = serial_write_blocking(serial, buf, strlen(buf), serial_timeout(serial, strlen(buf))); if (retc < 0) return SR_ERR; return SR_OK; }
static int agdmm_send(const struct sr_dev_inst *sdi, const char *cmd) { struct sr_serial_dev_inst *serial; char buf[32]; serial = sdi->conn; sr_spew("Sending '%s'.", cmd); strncpy(buf, cmd, 28); if (!strncmp(buf, "*IDN?", 5)) strcat(buf, "\r\n"); else strcat(buf, "\n\r\n"); if (serial_write_blocking(serial, buf, strlen(buf), SERIAL_WRITE_TIMEOUT_MS) < (int)strlen(buf)) { sr_err("Failed to send."); return SR_ERR; } return SR_OK; }
SR_PRIV int hcs_send_cmd(struct sr_serial_dev_inst *serial, const char *cmd, ...) { int ret; char cmdbuf[50]; char *cmd_esc; va_list args; va_start(args, cmd); vsnprintf(cmdbuf, sizeof(cmdbuf), cmd, args); va_end(args); cmd_esc = g_strescape(cmdbuf, NULL); sr_dbg("Sending '%s'.", cmd_esc); g_free(cmd_esc); if ((ret = serial_write_blocking(serial, cmdbuf, strlen(cmdbuf), serial_timeout(serial, strlen(cmdbuf)))) < 0) { sr_err("Error sending command: %d.", ret); return ret; } return ret; }
static int agdmm_send(const struct sr_dev_inst *sdi, const char *cmd, ...) { struct sr_serial_dev_inst *serial; va_list args; char buf[32]; serial = sdi->conn; va_start(args, cmd); vsnprintf(buf, sizeof(buf) - 3, cmd, args); va_end(args); sr_spew("Sending '%s'.", buf); if (!strncmp(buf, "*IDN?", 5)) strcat(buf, "\r\n"); else strcat(buf, "\n\r\n"); if (serial_write_blocking(serial, buf, strlen(buf), SERIAL_WRITE_TIMEOUT_MS) < (int)strlen(buf)) { sr_err("Failed to send."); return SR_ERR; } return SR_OK; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; 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; int ret, len; const char *conn, *serialcomm; char buf[100]; char *bufptr; double version; 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_INACTIVE; sdi->vendor = g_strdup("Arachnid Labs"); sdi->model = g_strdup("Re:load Pro"); sdi->version = g_strdup(buf + 8); 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)); sr_sw_limits_init(&devc->limits); sdi->priv = devc; serial_close(serial); return std_scan_complete(di, g_slist_append(NULL, sdi)); }
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 void handle_line(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_serial_dev_inst *serial; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old *analog; int num_tokens, n, i; char cmd[16], **tokens; devc = sdi->priv; serial = sdi->conn; sr_spew("Received line '%s' (%d).", devc->buf, devc->buflen); if (devc->buflen == 1) { if (devc->buf[0] != '0') { /* Not just a CMD_ACK from the query command. */ sr_dbg("Got CMD_ACK '%c'.", devc->buf[0]); devc->expect_response = FALSE; } devc->buflen = 0; return; } analog = NULL; tokens = g_strsplit(devc->buf, ",", 0); if (tokens[0]) { if (devc->profile->model == FLUKE_187 || devc->profile->model == FLUKE_189) { devc->expect_response = FALSE; analog = handle_qm_18x(sdi, tokens); } else if (devc->profile->model == FLUKE_287 || devc->profile->model == FLUKE_289) { devc->expect_response = FALSE; analog = handle_qm_28x(sdi, tokens); } else if (devc->profile->model == FLUKE_190) { devc->expect_response = FALSE; for (num_tokens = 0; tokens[num_tokens]; num_tokens++); if (num_tokens >= 7) { /* Response to QM: this is a comma-separated list of * fields with metadata about the measurement. This * format can return multiple sets of metadata, * split into sets of 7 tokens each. */ devc->meas_type = 0; for (i = 0; i < num_tokens; i += 7) handle_qm_19x_meta(sdi, tokens + i); if (devc->meas_type) { /* Slip the request in now, before the main * timer loop asks for metadata again. */ n = sprintf(cmd, "QM %d\r", devc->meas_type); if (serial_write_blocking(serial, cmd, n, SERIAL_WRITE_TIMEOUT_MS) < 0) sr_err("Unable to send QM (measurement)."); } } else { /* Response to QM <n> measurement request. */ handle_qm_19x_data(sdi, tokens); } } } g_strfreev(tokens); devc->buflen = 0; if (analog) { /* Got a measurement. */ packet.type = SR_DF_ANALOG_OLD; packet.payload = analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); g_free(analog->data); g_free(analog); } }
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; }