struct channel_priv {
int ch_type;
+ int fd;
struct channel_group_priv *probe;
};
cp->ch_type = type;
cp->probe = cg->priv;
- ch = sr_channel_new(devc->num_channels++,
+ ch = sr_channel_new(sdi, devc->num_channels++,
SR_CHANNEL_ANALOG, TRUE, name);
g_free(name);
ch->priv = cp;
cg->channels = g_slist_append(cg->channels, ch);
- sdi->channels = g_slist_append(sdi->channels, ch);
}
SR_PRIV gboolean bl_acme_register_probe(struct sr_dev_inst *sdi, int type,
return TRUE;
}
+SR_PRIV int bl_acme_get_probe_type(const struct sr_channel_group *cg)
+{
+ struct channel_group_priv *cgp = cg->priv;
+
+ return cgp->probe_type;
+}
+
+SR_PRIV int bl_acme_probe_has_pws(const struct sr_channel_group *cg)
+{
+ struct channel_group_priv *cgp = cg->priv;
+
+ return sr_gpio_getval_export(pws_info_gpios[cgp->index]);
+}
+
/*
* Sets path to the hwmon attribute if this channel group
* supports shunt resistance setting. The caller has to supply
return ret;
}
+/*
+ * Try setting the update_interval sysfs attribute for each probe according
+ * to samplerate.
+ */
+SR_PRIV void bl_acme_maybe_set_update_interval(const struct sr_dev_inst *sdi,
+ uint64_t samplerate)
+{
+ struct sr_channel_group *cg;
+ struct channel_group_priv *cgp;
+ GString *hwmon;
+ GSList *l;
+ FILE *fd;
+
+ for (l = sdi->channel_groups; l != NULL; l = l->next) {
+ cg = l->data;
+ cgp = cg->priv;
+
+ hwmon = g_string_sized_new(64);
+ g_string_append_printf(hwmon,
+ "/sys/class/hwmon/hwmon%d/update_interval",
+ cgp->hwmon_num);
+
+ if (g_file_test(hwmon->str, G_FILE_TEST_EXISTS)) {
+ fd = g_fopen(hwmon->str, "w");
+ if (!fd) {
+ g_string_free(hwmon, TRUE);
+ continue;
+ }
+
+ g_fprintf(fd, "%" PRIu64 "\n", 1000 / samplerate);
+ fclose(fd);
+ }
+
+ g_string_free(hwmon, TRUE);
+ }
+}
+
SR_PRIV int bl_acme_get_shunt(const struct sr_channel_group *cg,
uint64_t *shunt)
{
fd = g_fopen(path->str, "w");
if (!fd) {
sr_err("Error opening %s: %s", path->str, strerror(errno));
- g_string_free(path, TRUE);
- return SR_ERR_IO;
+ ret = SR_ERR_IO;
+ goto out;
}
- g_string_free(path, TRUE);
g_fprintf(fd, "%" PRIu64 "\n", MOHM_TO_UOHM(shunt));
- /*
- * XXX There's no g_fclose() in GLib. This seems to work,
- * but is it safe?
- */
fclose(fd);
out:
cgp = cg->priv;
- val = sr_gpio_getval_export(pws_info_gpios[cgp->index]);
- if (val != 1) {
+ if (!bl_acme_probe_has_pws(cg)) {
sr_err("Probe has no power-switch");
return SR_ERR_ARG;
}
cgp = cg->priv;
- val = sr_gpio_getval_export(pws_info_gpios[cgp->index]);
- if (val != 1) {
+ if (!bl_acme_probe_has_pws(cg)) {
sr_err("Probe has no power-switch");
return SR_ERR_ARG;
}
val = sr_gpio_setval_export(pws_gpios[cgp->index], off ? 0 : 1);
+ if (val < 0) {
+ sr_err("Error setting power-off state: gpio: %d",
+ pws_gpios[cgp->index]);
+ return SR_ERR_IO;
+ }
return SR_OK;
}
static float read_sample(struct sr_channel *ch)
{
struct channel_priv *chp;
- char path[64], *file, buf[16];
+ char buf[16];
ssize_t len;
int fd;
+ chp = ch->priv;
+ fd = chp->fd;
+
+ lseek(fd, 0, SEEK_SET);
+
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0) {
+ sr_err("Error reading from channel %s (hwmon: %s): %s",
+ ch->name, chp->probe->hwmon_num, strerror(errno));
+ ch->enabled = FALSE;
+ return -1.0;
+ }
+
+ return adjust_data(strtol(buf, NULL, 10), chp->ch_type);
+}
+
+SR_PRIV int bl_acme_open_channel(struct sr_channel *ch)
+{
+ struct channel_priv *chp;
+ char path[64], *file;
+ int fd;
+
chp = ch->priv;
switch (chp->ch_type) {
case TEMP_OUT: file = "temp2_input"; break;
default:
sr_err("Invalid channel type: %d.", chp->ch_type);
- return -1.0;
+ return SR_ERR;
}
snprintf(path, sizeof(path), "/sys/class/hwmon/hwmon%d/%s",
chp->probe->hwmon_num, file);
+
fd = open(path, O_RDONLY);
if (fd < 0) {
sr_err("Error opening %s: %s", path, strerror(errno));
ch->enabled = FALSE;
- return -1.0;
+ return SR_ERR;
}
- len = read(fd, buf, sizeof(buf));
- close(fd);
- if (len < 0) {
- sr_err("Error reading from %s: %s", path, strerror(errno));
- ch->enabled = FALSE;
- return -1.0;
- }
+ chp->fd = fd;
- return adjust_data(strtol(buf, NULL, 10), chp->ch_type);
+ return 0;
+}
+
+SR_PRIV void bl_acme_close_channel(struct sr_channel *ch)
+{
+ struct channel_priv *chp;
+
+ chp = ch->priv;
+ close(chp->fd);
+ chp->fd = -1;
}
SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
packet.type = SR_DF_ANALOG;
packet.payload = &analog;
- memset(&analog, 0, sizeof(analog));
+ memset(&analog, 0, sizeof(struct sr_datafeed_analog));
analog.data = &valf;
/*