]> sigrok.org Git - libsigrok.git/blame - src/hardware/atorch/api.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / atorch / api.c
CommitLineData
cc9653de
MP
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2023 Mathieu Pilato <pilato.mathieu@free.fr>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <config.h>
21#include "protocol.h"
22
23static struct sr_dev_driver atorch_driver_info;
24
a5800e90
MP
25static const uint32_t scanopts[] = {
26 SR_CONF_CONN,
27 SR_CONF_SERIALCOMM,
28};
cc9653de 29
a5800e90
MP
30static const uint32_t drvopts[] = {
31 SR_CONF_ENERGYMETER,
32 SR_CONF_POWERMETER,
33 SR_CONF_ELECTRONIC_LOAD,
34};
cc9653de 35
a5800e90
MP
36static const uint32_t devopts[] = {
37 SR_CONF_CONTINUOUS,
38 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
39 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
40};
cc9653de 41
a5800e90
MP
42static int create_channels_feed_queues(struct sr_dev_inst *sdi,
43 struct dev_context *devc)
44{
45 size_t i;
46 struct sr_channel *sr_ch;
47 const struct atorch_channel_desc *at_ch;
48 struct feed_queue_analog *feed;
49 const struct atorch_device_profile *p;
50
51 p = devc->profile;
52 devc->feeds = g_malloc0(p->channel_count * sizeof(devc->feeds[0]));
53 for (i = 0; i < p->channel_count; i++) {
54 at_ch = &p->channels[i];
55 sr_ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE, at_ch->name);
56 feed = feed_queue_analog_alloc(sdi, 1, at_ch->digits, sr_ch);
57 feed_queue_analog_mq_unit(feed, at_ch->mq, at_ch->flags, at_ch->unit);
58 feed_queue_analog_scale_offset(feed, &at_ch->scale, NULL);
59 devc->feeds[i] = feed;
60 }
cc9653de 61
a5800e90 62 return SR_OK;
cc9653de
MP
63}
64
a5800e90
MP
65static GSList *atorch_scan(struct sr_dev_driver *di,
66 const char *conn, const char *serialcomm)
cc9653de 67{
a5800e90
MP
68 struct sr_serial_dev_inst *serial;
69 GSList *devices;
70 struct dev_context *devc;
71 struct sr_dev_inst *sdi;
cc9653de 72
a5800e90
MP
73 serial = sr_serial_dev_inst_new(conn, serialcomm);
74 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
75 goto err_out;
cc9653de 76
a5800e90
MP
77 devc = g_malloc0(sizeof(*devc));
78
79 if (atorch_probe(serial, devc) != SR_OK) {
80 sr_err("Failed to find a supported Atorch device.");
81 goto err_out_serial;
82 }
83
84 sr_sw_limits_init(&devc->limits);
85
86 sdi = g_malloc0(sizeof(*sdi));
87 sdi->priv = devc;
88 sdi->status = SR_ST_INACTIVE;
89 sdi->vendor = g_strdup("Atorch");
90 sdi->model = g_strdup(devc->profile->device_name);
91 sdi->version = NULL;
92 sdi->inst_type = SR_INST_SERIAL;
93 sdi->conn = serial;
94
95 create_channels_feed_queues(sdi, devc);
96
97 serial_close(serial);
98
99 devices = g_slist_append(NULL, sdi);
100 return std_scan_complete(di, devices);
101
102err_out_serial:
103 g_free(devc);
104 serial_close(serial);
105err_out:
106 sr_serial_dev_inst_free(serial);
107
108 return NULL;
cc9653de
MP
109}
110
a5800e90 111static GSList *scan(struct sr_dev_driver *di, GSList *options)
cc9653de 112{
a5800e90 113 const char *serial_device, *serial_options;
cc9653de 114
a5800e90
MP
115 serial_device = NULL;
116 serial_options = "9600/8n1";
cc9653de 117
a5800e90
MP
118 (void)sr_serial_extract_options(options, &serial_device, &serial_options);
119 if (!serial_device || !*serial_device)
120 return NULL;
121
122 return atorch_scan(di, serial_device, serial_options);
cc9653de
MP
123}
124
125static int config_get(uint32_t key, GVariant **data,
126 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
127{
a5800e90 128 struct dev_context *devc;
cc9653de 129
cc9653de
MP
130 (void)cg;
131
a5800e90
MP
132 if (!sdi || !data)
133 return SR_ERR_ARG;
134
135 devc = sdi->priv;
136
cc9653de 137 switch (key) {
a5800e90
MP
138 case SR_CONF_LIMIT_SAMPLES:
139 case SR_CONF_LIMIT_FRAMES:
140 case SR_CONF_LIMIT_MSEC:
141 return sr_sw_limits_config_get(&devc->limits, key, data);
cc9653de
MP
142 default:
143 return SR_ERR_NA;
144 }
cc9653de
MP
145}
146
147static int config_set(uint32_t key, GVariant *data,
148 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
149{
a5800e90 150 struct dev_context *devc;
cc9653de 151
cc9653de
MP
152 (void)data;
153 (void)cg;
154
a5800e90
MP
155 devc = sdi->priv;
156
cc9653de 157 switch (key) {
a5800e90
MP
158 case SR_CONF_LIMIT_SAMPLES:
159 case SR_CONF_LIMIT_FRAMES:
160 case SR_CONF_LIMIT_MSEC:
161 return sr_sw_limits_config_set(&devc->limits, key, data);
cc9653de 162 default:
a5800e90 163 return SR_ERR_NA;
cc9653de 164 }
cc9653de
MP
165}
166
167static int config_list(uint32_t key, GVariant **data,
168 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
169{
a5800e90 170 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
cc9653de
MP
171}
172
173static int dev_acquisition_start(const struct sr_dev_inst *sdi)
174{
a5800e90
MP
175 struct sr_serial_dev_inst *serial;
176 struct dev_context *devc;
177
178 serial = sdi->conn;
179 devc = sdi->priv;
180
181 sr_sw_limits_acquisition_start(&devc->limits);
182 std_session_send_df_header(sdi);
cc9653de 183
a5800e90
MP
184 serial_source_add(sdi->session, serial, G_IO_IN, 100,
185 atorch_receive_data_callback, (void *)sdi);
cc9653de
MP
186
187 return SR_OK;
188}
189
a5800e90 190static void clear_helper(struct dev_context *devc)
cc9653de 191{
a5800e90 192 size_t idx;
cc9653de 193
a5800e90
MP
194 if (!devc)
195 return;
cc9653de 196
a5800e90
MP
197 if (devc->feeds && devc->profile) {
198 for (idx = 0; idx < devc->profile->channel_count; idx++)
199 feed_queue_analog_free(devc->feeds[idx]);
200 g_free(devc->feeds);
201 }
202}
203
204static int dev_clear(const struct sr_dev_driver *driver)
205{
206 return std_dev_clear_with_callback(driver, (std_dev_clear_callback)clear_helper);
cc9653de
MP
207}
208
209static struct sr_dev_driver atorch_driver_info = {
210 .name = "atorch",
a5800e90 211 .longname = "atorch meters and loads",
cc9653de
MP
212 .api_version = 1,
213 .init = std_init,
214 .cleanup = std_cleanup,
215 .scan = scan,
216 .dev_list = std_dev_list,
a5800e90 217 .dev_clear = dev_clear,
cc9653de
MP
218 .config_get = config_get,
219 .config_set = config_set,
220 .config_list = config_list,
a5800e90
MP
221 .dev_open = std_serial_dev_open,
222 .dev_close = std_serial_dev_close,
cc9653de 223 .dev_acquisition_start = dev_acquisition_start,
a5800e90 224 .dev_acquisition_stop = std_serial_dev_acquisition_stop,
cc9653de
MP
225 .context = NULL,
226};
227SR_REGISTER_DEV_DRIVER(atorch_driver_info);