]> sigrok.org Git - libsigrok.git/commitdiff
serial: prepare alternative transports for serial communication
authorGerhard Sittig <redacted>
Sat, 30 Sep 2017 23:21:08 +0000 (00:21 +0100)
committerUwe Hermann <redacted>
Sun, 2 Jun 2019 18:39:02 +0000 (20:39 +0200)
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.

src/libsigrok-internal.h
src/serial.c
src/serial_libsp.c

index a6497c958ac86b725c753f8f182aec562d53bd9d..9384bbb68692dc8dfde720e333d9a50165b20169 100644 (file)
@@ -722,19 +722,23 @@ struct sr_usb_dev_inst {
 #endif
 
 #ifdef HAVE_LIBSERIALPORT
+struct ser_lib_functions;
 struct sr_serial_dev_inst {
        /** Port name, e.g. '/dev/tty42'. */
        char *port;
        /** Comm params for serial_set_paramstr(). */
        char *serialcomm;
+       struct ser_lib_functions *lib_funcs;
        struct {
                int bit_rate;
                int data_bits;
                int parity_bits;
                int stop_bits;
        } comm_params;
+#ifdef HAVE_LIBSERIALPORT
        /** libserialport port handle */
        struct sp_port *sp_data;
+#endif
 };
 #endif
 
@@ -1109,31 +1113,34 @@ SR_PRIV int serial_source_remove(struct sr_session *session,
 SR_PRIV GSList *sr_serial_find_usb(uint16_t vendor_id, uint16_t product_id);
 SR_PRIV int serial_timeout(struct sr_serial_dev_inst *port, int num_bytes);
 
-SR_PRIV int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags);
-SR_PRIV int sr_ser_libsp_close(struct sr_serial_dev_inst *serial);
-SR_PRIV int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial);
-SR_PRIV int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial);
-SR_PRIV int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
-               const void *buf, size_t count,
-               int nonblocking, unsigned int timeout_ms);
-SR_PRIV int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
-               void *buf, size_t count,
-               int nonblocking, unsigned int timeout_ms);
-SR_PRIV int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial,
-               int baudrate, int bits, int parity, int stopbits,
-               int flowcontrol, int rts, int dtr);
-SR_PRIV int sr_ser_libsp_source_add(struct sr_session *session,
-               struct sr_serial_dev_inst *serial,
-               int events, int timeout,
-               sr_receive_data_callback cb, void *cb_data);
-SR_PRIV int sr_ser_libsp_source_remove(struct sr_session *session,
-               struct sr_serial_dev_inst *serial);
-SR_PRIV GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append);
-SR_PRIV GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
-               uint16_t vendor_id, uint16_t product_id);
-SR_PRIV int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
-               int *baud, int *bits);
-SR_PRIV size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial);
+struct ser_lib_functions {
+       int (*open)(struct sr_serial_dev_inst *serial, int flags);
+       int (*close)(struct sr_serial_dev_inst *serial);
+       int (*flush)(struct sr_serial_dev_inst *serial);
+       int (*drain)(struct sr_serial_dev_inst *serial);
+       int (*write)(struct sr_serial_dev_inst *serial,
+                       const void *buf, size_t count,
+                       int nonblocking, unsigned int timeout_ms);
+       int (*read)(struct sr_serial_dev_inst *serial,
+                       void *buf, size_t count,
+                       int nonblocking, unsigned int timeout_ms);
+       int (*set_params)(struct sr_serial_dev_inst *serial,
+                       int baudrate, int bits, int parity, int stopbits,
+                       int flowcontrol, int rts, int dtr);
+       int (*setup_source_add)(struct sr_session *session,
+                       struct sr_serial_dev_inst *serial,
+                       int events, int timeout,
+                       sr_receive_data_callback cb, void *cb_data);
+       int (*setup_source_remove)(struct sr_session *session,
+                       struct sr_serial_dev_inst *serial);
+       GSList *(*list)(GSList *list, sr_ser_list_append_t append);
+       GSList *(*find_usb)(GSList *list, sr_ser_find_append_t append,
+                       uint16_t vendor_id, uint16_t product_id);
+       int (*get_frame_format)(struct sr_serial_dev_inst *serial,
+                       int *baud, int *bits);
+       size_t (*get_rx_avail)(struct sr_serial_dev_inst *serial);
+};
+extern SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp;
 #endif
 
 /*--- ezusb.c ---------------------------------------------------------------*/
