From: Gerhard Sittig Date: Sun, 20 Sep 2020 07:14:01 +0000 (+0200) Subject: serial: add routine to manipulate handshake state (RTS, DTR) X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=3ad30b4e19211eda2f4e00f78c76feeea3323b49;p=libsigrok.git serial: add routine to manipulate handshake state (RTS, DTR) Introduce a routine in libsigrok's internal serial layer which lets applications manipulate the state of handshake signals (RTS and DTR) after the serial port got opened and configured. This allows for timed pulses which cannot get expressed with static "rts=1" etc phrases in parameter strings, and allows handshake signal control while leaving bitrate and frame format untouched. Applications specify which signals to modify while other signals remain as they are (ternary input). Do implement the signal manipulation in the libserialport transport, do nothing and silently pass in the HID and BT transports. These can get extended later as the need arises, depending on the HID chips' and RFCOMM peers' capability to control these signals. This extension is transparent to application code (acquisition device drivers). --- diff --git a/src/libsigrok-internal.h b/src/libsigrok-internal.h index 75c91e92..b614c93d 100644 --- a/src/libsigrok-internal.h +++ b/src/libsigrok-internal.h @@ -1759,6 +1759,8 @@ SR_PRIV int std_cg_idx(const struct sr_channel_group *cg, struct sr_channel_grou SR_PRIV int std_dummy_set_params(struct sr_serial_dev_inst *serial, int baudrate, int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr); +SR_PRIV int std_dummy_set_handshake(struct sr_serial_dev_inst *serial, + int rts, int dtr); /*--- resource.c ------------------------------------------------------------*/ @@ -1843,6 +1845,8 @@ SR_PRIV int serial_set_read_chunk_cb(struct sr_serial_dev_inst *serial, serial_rx_chunk_callback cb, void *cb_data); SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate, int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr); +SR_PRIV int serial_set_handshake(struct sr_serial_dev_inst *serial, + int rts, int dtr); SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, const char *paramstr); SR_PRIV int serial_readline(struct sr_serial_dev_inst *serial, char **buf, @@ -1883,6 +1887,8 @@ struct ser_lib_functions { int (*set_params)(struct sr_serial_dev_inst *serial, int baudrate, int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr); + int (*set_handshake)(struct sr_serial_dev_inst *serial, + int rts, int dtr); int (*setup_source_add)(struct sr_session *session, struct sr_serial_dev_inst *serial, int events, int timeout, diff --git a/src/serial.c b/src/serial.c index 8ffba795..34d7cbea 100644 --- a/src/serial.c +++ b/src/serial.c @@ -561,6 +561,37 @@ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, return ret; } +/** + * Manipulate handshake state for the specified serial port. + * + * @param serial Previously initialized serial port structure. + * @param[in] rts Status of RTS line (0 or 1; or -1 to ignore). + * @param[in] dtr Status of DTR line (0 or 1; or -1 to ignore). + * + * @retval SR_OK Success. + * @retval SR_ERR Failure. + * + * @private + */ +SR_PRIV int serial_set_handshake(struct sr_serial_dev_inst *serial, + int rts, int dtr) +{ + int ret; + + if (!serial) { + sr_dbg("Invalid serial port."); + return SR_ERR; + } + + sr_spew("Modifying serial parameters on port %s.", serial->port); + + if (!serial->lib_funcs || !serial->lib_funcs->set_handshake) + return SR_ERR_NA; + ret = serial->lib_funcs->set_handshake(serial, rts, dtr); + + return ret; +} + /** * Set serial parameters for the specified serial port from parameter string. * diff --git a/src/serial_bt.c b/src/serial_bt.c index 42d6289a..9d7cfb2b 100644 --- a/src/serial_bt.c +++ b/src/serial_bt.c @@ -816,6 +816,7 @@ static struct ser_lib_functions serlib_bt = { * here, since the caller will cache/register them already. */ .set_params = std_dummy_set_params, + .set_handshake = std_dummy_set_handshake, .setup_source_add = ser_bt_setup_source_add, .setup_source_remove = ser_bt_setup_source_remove, .list = ser_bt_list, diff --git a/src/serial_hid.c b/src/serial_hid.c index 0db5cab5..eccdf0f2 100644 --- a/src/serial_hid.c +++ b/src/serial_hid.c @@ -1340,6 +1340,7 @@ static struct ser_lib_functions serlib_hid = { .write = ser_hid_write, .read = ser_hid_read, .set_params = ser_hid_set_params, + .set_handshake = std_dummy_set_handshake, .setup_source_add = ser_hid_setup_source_add, .setup_source_remove = ser_hid_setup_source_remove, .list = ser_hid_list, diff --git a/src/serial_libsp.c b/src/serial_libsp.c index f5a2b74b..bfdc3202 100644 --- a/src/serial_libsp.c +++ b/src/serial_libsp.c @@ -280,6 +280,30 @@ static int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial, return SR_OK; } +static int sr_ser_libsp_set_handshake(struct sr_serial_dev_inst *serial, + int rts, int dtr) +{ + int ret; + + if (!serial->sp_data) { + sr_dbg("Cannot configure unopened serial port %s.", serial->port); + return SR_ERR; + } + + if (rts >= 0) { + ret = sp_set_rts(serial->sp_data, rts ? SP_RTS_ON : SP_RTS_OFF); + if (ret != SP_OK) + return SR_ERR; + } + if (dtr >= 0) { + ret = sp_set_dtr(serial->sp_data, dtr ? SP_DTR_ON : SP_DTR_OFF); + if (ret != SP_OK) + return SR_ERR; + } + + return SR_OK; +} + #ifdef G_OS_WIN32 typedef HANDLE event_handle; #else @@ -494,6 +518,7 @@ static struct ser_lib_functions serlib_sp = { .write = sr_ser_libsp_write, .read = sr_ser_libsp_read, .set_params = sr_ser_libsp_set_params, + .set_handshake = sr_ser_libsp_set_handshake, .setup_source_add = sr_ser_libsp_source_add, .setup_source_remove = sr_ser_libsp_source_remove, .list = sr_ser_libsp_list, diff --git a/src/std.c b/src/std.c index d1e2eedf..81f269fa 100644 --- a/src/std.c +++ b/src/std.c @@ -928,3 +928,12 @@ SR_PRIV int std_dummy_set_params(struct sr_serial_dev_inst *serial, return SR_OK; } +SR_PRIV int std_dummy_set_handshake(struct sr_serial_dev_inst *serial, + int rts, int dtr) +{ + (void)serial; + (void)rts; + (void)dtr; + + return SR_OK; +}