* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>
#include <libserialport.h>
#include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h"
-#ifdef G_OS_WIN32
+#ifdef _WIN32
#include <windows.h> /* for HANDLE */
#endif
*
* @param serial Previously initialized serial port structure.
* @param[in] flags Flags to use when opening the serial port. Possible flags
- * include SERIAL_RDWR, SERIAL_RDONLY.
+ * include SERIAL_RDWR, SERIAL_RDONLY.
*
* If the serial structure contains a serialcomm string, it will be
* passed to serial_set_paramstr() after the port is opened.
sr_spew("Opening serial port '%s' (flags %d).", serial->port, flags);
- sp_get_port_by_name(serial->port, &serial->data);
+ sp_get_port_by_name(serial->port, &serial->sp_data);
if (flags & SERIAL_RDWR)
sp_flags = (SP_MODE_READ | SP_MODE_WRITE);
else if (flags & SERIAL_RDONLY)
sp_flags = SP_MODE_READ;
- ret = sp_open(serial->data, sp_flags);
+ ret = sp_open(serial->sp_data, sp_flags);
switch (ret) {
case SP_ERR_ARG:
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot close unopened serial port %s.", serial->port);
return SR_ERR;
}
sr_spew("Closing serial port %s.", serial->port);
- ret = sp_close(serial->data);
+ ret = sp_close(serial->sp_data);
switch (ret) {
case SP_ERR_ARG:
return SR_ERR;
}
- sp_free_port(serial->data);
- serial->data = NULL;
+ sp_free_port(serial->sp_data);
+ serial->sp_data = NULL;
return SR_OK;
}
/**
- * Flush serial port buffers.
+ * Flush serial port buffers. Empty buffers, discard pending RX and TX data.
*
* @param serial Previously initialized serial port structure.
*
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot flush unopened serial port %s.", serial->port);
return SR_ERR;
}
sr_spew("Flushing serial port %s.", serial->port);
- ret = sp_flush(serial->data, SP_BUF_BOTH);
+ ret = sp_flush(serial->sp_data, SP_BUF_BOTH);
switch (ret) {
case SP_ERR_ARG:
}
/**
- * Drain serial port buffers.
+ * Drain serial port buffers. Wait for pending TX data to be sent.
*
* @param serial Previously initialized serial port structure.
*
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot drain unopened serial port %s.", serial->port);
return SR_ERR;
}
sr_spew("Draining serial port %s.", serial->port);
- ret = sp_drain(serial->data);
+ ret = sp_drain(serial->sp_data);
if (ret == SP_ERR_FAIL) {
error = sp_last_error_message();
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot use unopened serial port %s.", serial->port);
return SR_ERR;
}
if (nonblocking)
- ret = sp_nonblocking_write(serial->data, buf, count);
+ ret = sp_nonblocking_write(serial->sp_data, buf, count);
else
- ret = sp_blocking_write(serial->data, buf, count, timeout_ms);
+ ret = sp_blocking_write(serial->sp_data, buf, count, timeout_ms);
switch (ret) {
case SP_ERR_ARG:
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot use unopened serial port %s.", serial->port);
return SR_ERR;
}
if (nonblocking)
- ret = sp_nonblocking_read(serial->data, buf, count);
+ ret = sp_nonblocking_read(serial->sp_data, buf, count);
else
- ret = sp_blocking_read(serial->data, buf, count, timeout_ms);
+ ret = sp_blocking_read(serial->sp_data, buf, count, timeout_ms);
switch (ret) {
case SP_ERR_ARG:
* @param[in] timeout_ms Timeout in ms, or 0 for no timeout.
*
* @retval SR_ERR_ARG Invalid argument.
- * @retval SR_ERR Other error.
- * @retval other The number of bytes read. If this is less than the number
+ * @retval SR_ERR Other error.
+ * @retval other The number of bytes read. If this is less than the number
* requested, the timeout was reached.
*
* @private
* @param[in] count The number of bytes to read.
*
* @retval SR_ERR_ARG Invalid argument.
- * @retval SR_ERR Other error.
- * @retval other The number of bytes read.
+ * @retval SR_ERR Other error.
+ * @retval other The number of bytes read.
*
* @private
*/
* @param[in] parity The parity setting to use (0 = none, 1 = even, 2 = odd).
* @param[in] stopbits The number of stop bits to use (1 or 2).
* @param[in] flowcontrol The flow control settings to use (0 = none,
- * 1 = RTS/CTS, 2 = XON/XOFF).
+ * 1 = RTS/CTS, 2 = XON/XOFF).
* @param[in] rts Status of RTS line (0 or 1; required by some interfaces).
* @param[in] dtr Status of DTR line (0 or 1; required by some interfaces).
*
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot configure unopened serial port %s.", serial->port);
return SR_ERR;
}
sp_set_config_dsr(config, SP_DSR_IGNORE);
sp_set_config_xon_xoff(config, flowcontrol == 2 ? SP_XONXOFF_INOUT : SP_XONXOFF_DISABLED);
- ret = sp_set_config(serial->data, config);
+ ret = sp_set_config(serial->sp_data, config);
sp_free_config(config);
switch (ret) {
return SR_ERR;
}
+ serial->comm_params.bit_rate = baudrate;
+ serial->comm_params.data_bits = bits;
+ serial->comm_params.parity_bits = parity ? 1 : 0;
+ serial->comm_params.stop_bits = stopbits;
+ sr_dbg("DBG: %s() rate %d, %d%s%d", __func__,
+ baudrate, bits,
+ (parity == 0) ? "n" : "x",
+ stopbits);
+
return SR_OK;
}
* @param serial Previously initialized serial port structure.
* @param[in] paramstr A serial communication parameters string of the form
* "<baudrate>/<bits><parity><stopbits>{/<option>}".\n
- * Examples: "9600/8n1", "600/7o2/dtr=1/rts=0" or "460800/8n1/flow=2".\n
+ * Examples: "9600/8n1", "600/7o2/dtr=1/rts=0" or "460800/8n1/flow=2".\n
* \<baudrate\>=integer Baud rate.\n
* \<bits\>=5|6|7|8 Number of data bits.\n
* \<parity\>=n|e|o None, even, odd.\n
if ((mstr = g_match_info_fetch(match, 3))) {
switch (mstr[0]) {
case 'n':
- parity = SERIAL_PARITY_NONE;
+ parity = SP_PARITY_NONE;
break;
case 'e':
- parity = SERIAL_PARITY_EVEN;
+ parity = SP_PARITY_EVEN;
break;
case 'o':
- parity = SERIAL_PARITY_ODD;
+ parity = SP_PARITY_ODD;
break;
}
}
/**
* Read a line from the specified serial port.
*
- * @param serial Previously initialized serial port structure.
- * @param buf Buffer where to store the bytes that are read.
- * @param buflen Size of the buffer.
+ * @param[in] serial Previously initialized serial port structure.
+ * @param[out] buf Buffer where to store the bytes that are read.
+ * @param[in] buflen Size of the buffer.
* @param[in] timeout_ms How long to wait for a line to come in.
*
- * Reading stops when CR of LR is found, which is stripped from the buffer.
+ * Reading stops when CR or LF is found, which is stripped from the buffer.
*
* @retval SR_OK Success.
* @retval SR_ERR Failure.
return SR_ERR;
}
- if (!serial->data) {
+ if (!serial->sp_data) {
sr_dbg("Cannot use unopened serial port %s.", serial->port);
return -1;
}
len = maxlen - *buflen - 1;
if (len < 1)
break;
- len = sp_blocking_read(serial->data, *buf + *buflen, 1, remaining);
+ len = sp_blocking_read(serial->sp_data, *buf + *buflen, 1, remaining);
if (len > 0) {
*buflen += len;
*(*buf + *buflen) = '\0';
* @param[in] packet_size Size, in bytes, of a valid packet.
* @param is_valid Callback that assesses whether the packet is valid or not.
* @param[in] timeout_ms The timeout after which, if no packet is detected, to
- * abort scanning.
+ * abort scanning.
* @param[in] baudrate The baudrate of the serial port. This parameter is not
- * critical, but it helps fine tune the serial port polling
- * delay.
+ * critical, but it helps fine tune the serial port polling
+ * delay.
*
* @retval SR_OK Valid packet was found within the given timeout.
* @retval SR_ERR Failure.
time /= 1000;
if ((ibuf - i) >= packet_size) {
+ GString *text;
/* We have at least a packet's worth of data. */
+ text = sr_hexdump_new(&buf[i], packet_size);
+ sr_spew("Trying packet: %s", text->str);
+ sr_hexdump_free(text);
if (is_valid(&buf[i])) {
sr_spew("Found valid %zu-byte packet after "
"%" PRIu64 "ms.", (ibuf - i), time);
}
/** @cond PRIVATE */
-#ifdef G_OS_WIN32
+#ifdef _WIN32
typedef HANDLE event_handle;
#else
typedef int event_handle;
if (events & G_IO_ERR)
mask |= SP_EVENT_ERROR;
- if (sp_add_port_events(event_set, serial->data, mask) != SP_OK) {
+ if (sp_add_port_events(event_set, serial->sp_data, mask) != SP_OK) {
sp_free_event_set(event_set);
return SR_ERR;
}
if (mask & SP_EVENT_ERROR)
poll_events |= G_IO_ERR;
/*
- * Using serial->data as the key for the event source is not quite
+ * Using serial->sp_data as the key for the event source is not quite
* proper, as it makes it impossible to create another event source
* for the same serial port. However, these fixed keys will soon be
* removed from the API anyway, so this is OK for now.
*/
- return sr_session_fd_source_add(session, serial->data,
+ return sr_session_fd_source_add(session, serial->sp_data,
poll_fd, poll_events, timeout, cb, cb_data);
}
SR_PRIV int serial_source_remove(struct sr_session *session,
struct sr_serial_dev_inst *serial)
{
- return sr_session_source_remove_internal(session, serial->data);
+ return sr_session_source_remove_internal(session, serial->sp_data);
}
/**
if (!name)
return NULL;
- serial = g_malloc(sizeof(struct sr_serial_port));
+ serial = g_malloc0(sizeof(*serial));
serial->name = g_strdup(name);
serial->description = g_strdup(description ? description : "");
if (sp_new_config(&config) < 0)
return timeout_ms;
+ /* Get the bitrate and frame length. */
bits = baud = 0;
do {
- if (sp_get_config(port->data, config) < 0)
+ if (sp_get_config(port->sp_data, config) < 0)
break;
/* Start bit. */
break;
baud = tmp;
} while (FALSE);
+ if (!bits || !baud) {
+ baud = port->comm_params.bit_rate;
+ bits = 1 + port->comm_params.data_bits +
+ port->comm_params.parity_bits +
+ port->comm_params.stop_bits;
+ }
+ /* Derive the timeout. */
if (bits && baud) {
/* Throw in 10ms for misc OS overhead. */
timeout_ms = 10;