1
0
mirror of git://sigrok.org/libserialport synced 2023-08-10 21:13:24 +03:00

New API for serial control lines.

This commit is contained in:
Martin Ling 2013-11-14 21:12:17 +00:00
parent cbf628c7fe
commit d514a26f81
2 changed files with 160 additions and 42 deletions

View File

@ -60,7 +60,10 @@ struct sp_port_config {
int stopbits; int stopbits;
int flowcontrol; int flowcontrol;
int rts; int rts;
int cts;
int dtr; int dtr;
int dsr;
int xon_xoff;
}; };
/* Return values. */ /* Return values. */
@ -95,14 +98,38 @@ enum {
SP_PARITY_ODD = 2, SP_PARITY_ODD = 2,
}; };
/* Flow control settings. */ /* RTS pin behaviour. */
enum { enum {
/* No flow control. */ SP_RTS_OFF = 0,
SP_FLOW_NONE = 0, SP_RTS_ON = 1,
/* Hardware (RTS/CTS) flow control. */ SP_RTS_FLOW_CONTROL = 2
SP_FLOW_HARDWARE = 1, };
/* Software (XON/XOFF) flow control. */
SP_FLOW_SOFTWARE = 2, /* CTS pin behaviour. */
enum {
SP_CTS_IGNORE = 0,
SP_CTS_FLOW_CONTROL = 1
};
/* DTR pin behaviour. */
enum {
SP_DTR_OFF = 0,
SP_DTR_ON = 1,
SP_DTR_FLOW_CONTROL = 2
};
/* DSR pin behaviour. */
enum {
SP_DSR_IGNORE = 0,
SP_DSR_FLOW_CONTROL = 1
};
/* XON/XOFF flow control behaviour. */
enum {
SP_XONXOFF_DISABLED = 0,
SP_XONXOFF_IN = 1,
SP_XONXOFF_OUT = 2,
SP_XONXOFF_INOUT = 3
}; };
int sp_get_port_by_name(const char *portname, struct sp_port **port_ptr); int sp_get_port_by_name(const char *portname, struct sp_port **port_ptr);

View File

