serial: allow for extra rts and dtr options in conn string

Options in addition to the usual "9600/8n1" syntax start with a
slash, and take the form of key=value, where different options are
also separated by slashes. For example:

	"9600/8n1/rts=0/dtr=1"

This sets RTS low and DTR high.
This commit is contained in:
Bert Vermeulen 2012-11-27 00:50:51 +01:00
parent 700dcd5caa
commit 71caaad46b
2 changed files with 58 additions and 20 deletions

View File

@ -284,7 +284,7 @@ SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
* @return SR_OK upon success, SR_ERR upon failure.
*/
SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
int bits, int parity, int stopbits, int flowcontrol)
int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr)
{
if (!serial) {
sr_dbg("Invalid serial port.");
@ -506,23 +506,25 @@ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
return SR_ERR;
}
#if 0
/* TODO: Make configurable via driver options. */
sr_spew("Configuring RTS to 1/high.");
controlbits = TIOCM_RTS;
if ((ret = ioctl(serial->fd, TIOCMBIC, &controlbits)) < 0) {
sr_err("Error setting RTS to 1: %s.", strerror(errno));
return SR_ERR;
if (rts != -1) {
sr_spew("Setting RTS %s.", rts ? "high" : "low");
controlbits = TIOCM_RTS;
if ((ret = ioctl(serial->fd, rts ? TIOCMBIS : TIOCMBIC,
&controlbits)) < 0) {
sr_err("Error setting RTS: %s.", strerror(errno));
return SR_ERR;
}
}
sr_spew("Configuring DTR to 0/low.");
controlbits = TIOCM_DTR;
if ((ret = ioctl(serial->fd, TIOCMBIS, &controlbits)) < 0) {
sr_err("Error setting DTR to 0: %s.", strerror(errno));
return SR_ERR;
if (dtr != -1) {
sr_spew("Setting DTR %s.", dtr ? "high" : "low");
controlbits = TIOCM_DTR;
if ((ret = ioctl(serial->fd, dtr ? TIOCMBIS : TIOCMBIC,
&controlbits)) < 0) {
sr_err("Error setting DTR: %s.", strerror(errno));
return SR_ERR;
}
}
#endif
#endif
@ -539,16 +541,17 @@ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
*
* @return SR_OK upon success, SR_ERR upon failure.
*/
#define SERIAL_COMM_SPEC "^(\\d+)/([78])([neo])([12])$"
#define SERIAL_COMM_SPEC "^(\\d+)/([78])([neo])([12])(.*)$"
SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
const char *paramstr)
{
GRegex *reg;
GMatchInfo *match;
int speed, databits, parity, stopbits;
char *mstr;
int speed, databits, parity, stopbits, rts, dtr, i;
char *mstr, **opts, **kv;
speed = databits = parity = stopbits = 0;
rts = dtr = -1;
reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL);
if (g_regex_match(reg, paramstr, 0, &match)) {
if ((mstr = g_match_info_fetch(match, 1)))
@ -574,12 +577,47 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
if ((mstr = g_match_info_fetch(match, 4)))
stopbits = strtoul(mstr, NULL, 10);
g_free(mstr);
if ((mstr = g_match_info_fetch(match, 5)) && mstr[0] != '\0') {
if (mstr[0] != '/') {
sr_dbg("missing separator before extra options");
speed = 0;
} else {
/* A set of "key=value" options separated by / */
opts = g_strsplit(mstr + 1, "/", 0);
for (i = 0; opts[i]; i++) {
kv = g_strsplit(opts[i], "=", 2);
if (!strncmp(kv[0], "rts", 3)) {
if (kv[1][0] == '1')
rts = 1;
else if (kv[1][0] == '0')
rts = 0;
else {
sr_dbg("invalid value for rts: %c", kv[1][0]);
speed = 0;
}
} else if (!strncmp(kv[0], "dtr", 3)) {
if (kv[1][0] == '1')
dtr = 1;
else if (kv[1][0] == '0')
dtr = 0;
else {
sr_dbg("invalid value for dtr: %c", kv[1][0]);
speed = 0;
}
}
g_strfreev(kv);
}
g_strfreev(opts);
}
}
g_free(mstr);
}
g_match_info_unref(match);
g_regex_unref(reg);
if (speed)
return serial_set_params(serial, speed, databits, parity, stopbits, 0);
return serial_set_params(serial, speed, databits, parity, stopbits,
0, rts, dtr);
else
return SR_ERR_ARG;
}

View File

@ -135,7 +135,7 @@ SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
size_t count);
SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
int bits, int parity, int stopbits, int flowcontrol);
int bits, int parity, int stopbits, int flowcontrol, 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,