serial_ftdi Issues

John Van Ostrand john at vanostrand.com
Tue Aug 29 10:02:28 PDT 2017


I'm trying to get the Cochran computers working with the FTDI library and
serial_ftdi so I can read them on an Android biuld. I'm having two issues
that I have to ask for advice about.

1. In serial_ftdi_read() a failed read exponentially backs off when there's
a short read. This is causing Cochran reads to timeout about 95% of the
time. It's as if reading too late causes lost data. Having a fixed backoff
of 10ms works. Are there any issues if I alter this backoff tactic? It
could be shortened to 1ms if 10ms is too long.

diff --git a/core/serial_ftdi.c b/core/serial_ftdi.c
index f8cba95..bc20ce1 100644
--- a/core/serial_ftdi.c
+++ b/core/serial_ftdi.c
@@ -384,7 +384,7 @@ static dc_status_t serial_ftdi_read (dc_custom_io_t
*io, void *data, size_t size
        if (timeout == -1)
                timeout = 10000;

-       int backoff = 1;
+       int backoff = 10;
        int slept = 0;
        unsigned int nbytes = 0;
        while (nbytes < size) {
@@ -402,12 +402,11 @@ static dc_status_t serial_ftdi_read (dc_custom_io_t
*io, void *data, size_t size
                        }
                        serial_ftdi_sleep (device, backoff);
                        slept += backoff;
-                       backoff *= 2;
                        if (backoff + slept > timeout)
                                backoff = timeout - slept;
                } else {
                        // Reset backoff to 1 on success.
-                       backoff = 1;
+                       backoff = 10;
                }

                nbytes += n;

2. It doesn't make any sense to me but setting serial break on then off is
the trigger to the Cochran to wake up, so I need the ability to set breaks.
Currently the code doesn't support setting breaks and is explained with the
comment "// Not implemented in libftdi yet. Research it further."

So I looked at it and it's supported with the following libftdi-1.3
function:

      int ftdi_set_line_property2(struct ftdi_context *ftdi, enum
ftdi_bits_type bits,
                                enum ftdi_stopbits_type sbit, enum
ftdi_parity_type parity,
                                enum ftdi_break_type break_type);

To make this work seamlessly with libdivecomputer's serial function I need
to emulate the dc_serial_set_break function. A prototype
serial_ftdi_set_break function is there and I can change it to use
ftdi_set_line_property2, which means I have to get the parameters bits,
sbit, and parity from somewhere.

There isn't a function that will read this from the device.

I could create some global vars in serial_ftdi.c, initialize them with
8,1,N values, update them as needed. To support multiple devices
concurrently it would have to be an array indexed by device but it's not
clear what index would work best.

I was thinking of a global variable like:

   struct serial_parm {
      struct ftdi_context *ftdi_ctx;
      enum ftdi_bits_type bits;
      enum ftdi_stopbits_type sbit;
      enum ftdi_parity_type parity;
   } *serial_parms = NULL;

Then realloc() to add (on serial_ftdi_open) or remove (on
serial_ftdi_close). When serial_ftdi_configure is called I can search the
array and update the values so I can use them in serial_ftdi_set_break.

Does this work or is there a better idea?

-- 
John Van Ostrand
At large on sabbatical
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://libdivecomputer.org/pipermail/devel/attachments/20170829/e16a8f86/attachment.html>


More information about the devel mailing list