]> sigrok.org Git - libsigrok.git/blobdiff - src/serial_bt.c
scpi: add Siglent to the vendor alias list
[libsigrok.git] / src / serial_bt.c
index 8ed4523b8167ee1f42686d1ff9309f3b0f9c8c8f..a851dad8c6fff16a1e2874b7fb165a08b41c11b3 100644 (file)
@@ -24,9 +24,7 @@
 #include <string.h>
 #include <memory.h>
 
-/** @cond PRIVATE */
 #define LOG_PREFIX "serial-bt"
-/** @endcond */
 
 #ifdef HAVE_SERIAL_COMM
 #ifdef HAVE_BLUETOOTH
 #define SER_BT_CONN_PREFIX     "bt"
 #define SER_BT_CHUNK_SIZE      1200
 
+#define SER_BT_PARAM_PREFIX_CHANNEL    "channel="
+#define SER_BT_PARAM_PREFIX_HDL_RX     "handle_rx="
+#define SER_BT_PARAM_PREFIX_HDL_TX     "handle_tx="
+#define SER_BT_PARAM_PREFIX_HDL_CCCD   "handle_cccd="
+#define SER_BT_PARAM_PREFIX_VAL_CCCD   "value_cccd="
+
 /**
  * @file
  *
@@ -109,8 +113,6 @@ static const char *conn_name_text(enum ser_bt_conn_t type)
  *
  * @return 0 upon success, non-zero upon failure.
  *
- * @internal
- *
  * Summary of parsing rules as they are implemented:
  * - Implementor's note: Automatic scan for available devices is not
  *   yet implemented. So strictly speaking some parts of the input
@@ -146,9 +148,13 @@ static int ser_bt_parse_conn_spec(
        uint16_t *read_hdl, uint16_t *write_hdl,
        uint16_t *cccd_hdl, uint16_t *cccd_val)
 {
+       char **fields, *field;
        enum ser_bt_conn_t type;
        const char *addr;
-       char **fields, *field;
+       int ret_parse, ret;
+       size_t fields_count, field_idx;
+       char *endp;
+       unsigned long parm_val;
 
        if (conn_type)
                *conn_type = SER_BT_CONN_UNKNOWN;
@@ -165,9 +171,6 @@ static int ser_bt_parse_conn_spec(
        if (cccd_val)
                *cccd_val = 0;
 
-       type = SER_BT_CONN_UNKNOWN;
-       addr = NULL;
-
        if (!serial || !spec || !spec[0])
                return SR_ERR_ARG;
 
@@ -248,10 +251,83 @@ static int ser_bt_parse_conn_spec(
                return SR_ERR_ARG;
        }
 
-       /* TODO Evaluate optionally trailing fields, override defaults? */
+       /*
+        * Preset a successful return value for the conn= parse call.
+        * Scan optional additional fields which specify more params.
+        * Update the defaults which were setup above. Pessimize the
+        * routine's return value in error paths.
+        */
+       ret_parse = SR_OK;
+       fields_count = g_strv_length(fields);
+       for (field_idx = 3; field_idx < fields_count; field_idx++) {
+               field = fields[field_idx];
+               if (!field || !*field)
+                       continue;
+               if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_CHANNEL)) {
+                       field += strlen(SER_BT_PARAM_PREFIX_CHANNEL);
+                       endp = NULL;
+                       ret = sr_atoul_base(field, &parm_val, &endp, 0);
+                       if (ret != SR_OK || !endp || *endp != '\0') {
+                               ret_parse = SR_ERR_ARG;
+                               break;
+                       }
+                       if (rfcomm_channel)
+                               *rfcomm_channel = parm_val;
+                       continue;
+               }
+               if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_HDL_RX)) {
+                       field += strlen(SER_BT_PARAM_PREFIX_HDL_RX);
+                       endp = NULL;
+                       ret = sr_atoul_base(field, &parm_val, &endp, 0);
+                       if (ret != SR_OK || !endp || *endp != '\0') {
+                               ret_parse = SR_ERR_ARG;
+                               break;
+                       }
+                       if (read_hdl)
+                               *read_hdl = parm_val;
+                       continue;
+               }
+               if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_HDL_TX)) {
+                       field += strlen(SER_BT_PARAM_PREFIX_HDL_TX);
+                       endp = NULL;
+                       ret = sr_atoul_base(field, &parm_val, &endp, 0);
+                       if (ret != SR_OK || !endp || *endp != '\0') {
+                               ret_parse = SR_ERR_ARG;
+                               break;
+                       }
+                       if (write_hdl)
+                               *write_hdl = parm_val;
+                       continue;
+               }
+               if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_HDL_CCCD)) {
+                       field += strlen(SER_BT_PARAM_PREFIX_HDL_CCCD);
+                       endp = NULL;
+                       ret = sr_atoul_base(field, &parm_val, &endp, 0);
+                       if (ret != SR_OK || !endp || *endp != '\0') {
+                               ret_parse = SR_ERR_ARG;
+                               break;
+                       }
+                       if (cccd_hdl)
+                               *cccd_hdl = parm_val;
+                       continue;
+               }
+               if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_VAL_CCCD)) {
+                       field += strlen(SER_BT_PARAM_PREFIX_VAL_CCCD);
+                       endp = NULL;
+                       ret = sr_atoul_base(field, &parm_val, &endp, 0);
+                       if (ret != SR_OK || !endp || *endp != '\0') {
+                               ret_parse = SR_ERR_ARG;
+                               break;
+                       }
+                       if (cccd_val)
+                               *cccd_val = parm_val;
+                       continue;
+               }
+               return SR_ERR_DATA;
+       }
 
        g_strfreev(fields);
