X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fopenbench-logic-sniffer%2Fols.c;h=23104cfddc3d8aa455984a19043d573099ded007;hb=d458a0ac290c4be4cad19c22e143748a5ddff0e6;hp=296a59149044aa576341790e54a2fb7a76119415;hpb=fefc4b858e8db2b1c569dd302af1b30c1a4bce4f;p=libsigrok.git diff --git a/hardware/openbench-logic-sniffer/ols.c b/hardware/openbench-logic-sniffer/ols.c index 296a5914..23104cfd 100644 --- a/hardware/openbench-logic-sniffer/ols.c +++ b/hardware/openbench-logic-sniffer/ols.c @@ -42,9 +42,7 @@ #include "libsigrok-internal.h" #include "ols.h" -#ifdef _WIN32 -#define O_NONBLOCK FIONBIO -#endif +#define SERIALCOMM "115200/8n1" static const int hwcaps[] = { SR_HWCAP_LOGIC_ANALYZER, @@ -103,19 +101,21 @@ static const struct sr_samplerates samplerates = { SR_PRIV struct sr_dev_driver ols_driver_info; static struct sr_dev_driver *odi = &ols_driver_info; -static int send_shortcommand(int fd, uint8_t command) +static int send_shortcommand(struct sr_serial_dev_inst *serial, + uint8_t command) { char buf[1]; sr_dbg("ols: sending cmd 0x%.2x", command); buf[0] = command; - if (serial_write(fd, buf, 1) != 1) + if (serial_write(serial, buf, 1) != 1) return SR_ERR; return SR_OK; } -static int send_longcommand(int fd, uint8_t command, uint32_t data) +static int send_longcommand(struct sr_serial_dev_inst *serial, + uint8_t command, uint32_t data) { char buf[5]; @@ -125,19 +125,22 @@ static int send_longcommand(int fd, uint8_t command, uint32_t data) buf[2] = (data & 0xff0000) >> 16; buf[3] = (data & 0xff00) >> 8; buf[4] = data & 0xff; - if (serial_write(fd, buf, 5) != 5) + if (serial_write(serial, buf, 5) != 5) return SR_ERR; return SR_OK; } -static int configure_probes(struct dev_context *devc, const GSList *probes) +static int configure_probes(const struct sr_dev_inst *sdi) { + struct dev_context *devc; const struct sr_probe *probe; const GSList *l; int probe_bit, stage, i; char *tc; + devc = sdi->priv; + devc->probe_mask = 0; for (i = 0; i < NUM_TRIGGER_STAGES; i++) { devc->trigger_mask[i] = 0; @@ -145,7 +148,7 @@ static int configure_probes(struct dev_context *devc, const GSList *probes) } devc->num_stages = 0; - for (l = probes; l; l = l->next) { + for (l = sdi->probes; l; l = l->next) { probe = (const struct sr_probe *)l->data; if (!probe->enabled) continue; @@ -209,7 +212,6 @@ static struct dev_context *ols_dev_new(void) { struct dev_context *devc; - /* TODO: Is 'devc' ever g_free()'d? */ if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { sr_err("ols: %s: devc malloc failed", __func__); return NULL; @@ -223,7 +225,7 @@ static struct dev_context *ols_dev_new(void) return devc; } -static struct sr_dev_inst *get_metadata(int fd) +static struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) { struct sr_dev_inst *sdi; struct dev_context *devc; @@ -243,7 +245,7 @@ static struct sr_dev_inst *get_metadata(int fd) key = 0xff; while (key) { - if (serial_read(fd, &key, 1) != 1 || key == 0x00) + if (serial_read(serial, &key, 1) != 1 || key == 0x00) break; type = key >> 5; token = key & 0x1f; @@ -251,7 +253,7 @@ static struct sr_dev_inst *get_metadata(int fd) case 0: /* NULL-terminated string */ tmp_str = g_string_new(""); - while (serial_read(fd, &tmp_c, 1) == 1 && tmp_c != '\0') + while (serial_read(serial, &tmp_c, 1) == 1 && tmp_c != '\0') g_string_append_c(tmp_str, tmp_c); sr_dbg("ols: got metadata key 0x%.2x value '%s'", key, tmp_str->str); @@ -283,7 +285,7 @@ static struct sr_dev_inst *get_metadata(int fd) break; case 1: /* 32-bit unsigned integer */ - if (serial_read(fd, &tmp_int, 4) != 4) + if (serial_read(serial, &tmp_int, 4) != 4) break; tmp_int = reverse32(tmp_int); sr_dbg("ols: got metadata key 0x%.2x value 0x%.8x", @@ -322,7 +324,7 @@ static struct sr_dev_inst *get_metadata(int fd) break; case 2: /* 8-bit unsigned integer */ - if (serial_read(fd, &tmp_c, 1) != 1) + if (serial_read(serial, &tmp_c, 1) != 1) break; sr_dbg("ols: got metadata key 0x%.2x value 0x%.2x", key, tmp_c); @@ -360,14 +362,15 @@ static struct sr_dev_inst *get_metadata(int fd) return sdi; } -static int hw_init(void) +static int hw_init(struct sr_context *sr_ctx) { struct drv_context *drvc; if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) { sr_err("ols: driver context malloc failed."); - return SR_ERR; + return SR_ERR_MALLOC; } + drvc->sr_ctx = sr_ctx; odi->priv = drvc; return SR_OK; @@ -375,155 +378,129 @@ static int hw_init(void) static GSList *hw_scan(GSList *options) { + struct sr_hwopt *opt; struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; struct sr_probe *probe; - GSList *devices, *ports, *l; - GPollFD *fds, probefd; - int devcnt, final_devcnt, num_ports, fd, ret, i, j; - char buf[8], **dev_names, **serial_params; + struct sr_serial_dev_inst *serial; + GPollFD probefd; + GSList *l, *devices; + int ret, i; + const char *conn, *serialcomm; + char buf[8]; (void)options; drvc = odi->priv; - final_devcnt = 0; devices = NULL; - /* Scan all serial ports. */ - ports = list_serial_ports(); - num_ports = g_slist_length(ports); - - if (!(fds = g_try_malloc0(num_ports * sizeof(GPollFD)))) { - sr_err("ols: %s: fds malloc failed", __func__); - goto hw_init_free_ports; /* TODO: SR_ERR_MALLOC. */ + conn = serialcomm = NULL; + for (l = options; l; l = l->next) { + opt = l->data; + switch (opt->hwopt) { + case SR_HWOPT_CONN: + conn = opt->value; + break; + case SR_HWOPT_SERIALCOMM: + serialcomm = opt->value; + break; + } } + if (!conn) + return NULL; - if (!(dev_names = g_try_malloc(num_ports * sizeof(char *)))) { - sr_err("ols: %s: dev_names malloc failed", __func__); - goto hw_init_free_fds; /* TODO: SR_ERR_MALLOC. */ - } + if (serialcomm == NULL) + serialcomm = SERIALCOMM; - if (!(serial_params = g_try_malloc(num_ports * sizeof(char *)))) { - sr_err("ols: %s: serial_params malloc failed", __func__); - goto hw_init_free_dev_names; /* TODO: SR_ERR_MALLOC. */ - } + if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) + return NULL; - devcnt = 0; - for (l = ports; l; l = l->next) { - /* The discovery procedure is like this: first send the Reset - * command (0x00) 5 times, since the device could be anywhere - * in a 5-byte command. Then send the ID command (0x02). - * If the device responds with 4 bytes ("OLS1" or "SLA1"), we - * have a match. - * - * Since it may take the device a while to respond at 115Kb/s, - * we do all the sending first, then wait for all of them to - * respond with g_poll(). - */ - sr_info("ols: probing %s...", (char *)l->data); - fd = serial_open(l->data, O_RDWR | O_NONBLOCK); - if (fd != -1) { - serial_params[devcnt] = serial_backup_params(fd); - serial_set_params(fd, 115200, 8, SERIAL_PARITY_NONE, 1, 2); - ret = SR_OK; - for (i = 0; i < 5; i++) { - if ((ret = send_shortcommand(fd, - CMD_RESET)) != SR_OK) { - /* Serial port is not writable. */ - break; - } - } - if (ret != SR_OK) { - serial_restore_params(fd, - serial_params[devcnt]); - serial_close(fd); - continue; - } - send_shortcommand(fd, CMD_ID); - fds[devcnt].fd = fd; - fds[devcnt].events = G_IO_IN; - dev_names[devcnt] = g_strdup(l->data); - devcnt++; + /* The discovery procedure is like this: first send the Reset + * command (0x00) 5 times, since the device could be anywhere + * in a 5-byte command. Then send the ID command (0x02). + * If the device responds with 4 bytes ("OLS1" or "SLA1"), we + * have a match. + */ + sr_info("ols: probing %s .", conn); + if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) + return NULL; + + ret = SR_OK; + for (i = 0; i < 5; i++) { + if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) { + sr_err("ols: port %s is not writable.", conn); + break; } - g_free(l->data); } + if (ret != SR_OK) { + serial_close(serial); + sr_err("ols: Could not use port %s. Quitting.", conn); + return NULL; + } + send_shortcommand(serial, CMD_ID); - /* 2ms isn't enough for reliable transfer with pl2303, let's try 10 */ + /* Wait 10ms for a response. */ usleep(10000); - g_poll(fds, devcnt, 1); - - for (i = 0; i < devcnt; i++) { - if (fds[i].revents != G_IO_IN) - continue; - if (serial_read(fds[i].fd, buf, 4) != 4) - continue; - if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) - continue; - - /* definitely using the OLS protocol, check if it supports - * the metadata command - */ - send_shortcommand(fds[i].fd, CMD_METADATA); - probefd.fd = fds[i].fd; - probefd.events = G_IO_IN; - if (g_poll(&probefd, 1, 10) > 0) { - /* got metadata */ - sdi = get_metadata(fds[i].fd); - sdi->index = final_devcnt; - devc = sdi->priv; - } else { - /* not an OLS -- some other board that uses the sump protocol */ - sdi = sr_dev_inst_new(final_devcnt, SR_ST_INACTIVE, - "Sump", "Logic Analyzer", "v1.0"); - sdi->driver = odi; - devc = ols_dev_new(); - for (j = 0; j < 32; j++) { - if (!(probe = sr_probe_new(j, SR_PROBE_LOGIC, TRUE, - probe_names[j]))) - return 0; - sdi->probes = g_slist_append(sdi->probes, probe); - } - sdi->priv = devc; - } - devc->serial = sr_serial_dev_inst_new(dev_names[i], -1); - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); + probefd.fd = serial->fd; + probefd.events = G_IO_IN; + g_poll(&probefd, 1, 1); - final_devcnt++; - serial_close(fds[i].fd); - fds[i].fd = 0; - } + if (probefd.revents != G_IO_IN) + return NULL; + if (serial_read(serial, buf, 4) != 4) + return NULL; + if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) + return NULL; - /* clean up after all the probing */ - for (i = 0; i < devcnt; i++) { - if (fds[i].fd != 0) { - serial_restore_params(fds[i].fd, serial_params[i]); - serial_close(fds[i].fd); + /* Definitely using the OLS protocol, check if it supports + * the metadata command. + */ + send_shortcommand(serial, CMD_METADATA); + if (g_poll(&probefd, 1, 10) > 0) { + /* Got metadata. */ + sdi = get_metadata(serial); + sdi->index = 0; + devc = sdi->priv; + } else { + /* Not an OLS -- some other board that uses the sump protocol. */ + sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, + "Sump", "Logic Analyzer", "v1.0"); + sdi->driver = odi; + devc = ols_dev_new(); + for (i = 0; i < 32; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, + probe_names[i]))) + return 0; + sdi->probes = g_slist_append(sdi->probes, probe); } - g_free(serial_params[i]); - g_free(dev_names[i]); + sdi->priv = devc; } + devc->serial = serial; + drvc->instances = g_slist_append(drvc->instances, sdi); + devices = g_slist_append(devices, sdi); - g_free(serial_params); -hw_init_free_dev_names: - g_free(dev_names); -hw_init_free_fds: - g_free(fds); -hw_init_free_ports: - g_slist_free(ports); + serial_close(serial); return devices; } +static GSList *hw_dev_list(void) +{ + struct drv_context *drvc; + + drvc = odi->priv; + + return drvc->instances; +} + static int hw_dev_open(struct sr_dev_inst *sdi) { struct dev_context *devc; devc = sdi->priv; - devc->serial->fd = serial_open(devc->serial->port, O_RDWR); - if (devc->serial->fd == -1) + if (serial_open(devc->serial, SERIAL_RDWR) != SR_OK) return SR_ERR; sdi->status = SR_ST_ACTIVE; @@ -537,9 +514,8 @@ static int hw_dev_close(struct sr_dev_inst *sdi) devc = sdi->priv; - if (devc->serial->fd != -1) { - serial_close(devc->serial->fd); - devc->serial->fd = -1; + if (devc->serial && devc->serial->fd != -1) { + serial_close(devc->serial); sdi->status = SR_ST_INACTIVE; } @@ -572,9 +548,7 @@ static int hw_cleanup(void) ret = SR_ERR_BUG; continue; } - /* TODO: Check for serial != NULL. */ - if (devc->serial->fd != -1) - serial_close(devc->serial->fd); + hw_dev_close(sdi); sr_serial_dev_inst_free(devc->serial); sr_dev_inst_free(sdi); } @@ -667,9 +641,6 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, case SR_HWCAP_SAMPLERATE: ret = set_samplerate(sdi, *(const uint64_t *)value); break; - case SR_HWCAP_PROBECONFIG: - ret = configure_probes(devc, (const GSList *)value); - break; case SR_HWCAP_LIMIT_SAMPLES: tmp_u64 = value; if (*tmp_u64 < MIN_NUM_SAMPLES) @@ -702,6 +673,22 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, return ret; } +static void abort_acquisition(const struct sr_dev_inst *sdi) +{ + struct sr_datafeed_packet packet; + struct dev_context *devc; + + devc = sdi->priv; + sr_source_remove(devc->serial->fd); + + /* Terminate session */ + packet.type = SR_DF_END; + sr_session_send(sdi, &packet); + +} + + + static int receive_data(int fd, int revents, void *cb_data) { struct sr_datafeed_packet packet; @@ -720,9 +707,8 @@ static int receive_data(int fd, int revents, void *cb_data) for (l = drvc->instances; l; l = l->next) { sdi = l->data; devc = sdi->priv; - if (devc->serial->fd == fd) { + if (devc->serial->fd == fd) break; - } devc = NULL; } if (!devc) @@ -738,6 +724,7 @@ static int receive_data(int fd, int revents, void *cb_data) */ sr_source_remove(fd); sr_source_add(fd, G_IO_IN, 30, receive_data, cb_data); + /* TODO: Check malloc return code. */ devc->raw_sample_buf = g_try_malloc(devc->limit_samples * 4); if (!devc->raw_sample_buf) { sr_err("ols: %s: devc->raw_sample_buf malloc failed", @@ -755,7 +742,7 @@ static int receive_data(int fd, int revents, void *cb_data) } if (revents == G_IO_IN) { - if (serial_read(fd, &byte, 1) != 1) + if (serial_read(devc->serial, &byte, 1) != 1) return FALSE; /* Ignore it if we've read enough. */ @@ -876,10 +863,9 @@ static int receive_data(int fd, int revents, void *cb_data) } g_free(devc->raw_sample_buf); - serial_flush(fd); - serial_close(fd); - packet.type = SR_DF_END; - sr_session_send(cb_data, &packet); + serial_flush(devc->serial); + abort_acquisition(sdi); + serial_close(devc->serial); } return TRUE; @@ -904,6 +890,11 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, if (sdi->status != SR_ST_ACTIVE) return SR_ERR; + if (configure_probes(sdi) != SR_OK) { + sr_err("ols: failed to configured probes"); + return SR_ERR; + } + /* * Enable/disable channel groups in the flag register according to the * probe mask. Calculate this here, because num_channels is needed @@ -930,53 +921,53 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, delaycount = readcount * (1 - devc->capture_ratio / 100.0); devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_MASK_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0, reverse32(devc->trigger_mask[0])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_VALUE_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0, reverse32(devc->trigger_value[0])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_CONFIG_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0, trigger_config[0]) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_MASK_1, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_1, reverse32(devc->trigger_mask[1])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_VALUE_1, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_1, reverse32(devc->trigger_value[1])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_CONFIG_1, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_1, trigger_config[1]) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_MASK_2, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_2, reverse32(devc->trigger_mask[2])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_VALUE_2, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_2, reverse32(devc->trigger_value[2])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_CONFIG_2, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_2, trigger_config[2]) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_MASK_3, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_3, reverse32(devc->trigger_mask[3])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_VALUE_3, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_3, reverse32(devc->trigger_value[3])) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_CONFIG_3, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_3, trigger_config[3]) != SR_OK) return SR_ERR; } else { - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_MASK_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0, devc->trigger_mask[0]) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_VALUE_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0, devc->trigger_value[0]) != SR_OK) return SR_ERR; - if (send_longcommand(devc->serial->fd, CMD_SET_TRIGGER_CONFIG_0, + if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0, 0x00000008) != SR_OK) return SR_ERR; delaycount = readcount; @@ -985,14 +976,14 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, sr_info("ols: setting samplerate to %" PRIu64 " Hz (divider %u, " "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider, devc->flag_reg & FLAG_DEMUX ? "on" : "off"); - if (send_longcommand(devc->serial->fd, CMD_SET_DIVIDER, + if (send_longcommand(devc->serial, CMD_SET_DIVIDER, reverse32(devc->cur_samplerate_divider)) != SR_OK) return SR_ERR; /* Send sample limit and pre/post-trigger capture ratio. */ data = ((readcount - 1) & 0xffff) << 16; data |= (delaycount - 1) & 0xffff; - if (send_longcommand(devc->serial->fd, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK) + if (send_longcommand(devc->serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK) return SR_ERR; /* The flag register wants them here, and 1 means "disable channel". */ @@ -1000,11 +991,11 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, devc->flag_reg |= FLAG_FILTER; devc->rle_count = 0; data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000); - if (send_longcommand(devc->serial->fd, CMD_SET_FLAGS, data) != SR_OK) + if (send_longcommand(devc->serial, CMD_SET_FLAGS, data) != SR_OK) return SR_ERR; /* Start acquisition on the device. */ - if (send_shortcommand(devc->serial->fd, CMD_RUN) != SR_OK) + if (send_shortcommand(devc->serial, CMD_RUN) != SR_OK) return SR_ERR; sr_source_add(devc->serial->fd, G_IO_IN, -1, receive_data, @@ -1042,16 +1033,12 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, } /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */ -static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi, - void *cb_data) +static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { - struct sr_datafeed_packet packet; - /* Avoid compiler warnings. */ - (void)sdi; + (void)cb_data; - packet.type = SR_DF_END; - sr_session_send(cb_data, &packet); + abort_acquisition(sdi); return SR_OK; } @@ -1063,6 +1050,8 @@ SR_PRIV struct sr_dev_driver ols_driver_info = { .init = hw_init, .cleanup = hw_cleanup, .scan = hw_scan, + .dev_list = hw_dev_list, + .dev_clear = hw_cleanup, .dev_open = hw_dev_open, .dev_close = hw_dev_close, .info_get = hw_info_get,