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 SERIAL_TIMEOUT_MS 1000
26 #define ICSTATION_USBRELAY_CMD_ID 0x50
27 #define ICSTATION_USBRELAY_CMD_START 0x51
29 static int icstation_usbrelay_send_byte(struct sr_serial_dev_inst *serial,
34 ret = serial_write_blocking(serial, &b, sizeof(b), SERIAL_TIMEOUT_MS);
37 if ((size_t)ret != sizeof(b))
43 static int icstation_usbrelay_recv_byte(struct sr_serial_dev_inst *serial,
48 ret = serial_read_blocking(serial, b, sizeof(*b), SERIAL_TIMEOUT_MS);
51 if ((size_t)ret != sizeof(*b))
57 SR_PRIV int icstation_usbrelay_identify(struct sr_serial_dev_inst *serial,
66 * Send the identification request. Receive the device firmware's
67 * identification response.
70 * A vendor firmware implementation detail prevents the host from
71 * identifying the device again once command mode was entered.
72 * The UART protocol provides no means to leave command mode.
73 * The subsequent identification request is mistaken instead as
74 * another relay control request! Identifying the device will fail.
75 * The device must be power cycled before it identifies again.
77 ret = icstation_usbrelay_send_byte(serial, ICSTATION_USBRELAY_CMD_ID);
79 sr_dbg("Could not send identification request.");
82 ret = icstation_usbrelay_recv_byte(serial, id);
84 sr_dbg("Could not receive identification response.");
87 sr_dbg("Identification response 0x%02hhx.", *id);
92 SR_PRIV int icstation_usbrelay_start(const struct sr_dev_inst *sdi)
94 struct sr_serial_dev_inst *serial;
102 return icstation_usbrelay_send_byte(serial,
103 ICSTATION_USBRELAY_CMD_START);
106 SR_PRIV int icstation_usbrelay_switch_cg(const struct sr_dev_inst *sdi,
107 const struct sr_channel_group *cg, gboolean on)
109 struct dev_context *devc;
110 struct channel_group_context *cgc;
117 * The device requires the communication of all relay states
118 * at the same time. Calling applications control individual
119 * relays. The device wants active-low state in the physical
120 * transport. Application uses positive logic (active-high).
122 * Update the locally cached state from the most recent request.
123 * Invert the result and send it to the device. Only update
124 * the internal cache after successful transmission.
127 state = devc->relay_state;
129 /* Set all relays. */
131 state |= devc->relay_mask;
133 state &= ~devc->relay_mask;
136 mask = 1UL << cgc->index;
143 tx_state = ~state & devc->relay_mask;
144 sr_spew("Sending status byte: %x", tx_state);
145 if (icstation_usbrelay_send_byte(sdi->conn, tx_state) != SR_OK) {
146 sr_err("Unable to send status byte.");
150 devc->relay_state = state;