]> sigrok.org Git - libsigrok.git/blame - src/hardware/itech-it8500/api.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / itech-it8500 / api.c
CommitLineData
c16effae
TK
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2020 Timo Kokkonen <tjko@iki.fi>
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>
f21b6983 21#include <string.h>
c16effae
TK
22#include "protocol.h"
23
f21b6983
TK
24#define MIN_SAMPLE_RATE SR_HZ(1)
25#define MAX_SAMPLE_RATE SR_HZ(60)
26#define DEFAULT_SAMPLE_RATE SR_HZ(10)
c16effae 27
f21b6983
TK
28static const uint32_t scanopts[] = {
29 SR_CONF_CONN,
30 SR_CONF_SERIALCOMM,
31};
c16effae 32
f21b6983
TK
33static const uint32_t drvopts[] = {
34 SR_CONF_ELECTRONIC_LOAD,
35};
c16effae 36
f21b6983
TK
37static const uint32_t devopts[] = {
38 SR_CONF_CONTINUOUS,
39 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
40 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
41 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
42};
c16effae 43
f21b6983
TK
44static const uint32_t devopts_cg[] = {
45 SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
46 SR_CONF_REGULATION | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
47 SR_CONF_VOLTAGE | SR_CONF_GET,
48 SR_CONF_VOLTAGE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
49 SR_CONF_CURRENT | SR_CONF_GET,
50 SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
51 SR_CONF_POWER | SR_CONF_GET,
52 SR_CONF_POWER_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
53 SR_CONF_RESISTANCE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
54 SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED | SR_CONF_GET,
55 SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE | SR_CONF_GET,
56 SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
57 SR_CONF_OVER_CURRENT_PROTECTION_ENABLED | SR_CONF_GET,
58 SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE | SR_CONF_GET,
59 SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
60 SR_CONF_UNDER_VOLTAGE_CONDITION | SR_CONF_GET,
61 SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE | SR_CONF_GET,
62 SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
63 SR_CONF_OVER_TEMPERATURE_PROTECTION | SR_CONF_GET,
64 SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE | SR_CONF_GET,
65};
c16effae 66
f21b6983
TK
67static const uint64_t samplerates[] = {
68 SR_HZ(1),
69 SR_HZ(2),
70 SR_HZ(5),
71 SR_HZ(10),
72 SR_HZ(15),
73 SR_HZ(20),
74 SR_HZ(30),
75 SR_HZ(40),
76 SR_HZ(50),
77 SR_HZ(60),
78};
c16effae 79
f21b6983
TK
80static const char *default_serial_parameters[] = {
81 "9600/8n1", /* Factory default. */
82 "38400/8n1",
83 "19200/8n1",
84 "4800/8n1",
85 NULL,
86};
c16effae 87
f21b6983 88static struct sr_dev_driver itech_it8500_driver_info;
c16effae 89
f21b6983 90static GSList *scan(struct sr_dev_driver *di, GSList *options)
c16effae 91{
f21b6983
TK
92 struct sr_dev_inst *sdi;
93 struct sr_config *conf;
94 struct sr_serial_dev_inst *serial;
95 struct sr_channel_group *cg;
96 struct sr_channel *ch;
97 struct dev_context *devc;
98 const char *custom_serial_parameters[2];
99 const char **serial_parameters;
100 const char *conn, *serialcomm;
101 GSList *l;
102 struct itech_it8500_cmd_packet *cmd, *response;
103 uint8_t fw_major, fw_minor;
104 const uint8_t *p;
105 char *unit_model, *unit_serial, *unit_barcode;
106 double max_i, max_v, min_v, max_p, max_r, min_r;
107 uint64_t max_samplerate;
108
109 size_t u, i;
110 int ret;
111
112 cmd = g_malloc0(sizeof(*cmd));
113 devc = g_malloc0(sizeof(*devc));
114 sdi = g_malloc0(sizeof(*sdi));
115 if (!cmd || !devc || !sdi)
116 return NULL;
117
118 serial = NULL;
119 response = NULL;
120 unit_model = NULL;
121 unit_serial = NULL;
122
123 /*
124 * Use a list of typical parameters for serial communication by
125 * default. Prefer user specified parameters when available.
126 * Lack of a user specified serial port is fatal.
127 */
128 conn = NULL;
129 serialcomm = NULL;
130 serial_parameters = default_serial_parameters;
131 for (l = options; l; l = l->next) {
132 conf = l->data;
133 switch (conf->key) {
134 case SR_CONF_CONN:
135 conn = g_variant_get_string(conf->data, NULL);
136 break;
137 case SR_CONF_SERIALCOMM:
138 serialcomm = g_variant_get_string(conf->data, NULL);
139 custom_serial_parameters[0] = serialcomm;
140 custom_serial_parameters[1] = NULL;
141 serial_parameters = custom_serial_parameters;
142 break;
143 }
144 }
145 if (!conn)
146 goto error;
147
148 /*
149 * Try different serial parameters in the list
150 * until we get a response (or none at all).
151 */
152 sr_info("Probing serial port: %s", conn);
153 for (i = 0; (serialcomm = serial_parameters[i]); i++) {
154 serial = sr_serial_dev_inst_new(conn, serialcomm);
155 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
156 goto error;
157 serial_flush(serial);
158
159 cmd->address = 0xff; /* Use "broadcast" address. */
160 cmd->command = CMD_GET_MODEL_INFO;
161 if (itech_it8500_send_cmd(serial, cmd, &response) == SR_OK)
162 break;
163
164 serial_close(serial);
165 sr_serial_dev_inst_free(serial);
166 serial = NULL;
167 }
168 if (!serialcomm)
169 goto error;
170
171 /*
172 * The "dense" response string consists of several fields. Grab
173 * integer data before putting terminators in their place to
174 * grab text strings afterwards. Order is important here.
175 */
176 devc->address = response->address;
177 fw_major = response->data[6];
178 fw_minor = response->data[5];
179 response->data[5] = 0;
180 unit_model = g_strdup((const char *)&response->data[0]);
181 response->data[17] = 0;
182 unit_serial = g_strdup((const char *)&response->data[7]);
183 sr_info("Model name: %s (v%x.%02x)", unit_model, fw_major, fw_minor);
184 sr_info("Address: %d", devc->address);
185 sr_info("Serial number: %s", unit_serial);
186
187 sdi->status = SR_ST_INACTIVE;
188 sdi->conn = serial;
189 sdi->inst_type = SR_INST_SERIAL;
190 sdi->driver = &itech_it8500_driver_info;
191 sdi->priv = devc;
192 g_mutex_init(&devc->mutex);
193
194 /*
195 * Calculate maxium "safe" sample rate based on serial connection
196 * speed / bitrate.
197 */
198 max_samplerate = serial->comm_params.bit_rate * 15 / 9600;
199 if (max_samplerate < 15)
200 max_samplerate = 10;
201 if (max_samplerate > MAX_SAMPLE_RATE)
202 max_samplerate = MAX_SAMPLE_RATE;
203 devc->max_sample_rate_idx = 0;
204 for (u = 0; u < ARRAY_SIZE(samplerates); u++) {
205 if (samplerates[u] > max_samplerate)
206 break;
207 devc->max_sample_rate_idx = u;
208 }
209 devc->sample_rate = DEFAULT_SAMPLE_RATE;
210
211 /*
212 * Get full serial number (barcode).
213 */
214 cmd->address = devc->address;
215 cmd->command = CMD_GET_BARCODE_INFO;
216 if (itech_it8500_send_cmd(serial, cmd, &response) == SR_OK) {
217 unit_barcode = g_malloc0(IT8500_DATA_LEN + 1);
218 memcpy(unit_barcode, response->data, IT8500_DATA_LEN);
219 sr_info("Barcode: %s", response->data);
220 g_free(unit_barcode);
221 }
c16effae 222
f21b6983
TK
223 /*
224 * Query unit capabilities.
225 */
226 cmd->command = CMD_GET_LOAD_LIMITS;
227 if (itech_it8500_send_cmd(serial, cmd, &response) != SR_OK)
228 goto error;
229 p = response->data;
230 max_i = read_u32le_inc(&p) / 10000.0;
231 max_v = read_u32le_inc(&p) / 1000.0;
232 min_v = read_u32le_inc(&p) / 1000.0;
233 max_p = read_u32le_inc(&p) / 1000.0;
234 max_r = read_u32le_inc(&p) / 1000.0;
235 min_r = read_u16le_inc(&p) / 1000.0;
236 sr_info("Max current: %.0f A", max_i);
237 sr_info("Max power: %.0f W", max_p);
238 sr_info("Voltage range: %.1f - %.1f V", min_v, max_v);
239 sr_info("Resistance range: %.2f - %.2f Ohm", min_r, max_r);
240
241 /*
242 * Get current status of the unit.
243 */
244 if ((ret = itech_it8500_get_status(sdi)) != SR_OK) {
245 sr_err("Failed to get unit status: %d", ret);
246 goto error;
247 }
248 sr_info("Mode: %s", itech_it8500_mode_to_string(devc->mode));
249 sr_info("State: %s", devc->load_on ? "ON" : "OFF");
250 sr_info("Default sample rate: %" PRIu64 " Hz", devc->sample_rate);
251 sr_info("Maximum sample rate: %" PRIu64 " Hz",
252 samplerates[devc->max_sample_rate_idx]);
253
254 /*
255 * Populate data structures.
256 */
257
258 devc->fw_ver_major = fw_major;
259 devc->fw_ver_minor = fw_minor;
260 snprintf(devc->model, sizeof(devc->model), "%s", unit_model);
261 devc->max_current = max_i;
262 devc->min_voltage = min_v;
263 devc->max_voltage = max_v;
264 devc->max_power = max_p;
265 devc->min_resistance = min_r;
266 devc->max_resistance = max_r;
267
268 sdi->vendor = g_strdup("ITECH");
269 sdi->model = unit_model;
270 sdi->version = g_strdup_printf("%x.%02x", fw_major, fw_minor);
271 sdi->serial_num = unit_serial;
272
d810901a 273 cg = sr_channel_group_new(sdi, "1", NULL);
f21b6983
TK
274 ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V1");
275 cg->channels = g_slist_append(cg->channels, ch);
276 ch = sr_channel_new(sdi, 1, SR_CHANNEL_ANALOG, TRUE, "I1");
277 cg->channels = g_slist_append(cg->channels, ch);
278 ch = sr_channel_new(sdi, 2, SR_CHANNEL_ANALOG, TRUE, "P1");
279 cg->channels = g_slist_append(cg->channels, ch);
280
281 g_free(cmd);
282 g_free(response);
283 serial_close(serial);
284
285 return std_scan_complete(di, g_slist_append(NULL, sdi));
286
287error:
288 g_free(cmd);
289 g_free(devc);
290 g_free(sdi);
291 g_free(response);
292 g_free(unit_model);
293 g_free(unit_serial);
294 if (serial) {
295 serial_close(serial);
296 sr_serial_dev_inst_free(serial);
297 }
c16effae 298
f21b6983 299 return NULL;
c16effae
TK
300}
301
302static int config_get(uint32_t key, GVariant **data,
f21b6983
TK
303 const struct sr_dev_inst *sdi,
304 const struct sr_channel_group *cg)
c16effae 305{
f21b6983
TK
306 struct dev_context *devc;
307 const struct sr_key_info *kinfo;
308 const char *mode;
309 int ret, ival;
310 gboolean bval;
c16effae 311
c16effae
TK
312 (void)cg;
313
f21b6983
TK
314 if (!data || !sdi)
315 return SR_ERR_ARG;
316
317 devc = sdi->priv;
318 kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
c16effae 319 ret = SR_OK;
f21b6983 320
c16effae 321 switch (key) {
f21b6983
TK
322 case SR_CONF_LIMIT_SAMPLES:
323 case SR_CONF_LIMIT_MSEC:
324 ret = sr_sw_limits_config_get(&devc->limits, key, data);
325 break;
326 case SR_CONF_SAMPLERATE:
327 *data = g_variant_new_uint64(devc->sample_rate);
328 break;
329 case SR_CONF_ENABLED:
330 ret = itech_it8500_get_status(sdi);
78b07caf
GS
331 if (ret != SR_OK)
332 break;
333 *data = g_variant_new_boolean(devc->load_on);
f21b6983
TK
334 break;
335 case SR_CONF_REGULATION:
336 ret = itech_it8500_get_status(sdi);
78b07caf
GS
337 if (ret != SR_OK)
338 break;
339 mode = itech_it8500_mode_to_string(devc->mode);
340 *data = g_variant_new_string(mode);
f21b6983
TK
341 break;
342 case SR_CONF_VOLTAGE:
343 ret = itech_it8500_get_status(sdi);
78b07caf
GS
344 if (ret != SR_OK)
345 break;
346 *data = g_variant_new_double(devc->voltage);
f21b6983
TK
347 break;
348 case SR_CONF_VOLTAGE_TARGET:
349 ret = itech_it8500_get_int(sdi, CMD_GET_CV_VOLTAGE, &ival);
78b07caf
GS
350 if (ret != SR_OK)
351 break;
352 *data = g_variant_new_double((double)ival / 1000.0);
f21b6983
TK
353 break;
354 case SR_CONF_CURRENT:
355 ret = itech_it8500_get_status(sdi);
78b07caf
GS
356 if (ret != SR_OK)
357 break;
358 *data = g_variant_new_double(devc->current);
f21b6983
TK
359 break;
360 case SR_CONF_CURRENT_LIMIT:
361 ret = itech_it8500_get_int(sdi, CMD_GET_CC_CURRENT, &ival);
78b07caf
GS
362 if (ret != SR_OK)
363 break;
364 *data = g_variant_new_double((double)ival / 10000.0);
f21b6983
TK
365 break;
366 case SR_CONF_POWER:
367 ret = itech_it8500_get_status(sdi);
78b07caf
GS
368 if (ret != SR_OK)
369 break;
370 *data = g_variant_new_double(devc->power);
f21b6983
TK
371 break;
372 case SR_CONF_POWER_TARGET:
373 ret = itech_it8500_get_int(sdi, CMD_GET_CW_POWER, &ival);
78b07caf
GS
374 if (ret != SR_OK)
375 break;
376 *data = g_variant_new_double((double)ival / 1000.0);
f21b6983
TK
377 break;
378 case SR_CONF_RESISTANCE_TARGET:
379 ret = itech_it8500_get_int(sdi, CMD_GET_CR_RESISTANCE, &ival);
78b07caf
GS
380 if (ret != SR_OK)
381 break;
382 *data = g_variant_new_double((double)ival / 1000.0);
f21b6983
TK
383 break;
384 case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
385 *data = g_variant_new_boolean(TRUE);
386 break;
387 case SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE:
388 ret = itech_it8500_get_status(sdi);
78b07caf
GS
389 if (ret != SR_OK)
390 break;
391 bval = devc->demand_state & DS_OV_FLAG;
392 *data = g_variant_new_boolean(bval);
f21b6983
TK
393 break;
394 case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
395 ret = itech_it8500_get_int(sdi, CMD_GET_MAX_VOLTAGE, &ival);
78b07caf
GS
396 if (ret != SR_OK)
397 break;
398 *data = g_variant_new_double((double)ival / 1000.0);
f21b6983
TK
399 break;
400 case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
401 *data = g_variant_new_boolean(TRUE);
402 break;
403 case SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE:
404 ret = itech_it8500_get_status(sdi);
78b07caf
GS
405 if (ret != SR_OK)
406 break;
407 bval = devc->demand_state & DS_OC_FLAG;
408 *data = g_variant_new_boolean(bval);
f21b6983
TK
409 break;
410 case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
411 ret = itech_it8500_get_int(sdi, CMD_GET_MAX_CURRENT, &ival);
78b07caf
GS
412 if (ret != SR_OK)
413 break;
414 *data = g_variant_new_double((double)ival / 10000.0);
f21b6983
TK
415 break;
416 case SR_CONF_OVER_TEMPERATURE_PROTECTION:
417 *data = g_variant_new_boolean(TRUE);
418 break;
419 case SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE:
420 ret = itech_it8500_get_status(sdi);
78b07caf
GS
421 if (ret != SR_OK)
422 break;
423 bval = devc->demand_state & DS_OT_FLAG;
424 *data = g_variant_new_boolean(bval);
f21b6983
TK
425 break;
426 /* Hardware doesn't support under voltage reporting. */
427 case SR_CONF_UNDER_VOLTAGE_CONDITION:
428 case SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE:
429 *data = g_variant_new_boolean(FALSE);
430 break;
431 case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
432 *data = g_variant_new_double(0.0);
433 break;
c16effae 434 default:
f21b6983
TK
435 sr_dbg("%s: Unsupported key: %u (%s)", __func__, key,
436 kinfo ? kinfo->name : "unknown");
437 ret = SR_ERR_NA;
78b07caf 438 break;
c16effae
TK
439 }
440
441 return ret;
442}
443
444static int config_set(uint32_t key, GVariant *data,
f21b6983
TK
445 const struct sr_dev_inst *sdi,
446 const struct sr_channel_group *cg)
c16effae 447{
f21b6983
TK
448 struct dev_context *devc;
449 struct itech_it8500_cmd_packet *cmd, *response;
450 const struct sr_key_info *kinfo;
451 enum itech_it8500_modes mode;
452 int ret, ivalue;
453 uint64_t new_sr;
454 const char *s;
c16effae 455
c16effae
TK
456 (void)cg;
457
f21b6983
TK
458 if (!data || !sdi)
459 return SR_ERR_ARG;
460
461 cmd = g_malloc0(sizeof(*cmd));
462 if (!cmd)
463 return SR_ERR_MALLOC;
464
465 devc = sdi->priv;
466 response = NULL;
c16effae 467 ret = SR_OK;
f21b6983
TK
468
469 kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
470
c16effae 471 switch (key) {
f21b6983
TK
472 case SR_CONF_LIMIT_MSEC:
473 case SR_CONF_LIMIT_SAMPLES:
474 ret = sr_sw_limits_config_set(&devc->limits, key, data);
78b07caf 475 break;
f21b6983
TK
476 case SR_CONF_SAMPLERATE:
477 new_sr = g_variant_get_uint64(data);
78b07caf 478 if (new_sr < MIN_SAMPLE_RATE) {
f21b6983 479 ret = SR_ERR_SAMPLERATE;
78b07caf
GS
480 break;
481 }
482 if (new_sr > samplerates[devc->max_sample_rate_idx]) {
483 ret = SR_ERR_SAMPLERATE;
484 break;
f21b6983
TK
485 }
486 devc->sample_rate = new_sr;
78b07caf 487 break;
f21b6983
TK
488 case SR_CONF_ENABLED:
489 cmd->command = CMD_LOAD_ON_OFF;
490 cmd->data[0] = g_variant_get_boolean(data);
491 break;
492 case SR_CONF_REGULATION:
f21b6983
TK
493 s = g_variant_get_string(data, NULL);
494 if (itech_it8500_string_to_mode(s, &mode) != SR_OK) {
495 ret = SR_ERR_ARG;
78b07caf 496 break;
f21b6983 497 }
78b07caf 498 cmd->command = CMD_SET_MODE;
f21b6983
TK
499 cmd->data[0] = mode;
500 break;
501 case SR_CONF_VOLTAGE_TARGET:
502 cmd->command = CMD_SET_CV_VOLTAGE;
503 ivalue = g_variant_get_double(data) * 1000.0;
504 WL32(&cmd->data[0], ivalue);
505 break;
506 case SR_CONF_CURRENT_LIMIT:
507 cmd->command = CMD_SET_CC_CURRENT;
508 ivalue = g_variant_get_double(data) * 10000.0;
509 WL32(&cmd->data[0], ivalue);
510 break;
511 case SR_CONF_POWER_TARGET:
512 cmd->command = CMD_SET_CW_POWER;
513 ivalue = g_variant_get_double(data) * 1000.0;
514 WL32(&cmd->data[0], ivalue);
515 break;
516 case SR_CONF_RESISTANCE_TARGET:
517 cmd->command = CMD_SET_CR_RESISTANCE;
518 ivalue = g_variant_get_double(data) * 1000.0;
519 WL32(&cmd->data[0], ivalue);
520 break;
521 case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
522 cmd->command = CMD_SET_MAX_VOLTAGE;
523 ivalue = g_variant_get_double(data) * 1000.0;
524 WL32(&cmd->data[0], ivalue);
525 break;
526 case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
527 cmd->command = CMD_SET_MAX_CURRENT;
528 ivalue = g_variant_get_double(data) * 10000.0;
529 WL32(&cmd->data[0], ivalue);
530 break;
c16effae 531 default:
f21b6983
TK
532 sr_dbg("%s: Unsupported key: %u (%s)", __func__, key,
533 kinfo ? kinfo->name : "unknown");
c16effae 534 ret = SR_ERR_NA;
78b07caf 535 break;
c16effae
TK
536 }
537
78b07caf
GS
538 if (ret == SR_OK && cmd->command) {
539 cmd->address = devc->address;
540 ret = itech_it8500_cmd(sdi, cmd, &response);
541 }
f21b6983 542
f21b6983
TK
543 g_free(cmd);
544 g_free(response);
545
c16effae
TK
546 return ret;
547}
548
549static int config_list(uint32_t key, GVariant **data,
f21b6983
TK
550 const struct sr_dev_inst *sdi,
551 const struct sr_channel_group *cg)
c16effae 552{
f21b6983
TK
553 const struct dev_context *devc;
554 const struct sr_key_info *kinfo;
555 GVariantBuilder *b;
c16effae 556
f21b6983
TK
557 devc = sdi ? sdi->priv : NULL;
558 if (!data)
559 return SR_ERR_ARG;
560
561 if (!cg)
562 return STD_CONFIG_LIST(key, data, sdi, cg,
563 scanopts, drvopts, devopts);
564
565 kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
c16effae 566
c16effae 567 switch (key) {
f21b6983
TK
568 case SR_CONF_DEVICE_OPTIONS:
569 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg));
570 break;
571 case SR_CONF_SAMPLERATE:
572 *data = std_gvar_samplerates_steps(samplerates,
573 1 + devc->max_sample_rate_idx);
574 break;
575 case SR_CONF_REGULATION:
576 b = g_variant_builder_new(G_VARIANT_TYPE("as"));
577 g_variant_builder_add(b, "s", itech_it8500_mode_to_string(CC));
578 g_variant_builder_add(b, "s", itech_it8500_mode_to_string(CV));
579 g_variant_builder_add(b, "s", itech_it8500_mode_to_string(CW));
580 g_variant_builder_add(b, "s", itech_it8500_mode_to_string(CR));
581 *data = g_variant_new("as", b);
582 g_variant_builder_unref(b);
583 break;
584 case SR_CONF_VOLTAGE_TARGET:
585 if (!devc)
586 return SR_ERR_ARG;
587 *data = std_gvar_min_max_step(devc->min_voltage,
588 devc->max_voltage, 0.01);
589 break;
590 case SR_CONF_CURRENT_LIMIT:
591 if (!devc)
592 return SR_ERR_ARG;
593 *data = std_gvar_min_max_step(0.0, devc->max_current, 0.001);
594 break;
595 case SR_CONF_POWER_TARGET:
596 if (!devc)
597 return SR_ERR_ARG;
598 *data = std_gvar_min_max_step(0.0, devc->max_power, 0.01);
599 break;
600 case SR_CONF_RESISTANCE_TARGET:
601 if (!devc)
602 return SR_ERR_ARG;
603 *data = std_gvar_min_max_step(devc->min_resistance,
604 devc->max_resistance, 0.01);
605 break;
606
c16effae 607 default:
f21b6983
TK
608 sr_dbg("%s: Unsupported key: %u (%s)", __func__, key,
609 kinfo ? kinfo->name : "unknown");
c16effae
TK
610 return SR_ERR_NA;
611 }
612
f21b6983 613 return SR_OK;
c16effae
TK
614}
615
616static int dev_acquisition_start(const struct sr_dev_inst *sdi)
617{
f21b6983
TK
618 struct dev_context *devc;
619 struct sr_serial_dev_inst *serial;
620 int ret;
c16effae 621
f21b6983
TK
622 if (!sdi)
623 return SR_ERR_ARG;
c16effae 624
f21b6983
TK
625 devc = sdi->priv;
626 serial = sdi->conn;
627
8c8fff47
GS
628 ret = serial_source_add(sdi->session, serial,
629 G_IO_IN, (1000.0 / devc->sample_rate),
f21b6983
TK
630 itech_it8500_receive_data, (void *)sdi);
631 if (ret == SR_OK) {
632 sr_sw_limits_acquisition_start(&devc->limits);
633 std_session_send_df_header(sdi);
634 }
635
636 return ret;
c16effae
TK
637}
638
639static int dev_acquisition_stop(struct sr_dev_inst *sdi)
640{
f21b6983
TK
641 struct sr_serial_dev_inst *serial;
642
643 if (!sdi)
644 return SR_ERR_ARG;
c16effae 645
f21b6983
TK
646 serial = sdi->conn;
647
648 std_session_send_df_end(sdi);
649 serial_source_remove(sdi->session, serial);
c16effae
TK
650
651 return SR_OK;
652}
653
f21b6983
TK
654static int dev_open(struct sr_dev_inst *sdi)
655{
656 struct dev_context *devc;
657 struct itech_it8500_cmd_packet *cmd, *response;
658 int ret, res;
659
660 if (!sdi)
661 return SR_ERR_ARG;
662
663 devc = sdi->priv;
664 ret = std_serial_dev_open(sdi);
665 if (ret == SR_OK) {
666 /* Request the unit to enter remote control mode. */
667 response = NULL;
668 cmd = g_malloc0(sizeof(*cmd));
669 if (cmd) {
670 cmd->address = devc->address;
671 cmd->command = CMD_SET_REMOTE_MODE;
672 cmd->data[0] = 1;
673 res = itech_it8500_cmd(sdi, cmd, &response);
674 if (res != SR_OK)
675 sr_dbg("Failed to set unit to remote mode");
676 g_free(cmd);
677 g_free(response);
678 }
679 }
680
681 return ret;
682}
683
684static int dev_close(struct sr_dev_inst *sdi)
685{
686 struct dev_context *devc;
687 struct itech_it8500_cmd_packet *cmd, *response;
688 int ret;
689
690 if (!sdi)
691 return SR_ERR_ARG;
692
693 devc = sdi->priv;
694 response = NULL;
695 cmd = g_malloc0(sizeof(*cmd));
696 if (cmd) {
697 /* Request the unit to enter local control mode. */
698 cmd->address = devc->address;
699 cmd->command = CMD_SET_REMOTE_MODE;
700 cmd->data[0] = 0;
701 ret = itech_it8500_cmd(sdi, cmd, &response);
702 if (ret != SR_OK)
703 sr_dbg("Failed to set unit back to local mode: %d",
704 ret);
705 }
706
707 g_free(cmd);
708 g_free(response);
709
710 return std_serial_dev_close(sdi);
711}
712
713static void dev_clear_callback(void *priv)
714{
715 struct dev_context *devc;
716
717 if (!priv)
718 return;
719
720 devc = priv;
721 g_mutex_clear(&devc->mutex);
722}
723
724static int dev_clear(const struct sr_dev_driver *di)
725{
726 return std_dev_clear_with_callback(di, dev_clear_callback);
727}
728
c16effae
TK
729static struct sr_dev_driver itech_it8500_driver_info = {
730 .name = "itech-it8500",
f21b6983 731 .longname = "ITECH IT8500 series",
c16effae
TK
732 .api_version = 1,
733 .init = std_init,
734 .cleanup = std_cleanup,
735 .scan = scan,
736 .dev_list = std_dev_list,
f21b6983 737 .dev_clear = dev_clear,
c16effae
TK
738 .config_get = config_get,
739 .config_set = config_set,
740 .config_list = config_list,
741 .dev_open = dev_open,
742 .dev_close = dev_close,
743 .dev_acquisition_start = dev_acquisition_start,
744 .dev_acquisition_stop = dev_acquisition_stop,
745 .context = NULL,
746};
747SR_REGISTER_DEV_DRIVER(itech_it8500_driver_info);