The previous implementation considered both the UART bitrate and the
frame format mandatory, users had to specify "/8n1" as well just to
change the bitrate.
This commit makes the frame format optional, and defaults to 8n1 which
is so popular these days. When specified, the frame format still needs
to preceed the other optional flow and handshake flags, for maximum
backwards compatibility, and equal robustness in the process of parsing
serialcomm= specs.
Unfortunately device drivers cannot specify their preferred or default
UART frame format. Which means that users still need to provide these
when a device does not use 8n1. This is not a regression, the previous
implementation always needed the frame format spec.
src/resource.c:414: warning: unbalanced grouping commands
conversion.c:81: warning: argument 'lo_thr' from the argument list of sr_a2l_schmitt_trigger has multiple @param documentation sections
src/analog.c:611: warning: return value 'SR_ERR_ARG' of sr_rational_div has multiple documentation sections
src/device.c:205: warning: explicit link request to 'TRUE' could not be resolved
src/device.c:205: warning: explicit link request to 'FALSE' could not be resolved
src/device.c:231: warning: explicit link request to 'TRUE' could not be resolved
src/device.c:231: warning: explicit link request to 'FALSE' could not be resolved
src/serial.c:246: warning: explicit link request to 'NULL' could not be resolved
src/strutil.c:602: warning: explicit link request to 'NULL' could not be resolved
src/device.c:94: warning: unable to resolve reference to 'sr_channel_free()' for \ref command
src/strutil.c:597: warning: unable to resolve reference to 'sr_hexdump_free()' for \ref command
src/strutil.c:622: warning: unable to resolve reference to 'sr_hexdump_new()' for \ref command
src/device.c:430: warning: The following parameters of sr_dev_inst_channel_add(struct sr_dev_inst *sdi, int index, int type, const char *name) are not documented: parameter 'sdi'
src/session.c:163: warning: The following parameters of fd_source_new(struct sr_session *session, void *key, gintptr fd, int events, int timeout_ms) are not documented: parameter 'events'
The serial_stream_detect() routine needs to estimate the time which is
needed to communicate a given amount of data. Since the serial port got
opened and configured before, the serial communication parameters are
known, and callers need not redundantly specify the bit rate.
The previous implementation provided a raw input stream of RX data from
read() calls to device drivers. This works great with genuine COM ports,
as well as with most setups which involve simple "cable expanders".
Recent additions of alternative transports (serial over HID and BLE)
added more protocol layers to the setup, and some device drivers are
reported to depend on the very framing of these transports: Mooshimeter
cares about individual BLE notification "frames", and the information
cannot get derived from the payload bytes. Some HID based cables which
obscure the DMM chips' serial protocol, or some HID based setups which
the serial layer does not abstract away as "a cable" may suffer from
similar requirements (do some drivers require access to individual HID
reports? Ikalogic? Victor DMM?).
Add support for an optional "RX chunk callback" which takes precedence
over "mere payload byte streams". Instead of returning payload bytes
from read() calls, the serial layer can call an application defined
routine and pass data bytes in the very framing which the physical
transport happens to use.
It's still up to the implementation of the specific transport whether
the callback approach is supported, and whether the wire's framing is
obeyed or whether payload data keeps getting provided as one raw stream.
It's also implementation dependent whether data reception transparently
occurs in background, or whether callers need to periodically "stimulate"
data reception by calling read or check routines which happen to call
back into the caller should RX data become available.
The approach that got implemented here is not universally applicable,
but serves those specific environments that were identified so far.
Introduce the serial_bt.c source file which implements the methods of a
serial transport and calls into the platform agnostic src/bt/ support
code.
Implement support for several chips and modules: RFCOMM (BT classic,
tested with HC-05), BLE122 (tested with 121GW), Nordic nRF51, and TI
CC254x (the latter untested). Read support is assumed to be complete,
write support for BLE may be incomplete due to lack of access to
hardware for tests.
Search for the optional HIDAPI library. Call the library's init and exit
routine, and print version information. Extend the common serial layer's
code paths for open, list, and find USB to also support serial over HID.
This commit prepares serial over HID, but the HIDAPI specific transport
for serial communication still is empty in this implementation.
Add a local RX buffer to the common code of libsigrok's serial layer.
Callers of the serial layer's API won't notice, this is an internal
detail of how alternative transports receive their data from the
physical line, and pass it to read() calls emitted by device drivers.
The libserialport specific code still calls into the library, and does
not use the RX buffer. Future HID and BLE support will use the buffer.
Only reference the libserialport header when the library is available.
Allow to always compile the serial.c source file, but optionally end
up with an empty implementation. Make the sr_serial_dev_inst symbol
available outside of HAVE_SERIAL_COMM such that empty stub code can
compile. This prepares the introduction of alternative transports for
serial communication, while all of them remain optional.
The libsigrok serial layer internally uses parity and flow control
symbols which are provided by libserialport. Optionally locally declare
these symbols when libserialport is not available.
Add an indirection between the common serial communication code and the
libserialport specific support code. Prepare the use of alternative
transports like USB HID in the future. Decide in the open() routine
which transport to use for subsequent operations (based on port names).
In theory only the transport specific layer depends on the libserialport
library's availability. In this implementation all support for serial
communication still depends on the HAVE_LIBSERIALPORT preprocessor
symbol. This needs to get addressed in later commits.
Add a serial_has_receive_data() routine to the serial layer's API which
returns the number of (known to be) available RX data bytes. Implement
support in the libserialport specific code.
Introduce a new serial_libsp.c source file, and move code from serial.c
there which is specific to libserialport. Keep the existing serial.c API
in place, this is a pure internal refactoring.
Adjust a little whitespace while we are here. Rearrange long lines to
keep related parameter groups adjacent (like pointer and size, or UART
frame length and flow control). Consistently reduce indentation of
continuation lines.
Store the most recent successfully applied set of parameters for serial
communication. Re-use these values as a fallback to calculate timeouts,
when the underlying transport fails to provide the current settings.
It's important to remain aware that the serial layer's flush and drain
semantics differs from e.g. filesystem calls. The libserialport API is
said to follow the termios example.
Extend comments in the libsigrok API, to not depend on the libserialport
layer and the availability of its documentation. This raises awareness
during maintenance of sigrok device drivers, as well as the pending
addition of alternative transports for serial communication.
Adjust the doxygen comment for the read line routine while we are here.
Add "in" and "out" attributes for routine parameters.
Just allocate the memory needed to hold the very variable's size. No
need to duplicate the variable's type. Reduces redundancy and increases
robustness during maintenance.
Use g_malloc0() in sr_serial_new() to make sure all of the structure is
initialized.
Regular operation of serial DMM drivers optionally can dump packet bytes
after the intialization phase has synchronized to the stream. Failure to
synchronize to the stream left developers without a dump, which complicates
research what went wrong.
Do dump packet content while the serial_stream_detect() routine tries to
synchronize to the stream. Use the spew level since the dump occurs upon
every attempt, which translates to: every received byte until a valid
packet was seen (or the synchronization phase expired).
Since Autoconf places some important feature flags only into the
configuration header, it is necessary to include it globally to
guarantee a consistent build.
Disallow polling for input/error and output-ready events at the
same time, and ensure only a single FD event source is installed.
Also, do not leak if the FD event source is removed by means
other than calling serial_source_remove().
A few of these were pretty serious, like missing arguments,
passing integers where a string was expected, and so on.
In some places, change the types used by the code rather than
just the format strings.
Move the include flags for files in the source tree from
configure.ac to Makefile.am where they belong. Also use
AM_CPPFLAGS instead of CFLAGS/CXXFLAGS to make sure the
files in the build/source tree are always picked up first.
Also, remove the include/libsigrok sub-directory from the
search path, thereby making the <libsigrok/> prefix mandatory
when building libsigrok itself. This matches the convention
already imposed on users of the library.
This calculates a proper timeout value for blocking writes on the
given serial port, for the given number of bytes. Timeout is based
on a fixed 10ms OS overhead, baud rate, data bits and stop bits.
Set this new parameter to 0 (no timeout) at every call site. This is
consistent with previous behaviour, so cannot cause any regressions.
Waiting forever for a serial operation is clearly always wrong. Without
specific knowledge of each device and driver however, I can't choose
appropriate timeouts for each call. The maintainers of these drivers
will need to do so, and also add appropriate handling of timeouts.
When this commit is merged, a bug should be entered for each driver
that is touched by it.
This code implements its own waiting based on baudrate, so the read itself
should be nonblocking. In general it will have been already, since drivers
almost universally use the SERIAL_NONBLOCK flag.