index ef1563829eb13d54cd8492fbc853fa1415a1ec8e..dc6e0126eefa164b67f57061d83e420c35f67df5 100644 (file)
  * @{
  */
 
+/* See if a (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)
+               return 0;
+
+       return 1;
+}
+
 /**
  * Open the specified serial port.
  *
@@ -76,7 +87,18 @@ SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags)
 
        sr_spew("Opening serial port '%s' (flags %d).", serial->port, flags);
 
-       ret = sr_ser_libsp_open(serial, flags);
+       /* Default to the libserialport transport layer. */
+       serial->lib_funcs = ser_lib_funcs_libsp;
+       if (!serial->lib_funcs)
+               return SR_ERR_NA;
+
+       /*
+        * Run the transport's open routine. Setup the bitrate and the
+        * UART frame format.
+        */
+       if (!serial->lib_funcs->open)
+               return SR_ERR_NA;
+       ret = serial->lib_funcs->open(serial, flags);
        if (ret != SR_OK)
                return ret;
 
@@ -105,7 +127,10 @@ SR_PRIV int serial_close(struct sr_serial_dev_inst *serial)
 
        sr_spew("Closing serial port %s.", serial->port);
 
-       return sr_ser_libsp_close(serial);
+       if (!serial->lib_funcs || !serial->lib_funcs->close)
+               return SR_ERR_NA;
+
+       return serial->lib_funcs->close(serial);
 }
 
 /**
@@ -127,7 +152,10 @@ SR_PRIV int serial_flush(struct sr_serial_dev_inst *serial)
 
        sr_spew("Flushing serial port %s.", serial->port);
 
-       return sr_ser_libsp_flush(serial);
+       if (!serial->lib_funcs || !serial->lib_funcs->flush)
+               return SR_ERR_NA;
+
+       return serial->lib_funcs->flush(serial);
 }
 
 /**
@@ -149,7 +177,10 @@ SR_PRIV int serial_drain(struct sr_serial_dev_inst *serial)
 
        sr_spew("Draining serial port %s.", serial->port);
 
-       return sr_ser_libsp_drain(serial);
+       if (!serial->lib_funcs || !serial->lib_funcs->drain)
+               return SR_ERR_NA;
+
+       return serial->lib_funcs->drain(serial);
 }
 
 /**
@@ -164,7 +195,16 @@ SR_PRIV int serial_drain(struct sr_serial_dev_inst *serial)
  */
 SR_PRIV size_t serial_has_receive_data(struct sr_serial_dev_inst *serial)
 {
-       return sr_ser_libsp_get_rx_avail(serial);
+       size_t lib_count;
+
+       if (!serial)
+               return 0;
+
+       lib_count = 0;
+       if (serial->lib_funcs && serial->lib_funcs->get_rx_avail)
+               lib_count = serial->lib_funcs->get_rx_avail(serial);
+
+       return lib_count;
 }
 
 static int _serial_write(struct sr_serial_dev_inst *serial,
@@ -178,7 +218,10 @@ static int _serial_write(struct sr_serial_dev_inst *serial,
                return SR_ERR;
        }
 
-       ret = sr_ser_libsp_write(serial, buf, count, nonblocking, timeout_ms);
+       if (!serial->lib_funcs || !serial->lib_funcs->write)
+               return SR_ERR_NA;
+       ret = serial->lib_funcs->write(serial, buf, count,
+               nonblocking, timeout_ms);
        sr_spew("Wrote %zd/%zu bytes.", ret, count);
 
        return ret;
@@ -234,7 +277,10 @@ static int _serial_read(struct sr_serial_dev_inst *serial,
                return SR_ERR;
        }
 
-       ret = sr_ser_libsp_read(serial, buf, count, nonblocking, timeout_ms);
+       if (!serial->lib_funcs || !serial->lib_funcs->read)
+               return SR_ERR_NA;
+       ret = serial->lib_funcs->read(serial, buf, count,
+               nonblocking, timeout_ms);
        if (ret > 0)
                sr_spew("Read %zd/%zu bytes.", ret, count);
 
@@ -313,8 +359,11 @@ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial,
 
        sr_spew("Setting serial parameters on port %s.", serial->port);
 
-       ret = sr_ser_libsp_set_params(serial,
-               baudrate, bits, parity, stopbits, flowcontrol, rts, dtr);
+       if (!serial->lib_funcs || !serial->lib_funcs->set_params)
+               return SR_ERR_NA;
+       ret = serial->lib_funcs->set_params(serial,
+               baudrate, bits, parity, stopbits,
+               flowcontrol, rts, dtr);
        if (ret == SR_OK) {
                serial->comm_params.bit_rate = baudrate;
                serial->comm_params.data_bits = bits;
@@ -476,7 +525,7 @@ SR_PRIV int serial_readline(struct sr_serial_dev_inst *serial,
                return SR_ERR;
        }
 
-       if (!serial->sp_data) {
+       if (!dev_is_supported(serial)) {
                sr_dbg("Cannot use unopened serial port %s.", serial->port);
                return -1;
        }
@@ -659,12 +708,15 @@ SR_PRIV int serial_source_add(struct sr_session *session,
                return SR_ERR_ARG;
        }
 
-       if (!serial->sp_data) {
+       if (!dev_is_supported(serial)) {
                sr_err("Invalid serial port.");
                return SR_ERR_ARG;
        }
 
-       return sr_ser_libsp_source_add(session, serial,
+       if (!serial->lib_funcs || !serial->lib_funcs->setup_source_add)
+               return SR_ERR_NA;
+
+       return serial->lib_funcs->setup_source_add(session, serial,
                events, timeout, cb, cb_data);
 }
 
@@ -672,12 +724,15 @@ SR_PRIV int serial_source_add(struct sr_session *session,
 SR_PRIV int serial_source_remove(struct sr_session *session,
        struct sr_serial_dev_inst *serial)
 {
-       if (!serial->sp_data) {
+       if (!dev_is_supported(serial)) {
                sr_err("Invalid serial port.");
                return SR_ERR_ARG;
        }
 
-       return sr_ser_libsp_source_remove(session, serial);
+       if (!serial->lib_funcs || !serial->lib_funcs->setup_source_remove)
+               return SR_ERR_NA;
+
+       return serial->lib_funcs->setup_source_remove(session, serial);
 }
 
 /**
@@ -734,12 +789,16 @@ static GSList *append_port_list(GSList *devs, const char *name, const char *desc
 SR_API GSList *sr_serial_list(const struct sr_dev_driver *driver)
 {
        GSList *tty_devs;
+       GSList *(*list_func)(GSList *list, sr_ser_list_append_t append);
 
        /* Currently unused, but will be used by some drivers later on. */
        (void)driver;
 
        tty_devs = NULL;
-       tty_devs = sr_ser_libsp_list(tty_devs, append_port_list);
+       if (ser_lib_funcs_libsp && ser_lib_funcs_libsp->list) {
+               list_func = ser_lib_funcs_libsp->list;
+               tty_devs = list_func(tty_devs, append_port_list);
+       }
 
        return tty_devs;
 }
@@ -767,10 +826,15 @@ static GSList *append_port_find(GSList *devs, const char *name)
 SR_PRIV GSList *sr_serial_find_usb(uint16_t vendor_id, uint16_t product_id)
 {
        GSList *tty_devs;
+       GSList *(*find_func)(GSList *list, sr_ser_find_append_t append,
+                       uint16_t vid, uint16_t pid);
 
        tty_devs = NULL;
-       tty_devs = sr_ser_libsp_find_usb(tty_devs, append_port_find,
-               vendor_id, product_id);
+       if (ser_lib_funcs_libsp && ser_lib_funcs_libsp->find_usb) {
+               find_func = ser_lib_funcs_libsp->find_usb;
+               tty_devs = find_func(tty_devs, append_port_find,
+                       vendor_id, product_id);
+       }
 
        return tty_devs;
 }
@@ -784,10 +848,11 @@ SR_PRIV int serial_timeout(struct sr_serial_dev_inst *port, int num_bytes)
 
        /* Get the bitrate and frame length. */
        bits = baud = 0;
-       ret = sr_ser_libsp_get_frame_format(port, &baud, &bits);
-       if (ret != SR_OK)
-               bits = baud = 0;
-       if (!bits || !baud) {
+       if (port->lib_funcs && port->lib_funcs->get_frame_format) {
+               ret = port->lib_funcs->get_frame_format(port, &baud, &bits);
+               if (ret != SR_OK)
+                       bits = baud = 0;
+       } else {
                baud = port->comm_params.bit_rate;
                bits = 1 + port->comm_params.data_bits +
                        port->comm_params.parity_bits +
index 69a9cc1ef7fbea2a6d8620d9a6a1ee516f9850b0..b16cd12e412ca9a66caa90a0062d869ea9103a8f 100644 (file)
@@ -41,6 +41,8 @@
  * Serial port handling, wraps the external libserialport dependency.
  */
 
+#ifdef HAVE_LIBSERIALPORT
+
 /**
  * @defgroup grp_serial_libsp Serial port handling, libserialport group
  *
@@ -49,7 +51,7 @@
  * @{
  */
 
-SR_PRIV int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
+static int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
 {
        int ret;
        char *error;
@@ -80,7 +82,7 @@ SR_PRIV int sr_ser_libsp_open(struct sr_serial_dev_inst *serial, int flags)
        return SR_OK;
 }
 
-SR_PRIV int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
+static int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
 {
        int ret;
        char *error;
@@ -110,7 +112,7 @@ SR_PRIV int sr_ser_libsp_close(struct sr_serial_dev_inst *serial)
        return SR_OK;
 }
 
-SR_PRIV int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
+static int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
 {
        int ret;
        char *error;
@@ -137,7 +139,7 @@ SR_PRIV int sr_ser_libsp_flush(struct sr_serial_dev_inst *serial)
        return SR_OK;
 }
 
-SR_PRIV int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
+static int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
 {
        int ret;
        char *error;
@@ -160,7 +162,7 @@ SR_PRIV int sr_ser_libsp_drain(struct sr_serial_dev_inst *serial)
        return SR_OK;
 }
 
-SR_PRIV int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
+static int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
        const void *buf, size_t count,
        int nonblocking, unsigned int timeout_ms)
 {
@@ -191,7 +193,7 @@ SR_PRIV int sr_ser_libsp_write(struct sr_serial_dev_inst *serial,
        return ret;
 }
 
-SR_PRIV int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
+static int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
        void *buf, size_t count,
        int nonblocking, unsigned int timeout_ms)
 {
@@ -222,7 +224,7 @@ SR_PRIV int sr_ser_libsp_read(struct sr_serial_dev_inst *serial,
        return ret;
 }
 
-SR_PRIV int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial,
+static int sr_ser_libsp_set_params(struct sr_serial_dev_inst *serial,
        int baudrate, int bits, int parity, int stopbits,
        int flowcontrol, int rts, int dtr)
 {
@@ -354,7 +356,7 @@ static int sr_ser_libsp_source_add_int(struct sr_serial_dev_inst *serial,
        return SR_OK;
 }
 
-SR_PRIV int sr_ser_libsp_source_add(struct sr_session *session,
+static int sr_ser_libsp_source_add(struct sr_session *session,
        struct sr_serial_dev_inst *serial, int events, int timeout,
        sr_receive_data_callback cb, void *cb_data)
 {
@@ -373,7 +375,7 @@ SR_PRIV int sr_ser_libsp_source_add(struct sr_session *session,
                timeout, cb, cb_data);
 }
 
-SR_PRIV int sr_ser_libsp_source_remove(struct sr_session *session,
+static int sr_ser_libsp_source_remove(struct sr_session *session,
        struct sr_serial_dev_inst *serial)
 {
        void *key;
@@ -382,7 +384,7 @@ SR_PRIV int sr_ser_libsp_source_remove(struct sr_session *session,
        return sr_session_source_remove_internal(session, key);
 }
 
-SR_PRIV GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
+static GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
 {
        struct sp_port **ports;
        size_t i;
@@ -403,7 +405,7 @@ SR_PRIV GSList *sr_ser_libsp_list(GSList *list, sr_ser_list_append_t append)
        return list;
 }
 
-SR_PRIV GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
+static GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
        uint16_t vendor_id, uint16_t product_id)
 {
        struct sp_port **ports;
@@ -429,7 +431,7 @@ SR_PRIV GSList *sr_ser_libsp_find_usb(GSList *list, sr_ser_find_append_t append,
        return list;
 }
 
-SR_PRIV int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
+static int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
        int *baud, int *bits)
 {
        struct sp_port_config *config;
@@ -474,7 +476,7 @@ SR_PRIV int sr_ser_libsp_get_frame_format(struct sr_serial_dev_inst *serial,
        return ret;
 }
 
-SR_PRIV size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
+static size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
 {
        int rc;
 
@@ -487,3 +489,26 @@ SR_PRIV size_t sr_ser_libsp_get_rx_avail(struct sr_serial_dev_inst *serial)
 
        return rc;
 }
+
+static struct ser_lib_functions serlib_sp = {
+       .open = sr_ser_libsp_open,
+       .close = sr_ser_libsp_close,
+       .flush = sr_ser_libsp_flush,
+       .drain = sr_ser_libsp_drain,
+       .write = sr_ser_libsp_write,
+       .read = sr_ser_libsp_read,
+       .set_params = sr_ser_libsp_set_params,
+       .setup_source_add = sr_ser_libsp_source_add,
+       .setup_source_remove = sr_ser_libsp_source_remove,
+       .list = sr_ser_libsp_list,
+       .find_usb = sr_ser_libsp_find_usb,
+       .get_frame_format = sr_ser_libsp_get_frame_format,
+       .get_rx_avail = sr_ser_libsp_get_rx_avail,
+};
+SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = &serlib_sp;
+
+#else
+
+SR_PRIV struct ser_lib_functions *ser_lib_funcs_libsp = NULL;
+
+#endif