]> sigrok.org Git - libsigrok.git/blobdiff - src/serial.c
serial: add support for optional "RX chunk" callback
[libsigrok.git] / src / serial.c
index acee0dcacca6e4960c888596b70095480957afd7..12026a8965d6b9228efc245cecf9d87b4d3231f3 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
  * Copyright (C) 2014 Uffe Jakobsen <uffe@uffe.org>
+ * Copyright (C) 2017-2019 Gerhard Sittig <gerhard.sittig@gmx.net>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -98,6 +99,8 @@ SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags)
         */
        if (ser_name_is_hid(serial))
                serial->lib_funcs = ser_lib_funcs_hid;
+       else if (ser_name_is_bt(serial))
+               serial->lib_funcs = ser_lib_funcs_bt;
        else
                serial->lib_funcs = ser_lib_funcs_libsp;
        if (!serial->lib_funcs)
@@ -223,8 +226,40 @@ SR_PRIV int serial_drain(struct sr_serial_dev_inst *serial)
  * via UART can get stored in a GString (which is a char array). Since
  * the API hides this detail, we can address this issue later when needed.
  * Callers use the API which communicates bytes.
+ *
+ * Applications optionally can register a "per RX chunk" callback, when
+ * they depend on the frame boundaries of the respective physical layer.
+ * Most callers just want the stream of RX data, and can use the buffer.
+ *
+ * The availability of RX chunks to callbacks, as well as the capability
+ * to pass on exact frames as chunks or potential re-assembly of chunks
+ * to a single data block, depend on each transport's implementation.
  */
 
+/**
+ * Register application callback for RX data chunks.
+ *
+ * @param[in] serial Previously initialized serial port instance.
+ * @param[in] cb Routine to call as RX data becomes available.
+ * @param[in] cb_data User data to pass to the callback in addition to RX data.
+ *
+ * @retval SR_ERR_ARG Invalid parameters.
+ * @retval SR_OK Successful registration.
+ *
+ * Callbacks get unregistered by specifying #NULL for the 'cb' parameter.
+ */
+SR_PRIV int serial_set_read_chunk_cb(struct sr_serial_dev_inst *serial,
+       serial_rx_chunk_callback cb, void *cb_data)
+{
+       if (!serial)
+               return SR_ERR_ARG;
+
+       serial->rx_chunk_cb_func = cb;
+       serial->rx_chunk_cb_data = cb_data;
+
+       return SR_OK;
+}
+
 /**
  * Discard previously queued RX data. Internal to the serial subsystem,
  * coordination between common and transport specific support code.
@@ -279,7 +314,9 @@ SR_PRIV void sr_ser_queue_rx_data(struct sr_serial_dev_inst *serial,
        if (!data || !len)
                return;
 
-       if (serial->rcv_buffer)
+       if (serial->rx_chunk_cb_func)
+               serial->rx_chunk_cb_func(serial, serial->rx_chunk_cb_data, data, len);
+       else if (serial->rcv_buffer)
                g_string_append_len(serial->rcv_buffer, (const gchar *)data, len);
 }
 
@@ -941,6 +978,10 @@ SR_API GSList *sr_serial_list(const struct sr_dev_driver *driver)
                list_func = ser_lib_funcs_hid->list;
                tty_devs = list_func(tty_devs, append_port_list);
        }
+       if (ser_lib_funcs_bt && ser_lib_funcs_bt->list) {
+               list_func = ser_lib_funcs_bt->list;
+               tty_devs = list_func(tty_devs, append_port_list);
+       }
 
        return tty_devs;
 }