]> sigrok.org Git - libsigrok.git/blobdiff - src/serial_bt.c
feed queue: add scale/offset support, rename MQ/unit routine
[libsigrok.git] / src / serial_bt.c
index 9d7cfb2b2699fbedbddd8348ff6fa0a1a13f8eba..a851dad8c6fff16a1e2874b7fb165a08b41c11b3 100644 (file)
 #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
  *
@@ -142,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;
@@ -161,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;
 
@@ -244,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,
@@ -498,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;