static int dev_open(struct sr_dev_inst *sdi) { struct sr_dev_driver *di = sdi->driver; struct dev_context *devc; struct drv_context *drvc; struct sr_usb_dev_inst *usb; libusb_device **devlist, *dev; int device_count, ret, i; char connection_id[64]; drvc = di->context; usb = sdi->conn; if (!(devc = sdi->priv)) { sr_err("%s: sdi->priv was NULL", __func__); return SR_ERR_ARG; } device_count = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); if (device_count < 0) { sr_err("Failed to retrieve device list."); return SR_ERR; } dev = NULL; for (i = 0; i < device_count; i++) { usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); if (!strcmp(sdi->connection_id, connection_id)) { dev = devlist[i]; break; } } if (!dev) { sr_err("Device on %d.%d (logical) / %s (physical) disappeared!", usb->bus, usb->address, sdi->connection_id); return SR_ERR; } if (!(ret = libusb_open(dev, &(usb->devhdl)))) { sdi->status = SR_ST_ACTIVE; sr_info("Opened device on %d.%d (logical) / %s (physical) interface %d.", usb->bus, usb->address, sdi->connection_id, USB_INTERFACE); } else { sr_err("Failed to open device: %s.", libusb_error_name(ret)); return SR_ERR; } ret = libusb_set_configuration(usb->devhdl, USB_CONFIGURATION); if (ret < 0) { sr_err("Unable to set USB configuration %d: %s.", USB_CONFIGURATION, libusb_error_name(ret)); return SR_ERR; } ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE); if (ret != 0) { sr_err("Unable to claim interface: %s.", libusb_error_name(ret)); return SR_ERR; } /* Set default configuration after power on. */ if (analyzer_read_status(usb->devhdl) == 0) analyzer_configure(usb->devhdl); analyzer_reset(usb->devhdl); analyzer_initialize(usb->devhdl); //analyzer_set_memory_size(MEMORY_SIZE_512K); // analyzer_set_freq(g_freq, g_freq_scale); analyzer_set_trigger_count(1); // analyzer_set_ramsize_trigger_address((((100 - g_pre_trigger) // * get_memory_size(g_memory_size)) / 100) >> 2); #if 0 if (g_double_mode == 1) analyzer_set_compression(COMPRESSION_DOUBLE); else if (g_compression == 1) analyzer_set_compression(COMPRESSION_ENABLE); else #endif analyzer_set_compression(COMPRESSION_NONE); if (devc->cur_samplerate == 0) { /* Samplerate hasn't been set. Default to 1MHz. */ analyzer_set_freq(1, FREQ_SCALE_MHZ); devc->cur_samplerate = SR_MHZ(1); } if (devc->cur_threshold == 0) set_voltage_threshold(devc, 1.5); return SR_OK; }
static int receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct session_vdev *vdev; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct zip_stat zs; GSList *l; int ret, got_data; char capturefile[16]; void *buf; (void)fd; (void)revents; got_data = FALSE; for (l = dev_insts; l; l = l->next) { sdi = l->data; if (!(vdev = sdi->priv)) /* Already done with this instance. */ continue; if (!(buf = g_try_malloc(CHUNKSIZE))) { sr_err("%s: buf malloc failed", __func__); return FALSE; } if (!vdev->capfile) { /* No capture file opened yet, or finished with the last * chunked one. */ if (vdev->cur_chunk == 0) { /* capturefile is always the unchunked base name. */ if (zip_stat(vdev->archive, vdev->capturefile, 0, &zs) != -1) { /* No chunks, just a single capture file. */ vdev->cur_chunk = 0; if (!(vdev->capfile = zip_fopen(vdev->archive, vdev->capturefile, 0))) return FALSE; sr_dbg("Opened %s.", vdev->capturefile); } else { /* Try as first chunk filename. */ snprintf(capturefile, 15, "%s-1", vdev->capturefile); if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { vdev->cur_chunk = 1; if (!(vdev->capfile = zip_fopen(vdev->archive, capturefile, 0))) return FALSE; sr_dbg("Opened %s.", capturefile); } else { sr_err("No capture file '%s' in " "session file '%s'.", vdev->capturefile, vdev->sessionfile); return FALSE; } } } else { /* Capture data is chunked, advance to the next chunk. */ vdev->cur_chunk++; snprintf(capturefile, 15, "%s-%d", vdev->capturefile, vdev->cur_chunk); if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { if (!(vdev->capfile = zip_fopen(vdev->archive, capturefile, 0))) return FALSE; sr_dbg("Opened %s.", capturefile); } else { /* We got all the chunks, finish up. */ g_free(vdev->capturefile); g_free(vdev); sdi->priv = NULL; continue; } } } ret = zip_fread(vdev->capfile, buf, CHUNKSIZE); if (ret > 0) { got_data = TRUE; packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = ret; logic.unitsize = vdev->unitsize; logic.data = buf; vdev->bytes_read += ret; sr_session_send(cb_data, &packet); } else { /* done with this capture file */ zip_fclose(vdev->capfile); vdev->capfile = NULL; if (vdev->cur_chunk == 0) { /* It was the only file. */ g_free(vdev->capturefile); g_free(vdev); sdi->priv = NULL; } else { /* There might be more chunks, so don't fall through * to the SR_DF_END here. */ return TRUE; } } } if (!got_data) { packet.type = SR_DF_END; sr_session_send(cb_data, &packet); sr_session_source_remove(-1); } return TRUE; }
/** * Create a new output instance using the specified output module. * * <code>options</code> is a *HashTable with the keys corresponding with * the module options' <code>id</code> field. The values should be GVariant * pointers with sunk * references, of the same GVariantType as the option's * default value. * * The sr_dev_inst passed in can be used by the instance to determine * channel names, samplerate, and so on. * * @since 0.4.0 */ SR_API const struct sr_output *sr_output_new(const struct sr_output_module *omod, GHashTable *options, const struct sr_dev_inst *sdi, const char *filename) { struct sr_output *op; const struct sr_option *mod_opts; const GVariantType *gvt; GHashTable *new_opts; GHashTableIter iter; gpointer key, value; int i; op = g_malloc(sizeof(struct sr_output)); op->module = omod; op->sdi = sdi; op->filename = g_strdup(filename); new_opts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); if (omod->options) { mod_opts = omod->options(); for (i = 0; mod_opts[i].id; i++) { if (options && g_hash_table_lookup_extended(options, mod_opts[i].id, &key, &value)) { /* Pass option along. */ gvt = g_variant_get_type(mod_opts[i].def); if (!g_variant_is_of_type(value, gvt)) { sr_err("Invalid type for '%s' option.", (char *)key); g_free(op); return NULL; } g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id), g_variant_ref(value)); } else { /* Option not given: insert the default value. */ g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id), g_variant_ref(mod_opts[i].def)); } } /* Make sure no invalid options were given. */ if (options) { g_hash_table_iter_init(&iter, options); while (g_hash_table_iter_next(&iter, &key, &value)) { if (!g_hash_table_lookup(new_opts, key)) { sr_err("Output module '%s' has no option '%s'", omod->id, (char *)key); g_hash_table_destroy(new_opts); g_free(op); return NULL; } } } } if (op->module->init && op->module->init(op, new_opts) != SR_OK) { g_free(op); op = NULL; } if (new_opts) g_hash_table_destroy(new_opts); return op; }
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; struct sr_channel *ch; const char *tmp_str; uint64_t samplerate; int analog_channel = -1; float smallest_diff = INFINITY; int idx = -1; unsigned i; if (!sdi) return SR_ERR_ARG; devc = sdi->priv; /* If a channel group is specified, it must be a valid one. */ if (cg && !g_slist_find(sdi->channel_groups, cg)) { sr_err("Invalid channel group specified."); return SR_ERR; } if (cg) { ch = g_slist_nth_data(cg->channels, 0); if (!ch) return SR_ERR; if (ch->type == SR_CHANNEL_ANALOG) { if (ch->name[2] < '1' || ch->name[2] > '4') return SR_ERR; analog_channel = ch->name[2] - '1'; } } switch (key) { case SR_CONF_NUM_HDIV: *data = g_variant_new_int32(devc->model->series->num_horizontal_divs); break; case SR_CONF_NUM_VDIV: *data = g_variant_new_int32(devc->num_vdivs); break; case SR_CONF_DATA_SOURCE: if (devc->data_source == DATA_SOURCE_LIVE) *data = g_variant_new_string("Live"); else if (devc->data_source == DATA_SOURCE_MEMORY) *data = g_variant_new_string("Memory"); else *data = g_variant_new_string("Segmented"); break; case SR_CONF_SAMPLERATE: if (devc->data_source == DATA_SOURCE_LIVE) { samplerate = analog_frame_size(sdi) / (devc->timebase * devc->model->series->num_horizontal_divs); *data = g_variant_new_uint64(samplerate); } else { sr_dbg("Unknown data source: %d.", devc->data_source); return SR_ERR_NA; } break; case SR_CONF_TRIGGER_SOURCE: if (!strcmp(devc->trigger_source, "ACL")) tmp_str = "AC Line"; else if (!strcmp(devc->trigger_source, "CHAN1")) tmp_str = "CH1"; else if (!strcmp(devc->trigger_source, "CHAN2")) tmp_str = "CH2"; else if (!strcmp(devc->trigger_source, "CHAN3")) tmp_str = "CH3"; else if (!strcmp(devc->trigger_source, "CHAN4")) tmp_str = "CH4"; else tmp_str = devc->trigger_source; *data = g_variant_new_string(tmp_str); break; case SR_CONF_TRIGGER_SLOPE: if (!strncmp(devc->trigger_slope, "POS", 3)) { tmp_str = "r"; } else if (!strncmp(devc->trigger_slope, "NEG", 3)) { tmp_str = "f"; } else { sr_dbg("Unknown trigger slope: '%s'.", devc->trigger_slope); return SR_ERR_NA; } *data = g_variant_new_string(tmp_str); break; case SR_CONF_TRIGGER_LEVEL: *data = g_variant_new_double(devc->trigger_level); break; case SR_CONF_TIMEBASE: for (i = 0; i < devc->num_timebases; i++) { float tb = (float)devc->timebases[i][0] / devc->timebases[i][1]; float diff = fabs(devc->timebase - tb); if (diff < smallest_diff) { smallest_diff = diff; idx = i; } } if (idx < 0) { sr_dbg("Negative timebase index: %d.", idx); return SR_ERR_NA; } *data = g_variant_new("(tt)", devc->timebases[idx][0], devc->timebases[idx][1]); break; case SR_CONF_VDIV: if (analog_channel < 0) { sr_dbg("Negative analog channel: %d.", analog_channel); return SR_ERR_NA; } for (i = 0; i < ARRAY_SIZE(vdivs); i++) { float vdiv = (float)vdivs[i][0] / vdivs[i][1]; float diff = fabs(devc->vdiv[analog_channel] - vdiv); if (diff < smallest_diff) { smallest_diff = diff; idx = i; } } if (idx < 0) { sr_dbg("Negative vdiv index: %d.", idx); return SR_ERR_NA; } *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]); break; case SR_CONF_COUPLING: if (analog_channel < 0) { sr_dbg("Negative analog channel: %d.", analog_channel); return SR_ERR_NA; } *data = g_variant_new_string(devc->coupling[analog_channel]); break; case SR_CONF_PROBE_FACTOR: if (analog_channel < 0) { sr_dbg("Negative analog channel: %d.", analog_channel); return SR_ERR_NA; } *data = g_variant_new_uint64(devc->attenuation[analog_channel]); break; default: return SR_ERR_NA; } return SR_OK; }
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { GVariant *tuple, *rational[2]; GVariantBuilder gvb; unsigned int i; struct dev_context *devc = NULL; if (key == SR_CONF_SCAN_OPTIONS) { *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t)); return SR_OK; } else if (key == SR_CONF_DEVICE_OPTIONS && !cg) { *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); return SR_OK; } /* Every other option requires a valid device instance. */ if (!sdi) return SR_ERR_ARG; devc = sdi->priv; /* If a channel group is specified, it must be a valid one. */ if (cg && !g_slist_find(sdi->channel_groups, cg)) { sr_err("Invalid channel group specified."); return SR_ERR; } switch (key) { case SR_CONF_DEVICE_OPTIONS: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } if (cg == devc->digital_group) { *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, NULL, 0, sizeof(uint32_t)); return SR_OK; } else { for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, analog_devopts, ARRAY_SIZE(analog_devopts), sizeof(uint32_t)); return SR_OK; } } return SR_ERR_NA; } break; case SR_CONF_COUPLING: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling)); break; case SR_CONF_PROBE_FACTOR: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64, probe_factor, ARRAY_SIZE(probe_factor), sizeof(uint64_t)); break; case SR_CONF_VDIV: if (!devc) /* Can't know this until we have the exact model. */ return SR_ERR_ARG; if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); for (i = 0; i < devc->num_vdivs; i++) { rational[0] = g_variant_new_uint64(devc->vdivs[i][0]); rational[1] = g_variant_new_uint64(devc->vdivs[i][1]); tuple = g_variant_new_tuple(rational, 2); g_variant_builder_add_value(&gvb, tuple); } *data = g_variant_builder_end(&gvb); break; case SR_CONF_TIMEBASE: if (!devc) /* Can't know this until we have the exact model. */ return SR_ERR_ARG; if (devc->num_timebases <= 0) return SR_ERR_NA; g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); for (i = 0; i < devc->num_timebases; i++) { rational[0] = g_variant_new_uint64(devc->timebases[i][0]); rational[1] = g_variant_new_uint64(devc->timebases[i][1]); tuple = g_variant_new_tuple(rational, 2); g_variant_builder_add_value(&gvb, tuple); } *data = g_variant_builder_end(&gvb); break; case SR_CONF_TRIGGER_SOURCE: if (!devc) /* Can't know this until we have the exact model. */ return SR_ERR_ARG; *data = g_variant_new_strv(trigger_sources, devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4); break; case SR_CONF_TRIGGER_SLOPE: *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes)); break; case SR_CONF_DATA_SOURCE: if (!devc) /* Can't know this until we have the exact model. */ return SR_ERR_ARG; switch (devc->model->series->protocol) { case PROTOCOL_V1: *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2); break; case PROTOCOL_V2: *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1); break; default: *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources)); break; } break; default: return SR_ERR_NA; } return SR_OK; }
/* USB output transfer completion callback. */ static void LIBUSB_CALL transfer_out_completed(struct libusb_transfer *transfer) { const struct sr_dev_inst *sdi; struct dev_context *devc; struct acquisition_state *acq; sdi = transfer->user_data; devc = sdi->priv; acq = devc->acquisition; if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { sr_err("Transfer to device failed (state %d): %s.", devc->state, libusb_error_name(transfer->status)); devc->transfer_error = TRUE; return; } /* If this was a read request, wait for the response. */ if ((devc->state & STATE_EXPECT_RESPONSE) != 0) { submit_transfer(devc, acq->xfer_in); return; } if (acq->reg_seq_pos < acq->reg_seq_len) acq->reg_seq_pos++; /* register write completed */ /* Repeat until all queued registers have been written. */ if (acq->reg_seq_pos < acq->reg_seq_len && !devc->cancel_requested) { next_reg_write(acq); submit_transfer(devc, acq->xfer_out); return; } switch (devc->state) { case STATE_START_CAPTURE: sr_info("Acquisition started."); if (!devc->cancel_requested) devc->state = STATE_STATUS_WAIT; else submit_request(sdi, STATE_STOP_CAPTURE); break; case STATE_STOP_CAPTURE: if (!devc->cancel_requested) submit_request(sdi, STATE_LENGTH_REQUEST); else devc->state = STATE_IDLE; break; case STATE_READ_PREPARE: if (acq->mem_addr_next < acq->mem_addr_stop && !devc->cancel_requested) submit_request(sdi, STATE_READ_REQUEST); else submit_request(sdi, STATE_READ_FINISH); break; case STATE_READ_FINISH: devc->state = STATE_IDLE; break; default: sr_err("Unexpected device state %d.", devc->state); devc->transfer_error = TRUE; break; } }
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; uint64_t tmp_u64, low, high; unsigned int i; int tmp, ret; const char *tmp_str; (void)cg; 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; } ret = SR_OK; switch (key) { case SR_CONF_LIMIT_SAMPLES: tmp_u64 = g_variant_get_uint64(data); devc->limit_samples = tmp_u64; ret = SR_OK; break; case SR_CONF_DATALOG: ret = cem_dt_885x_recording_set(sdi, g_variant_get_boolean(data)); break; case SR_CONF_SPL_WEIGHT_FREQ: tmp_str = g_variant_get_string(data, NULL); if (!strcmp(tmp_str, "A")) ret = cem_dt_885x_weight_freq_set(sdi, SR_MQFLAG_SPL_FREQ_WEIGHT_A); else if (!strcmp(tmp_str, "C")) ret = cem_dt_885x_weight_freq_set(sdi, SR_MQFLAG_SPL_FREQ_WEIGHT_C); else return SR_ERR_ARG; break; case SR_CONF_SPL_WEIGHT_TIME: tmp_str = g_variant_get_string(data, NULL); if (!strcmp(tmp_str, "F")) ret = cem_dt_885x_weight_time_set(sdi, SR_MQFLAG_SPL_TIME_WEIGHT_F); else if (!strcmp(tmp_str, "S")) ret = cem_dt_885x_weight_time_set(sdi, SR_MQFLAG_SPL_TIME_WEIGHT_S); else return SR_ERR_ARG; break; case SR_CONF_HOLD_MAX: tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MAX : 0; ret = cem_dt_885x_holdmode_set(sdi, tmp); break; case SR_CONF_HOLD_MIN: tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MIN : 0; ret = cem_dt_885x_holdmode_set(sdi, tmp); break; case SR_CONF_SPL_MEASUREMENT_RANGE: g_variant_get(data, "(tt)", &low, &high); ret = SR_ERR_ARG; for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { if (meas_ranges[i][0] == low && meas_ranges[i][1] == high) { ret = cem_dt_885x_meas_range_set(sdi, low, high); break; } } break; case SR_CONF_POWER_OFF: if (g_variant_get_boolean(data)) ret = cem_dt_885x_power_off(sdi); break; case SR_CONF_DATA_SOURCE: tmp_str = g_variant_get_string(data, NULL); if (!strcmp(tmp_str, "Live")) devc->cur_data_source = DATA_SOURCE_LIVE; else if (!strcmp(tmp_str, "Memory")) devc->cur_data_source = DATA_SOURCE_MEMORY; else return SR_ERR; devc->enable_data_source_memory = devc->cur_data_source == DATA_SOURCE_MEMORY; break; default: ret = SR_ERR_NA; } return ret; }
/** * Process received line. It consists of 20 hex digits + \\r\\n, * e.g. '08100400018100400000'. */ static void nma_process_line(const struct sr_dev_inst *sdi) { struct dev_context *devc; int pos, flags; int vt, range; /* Measurement value type, range in device format */ int mmode, devstat; /* Measuring mode, device status */ float value; /* Measured value */ float scale; /* Scaling factor depending on range and function */ struct sr_datafeed_analog analog; struct sr_datafeed_packet packet; devc = sdi->priv; devc->buf[20] = '\0'; sr_spew("Received line '%s'.", devc->buf); /* Check line. */ if (strlen((const char *)devc->buf) != 20) { sr_err("line: Invalid status '%s', must be 20 hex digits.", devc->buf); devc->buflen = 0; return; } for (pos = 0; pos < 20; pos++) { if (!isxdigit(devc->buf[pos])) { sr_err("line: Expected hex digit in '%s' at pos %d!", devc->buf, pos); devc->buflen = 0; return; } } /* Start decoding. */ value = 0.0; scale = 1.0; memset(&analog, 0, sizeof(analog)); /* * The numbers are hex digits, starting from 0. * 0: Keyboard status, currently not interesting. * 1: Central switch status, currently not interesting. * 2: Type of measured value. */ vt = xgittoint(devc->buf[2]); switch (vt) { case 0: analog.mq = SR_MQ_VOLTAGE; break; case 1: analog.mq = SR_MQ_CURRENT; /* 2A */ break; case 2: analog.mq = SR_MQ_RESISTANCE; break; case 3: analog.mq = SR_MQ_CAPACITANCE; break; case 4: analog.mq = SR_MQ_TEMPERATURE; break; case 5: analog.mq = SR_MQ_FREQUENCY; break; case 6: analog.mq = SR_MQ_CURRENT; /* 10A */ break; case 7: analog.mq = SR_MQ_GAIN; /* TODO: Scale factor */ break; case 8: analog.mq = SR_MQ_GAIN; /* Percentage */ scale /= 100.0; break; case 9: analog.mq = SR_MQ_GAIN; /* dB */ scale /= 100.0; break; default: sr_err("Unknown value type: 0x%02x.", vt); break; } /* 3: Measurement range for measured value */ range = xgittoint(devc->buf[3]); switch (vt) { case 0: /* V */ scale *= pow(10.0, range - 5); break; case 1: /* A */ scale *= pow(10.0, range - 7); break; case 2: /* Ω */ scale *= pow(10.0, range - 2); break; case 3: /* F */ scale *= pow(10.0, range - 12); break; case 4: /* °C */ scale *= pow(10.0, range - 1); break; case 5: /* Hz */ scale *= pow(10.0, range - 2); break; // No default, other value types have fixed display format. } /* 5: Sign and 1st digit */ flags = xgittoint(devc->buf[5]); value = (flags & 0x03); if (flags & 0x04) scale *= -1; /* 6-9: 2nd-4th digit */ for (pos = 6; pos < 10; pos++) value = value * 10 + xgittoint(devc->buf[pos]); value *= scale; /* 10: Display counter */ mmode = xgittoint(devc->buf[10]); switch (mmode) { case 0: /* Frequency */ analog.unit = SR_UNIT_HERTZ; break; case 1: /* V TRMS, only type 5 */ analog.unit = SR_UNIT_VOLT; analog.mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 2: /* V AC */ analog.unit = SR_UNIT_VOLT; analog.mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.mqflags |= SR_MQFLAG_RMS; break; case 3: /* V DC */ analog.unit = SR_UNIT_VOLT; analog.mqflags |= SR_MQFLAG_DC; break; case 4: /* Ohm */ analog.unit = SR_UNIT_OHM; break; case 5: /* Continuity */ analog.unit = SR_UNIT_BOOLEAN; analog.mq = SR_MQ_CONTINUITY; /* TODO: Continuity handling is a bit odd in libsigrok. */ break; case 6: /* Degree Celsius */ analog.unit = SR_UNIT_CELSIUS; break; case 7: /* Capacity */ analog.unit = SR_UNIT_FARAD; break; case 8: /* Current DC */ analog.unit = SR_UNIT_AMPERE; analog.mqflags |= SR_MQFLAG_DC; break; case 9: /* Current AC */ analog.unit = SR_UNIT_AMPERE; analog.mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.mqflags |= SR_MQFLAG_RMS; break; case 0xa: /* Current TRMS, only type 5 */ analog.unit = SR_UNIT_AMPERE; analog.mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 0xb: /* Diode */ analog.unit = SR_UNIT_VOLT; analog.mqflags |= (SR_MQFLAG_DIODE | SR_MQFLAG_DC); break; default: sr_err("Unknown mmode: 0x%02x.", mmode); break; } /* 11: Device status */ devstat = xgittoint(devc->buf[11]); switch (devstat) { case 1: /* Normal measurement */ break; case 2: /* Input loop (limit, reference values) */ break; case 3: /* TRANS/SENS */ break; case 4: /* Error */ sr_err("Device error. Fuse?"); /* TODO: Really abort? */ devc->buflen = 0; return; /* Cannot continue. */ default: sr_err("Unknown device status: 0x%02x", devstat); break; } /* 12-19: Flags and display symbols */ /* 12, 13 */ flags = (xgittoint(devc->buf[12]) << 8) | xgittoint(devc->buf[13]); /* 0x80: PRINT TODO: Stop polling when discovered? */ /* 0x40: EXTR */ if (analog.mq == SR_MQ_CONTINUITY) { if (flags & 0x20) value = 1.0; /* Beep */ else value = 0.0; } /* 0x10: AVG */ /* 0x08: Diode */ if (flags & 0x04) /* REL */ analog.mqflags |= SR_MQFLAG_RELATIVE; /* 0x02: SHIFT */ if (flags & 0x01) /* % */ analog.unit = SR_UNIT_PERCENTAGE; /* 14, 15 */ flags = (xgittoint(devc->buf[14]) << 8) | xgittoint(devc->buf[15]); if (!(flags & 0x80)) /* MAN: Manual range */ analog.mqflags |= SR_MQFLAG_AUTORANGE; if (flags & 0x40) /* LOBATT1: Low battery, measurement still within specs */ devc->lowbatt = 1; /* 0x20: PEAK */ /* 0x10: COUNT */ if (flags & 0x08) /* HOLD */ analog.mqflags |= SR_MQFLAG_HOLD; /* 0x04: LIMIT */ if (flags & 0x02) /* MAX */ analog.mqflags |= SR_MQFLAG_MAX; if (flags & 0x01) /* MIN */ analog.mqflags |= SR_MQFLAG_MIN; /* 16, 17 */ flags = (xgittoint(devc->buf[16]) << 8) | xgittoint(devc->buf[17]); /* 0xe0: undefined */ if (flags & 0x10) { /* LOBATT2: Low battery, measurement inaccurate */ devc->lowbatt = 2; sr_warn("Low battery, measurement quality degraded!"); } /* 0x08: SCALED */ /* 0x04: RATE (=lower resolution, allows higher rata rate up to 10/s. */ /* 0x02: Current clamp */ if (flags & 0x01) { /* dB */ /* * TODO: The Norma has an adjustable dB reference value. If * changed from default, this is not correct. */ if (analog.unit == SR_UNIT_VOLT) analog.unit = SR_UNIT_DECIBEL_VOLT; else analog.unit = SR_UNIT_UNITLESS; } /* 18, 19 */ /* flags = (xgittoint(devc->buf[18]) << 8) | xgittoint(devc->buf[19]); */ /* 0x80: Undefined. */ /* 0x40: Remote mode, keyboard locked */ /* 0x38: Undefined. */ /* 0x04: MIN > MAX */ /* 0x02: Measured value < Min */ /* 0x01: Measured value > Max */ /* 4: Flags. Evaluating this after setting value! */ flags = xgittoint(devc->buf[4]); if (flags & 0x04) /* Invalid value */ value = NAN; else if (flags & 0x01) /* Overload */ value = INFINITY; if (flags & 0x02) { /* Duplicate value, has been sent before. */ sr_spew("Duplicate value, dismissing!"); devc->buflen = 0; return; } sr_spew("range=%d/scale=%f/value=%f", range, (double)scale, (double)value); /* Finish and send packet. */ analog.probes = sdi->probes; analog.num_samples = 1; analog.data = &value; memset(&packet, 0, sizeof(packet)); packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(devc->cb_data, &packet); /* Finish processing. */ devc->num_samples++; devc->buflen = 0; }
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 int dev_open(struct sr_dev_inst *sdi) { struct dev_context *devc; int ret; devc = sdi->priv; /* Select interface A, otherwise communication will fail. */ ret = ftdi_set_interface(devc->ftdic, INTERFACE_A); if (ret < 0) { sr_err("Failed to set FTDI interface A (%d): %s", ret, ftdi_get_error_string(devc->ftdic)); return SR_ERR; } sr_dbg("FTDI chip interface A set successfully."); /* Open the device. */ ret = ftdi_usb_open_desc(devc->ftdic, USB_VENDOR_ID, USB_DEVICE_ID, USB_IPRODUCT, NULL); if (ret < 0) { sr_err("Failed to open device (%d): %s", ret, ftdi_get_error_string(devc->ftdic)); return SR_ERR; } sr_dbg("FTDI device opened successfully."); /* Purge RX/TX buffers in the FTDI chip. */ if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) { sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); goto err_dev_open_close_ftdic; } sr_dbg("FTDI chip buffers purged successfully."); /* Reset the FTDI bitmode. */ ret = ftdi_set_bitmode(devc->ftdic, 0xff, BITMODE_RESET); if (ret < 0) { sr_err("Failed to reset the FTDI chip bitmode (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); goto err_dev_open_close_ftdic; } sr_dbg("FTDI chip bitmode reset successfully."); /* Set FTDI bitmode to "sync FIFO". */ ret = ftdi_set_bitmode(devc->ftdic, 0xff, BITMODE_SYNCFF); if (ret < 0) { sr_err("Failed to put FTDI chip into sync FIFO mode (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); goto err_dev_open_close_ftdic; } sr_dbg("FTDI chip sync FIFO mode entered successfully."); /* Set the FTDI latency timer to 2. */ ret = ftdi_set_latency_timer(devc->ftdic, 2); if (ret < 0) { sr_err("Failed to set FTDI latency timer (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); goto err_dev_open_close_ftdic; } sr_dbg("FTDI chip latency timer set successfully."); /* Set the FTDI read data chunk size to 64kB. */ ret = ftdi_read_data_set_chunksize(devc->ftdic, 64 * 1024); if (ret < 0) { sr_err("Failed to set FTDI read data chunk size (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); goto err_dev_open_close_ftdic; } sr_dbg("FTDI chip read data chunk size set successfully."); /* Get the ScanaPLUS device ID from the FTDI EEPROM. */ if ((ret = scanaplus_get_device_id(devc)) < 0) { sr_err("Failed to get ScanaPLUS device ID: %d.", ret); goto err_dev_open_close_ftdic; } sr_dbg("Received ScanaPLUS device ID successfully: %02x %02x %02x.", devc->devid[0], devc->devid[1], devc->devid[2]); sdi->status = SR_ST_ACTIVE; return SR_OK; err_dev_open_close_ftdic: scanaplus_close(devc); return SR_ERR; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct dev_context *devc; unsigned int i; int ret; (void)options; /* Allocate memory for our private device context. */ devc = g_malloc0(sizeof(struct dev_context)); /* Allocate memory for the incoming compressed samples. */ if (!(devc->compressed_buf = g_try_malloc0(COMPRESSED_BUF_SIZE))) { sr_err("compressed_buf malloc failed."); goto err_free_devc; } /* Allocate memory for the uncompressed samples. */ if (!(devc->sample_buf = g_try_malloc0(SAMPLE_BUF_SIZE))) { sr_err("sample_buf malloc failed."); goto err_free_compressed_buf; } /* Allocate memory for the FTDI context (ftdic) and initialize it. */ if (!(devc->ftdic = ftdi_new())) { sr_err("Failed to initialize libftdi."); goto err_free_sample_buf; } /* Check for the device and temporarily open it. */ ret = ftdi_usb_open_desc(devc->ftdic, USB_VENDOR_ID, USB_DEVICE_ID, USB_IPRODUCT, NULL); if (ret < 0) { /* Log errors, except for -3 ("device not found"). */ if (ret != -3) sr_err("Failed to open device (%d): %s", ret, ftdi_get_error_string(devc->ftdic)); goto err_free_ftdic; } /* Register the device with libsigrok. */ sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(USB_VENDOR_NAME); sdi->model = g_strdup(USB_MODEL_NAME); sdi->priv = devc; for (i = 0; i < ARRAY_SIZE(channel_names); i++) sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]); /* Close device. We'll reopen it again when we need it. */ scanaplus_close(devc); return std_scan_complete(di, g_slist_append(NULL, sdi)); scanaplus_close(devc); err_free_ftdic: ftdi_free(devc->ftdic); /* NOT free() or g_free()! */ err_free_sample_buf: g_free(devc->sample_buf); err_free_compressed_buf: g_free(devc->compressed_buf); err_free_devc: g_free(devc); return NULL; }
/** * Set serial parameters for the specified serial port. * * @param serial Previously initialized serial port structure. * @param baudrate The baudrate to set. * @param bits The number of data bits to use. * @param parity The parity setting to use (0 = none, 1 = even, 2 = odd). * @param stopbits The number of stop bits to use (1 or 2). * @param flowcontrol The flow control settings to use (0 = none, 1 = RTS/CTS, * 2 = XON/XOFF). * * @return SR_OK upon success, SR_ERR upon failure. */ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate, int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr) { int ret; char *error; struct sp_port_config *config; if (!serial) { sr_dbg("Invalid serial port."); return SR_ERR; } if (serial->fd == -1) { sr_dbg("Cannot configure unopened serial port %s (fd %d).", serial->port, serial->fd); return SR_ERR; } sr_spew("Setting serial parameters on port %s (fd %d).", serial->port, serial->fd); sp_new_config(&config); sp_set_config_baudrate(config, baudrate); sp_set_config_bits(config, bits); switch (parity) { case 0: sp_set_config_parity(config, SP_PARITY_NONE); break; case 1: sp_set_config_parity(config, SP_PARITY_EVEN); break; case 2: sp_set_config_parity(config, SP_PARITY_ODD); break; default: return SR_ERR_ARG; } sp_set_config_stopbits(config, stopbits); sp_set_config_rts(config, flowcontrol == 1 ? SP_RTS_FLOW_CONTROL : rts); sp_set_config_cts(config, flowcontrol == 1 ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE); sp_set_config_dtr(config, dtr); sp_set_config_dsr(config, SP_DSR_IGNORE); sp_set_config_xon_xoff(config, flowcontrol == 2 ? SP_XONXOFF_INOUT : SP_XONXOFF_DISABLED); ret = sp_set_config(serial->data, config); sp_free_config(config); switch (ret) { case SP_ERR_ARG: sr_err("Invalid arguments for setting serial port parameters."); return SR_ERR_ARG; case SP_ERR_FAIL: error = sp_last_error_message(); sr_err("Error setting serial port parameters: %s.", error); sp_free_error_message(error); return SR_ERR; } return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; unsigned int samples_read; int res; unsigned int packet_num, n; unsigned char *buf; unsigned int status; unsigned int stop_address; unsigned int now_address; unsigned int trigger_address; unsigned int trigger_offset; unsigned int triggerbar; unsigned int ramsize_trigger; unsigned int memory_size; unsigned int valid_samples; unsigned int discard; int trigger_now; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; if (!(devc = sdi->priv)) { sr_err("%s: sdi->priv was NULL", __func__); return SR_ERR_ARG; } if (analyzer_add_triggers(sdi) != SR_OK) { sr_err("Failed to configure triggers."); return SR_ERR; } usb = sdi->conn; set_triggerbar(devc); /* Push configured settings to device. */ analyzer_configure(usb->devhdl); analyzer_start(usb->devhdl); sr_info("Waiting for data."); analyzer_wait_data(usb->devhdl); status = analyzer_read_status(usb->devhdl); stop_address = analyzer_get_stop_address(usb->devhdl); now_address = analyzer_get_now_address(usb->devhdl); trigger_address = analyzer_get_trigger_address(usb->devhdl); triggerbar = analyzer_get_triggerbar_address(); ramsize_trigger = analyzer_get_ramsize_trigger_address(); n = get_memory_size(devc->memory_size); memory_size = n / 4; sr_info("Status = 0x%x.", status); sr_info("Stop address = 0x%x.", stop_address); sr_info("Now address = 0x%x.", now_address); sr_info("Trigger address = 0x%x.", trigger_address); sr_info("Triggerbar address = 0x%x.", triggerbar); sr_info("Ramsize trigger = 0x%x.", ramsize_trigger); sr_info("Memory size = 0x%x.", memory_size); /* Send header packet to the session bus. */ std_session_send_df_header(cb_data, LOG_PREFIX); /* Check for empty capture */ if ((status & STATUS_READY) && !stop_address) { packet.type = SR_DF_END; sr_session_send(cb_data, &packet); return SR_OK; } buf = g_malloc(PACKET_SIZE); /* Check if the trigger is in the samples we are throwing away */ trigger_now = now_address == trigger_address || ((now_address + 1) % memory_size) == trigger_address; /* * STATUS_READY doesn't clear until now_address advances past * addr 0, but for our logic, clear it in that case */ if (!now_address) status &= ~STATUS_READY; analyzer_read_start(usb->devhdl); /* Calculate how much data to discard */ discard = 0; if (status & STATUS_READY) { /* * We haven't wrapped around, we need to throw away data from * our current position to the end of the buffer. * Additionally, the first two samples captured are always * bogus. */ discard += memory_size - now_address + 2; now_address = 2; } /* If we have more samples than we need, discard them */ valid_samples = (stop_address - now_address) % memory_size; if (valid_samples > ramsize_trigger + triggerbar) { discard += valid_samples - (ramsize_trigger + triggerbar); now_address += valid_samples - (ramsize_trigger + triggerbar); } sr_info("Need to discard %d samples.", discard); /* Calculate how far in the trigger is */ if (trigger_now) trigger_offset = 0; else trigger_offset = (trigger_address - now_address) % memory_size; /* Recalculate the number of samples available */ valid_samples = (stop_address - now_address) % memory_size; /* Send the incoming transfer to the session bus. */ samples_read = 0; for (packet_num = 0; packet_num < n / PACKET_SIZE; packet_num++) { unsigned int len; unsigned int buf_offset; res = analyzer_read_data(usb->devhdl, buf, PACKET_SIZE); sr_info("Tried to read %d bytes, actually read %d bytes.", PACKET_SIZE, res); if (discard >= PACKET_SIZE / 4) { discard -= PACKET_SIZE / 4; continue; } len = PACKET_SIZE - discard * 4; buf_offset = discard * 4; discard = 0; /* Check if we've read all the samples */ if (samples_read + len / 4 >= valid_samples) len = (valid_samples - samples_read) * 4; if (!len) break; if (samples_read < trigger_offset && samples_read + len / 4 > trigger_offset) { /* Send out samples remaining before trigger */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = (trigger_offset - samples_read) * 4; logic.unitsize = 4; logic.data = buf + buf_offset; sr_session_send(cb_data, &packet); len -= logic.length; samples_read += logic.length / 4; buf_offset += logic.length; } if (samples_read == trigger_offset) { /* Send out trigger */ packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(cb_data, &packet); } /* Send out data (or data after trigger) */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = len; logic.unitsize = 4; logic.data = buf + buf_offset; sr_session_send(cb_data, &packet); samples_read += len / 4; } analyzer_read_stop(usb->devhdl); g_free(buf); packet.type = SR_DF_END; sr_session_send(cb_data, &packet); return SR_OK; }
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; GVariant *gvar, *grange[2]; GVariantBuilder gvb; double v; GVariant *range[2]; (void)cg; switch (key) { case SR_CONF_DEVICE_OPTIONS: *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); break; case SR_CONF_SAMPLERATE: devc = sdi->priv; g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); if (devc->prof->max_sampling_freq == 100) { gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates_100, ARRAY_SIZE(samplerates_100), sizeof(uint64_t)); } else if (devc->prof->max_sampling_freq == 200) { gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates_200, ARRAY_SIZE(samplerates_200), sizeof(uint64_t)); } else { sr_err("Internal error: Unknown max. samplerate: %d.", devc->prof->max_sampling_freq); return SR_ERR_ARG; } g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); *data = g_variant_builder_end(&gvb); break; case SR_CONF_TRIGGER_MATCH: *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, trigger_matches, ARRAY_SIZE(trigger_matches), sizeof(int32_t)); break; case SR_CONF_VOLTAGE_THRESHOLD: g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); for (v = -6.0; v <= 6.0; v += 0.1) { range[0] = g_variant_new_double(v); range[1] = g_variant_new_double(v); gvar = g_variant_new_tuple(range, 2); g_variant_builder_add_value(&gvb, gvar); } *data = g_variant_builder_end(&gvb); break; case SR_CONF_LIMIT_SAMPLES: if (!sdi) return SR_ERR_ARG; devc = sdi->priv; grange[0] = g_variant_new_uint64(0); grange[1] = g_variant_new_uint64(devc->max_sample_depth); *data = g_variant_new_tuple(grange, 2); break; default: return SR_ERR_NA; } return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; int ret = SR_ERR; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; devc = sdi->priv; if (mso_configure_probes(sdi) != SR_OK) { sr_err("Failed to configure probes."); return SR_ERR; } /* FIXME: No need to do full reconfigure every time */ // ret = mso_reset_fsm(sdi); // if (ret != SR_OK) // return ret; /* FIXME: ACDC Mode */ devc->ctlbase1 &= 0x7f; // devc->ctlbase1 |= devc->acdcmode; ret = mso_configure_rate(sdi, devc->cur_rate); if (ret != SR_OK) return ret; /* set dac offset */ ret = mso_dac_out(sdi, devc->dac_offset); if (ret != SR_OK) return ret; ret = mso_configure_threshold_level(sdi); if (ret != SR_OK) return ret; ret = mso_configure_trigger(sdi); if (ret != SR_OK) return ret; /* END of config hardware part */ ret = mso_arm(sdi); if (ret != SR_OK) return ret; /* Start acquisition on the device. */ mso_check_trigger(devc->serial, &devc->trigger_state); ret = mso_check_trigger(devc->serial, NULL); if (ret != SR_OK) return ret; /* Reset trigger state. */ devc->trigger_state = 0x00; /* Send header packet to the session bus. */ std_session_send_df_header(cb_data, LOG_PREFIX); /* Our first probe is analog, the other 8 are of type 'logic'. */ /* TODO. */ sr_source_add(devc->serial->fd, G_IO_IN, -1, mso_receive_data, cb_data); return SR_OK; }
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) { int i; GSList *devices = NULL; const char *conn = NULL; const char *serialcomm = NULL; GSList *l; struct sr_config *src; struct udev *udev; int ptype; 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) conn = SERIALCONN; if (serialcomm == NULL) serialcomm = SERIALCOMM; udev = udev_new(); if (!udev) { sr_err("Failed to initialize udev."); } struct udev_enumerate *enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "usb-serial"); udev_enumerate_scan_devices(enumerate); struct udev_list_entry *devs = udev_enumerate_get_list_entry(enumerate); struct udev_list_entry *dev_list_entry; for (dev_list_entry = devs; dev_list_entry != NULL; dev_list_entry = udev_list_entry_get_next(dev_list_entry)) { const char *syspath = udev_list_entry_get_name(dev_list_entry); struct udev_device *dev = udev_device_new_from_syspath(udev, syspath); const char *sysname = udev_device_get_sysname(dev); struct udev_device *parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); if (!parent) { sr_err("Unable to find parent usb device for %s", sysname); continue; } const char *idVendor = udev_device_get_sysattr_value(parent, "idVendor"); const char *idProduct = udev_device_get_sysattr_value(parent, "idProduct"); if (strcmp(USB_VENDOR, idVendor) || strcmp(USB_PRODUCT, idProduct)) continue; const char *iSerial = udev_device_get_sysattr_value(parent, "serial"); const char *iProduct = udev_device_get_sysattr_value(parent, "product"); char path[32]; snprintf(path, sizeof(path), "/dev/%s", sysname); conn = path; size_t s = strcspn(iProduct, " "); char product[32]; char manufacturer[32]; if (s > sizeof(product) || strlen(iProduct) - s > sizeof(manufacturer)) { sr_err("Could not parse iProduct: %s.", iProduct); continue; } strncpy(product, iProduct, s); product[s] = 0; strcpy(manufacturer, iProduct + s + 1); //Create the device context and set its params struct dev_context *devc; if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { sr_err("Device context malloc failed."); return devices; } if (mso_parse_serial(iSerial, iProduct, devc) != SR_OK) { sr_err("Invalid iSerial: %s.", iSerial); g_free(devc); return devices; } char hwrev[32]; sprintf(hwrev, "r%d", devc->hwrev); devc->ctlbase1 = 0; devc->protocol_trigger.spimode = 0; for (i = 0; i < 4; i++) { devc->protocol_trigger.word[i] = 0; devc->protocol_trigger.mask[i] = 0xff; } if (!(devc->serial = sr_serial_dev_inst_new(conn, serialcomm))) { g_free(devc); return devices; } struct sr_dev_inst *sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, manufacturer, product, hwrev); if (!sdi) { sr_err("Unable to create device instance for %s", sysname); sr_dev_inst_free(sdi); g_free(devc); return devices; } sdi->driver = di; sdi->priv = devc; for (i = 0; i < NUM_PROBES; i++) { struct sr_probe *probe; ptype = (i == 0) ? SR_PROBE_ANALOG : SR_PROBE_LOGIC; if (!(probe = sr_probe_new(i, ptype, TRUE, mso19_probe_names[i]))) return 0; sdi->probes = g_slist_append(sdi->probes, probe); } //Add the driver struct drv_context *drvc = di->priv; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } return devices; }
static GSList *scan(GSList *options) { struct drv_context *drvc; struct dev_context *devc; struct sr_dev_inst *sdi; struct sr_config *src; struct sr_channel *ch; GSList *devices, *l; const char *conn, *serialcomm; struct sr_serial_dev_inst *serial; drvc = di->priv; drvc->instances = NULL; devices = NULL; conn = serialcomm = NULL; for (l = options; l; l = l->next) { if (!(src = l->data)) { sr_err("Invalid option data, skipping."); continue; } 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 = SERIALCOMM; sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup("Tondaj"); sdi->model = g_strdup("SL-814"); devc = g_malloc0(sizeof(struct dev_context)); if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; 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); return devices; }
/* Set up the acquisition state record. */ static int init_acquisition_state(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct acquisition_state *acq; devc = sdi->priv; usb = sdi->conn; if (devc->acquisition) { sr_err("Acquisition still in progress?"); return SR_ERR; } if (devc->cfg_clock_source == CLOCK_INTERNAL && devc->samplerate == 0) { sr_err("Samplerate not set."); return SR_ERR; } acq = g_try_malloc0(sizeof(struct acquisition_state)); if (!acq) return SR_ERR_MALLOC; acq->xfer_in = libusb_alloc_transfer(0); if (!acq->xfer_in) { g_free(acq); return SR_ERR_MALLOC; } acq->xfer_out = libusb_alloc_transfer(0); if (!acq->xfer_out) { libusb_free_transfer(acq->xfer_in); g_free(acq); return SR_ERR_MALLOC; } libusb_fill_bulk_transfer(acq->xfer_out, usb->devhdl, EP_COMMAND, (unsigned char *)acq->xfer_buf_out, 0, &transfer_out_completed, (struct sr_dev_inst *)sdi, USB_TIMEOUT_MS); libusb_fill_bulk_transfer(acq->xfer_in, usb->devhdl, EP_REPLY, (unsigned char *)acq->xfer_buf_in, sizeof(acq->xfer_buf_in), &transfer_in_completed, (struct sr_dev_inst *)sdi, USB_TIMEOUT_MS); if (devc->limit_msec > 0) { acq->duration_max = devc->limit_msec; sr_info("Acquisition time limit %" PRIu64 " ms.", devc->limit_msec); } else acq->duration_max = MAX_LIMIT_MSEC; if (devc->limit_samples > 0) { acq->samples_max = devc->limit_samples; sr_info("Acquisition sample count limit %" PRIu64 ".", devc->limit_samples); } else acq->samples_max = MAX_LIMIT_SAMPLES; if (devc->cfg_clock_source == CLOCK_INTERNAL) { sr_info("Internal clock, samplerate %" PRIu64 ".", devc->samplerate); /* Ramp up clock speed to enable samplerates above 100 MS/s. */ acq->clock_boost = (devc->samplerate > SR_MHZ(100)); /* If only one of the limits is set, derive the other one. */ if (devc->limit_msec == 0 && devc->limit_samples > 0) acq->duration_max = devc->limit_samples * 1000 / devc->samplerate + 1; else if (devc->limit_samples == 0 && devc->limit_msec > 0) acq->samples_max = devc->limit_msec * devc->samplerate / 1000; } else { acq->clock_boost = TRUE; if (devc->cfg_clock_edge == EDGE_POSITIVE) sr_info("External clock, rising edge."); else sr_info("External clock, falling edge."); } acq->rle_enabled = devc->cfg_rle; devc->acquisition = acq; return SR_OK; }
SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_datafeed_logic logic; double vdiv, offset; int len, i, vref; struct sr_channel *ch; gsize expected_data_bytes; (void)fd; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; if (!(revents == G_IO_IN || revents == 0)) return TRUE; switch (devc->wait_event) { case WAIT_NONE: break; case WAIT_TRIGGER: if (rigol_ds_trigger_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; case WAIT_BLOCK: if (rigol_ds_block_wait(sdi) != SR_OK) return TRUE; break; case WAIT_STOP: if (rigol_ds_stop_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_check_stop(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; default: sr_err("BUG: Unknown event target encountered"); break; } ch = devc->channel_entry->data; expected_data_bytes = ch->type == SR_CHANNEL_ANALOG ? devc->analog_frame_size : devc->digital_frame_size; if (devc->num_block_bytes == 0) { if (devc->model->series->protocol >= PROTOCOL_V4) { if (sr_scpi_send(sdi->conn, ":WAV:START %d", devc->num_channel_bytes + 1) != SR_OK) return TRUE; if (sr_scpi_send(sdi->conn, ":WAV:STOP %d", MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE, devc->analog_frame_size)) != SR_OK) return TRUE; } if (devc->model->series->protocol >= PROTOCOL_V3) if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK) return TRUE; if (sr_scpi_read_begin(scpi) != SR_OK) return TRUE; if (devc->format == FORMAT_IEEE488_2) { sr_dbg("New block header expected"); len = rigol_ds_read_header(sdi); if (len == 0) /* Still reading the header. */ return TRUE; if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } /* At slow timebases in live capture the DS2072 * sometimes returns "short" data blocks, with * apparently no way to get the rest of the data. * Discard these, the complete data block will * appear eventually. */ if (devc->data_source == DATA_SOURCE_LIVE && (unsigned)len < expected_data_bytes) { sr_dbg("Discarding short data block"); sr_scpi_read_data(scpi, (char *)devc->buffer, len + 1); return TRUE; } devc->num_block_bytes = len; } else { devc->num_block_bytes = expected_data_bytes; } devc->num_block_read = 0; } len = devc->num_block_bytes - devc->num_block_read; if (len > ACQ_BUFFER_SIZE) len = ACQ_BUFFER_SIZE; sr_dbg("Requesting read of %d bytes", len); len = sr_scpi_read_data(scpi, (char *)devc->buffer, len); if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } sr_dbg("Received %d bytes.", len); devc->num_block_read += len; if (ch->type == SR_CHANNEL_ANALOG) { vref = devc->vert_reference[ch->index]; vdiv = devc->vdiv[ch->index] / 25.6; offset = devc->vert_offset[ch->index]; if (devc->model->series->protocol >= PROTOCOL_V3) for (i = 0; i < len; i++) devc->data[i] = ((int)devc->buffer[i] - vref) * vdiv - offset; else for (i = 0; i < len; i++) devc->data[i] = (128 - devc->buffer[i]) * vdiv - offset; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(NULL, ch); analog.num_samples = len; analog.data = devc->data; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); } else { logic.length = len; // TODO: For the MSO1000Z series, we need a way to express that // this data is in fact just for a single channel, with the valid // data for that channel in the LSB of each byte. logic.unitsize = devc->model->series->protocol == PROTOCOL_V4 ? 1 : 2; logic.data = devc->buffer; packet.type = SR_DF_LOGIC; packet.payload = &logic; sr_session_send(sdi, &packet); } if (devc->num_block_read == devc->num_block_bytes) { sr_dbg("Block has been completed"); if (devc->model->series->protocol >= PROTOCOL_V3) { /* Discard the terminating linefeed */ sr_scpi_read_data(scpi, (char *)devc->buffer, 1); } if (devc->format == FORMAT_IEEE488_2) { /* Prepare for possible next block */ devc->num_header_bytes = 0; devc->num_block_bytes = 0; if (devc->data_source != DATA_SOURCE_LIVE) rigol_ds_set_wait_event(devc, WAIT_BLOCK); } if (!sr_scpi_read_complete(scpi)) { sr_err("Read should have been completed"); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } devc->num_block_read = 0; } else { sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read", devc->num_block_read, devc->num_block_bytes); } devc->num_channel_bytes += len; if (devc->num_channel_bytes < expected_data_bytes) /* Don't have the full data for this channel yet, re-run. */ return TRUE; /* End of data for this channel. */ if (devc->model->series->protocol == PROTOCOL_V3) { /* Signal end of data download to scope */ if (devc->data_source != DATA_SOURCE_LIVE) /* * This causes a query error, without it switching * to the next channel causes an error. Fun with * firmware... */ rigol_ds_config_set(sdi, ":WAV:END"); } if (devc->channel_entry->next) { /* We got the frame for this channel, now get the next channel. */ devc->channel_entry = devc->channel_entry->next; rigol_ds_channel_start(sdi); } else { /* Done with this frame. */ packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); if (++devc->num_frames == devc->limit_frames) { /* Last frame, stop capture. */ sdi->driver->dev_acquisition_stop(sdi); } else { /* Get the next frame, starting with the first channel. */ devc->channel_entry = devc->enabled_channels; rigol_ds_capture_start(sdi); /* Start of next frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); } } return TRUE; }
static GSList *scan_port(GSList *devices, struct sr_dev_driver *di, struct parport *port) { struct sr_dev_inst *sdi; struct sr_channel *ch; struct sr_channel_group *cg; struct dev_context *devc; struct drv_context *drvc; int i; if (ieee1284_open(port, 0, &i) != E1284_OK) { sr_err("Can't open parallel port %s", port->name); goto fail1; } if ((i & (CAP1284_RAW | CAP1284_BYTE)) != (CAP1284_RAW | CAP1284_BYTE)) { sr_err("Parallel port %s does not provide low-level bidirection access", port->name); goto fail2; } if (ieee1284_claim(port) != E1284_OK) { sr_err("Parallel port %s already in use", port->name); goto fail2; } if (!hung_chang_dso_2100_check_id(port)) goto fail3; sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup("Hung-Chang"); sdi->model = g_strdup("DSO-2100"); sdi->driver = di; drvc = di->context; sdi->inst_type = 0; /* FIXME */ sdi->conn = port; ieee1284_ref(port); for (i = 0; i < NUM_CHANNELS; i++) { cg = g_malloc0(sizeof(struct sr_channel_group)); cg->name = g_strdup(trigger_sources[i]); ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, FALSE, trigger_sources[i]); cg->channels = g_slist_append(cg->channels, ch); sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); } devc = g_malloc0(sizeof(struct dev_context)); devc->enabled_channel = g_slist_append(NULL, NULL); devc->channel = 0; devc->rate = 0; devc->probe[0] = 10; devc->probe[1] = 10; devc->cctl[0] = 0x31; /* 1V/div, DC coupling, trigger on channel A*/ devc->cctl[1] = 0x31; /* 1V/div, DC coupling, no tv sync trigger */ devc->edge = 0; devc->tlevel = 0x80; devc->pos[0] = 0x80; devc->pos[1] = 0x80; devc->offset[0] = 0x80; devc->offset[1] = 0x80; devc->gain[0] = 0x80; devc->gain[1] = 0x80; devc->frame_limit = 0; devc->last_step = 0; /* buffersize = 1000 */ sdi->priv = devc; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); fail3: ieee1284_release(port); fail2: ieee1284_close(port); fail1: return devices; }
/** * Load the session from the specified filename. * * @param ctx The context in which to load the session. * @param filename The name of the session file to load. * @param session The session to load the file into. * * @retval SR_OK Success * @retval SR_ERR_MALLOC Memory allocation error * @retval SR_ERR_DATA Malformed session file * @retval SR_ERR This is not a session file */ SR_API int sr_session_load(struct sr_context *ctx, const char *filename, struct sr_session **session) { GKeyFile *kf; GError *error; struct zip *archive; struct zip_stat zs; struct sr_dev_inst *sdi; struct sr_channel *ch; int ret, i, j; uint64_t tmp_u64; int total_channels, total_analog, k; GSList *l; int unitsize; char **sections, **keys, *val; char channelname[SR_MAX_CHANNELNAME_LEN + 1]; gboolean file_has_logic; if ((ret = sr_sessionfile_check(filename)) != SR_OK) return ret; if (!(archive = zip_open(filename, 0, NULL))) return SR_ERR; if (zip_stat(archive, "metadata", 0, &zs) < 0) { zip_discard(archive); return SR_ERR; } kf = sr_sessionfile_read_metadata(archive, &zs); zip_discard(archive); if (!kf) return SR_ERR_DATA; if ((ret = sr_session_new(ctx, session)) != SR_OK) { g_key_file_free(kf); return ret; } total_channels = 0; error = NULL; ret = SR_OK; file_has_logic = FALSE; sections = g_key_file_get_groups(kf, NULL); for (i = 0; sections[i] && ret == SR_OK; i++) { if (!strcmp(sections[i], "global")) /* nothing really interesting in here yet */ continue; if (!strncmp(sections[i], "device ", 7)) { /* device section */ sdi = NULL; keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); /* File contains analog data if there are analog channels. */ total_analog = g_key_file_get_integer(kf, sections[i], "total analog", &error); if (total_analog > 0 && !error) sdi = sr_session_prepare_sdi(filename, session); g_clear_error(&error); /* File contains logic data if a capturefile is set. */ val = g_key_file_get_string(kf, sections[i], "capturefile", &error); if (val && !error) { if (!sdi) sdi = sr_session_prepare_sdi(filename, session); sr_config_set(sdi, NULL, SR_CONF_CAPTUREFILE, g_variant_new_string(val)); g_free(val); file_has_logic = TRUE; } g_clear_error(&error); for (j = 0; keys[j]; j++) { if (!strcmp(keys[j], "samplerate")) { val = g_key_file_get_string(kf, sections[i], keys[j], &error); if (!sdi || !val || sr_parse_sizestring(val, &tmp_u64) != SR_OK) { g_free(val); ret = SR_ERR_DATA; break; } g_free(val); sr_config_set(sdi, NULL, SR_CONF_SAMPLERATE, g_variant_new_uint64(tmp_u64)); } else if (!strcmp(keys[j], "unitsize") && file_has_logic) { unitsize = g_key_file_get_integer(kf, sections[i], keys[j], &error); if (!sdi || unitsize <= 0 || error) { ret = SR_ERR_DATA; break; } sr_config_set(sdi, NULL, SR_CONF_CAPTURE_UNITSIZE, g_variant_new_uint64(unitsize)); } else if (!strcmp(keys[j], "total probes")) { total_channels = g_key_file_get_integer(kf, sections[i], keys[j], &error); if (!sdi || total_channels < 0 || error) { ret = SR_ERR_DATA; break; } sr_config_set(sdi, NULL, SR_CONF_NUM_LOGIC_CHANNELS, g_variant_new_int32(total_channels)); for (k = 0; k < total_channels; k++) { g_snprintf(channelname, sizeof(channelname), "%d", k); sr_channel_new(sdi, k, SR_CHANNEL_LOGIC, FALSE, channelname); } } else if (!strcmp(keys[j], "total analog")) { total_analog = g_key_file_get_integer(kf, sections[i], keys[j], &error); if (!sdi || total_analog < 0 || error) { ret = SR_ERR_DATA; break; } sr_config_set(sdi, NULL, SR_CONF_NUM_ANALOG_CHANNELS, g_variant_new_int32(total_analog)); for (k = total_channels; k < (total_channels + total_analog); k++) { g_snprintf(channelname, sizeof(channelname), "%d", k); sr_channel_new(sdi, k, SR_CHANNEL_ANALOG, FALSE, channelname); } } else if (!strncmp(keys[j], "probe", 5)) { tmp_u64 = g_ascii_strtoull(keys[j] + 5, NULL, 10); if (!sdi || tmp_u64 == 0 || tmp_u64 > G_MAXINT) { ret = SR_ERR_DATA; break; } ch = g_slist_nth_data(sdi->channels, tmp_u64 - 1); if (!ch) { ret = SR_ERR_DATA; break; } val = g_key_file_get_string(kf, sections[i], keys[j], &error); if (!val) { ret = SR_ERR_DATA; break; } /* sr_session_save() */ sr_dev_channel_name_set(ch, val); g_free(val); sr_dev_channel_enable(ch, TRUE); } else if (!strncmp(keys[j], "analog", 6)) { tmp_u64 = g_ascii_strtoull(keys[j]+6, NULL, 10); if (!sdi || tmp_u64 == 0 || tmp_u64 > G_MAXINT) { ret = SR_ERR_DATA; break; } ch = NULL; for (l = sdi->channels; l; l = l->next) { ch = l->data; if ((guint64)ch->index == tmp_u64 - 1) break; else ch = NULL; } if (!ch) { ret = SR_ERR_DATA; break; } val = g_key_file_get_string(kf, sections[i], keys[j], &error); if (!val) { ret = SR_ERR_DATA; break; } /* sr_session_save() */ sr_dev_channel_name_set(ch, val); g_free(val); sr_dev_channel_enable(ch, TRUE); } } g_strfreev(keys); } } g_strfreev(sections); g_key_file_free(kf); if (error) { sr_err("Failed to parse metadata: %s", error->message); g_error_free(error); } return ret; }
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; uint64_t p, q; double t_dbl; unsigned int i, j; int ret; const char *tmp_str; char buffer[16]; devc = sdi->priv; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; /* If a channel group is specified, it must be a valid one. */ if (cg && !g_slist_find(sdi->channel_groups, cg)) { sr_err("Invalid channel group specified."); return SR_ERR; } ret = SR_OK; switch (key) { case SR_CONF_LIMIT_FRAMES: devc->limit_frames = g_variant_get_uint64(data); break; case SR_CONF_TRIGGER_SLOPE: tmp_str = g_variant_get_string(data, NULL); if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r')) { sr_err("Unknown trigger slope: '%s'.", (tmp_str) ? tmp_str : "NULL"); return SR_ERR_ARG; } g_free(devc->trigger_slope); devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG"); ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope); break; case SR_CONF_HORIZ_TRIGGERPOS: t_dbl = g_variant_get_double(data); if (t_dbl < 0.0 || t_dbl > 1.0) { sr_err("Invalid horiz. trigger position: %g.", t_dbl); return SR_ERR; } devc->horiz_triggerpos = t_dbl; /* We have the trigger offset as a percentage of the frame, but * need to express this in seconds. */ t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases; g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl); ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer); break; case SR_CONF_TRIGGER_LEVEL: t_dbl = g_variant_get_double(data); g_ascii_formatd(buffer, sizeof(buffer), "%.3f", t_dbl); ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:LEV %s", buffer); if (ret == SR_OK) devc->trigger_level = t_dbl; break; case SR_CONF_TIMEBASE: g_variant_get(data, "(tt)", &p, &q); for (i = 0; i < devc->num_timebases; i++) { if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) { devc->timebase = (float)p / q; g_ascii_formatd(buffer, sizeof(buffer), "%.9f", devc->timebase); ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer); break; } } if (i == devc->num_timebases) { sr_err("Invalid timebase index: %d.", i); ret = SR_ERR_ARG; } break; case SR_CONF_TRIGGER_SOURCE: tmp_str = g_variant_get_string(data, NULL); for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) { if (!strcmp(trigger_sources[i], tmp_str)) { g_free(devc->trigger_source); devc->trigger_source = g_strdup(trigger_sources[i]); if (!strcmp(devc->trigger_source, "AC Line")) tmp_str = "ACL"; else if (!strcmp(devc->trigger_source, "CH1")) tmp_str = "CHAN1"; else if (!strcmp(devc->trigger_source, "CH2")) tmp_str = "CHAN2"; else if (!strcmp(devc->trigger_source, "CH3")) tmp_str = "CHAN3"; else if (!strcmp(devc->trigger_source, "CH4")) tmp_str = "CHAN4"; else tmp_str = (char *)devc->trigger_source; ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str); break; } } if (i == ARRAY_SIZE(trigger_sources)) { sr_err("Invalid trigger source index: %d.", i); ret = SR_ERR_ARG; } break; case SR_CONF_VDIV: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } g_variant_get(data, "(tt)", &p, &q); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(vdivs); j++) { if (vdivs[j][0] != p || vdivs[j][1] != q) continue; devc->vdiv[i] = (float)p / q; g_ascii_formatd(buffer, sizeof(buffer), "%.3f", devc->vdiv[i]); return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1, buffer); } sr_err("Invalid vdiv index: %d.", j); return SR_ERR_ARG; } } sr_dbg("Didn't set vdiv, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_COUPLING: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } tmp_str = g_variant_get_string(data, NULL); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(coupling); j++) { if (!strcmp(tmp_str, coupling[j])) { g_free(devc->coupling[i]); devc->coupling[i] = g_strdup(coupling[j]); return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1, devc->coupling[i]); } } sr_err("Invalid coupling index: %d.", j); return SR_ERR_ARG; } } sr_dbg("Didn't set coupling, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_PROBE_FACTOR: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } p = g_variant_get_uint64(data); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(probe_factor); j++) { if (p == probe_factor[j]) { devc->attenuation[i] = p; ret = rigol_ds_config_set(sdi, ":CHAN%d:PROB %"PRIu64, i + 1, p); if (ret == SR_OK) rigol_ds_get_dev_cfg_vertical(sdi); return ret; } } sr_err("Invalid probe factor: %"PRIu64".", p); return SR_ERR_ARG; } } sr_dbg("Didn't set probe factor, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_DATA_SOURCE: tmp_str = g_variant_get_string(data, NULL); if (!strcmp(tmp_str, "Live")) devc->data_source = DATA_SOURCE_LIVE; else if (devc->model->series->protocol >= PROTOCOL_V2 && !strcmp(tmp_str, "Memory")) devc->data_source = DATA_SOURCE_MEMORY; else if (devc->model->series->protocol >= PROTOCOL_V3 && !strcmp(tmp_str, "Segmented")) devc->data_source = DATA_SOURCE_SEGMENTED; else { sr_err("Unknown data source: '%s'.", tmp_str); return SR_ERR; } break; default: return SR_ERR_NA; } return ret; }
/** @private */ SR_PRIV void sr_zip_discard(struct zip *archive) { if (zip_unchange_all(archive) < 0 || zip_close(archive) < 0) sr_err("Failed to discard ZIP archive: %s", zip_strerror(archive)); }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_channel *ch; struct sr_datafeed_packet packet; gboolean some_digital; GSList *l; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; scpi = sdi->conn; devc = sdi->priv; devc->num_frames = 0; some_digital = FALSE; for (l = sdi->channels; l; l = l->next) { ch = l->data; sr_dbg("handling channel %s", ch->name); if (ch->type == SR_CHANNEL_ANALOG) { if (ch->enabled) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled != devc->analog_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->analog_channels[ch->index] = ch->enabled; } } else if (ch->type == SR_CHANNEL_LOGIC) { /* Only one list entry for DS1000D series. All channels are retrieved * together when this entry is processed. */ if (ch->enabled && ( devc->model->series->protocol > PROTOCOL_V2 || !some_digital)) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled) { some_digital = TRUE; /* Turn on LA module if currently off. */ if (!devc->la_enabled) { if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT ON" : ":LA:DISP ON") != SR_OK) return SR_ERR; devc->la_enabled = TRUE; } } if (ch->enabled != devc->digital_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:DIG%d:DISP %s" : ":DIG%d:TURN %s", ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->digital_channels[ch->index] = ch->enabled; } } } if (!devc->enabled_channels) return SR_ERR; /* Turn off LA module if on and no digital channels selected. */ if (devc->la_enabled && !some_digital) if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK) return SR_ERR; /* Set memory mode. */ if (devc->data_source == DATA_SOURCE_SEGMENTED) { sr_err("Data source 'Segmented' not yet supported"); return SR_ERR; } devc->analog_frame_size = analog_frame_size(sdi); devc->digital_frame_size = digital_frame_size(sdi); switch (devc->model->series->protocol) { case PROTOCOL_V2: if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK) return SR_ERR; break; case PROTOCOL_V3: /* Apparently for the DS2000 the memory * depth can only be set in Running state - * this matches the behaviour of the UI. */ if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d", devc->analog_frame_size) != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) return SR_ERR; break; default: break; } if (devc->data_source == DATA_SOURCE_LIVE) if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi); std_session_send_df_header(sdi); devc->channel_entry = devc->enabled_channels; if (rigol_ds_capture_start(sdi) != SR_OK) return SR_ERR; /* Start of first frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); return SR_OK; }
static struct sr_datafeed_analog *handle_qm_v2(const struct sr_dev_inst *sdi, char **tokens) { struct sr_datafeed_analog *analog; float fvalue; char *eptr; (void)sdi; fvalue = strtof(tokens[0], &eptr); if (fvalue == 0.0 && eptr == tokens[0]) { sr_err("Invalid float."); return NULL; } /* TODO: Check malloc return value. */ analog = g_try_malloc0(sizeof(struct sr_datafeed_analog)); analog->num_samples = 1; /* TODO: Check malloc return value. */ analog->data = g_try_malloc(sizeof(float)); *analog->data = fvalue; analog->mq = -1; if (!strcmp(tokens[1], "VAC") || !strcmp(tokens[1], "VDC")) { analog->mq = SR_MQ_VOLTAGE; analog->unit = SR_UNIT_VOLT; if (!strcmp(tokens[2], "NORMAL")) { if (tokens[1][1] == 'A') { analog->mqflags |= SR_MQFLAG_AC; analog->mqflags |= SR_MQFLAG_RMS; } else analog->mqflags |= SR_MQFLAG_DC; } else if (!strcmp(tokens[2], "OL") || !strcmp(tokens[2], "OL_MINUS")) { *analog->data = NAN; } else analog->mq = -1; } else if (!strcmp(tokens[1], "dBV") || !strcmp(tokens[1], "dBm")) { analog->mq = SR_MQ_VOLTAGE; if (tokens[1][2] == 'm') analog->unit = SR_UNIT_DECIBEL_MW; else analog->unit = SR_UNIT_DECIBEL_VOLT; analog->mqflags |= SR_MQFLAG_AC | SR_MQFLAG_RMS; } else if (!strcmp(tokens[1], "CEL") || !strcmp(tokens[1], "FAR")) { if (!strcmp(tokens[2], "NORMAL")) { analog->mq = SR_MQ_TEMPERATURE; if (tokens[1][0] == 'C') analog->unit = SR_UNIT_CELSIUS; else analog->unit = SR_UNIT_FAHRENHEIT; } } else if (!strcmp(tokens[1], "OHM")) { if (!strcmp(tokens[3], "NONE")) { analog->mq = SR_MQ_RESISTANCE; analog->unit = SR_UNIT_OHM; if (!strcmp(tokens[2], "OL") || !strcmp(tokens[2], "OL_MINUS")) { *analog->data = INFINITY; } else if (strcmp(tokens[2], "NORMAL")) analog->mq = -1; } else if (!strcmp(tokens[3], "OPEN_CIRCUIT")) { analog->mq = SR_MQ_CONTINUITY; analog->unit = SR_UNIT_BOOLEAN; *analog->data = 0.0; } else if (!strcmp(tokens[3], "SHORT_CIRCUIT")) { analog->mq = SR_MQ_CONTINUITY; analog->unit = SR_UNIT_BOOLEAN; *analog->data = 1.0; } } else if (!strcmp(tokens[1], "F") && !strcmp(tokens[2], "NORMAL") && !strcmp(tokens[3], "NONE")) { analog->mq = SR_MQ_CAPACITANCE; analog->unit = SR_UNIT_FARAD; } else if (!strcmp(tokens[1], "AAC") || !strcmp(tokens[1], "ADC")) { analog->mq = SR_MQ_CURRENT; analog->unit = SR_UNIT_AMPERE; if (!strcmp(tokens[2], "NORMAL")) { if (tokens[1][1] == 'A') { analog->mqflags |= SR_MQFLAG_AC; analog->mqflags |= SR_MQFLAG_RMS; } else analog->mqflags |= SR_MQFLAG_DC; } else if (!strcmp(tokens[2], "OL") || !strcmp(tokens[2], "OL_MINUS")) { *analog->data = NAN; } else analog->mq = -1; } if (!strcmp(tokens[1], "Hz") && !strcmp(tokens[2], "NORMAL")) { analog->mq = SR_MQ_FREQUENCY; analog->unit = SR_UNIT_HERTZ; } else if (!strcmp(tokens[1], "PCT") && !strcmp(tokens[2], "NORMAL")) { analog->mq = SR_MQ_DUTY_CYCLE; analog->unit = SR_UNIT_PERCENTAGE; } else if (!strcmp(tokens[1], "S") && !strcmp(tokens[2], "NORMAL")) { analog->mq = SR_MQ_PULSE_WIDTH; analog->unit = SR_UNIT_SECOND; } else if (!strcmp(tokens[1], "SIE") && !strcmp(tokens[2], "NORMAL")) { analog->mq = SR_MQ_CONDUCTANCE; analog->unit = SR_UNIT_SIEMENS; } if (analog->mq == -1) { /* Not a valid measurement. */ g_free(analog->data); g_free(analog); analog = NULL; } return analog; }
/** * Try to find a valid packet in a serial data stream. * * @param serial Previously initialized serial port structure. * @param buf Buffer containing the bytes to write. * @param buflen Size of the buffer. * @param[in] packet_size Size, in bytes, of a valid packet. * @param is_valid Callback that assesses whether the packet is valid or not. * @param[in] timeout_ms The timeout after which, if no packet is detected, to * abort scanning. * @param[in] baudrate The baudrate of the serial port. This parameter is not * critical, but it helps fine tune the serial port polling * delay. * * @retval SR_OK Valid packet was found within the given timeout. * @retval SR_ERR Failure. * * @private */ SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial, uint8_t *buf, size_t *buflen, size_t packet_size, packet_valid_callback is_valid, uint64_t timeout_ms, int baudrate) { uint64_t start, time, byte_delay_us; size_t ibuf, i, maxlen; ssize_t len; maxlen = *buflen; sr_dbg("Detecting packets on %s (timeout = %" PRIu64 "ms, baudrate = %d).", serial->port, timeout_ms, baudrate); if (maxlen < (packet_size / 2) ) { sr_err("Buffer size must be at least twice the packet size."); return SR_ERR; } /* Assume 8n1 transmission. That is 10 bits for every byte. */ byte_delay_us = 10 * ((1000 * 1000) / baudrate); start = g_get_monotonic_time(); i = ibuf = len = 0; while (ibuf < maxlen) { len = serial_read_nonblocking(serial, &buf[ibuf], 1); if (len > 0) { ibuf += len; } else if (len == 0) { /* No logging, already done in serial_read(). */ } else { /* Error reading byte, but continuing anyway. */ } time = g_get_monotonic_time() - start; time /= 1000; if ((ibuf - i) >= packet_size) { /* We have at least a packet's worth of data. */ if (is_valid(&buf[i])) { sr_spew("Found valid %zu-byte packet after " "%" PRIu64 "ms.", (ibuf - i), time); *buflen = ibuf; return SR_OK; } else { sr_spew("Got %zu bytes, but not a valid " "packet.", (ibuf - i)); } /* Not a valid packet. Continue searching. */ i++; } if (time >= timeout_ms) { /* Timeout */ sr_dbg("Detection timed out after %" PRIu64 "ms.", time); break; } if (len < 1) g_usleep(byte_delay_us); } *buflen = ibuf; sr_err("Didn't find a valid packet (read %zu bytes).", *buflen); return SR_ERR; }
static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) { int ret; struct dev_context *devc; uint64_t num_samples, slope; int trigger_pos; double pos; devc = sdi->priv; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; switch (id) { case SR_CONF_SAMPLERATE: // FIXME return mso_configure_rate(sdi, g_variant_get_uint64(data)); ret = SR_OK; break; case SR_CONF_LIMIT_SAMPLES: num_samples = g_variant_get_uint64(data); if (num_samples != 1024) { sr_err("Only 1024 samples are supported."); ret = SR_ERR_ARG; } else { devc->limit_samples = num_samples; sr_dbg("setting limit_samples to %i\n", num_samples); ret = SR_OK; } break; case SR_CONF_CAPTURE_RATIO: ret = SR_OK; break; case SR_CONF_TRIGGER_SLOPE: slope = g_variant_get_uint64(data); if (slope != SLOPE_NEGATIVE && slope != SLOPE_POSITIVE) { sr_err("Invalid trigger slope"); ret = SR_ERR_ARG; } else { devc->trigger_slope = slope; ret = SR_OK; } break; case SR_CONF_HORIZ_TRIGGERPOS: pos = g_variant_get_double(data); if (pos < 0 || pos > 255) { sr_err("Trigger position (%f) should be between 0 and 255.", pos); ret = SR_ERR_ARG; } else { trigger_pos = (int)pos; devc->trigger_holdoff[0] = trigger_pos & 0xff; ret = SR_OK; } break; case SR_CONF_RLE: ret = SR_OK; break; default: ret = SR_ERR_NA; break; } return ret; }
static int dev_open(struct sr_dev_inst *sdi) { struct drv_context *drvc; struct dev_context *devc; struct sr_usb_dev_inst *usb; uint8_t buffer[PACKET_LENGTH]; int ret; if (!(drvc = di->priv)) { sr_err("Driver was not initialized."); return SR_ERR; } usb = sdi->conn; devc = sdi->priv; if (sr_usb_open(drvc->sr_ctx->libusb_ctx, usb) != SR_OK) return SR_ERR; /* * Determine if a kernel driver is active on this interface and, if so, * detach it. */ if (libusb_kernel_driver_active(usb->devhdl, USB_INTERFACE) == 1) { ret = libusb_detach_kernel_driver(usb->devhdl, USB_INTERFACE); if (ret < 0) { sr_err("Failed to detach kernel driver: %s.", libusb_error_name(ret)); return SR_ERR; } } if ((ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE)) < 0) { sr_err("Failed to claim interface: %s.", libusb_error_name(ret)); return SR_ERR; } libusb_fill_control_transfer(devc->xfer_in, usb->devhdl, devc->xfer_buf_in, sl2_receive_transfer_in, sdi, USB_TIMEOUT); libusb_fill_control_transfer(devc->xfer_out, usb->devhdl, devc->xfer_buf_out, sl2_receive_transfer_out, sdi, USB_TIMEOUT); memset(buffer, 0, sizeof(buffer)); buffer[0] = CMD_RESET; if ((ret = sl2_transfer_out(usb->devhdl, buffer)) != PACKET_LENGTH) { sr_err("Device reset failed: %s.", libusb_error_name(ret)); return SR_ERR; } /* * Set the device to idle state. If the device is not in idle state it * possibly will reset itself after a few seconds without being used * and thereby close the connection. */ buffer[0] = CMD_IDLE; if ((ret = sl2_transfer_out(usb->devhdl, buffer)) != PACKET_LENGTH) { sr_err("Failed to set device in idle state: %s.", libusb_error_name(ret)); return SR_ERR; } sdi->status = SR_ST_ACTIVE; return SR_OK; }
static GSList *scan(GSList *options) { struct sr_dev_inst *sdi; struct sr_probe *probe; struct drv_context *drvc; struct dev_context *devc; GSList *devices; unsigned int i; int ret; (void)options; drvc = di->priv; devices = NULL; /* Allocate memory for our private device context. */ if (!(devc = g_try_malloc(sizeof(struct dev_context)))) { sr_err("Device context malloc failed."); goto err_free_nothing; } /* Set some sane defaults. */ devc->ftdic = NULL; devc->cur_samplerate = SR_MHZ(100); /* 100MHz == max. samplerate */ devc->limit_msec = 0; devc->limit_samples = 0; devc->cb_data = NULL; memset(devc->mangled_buf, 0, BS); devc->final_buf = NULL; devc->trigger_pattern = 0x00; /* Value irrelevant, see trigger_mask. */ devc->trigger_mask = 0x00; /* All probes are "don't care". */ devc->trigger_timeout = 10; /* Default to 10s trigger timeout. */ devc->trigger_found = 0; devc->done = 0; devc->block_counter = 0; devc->divcount = 0; /* 10ns sample period == 100MHz samplerate */ devc->usb_pid = 0; /* Allocate memory where we'll store the de-mangled data. */ if (!(devc->final_buf = g_try_malloc(SDRAM_SIZE))) { sr_err("final_buf malloc failed."); goto err_free_devc; } /* Allocate memory for the FTDI context (ftdic) and initialize it. */ if (!(devc->ftdic = ftdi_new())) { sr_err("%s: ftdi_new failed.", __func__); goto err_free_final_buf; } /* Check for the device and temporarily open it. */ for (i = 0; i < ARRAY_SIZE(usb_pids); i++) { sr_dbg("Probing for VID/PID %04x:%04x.", USB_VENDOR_ID, usb_pids[i]); ret = ftdi_usb_open_desc(devc->ftdic, USB_VENDOR_ID, usb_pids[i], USB_DESCRIPTION, NULL); if (ret == 0) { sr_dbg("Found LA8 device (%04x:%04x).", USB_VENDOR_ID, usb_pids[i]); devc->usb_pid = usb_pids[i]; } } if (devc->usb_pid == 0) goto err_free_ftdic; /* Register the device with libsigrok. */ sdi = sr_dev_inst_new(0, SR_ST_INITIALIZING, USB_VENDOR_NAME, USB_MODEL_NAME, USB_MODEL_VERSION); if (!sdi) { sr_err("%s: sr_dev_inst_new failed.", __func__); goto err_close_ftdic; } sdi->driver = di; sdi->priv = devc; for (i = 0; chronovu_la8_probe_names[i]; i++) { if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, chronovu_la8_probe_names[i]))) return NULL; sdi->probes = g_slist_append(sdi->probes, probe); } devices = g_slist_append(devices, sdi); drvc->instances = g_slist_append(drvc->instances, sdi); /* Close device. We'll reopen it again when we need it. */ (void) la8_close(devc); /* Log, but ignore errors. */ return devices; err_close_ftdic: (void) la8_close(devc); /* Log, but ignore errors. */ err_free_ftdic: ftdi_free(devc->ftdic); /* NOT free() or g_free()! */ err_free_final_buf: g_free(devc->final_buf); err_free_devc: g_free(devc); err_free_nothing: return NULL; }