]> sigrok.org Git - libsigrok.git/blobdiff - src/serial.c
ols: more robust device reset in acquisition stop
[libsigrok.git] / src / serial.c
index 1c0870d9f61cf9c1fe168cc76d21339a6b1a69a2..34d7cbea3f9b40b965d588b8c4a6003a8d54cc24 100644 (file)
@@ -122,10 +122,24 @@ SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags)
        if (ret != SR_OK)
                return ret;
 
-       if (serial->serialcomm)
-               return serial_set_paramstr(serial, serial->serialcomm);
-       else
-               return SR_OK;
+       if (serial->serialcomm) {
+               ret = serial_set_paramstr(serial, serial->serialcomm);
+               if (ret != SR_OK)
+                       return ret;
+       }
+
+       /*
+        * Flush potentially dangling RX data. Availability of the
+        * flush primitive depends on the transport/cable, absense
+        * is non-fatal.
+        */
+       ret = serial_flush(serial);
+       if (ret == SR_ERR_NA)
+               ret = SR_OK;
+       if (ret != SR_OK)
+               return ret;
+
+       return SR_OK;
 }
 
 /**
@@ -547,6 +561,37 @@ SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial,
        return ret;
 }
 
+/**
+ * Manipulate handshake state for the specified serial port.
+ *
+ * @param serial Previously initialized serial port structure.
+ * @param[in] rts Status of RTS line (0 or 1; or -1 to ignore).
+ * @param[in] dtr Status of DTR line (0 or 1; or -1 to ignore).
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR Failure.
+ *
+ * @private
+ */
+SR_PRIV int serial_set_handshake(struct sr_serial_dev_inst *serial,
+       int rts, int dtr)
+{
+       int ret;
+
+       if (!serial) {
+               sr_dbg("Invalid serial port.");
+               return SR_ERR;
+       }
+
+       sr_spew("Modifying serial parameters on port %s.", serial->port);
+
+       if (!serial->lib_funcs || !serial->lib_funcs->set_handshake)
+               return SR_ERR_NA;
+       ret = serial->lib_funcs->set_handshake(serial, rts, dtr);
+
+       return ret;
+}
+
 /**
  * Set serial parameters for the specified serial port from parameter string.
  *
@@ -574,7 +619,7 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
        const char *paramstr)
 {
 /** @cond PRIVATE */
-#define SERIAL_COMM_SPEC "^(\\d+)/([5678])([neo])([12])(.*)$"
+#define SERIAL_COMM_SPEC "^(\\d+)(/([5678])([neo])([12]))?(.*)$"
 /** @endcond */
 
        GRegex *reg;
@@ -582,7 +627,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
        int speed, databits, parity, stopbits, flow, rts, dtr, i;
        char *mstr, **opts, **kv;
 
-       speed = databits = parity = stopbits = flow = 0;
+       speed = flow = 0;
+       databits = 8;
+       parity = SP_PARITY_NONE;
+       stopbits = 1;
        rts = dtr = -1;
        sr_spew("Parsing parameters from \"%s\".", paramstr);
        reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL);
@@ -590,10 +638,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
                if ((mstr = g_match_info_fetch(match, 1)))
                        speed = strtoul(mstr, NULL, 10);
                g_free(mstr);
-               if ((mstr = g_match_info_fetch(match, 2)))
+               if ((mstr = g_match_info_fetch(match, 3)) && mstr[0])
                        databits = strtoul(mstr, NULL, 10);
                g_free(mstr);
-               if ((mstr = g_match_info_fetch(match, 3))) {
+               if ((mstr = g_match_info_fetch(match, 4)) && mstr[0]) {
                        switch (mstr[0]) {
                        case 'n':
                                parity = SP_PARITY_NONE;
@@ -607,10 +655,10 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
                        }
                }
                g_free(mstr);
-               if ((mstr = g_match_info_fetch(match, 4)))
+               if ((mstr = g_match_info_fetch(match, 5)) && mstr[0])
                        stopbits = strtoul(mstr, NULL, 10);
                g_free(mstr);
-               if ((mstr = g_match_info_fetch(match, 5)) && mstr[0] != '\0') {
+               if ((mstr = g_match_info_fetch(match, 6)) && mstr[0] != '\0') {
                        if (mstr[0] != '/') {
                                sr_dbg("missing separator before extra options");
                                speed = 0;
@@ -658,14 +706,17 @@ SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
        }
        g_match_info_unref(match);
        g_regex_unref(reg);
+       sr_spew("Got params: rate %d, frame %d/%d/%d, flow %d, rts %d, dtr %d.",
+               speed, databits, parity, stopbits, flow, rts, dtr);
 
-       if (speed) {
-               return serial_set_params(serial, speed, databits, parity,
-                                        stopbits, flow, rts, dtr);
-       } else {
+       if (!speed) {
                sr_dbg("Could not infer speed from parameter string.");
                return SR_ERR_ARG;
        }
+
+       return serial_set_params(serial, speed,
+                       databits, parity, stopbits,
+                       flow, rts, dtr);
 }
 
 /**