-       return SR_OK;
+       return ret_parse;
 }
 
 static void ser_bt_mask_databits(struct sr_serial_dev_inst *serial,
@@ -502,7 +578,6 @@ static int ser_bt_read(struct sr_serial_dev_inst *serial,
         * where to stop reception.
         */
        deadline_us = 0;
-       now_us = 0;     /* Silence a (false) compiler warning. */
        if (timeout_ms) {
                now_us = g_get_monotonic_time();
                deadline_us = now_us + timeout_ms * 1000;
@@ -574,28 +649,6 @@ static int ser_bt_read(struct sr_serial_dev_inst *serial,
        return sr_ser_unqueue_rx_data(serial, buf, dlen);
 }
 
-static int ser_bt_set_params(struct sr_serial_dev_inst *serial,
-               int baudrate, int bits, int parity, int stopbits,
-               int flowcontrol, int rts, int dtr)
-{
-       /*
-        * Bluetooth communication has no concept of bitrate, so ignore
-        * these arguments silently. Neither need we pass the frame format
-        * down to internal BT comm routines, nor need we keep the values
-        * here, since the caller will cache/register them already.
-        */
-       (void)serial;
-       (void)baudrate;
-       (void)bits;
-       (void)parity;
-       (void)stopbits;
-       (void)flowcontrol;
-       (void)rts;
-       (void)dtr;
-
-       return SR_OK;
-}
-
 struct bt_source_args_t {
        /* The application callback. */
        sr_receive_data_callback cb;
@@ -835,7 +888,14 @@ static struct ser_lib_functions serlib_bt = {
        .drain = ser_bt_drain,
        .write = ser_bt_write,
        .read = ser_bt_read,
-       .set_params = ser_bt_set_params,
+       /*
+        * Bluetooth communication has no concept of bitrate, so ignore
+        * these arguments silently. Neither need we pass the frame format
+        * down to internal BT comm routines, nor need we keep the values
+        * here, since the caller will cache/register them already.
+        */
+       .set_params = std_dummy_set_params,
+       .set_handshake = std_dummy_set_handshake,
        .setup_source_add = ser_bt_setup_source_add,
        .setup_source_remove = ser_bt_setup_source_remove,
        .list = ser_bt_list,