@ -52,7 +52,9 @@ struct sp_port_data {
#else #else
struct termios term; struct termios term;
int rts; int rts;
int cts;
int dtr; int dtr;
int dsr;
#endif #endif
}; };
@ -727,37 +729,43 @@ static int set_stopbits(struct sp_port_data *data, int stopbits)
return SP_OK; return SP_OK;
} }
static int set_flowcontrol(struct sp_port_data *data, int flowcontrol) static int set_rts(struct sp_port_data *data, int rts)
{ {
#ifndef _WIN32 #ifdef _WIN32
data->term.c_iflag &= ~(IXON | IXOFF | IXANY); switch (rts) {
data->term.c_cflag &= ~CRTSCTS; case SP_RTS_OFF:
switch (flowcontrol) { data->dcb.fRtsControl = RTS_CONTROL_DISABLE;
case 0:
/* No flow control. */
break; break;
case 1: case SP_RTS_ON:
data->term.c_cflag |= CRTSCTS; data->dcb.fRtsControl = RTS_CONTROL_ENABLE;
break; break;
case 2: case SP_RTS_FLOW_CONTROL:
data->term.c_iflag |= IXON | IXOFF | IXANY; data->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
break; break;
default: default:
return SP_ERR_ARG; return SP_ERR_ARG;
} }
#else
data->rts = rts;
#endif #endif
return SP_OK; return SP_OK;
} }
static int set_rts(struct sp_port_data *data, int rts) static int set_cts(struct sp_port_data *data, int cts)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (rts) switch (cts) {
data->dcb.fRtsControl = RTS_CONTROL_ENABLE; case SP_CTS_IGNORE:
else data->dcb.fOutxCtsFlow = FALSE;
data->dcb.fRtsControl = RTS_CONTROL_DISABLE; break;
case SP_CTS_FLOW_CONTROL:
data->dcb.fOutxCtsFlow = TRUE;
break;
default:
return SP_ERR_ARG;
}
#else #else
data->rts = rts; data->cts = cts;
#endif #endif
return SP_OK; return SP_OK;
} }
@ -765,16 +773,88 @@ static int set_rts(struct sp_port_data *data, int rts)
static int set_dtr(struct sp_port_data *data, int dtr) static int set_dtr(struct sp_port_data *data, int dtr)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (dtr) switch (dtr) {
data->dcb.fDtrControl = DTR_CONTROL_ENABLE; case SP_DTR_OFF:
else
data->dcb.fDtrControl = DTR_CONTROL_DISABLE; data->dcb.fDtrControl = DTR_CONTROL_DISABLE;
break;
case SP_DTR_ON:
data->dcb.fDtrControl = DTR_CONTROL_ENABLE;
break;
case SP_DTR_FLOW_CONTROL:
data->dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
break;
default:
return SP_ERR_ARG;
}
#else #else
data->dtr = dtr; data->dtr = dtr;
#endif #endif
return SP_OK; return SP_OK;
} }
static int set_dsr(struct sp_port_data *data, int dsr)
{
#ifdef _WIN32
switch (dsr) {
case SP_DSR_IGNORE:
data->dcb.fOutxDsrFlow = FALSE;
break;
case SP_DSR_FLOW_CONTROL:
data->dcb.fOutxDsrFlow = TRUE;
break;
default:
return SP_ERR_ARG;
}
#else
data->dsr = dsr;
#endif
return SP_OK;
}
static int set_xon_xoff(struct sp_port_data *data, int xon_xoff)
{
#ifdef _WIN32
switch (xon_xoff) {
case SP_XONXOFF_DISABLED:
data->dcb.fInX = FALSE;
data->dcb.fOutX = FALSE;
break;
case SP_XONXOFF_IN:
data->dcb.fInX = TRUE;
data->dcb.fOutX = FALSE;
break;
case SP_XONXOFF_OUT:
data->dcb.fInX = FALSE;
data->dcb.fOutX = TRUE;
break;
case SP_XONXOFF_INOUT:
data->dcb.fInX = TRUE;
data->dcb.fOutX = TRUE;
break;
default:
return SP_ERR_ARG;
}
#else
data->term.c_iflag &= ~(IXON | IXOFF | IXANY);
switch (xon_xoff) {
case SP_XONXOFF_DISABLED:
break;
case SP_XONXOFF_IN:
data->term.c_iflag |= IXOFF;
break;
case SP_XONXOFF_OUT:
data->term.c_iflag |= IXON | IXANY;
break;
case SP_XONXOFF_INOUT:
data->term.c_iflag |= IXON | IXOFF | IXANY;
break;
default:
return SP_ERR_ARG;
}
#endif
return SP_OK;
}
static int apply_config(struct sp_port *port, struct sp_port_data *data) static int apply_config(struct sp_port *port, struct sp_port_data *data)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -795,23 +875,32 @@ static int apply_config(struct sp_port *port, struct sp_port_data *data)
/* Ignore modem status lines; enable receiver */ /* Ignore modem status lines; enable receiver */
data->term.c_cflag |= (CLOCAL | CREAD); data->term.c_cflag |= (CLOCAL | CREAD);
/* Asymmetric use of RTS/CTS not supported yet. */
if ((data->rts == SP_RTS_FLOW_CONTROL) != (data->cts == SP_CTS_FLOW_CONTROL))
return SP_ERR_ARG;
/* DTR/DSR flow control not supported yet. */
if (data->dtr == SP_DTR_FLOW_CONTROL || data->dsr == SP_DSR_FLOW_CONTROL)
return SP_ERR_ARG;
if (data->rts == SP_RTS_FLOW_CONTROL)
data->term.c_iflag |= CRTSCTS;
else
{
controlbits = TIOCM_RTS;
if (ioctl(port->fd, data->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC,
&controlbits) < 0)
return SP_ERR_FAIL;
}
controlbits = TIOCM_DTR;
if (ioctl(port->fd, data->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC,
&controlbits) < 0)
return SP_ERR_FAIL;
/* Write the configured settings. */ /* Write the configured settings. */
if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0) if (tcsetattr(port->fd, TCSADRAIN, &data->term) < 0)
return SP_ERR_FAIL; return SP_ERR_FAIL;
if (data->rts != -1) {
controlbits = TIOCM_RTS;
if (ioctl(port->fd, data->rts ? TIOCMBIS : TIOCMBIC,
&controlbits) < 0)
return SP_ERR_FAIL;
}
if (data->dtr != -1) {
controlbits = TIOCM_DTR;
if (ioctl(port->fd, data->dtr ? TIOCMBIS : TIOCMBIC,
&controlbits) < 0)
return SP_ERR_FAIL;
}
#endif #endif
return SP_OK; return SP_OK;
} }
@ -828,9 +917,11 @@ int sp_set_config(struct sp_port *port, struct sp_port_config *config)
TRY_SET(bits); TRY_SET(bits);
TRY_SET(parity); TRY_SET(parity);
TRY_SET(stopbits); TRY_SET(stopbits);
TRY_SET(flowcontrol);
TRY_SET(rts); TRY_SET(rts);
TRY_SET(cts);
TRY_SET(dtr); TRY_SET(dtr);
TRY_SET(dsr);
TRY_SET(xon_xoff);
TRY(apply_config(port, &data)); TRY(apply_config(port, &data));
return SP_OK; return SP_OK;