2 * This file is part of the libsigrok project.
4 * Copyright (C) 2021-2023 Frank Stettner <frank-stettner@gmx.net>
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.
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.
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/>.
24 #define SERIALCOMM "9600/8n1"
26 static const uint32_t scanopts[] = {
31 static const uint32_t drvopts[] = {
35 static const uint32_t devopts[] = {
36 SR_CONF_CONN | SR_CONF_GET,
37 SR_CONF_ENABLED | SR_CONF_SET, /* Enable/disable all relays at once. */
40 static const uint32_t devopts_cg[] = {
41 SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
44 static const struct ics_usbrelay_profile supported_ics_usbrelay[] = {
45 { ICSE012A, 0xAB, "ICSE012A", 4 },
46 { ICSE013A, 0xAD, "ICSE013A", 2 },
47 { ICSE014A, 0xAC, "ICSE014A", 8 },
50 static GSList *scan(struct sr_dev_driver *di, GSList *options)
52 struct sr_dev_inst *sdi;
53 struct dev_context *devc;
54 struct sr_serial_dev_inst *serial;
57 const char *conn, *serialcomm;
60 const struct ics_usbrelay_profile *profile;
61 struct sr_channel_group *cg;
62 struct channel_group_context *cgc;
66 /* Only scan for a device when conn= was specified. */
68 serialcomm = SERIALCOMM;
69 if (sr_serial_extract_options(options, &conn, &serialcomm) != SR_OK)
72 serial = sr_serial_dev_inst_new(conn, serialcomm);
73 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
76 /* Get device model. */
77 ret = icstation_usbrelay_identify(serial, &device_id);
79 sr_err("Cannot retrieve identification details.");
84 for (i = 0; i < ARRAY_SIZE(supported_ics_usbrelay); i++) {
85 profile = &supported_ics_usbrelay[i];
86 if (device_id != profile->id)
88 sdi = g_malloc0(sizeof(*sdi));
89 sdi->status = SR_ST_INACTIVE;
90 sdi->vendor = g_strdup("ICStation");
91 sdi->model = g_strdup(profile->modelname);
92 sdi->inst_type = SR_INST_SERIAL;
94 sdi->connection_id = g_strdup(conn);
96 devc = g_malloc0(sizeof(*devc));
98 devc->relay_count = profile->nb_channels;
99 devc->relay_mask = (1U << devc->relay_count) - 1;
100 /* Assume that all relays are off at the start. */
101 devc->relay_state = 0;
102 for (ch_idx = 0; ch_idx < devc->relay_count; ch_idx++) {
103 cg = g_malloc0(sizeof(*cg));
104 cg->name = g_strdup_printf("R%zu", ch_idx + 1);
105 cgc = g_malloc0(sizeof(*cgc));
108 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
111 devices = g_slist_append(devices, sdi);
115 serial_close(serial);
117 sr_serial_dev_inst_free(serial);
118 sr_warn("Unknown device identification 0x%02hhx.", device_id);
121 return std_scan_complete(di, devices);
124 static int config_get(uint32_t key, GVariant **data,
125 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
127 struct dev_context *devc;
128 struct channel_group_context *cgc;
139 *data = g_variant_new_string(sdi->connection_id);
147 case SR_CONF_ENABLED:
149 mask = 1U << cgc->index;
150 on = devc->relay_state & mask;
151 *data = g_variant_new_boolean(on);
160 static int config_set(uint32_t key, GVariant *data,
161 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
167 case SR_CONF_ENABLED:
168 /* Enable/disable all channels at the same time. */
169 on = g_variant_get_boolean(data);
170 return icstation_usbrelay_switch_cg(sdi, cg, on);
176 case SR_CONF_ENABLED:
177 on = g_variant_get_boolean(data);
178 return icstation_usbrelay_switch_cg(sdi, cg, on);
187 static int config_list(uint32_t key, GVariant **data,
188 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
192 case SR_CONF_SCAN_OPTIONS:
193 case SR_CONF_DEVICE_OPTIONS:
194 return STD_CONFIG_LIST(key, data, sdi, cg,
195 scanopts, drvopts, devopts);
202 case SR_CONF_DEVICE_OPTIONS:
203 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg));
210 static int dev_open(struct sr_dev_inst *sdi)
212 struct sr_serial_dev_inst *serial;
221 ret = std_serial_dev_open(sdi);
225 /* Start command mode. */
226 ret = icstation_usbrelay_start(sdi);
228 sr_err("Cannot initiate command mode.");
229 serial_close(serial);
236 static struct sr_dev_driver icstation_usbrelay_driver_info = {
237 .name = "icstation-usbrelay",
238 .longname = "ICStation USBRelay",
241 .cleanup = std_cleanup,
243 .dev_list = std_dev_list,
244 .dev_clear = std_dev_clear,
245 .config_get = config_get,
246 .config_set = config_set,
247 .config_list = config_list,
248 .dev_open = dev_open,
249 .dev_close = std_serial_dev_close,
250 .dev_acquisition_start = std_dummy_dev_acquisition_start,
251 .dev_acquisition_stop = std_dummy_dev_acquisition_stop,
254 SR_REGISTER_DEV_DRIVER(icstation_usbrelay_driver_info);