X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fserial.c;h=1b76c935e3a0e1b73874b875185a18105f1f7f37;hb=92cd85149a2497e6eecd8f35e43893b905dc2faa;hp=a2d0189fbb734c9908079e3d8bee768acc48b82a;hpb=d03815a0662a905392e428612507ad4de9f2f8b1;p=libsigrok.git diff --git a/src/serial.c b/src/serial.c index a2d0189f..1b76c935 100644 --- a/src/serial.c +++ b/src/serial.c @@ -55,12 +55,10 @@ #ifdef HAVE_SERIAL_COMM -/* See if a (assumed opened) serial port is of any supported type. */ +/* See if an (assumed opened) serial port is of any supported type. */ static int dev_is_supported(struct sr_serial_dev_inst *serial) { - if (!serial) - return 0; - if (!serial->lib_funcs) + if (!serial || !serial->lib_funcs) return 0; return 1; @@ -124,10 +122,24 @@ SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags) if (ret != SR_OK) return ret; - if (serial->serialcomm) - return serial_set_paramstr(serial, serial->serialcomm); - else - return SR_OK; + if (serial->serialcomm) { + ret = serial_set_paramstr(serial, serial->serialcomm); + if (ret != SR_OK) + return ret; + } + + /* + * Flush potentially dangling RX data. Availability of the + * flush primitive depends on the transport/cable, absense + * is non-fatal. + */ + ret = serial_flush(serial); + if (ret == SR_ERR_NA) + ret = SR_OK; + if (ret != SR_OK) + return ret; + + return SR_OK; } /** @@ -246,7 +258,9 @@ SR_PRIV int serial_drain(struct sr_serial_dev_inst *serial) * @retval SR_ERR_ARG Invalid parameters. * @retval SR_OK Successful registration. * - * Callbacks get unregistered by specifying #NULL for the 'cb' parameter. + * Callbacks get unregistered by specifying NULL for the 'cb' parameter. + * + * @private */ SR_PRIV int serial_set_read_chunk_cb(struct sr_serial_dev_inst *serial, serial_rx_chunk_callback cb, void *cb_data) @@ -266,13 +280,11 @@ SR_PRIV int serial_set_read_chunk_cb(struct sr_serial_dev_inst *serial, * * @param[in] serial Previously opened serial port instance. * - * @internal + * @private */ SR_PRIV void sr_ser_discard_queued_data(struct sr_serial_dev_inst *serial) { - if (!serial) - return; - if (!serial->rcv_buffer) + if (!serial || !serial->rcv_buffer) return; g_string_truncate(serial->rcv_buffer, 0); @@ -284,13 +296,11 @@ SR_PRIV void sr_ser_discard_queued_data(struct sr_serial_dev_inst *serial) * * @param[in] serial Previously opened serial port instance. * - * @internal + * @private */ SR_PRIV size_t sr_ser_has_queued_data(struct sr_serial_dev_inst *serial) { - if (!serial) - return 0; - if (!serial->rcv_buffer) + if (!serial || !serial->rcv_buffer) return 0; return serial->rcv_buffer->len; @@ -304,14 +314,12 @@ SR_PRIV size_t sr_ser_has_queued_data(struct sr_serial_dev_inst *serial) * @param[in] data Pointer to data bytes to queue. * @param[in] len Number of data bytes to queue. * - * @internal + * @private */ SR_PRIV void sr_ser_queue_rx_data(struct sr_serial_dev_inst *serial, const uint8_t *data, size_t len) { - if (!serial) - return; - if (!data || !len) + if (!serial || !data || !len) return; if (serial->rx_chunk_cb_func) @@ -328,7 +336,7 @@ SR_PRIV void sr_ser_queue_rx_data(struct sr_serial_dev_inst *serial, * @param[out] data Pointer to store retrieved data bytes into. * @param[in] len Number of data bytes to retrieve. * - * @internal + * @private */ SR_PRIV size_t sr_ser_unqueue_rx_data(struct sr_serial_dev_inst *serial, uint8_t *data, size_t len) @@ -336,9 +344,7 @@ SR_PRIV size_t sr_ser_unqueue_rx_data(struct sr_serial_dev_inst *serial, size_t qlen; GString *buf; - if (!serial) - return 0; - if (!data || !len) + if (!serial || !data || !len) return 0; qlen = sr_ser_has_queued_data(serial); @@ -365,6 +371,8 @@ SR_PRIV size_t sr_ser_unqueue_rx_data(struct sr_serial_dev_inst *serial, * * Returns 0 if no receive data is available, or if the amount of * available receive data cannot get determined. + * + * @private */ SR_PRIV size_t serial_has_receive_data(struct sr_serial_dev_inst *serial) { @@ -553,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. * @@ -580,7 +619,7 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, const char *paramstr) { /** @cond PRIVATE */ -#define SERIAL_COMM_SPEC "^(\\d+)/([5678])([neo])([12])(.*)$" +#define SERIAL_COMM_SPEC "^(\\d+)(/([5678])([neo])([12]))?(.*)$" /** @endcond */ GRegex *reg; @@ -588,7 +627,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, int speed, databits, parity, stopbits, flow, rts, dtr, i; char *mstr, **opts, **kv; - speed = databits = parity = stopbits = flow = 0; + speed = flow = 0; + databits = 8; + parity = SP_PARITY_NONE; + stopbits = 1; rts = dtr = -1; sr_spew("Parsing parameters from \"%s\".", paramstr); reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL); @@ -596,10 +638,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, if ((mstr = g_match_info_fetch(match, 1))) speed = strtoul(mstr, NULL, 10); g_free(mstr); - if ((mstr = g_match_info_fetch(match, 2))) + if ((mstr = g_match_info_fetch(match, 3)) && mstr[0]) databits = strtoul(mstr, NULL, 10); g_free(mstr); - if ((mstr = g_match_info_fetch(match, 3))) { + if ((mstr = g_match_info_fetch(match, 4)) && mstr[0]) { switch (mstr[0]) { case 'n': parity = SP_PARITY_NONE; @@ -613,10 +655,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, } } g_free(mstr); - if ((mstr = g_match_info_fetch(match, 4))) + if ((mstr = g_match_info_fetch(match, 5)) && mstr[0]) stopbits = strtoul(mstr, NULL, 10); g_free(mstr); - if ((mstr = g_match_info_fetch(match, 5)) && mstr[0] != '\0') { + if ((mstr = g_match_info_fetch(match, 6)) && mstr[0] != '\0') { if (mstr[0] != '/') { sr_dbg("missing separator before extra options"); speed = 0; @@ -664,14 +706,17 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial, } g_match_info_unref(match); g_regex_unref(reg); + sr_spew("Got params: rate %d, frame %d/%d/%d, flow %d, rts %d, dtr %d.", + speed, databits, parity, stopbits, flow, rts, dtr); - if (speed) { - return serial_set_params(serial, speed, databits, parity, - stopbits, flow, rts, dtr); - } else { + if (!speed) { sr_dbg("Could not infer speed from parameter string."); return SR_ERR_ARG; } + + return serial_set_params(serial, speed, + databits, parity, stopbits, + flow, rts, dtr); } /** @@ -822,7 +867,7 @@ SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial, *buflen = ibuf; - sr_err("Didn't find a valid packet (read %zu bytes).", *buflen); + sr_info("Didn't find a valid packet (read %zu bytes).", *buflen); return SR_ERR; } @@ -1027,9 +1072,7 @@ SR_PRIV GSList *sr_serial_find_usb(uint16_t vendor_id, uint16_t product_id) /** @private */ SR_PRIV int serial_timeout(struct sr_serial_dev_inst *port, int num_bytes) { - int bits, baud; - int ret; - int timeout_ms; + int bits, baud, ret, timeout_ms; /* Get the bitrate and frame length. */ bits = baud = 0;