libftdi Archives

Subject: [PATCH 07/10] use timespec_get instead of gettimeofday timespec_get is in C11 hide some internal stream state from public api this is breaking change, but required as the old one was unusable anyway.

From: Shawn Hoffman <business@xxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Cc: Shawn Hoffman <godisgovernment@xxxxxxxxx>
Date: Wed, 10 Apr 2024 07:15:46 -0700
From: Shawn Hoffman <godisgovernment@xxxxxxxxx>

---
 CMakeLists.txt         |   2 +
 examples/stream_test.c |  14 +++---
 src/ftdi.h             |  35 ++++----------
 src/ftdi_stream.c      | 106 +++++++++++++++++++++++++++--------------
 4 files changed, 89 insertions(+), 68 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b495f6d..7c236ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,8 @@ message(STATUS "CMake version: ${CMAKE_VERSION}")
 
 # Project
 project(libftdi1 C)
+set(C_STANDARD 11)
+set(C_STANDARD_REQUIRED TRUE)
 set(MAJOR_VERSION 1)
 set(MINOR_VERSION 5)
 set(PACKAGE libftdi1)
diff --git a/examples/stream_test.c b/examples/stream_test.c
index 10e0977..0f01589 100644
--- a/examples/stream_test.c
+++ b/examples/stream_test.c
@@ -69,7 +69,7 @@ static uint64_t blocks = 0;
 static uint32_t skips = 0;
 static uint32_t n_err = 0;
 static int
-readCallback(uint8_t *buffer, int length, FTDIProgressInfo *progress, void 
*userdata)
+readCallback(uint8_t *buffer, int length, struct ftdi_stream_progress 
*progress, void *userdata)
 {
    if (length)
    {
@@ -124,11 +124,11 @@ readCallback(uint8_t *buffer, int length, 
FTDIProgressInfo *progress, void *user
    }
    if (progress)
    {
-       fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr 
rate %7.1f kB/s totalrate %d dropouts\n",
-               progress->totalTime,
-               progress->current.totalBytes / (1024.0 * 1024.0),
-               progress->currentRate / 1024.0,
-               progress->totalRate / 1024.0,
+       fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr 
rate %7.1f kB/s total_rate %d dropouts\n",
+               ftdi_stream_total_time(progress),
+               ftdi_stream_total_bytes(progress) / (1024.0 * 1024.0),
+               ftdi_stream_current_rate(progress) / 1024.0,
+               ftdi_stream_total_rate(progress) / 1024.0,
                n_err);
    }
    return exitRequested ? 1 : 0;
@@ -214,7 +214,7 @@ int main(int argc, char **argv)
            outputFile = of;
    signal(SIGINT, sigintHandler);
    
-   err = ftdi_readstream(ftdi, readCallback, NULL, 8, 256);
+   err = ftdi_stream_read(ftdi, readCallback, NULL, 8, 256);
    if (err < 0 && !exitRequested)
        exit(1);
    
diff --git a/src/ftdi.h b/src/ftdi.h
index 186cf9e..a1b4912 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -19,9 +19,6 @@
 #define __libftdi_h__
 
 #include <stdint.h>
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
 
 /* Define _FTDI_DISABLE_DEPRECATED to disable deprecated messages. */
 #ifdef _FTDI_DISABLE_DEPRECATED
@@ -421,27 +418,10 @@ enum ftdi_cbusx_func
 #define HIGH_CURRENT_DRIVE   0x10
 #define HIGH_CURRENT_DRIVE_R 0x04
 
-/**
-    \brief Progress Info for streaming read
-*/
-struct size_and_time
-{
-    uint64_t totalBytes;
-    struct timeval time;
-};
-
-typedef struct
-{
-    struct size_and_time first;
-    struct size_and_time prev;
-    struct size_and_time current;
-    double totalTime;
-    double totalRate;
-    double currentRate;
-} FTDIProgressInfo;
+struct ftdi_stream_progress;
 
-typedef int (FTDIStreamCallback)(uint8_t *buffer, int length,
-                                 FTDIProgressInfo *progress, void *userdata);
+typedef int (ftdi_stream_callback)(uint8_t *buffer, int length,
+                                 struct ftdi_stream_progress *progress, void 
*userdata);
 
 /**
  * Provide libftdi version information
@@ -527,8 +507,13 @@ extern "C"
     int ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int 
chunksize);
     int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int 
*chunksize);
 
-    int ftdi_readstream(struct ftdi_context *ftdi, FTDIStreamCallback 
*callback,
-                        void *userdata, int packetsPerTransfer, int 
numTransfers);
+    int ftdi_stream_read(struct ftdi_context *ftdi, ftdi_stream_callback 
*callback,
+                        void *userdata, int packets_per_transfer, int 
num_transfers);
+    uint64_t ftdi_stream_total_bytes(struct ftdi_stream_progress *progress);
+    double ftdi_stream_total_time(struct ftdi_stream_progress *progress);
+    double ftdi_stream_total_rate(struct ftdi_stream_progress *progress);
+    double ftdi_stream_current_rate(struct ftdi_stream_progress *progress);
+
     struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context 
*ftdi, unsigned char *buf, int size);
 
     struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context 
*ftdi, unsigned char *buf, int size);
diff --git a/src/ftdi_stream.c b/src/ftdi_stream.c
index d146afd..0e80664 100644
--- a/src/ftdi_stream.c
+++ b/src/ftdi_stream.c
@@ -42,21 +42,35 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
+#include <time.h>
 #include <libusb.h>
 
 #include "ftdi.h"
 
+struct size_and_time
+{
+    uint64_t total_bytes;
+    struct timespec time;
+};
+
+struct ftdi_stream_progress
+{
+    struct size_and_time first;
+    struct size_and_time prev;
+    struct size_and_time current;
+    double total_time;
+    double total_rate;
+    double current_rate;
+};
+
 typedef struct
 {
-    FTDIStreamCallback *callback;
+    ftdi_stream_callback *callback;
     void *userdata;
     int packetsize;
     int activity;
     int result;
-    FTDIProgressInfo progress;
+    struct ftdi_stream_progress progress;
 } FTDIStreamState;
 
 /* Handle callbacks
@@ -66,7 +80,7 @@ typedef struct
  * state->result is only set when some error happens
  */
 static void LIBUSB_CALL
-ftdi_readstream_cb(struct libusb_transfer *transfer)
+ftdi_stream_read_cb(struct libusb_transfer *transfer)
 {
     FTDIStreamState *state = transfer->user_data;
     int packet_size = state->packetsize;
@@ -89,7 +103,7 @@ ftdi_readstream_cb(struct libusb_transfer *transfer)
                 packetLen = packet_size;
 
             payloadLen = packetLen - 2;
-            state->progress.current.totalBytes += payloadLen;
+            state->progress.current.total_bytes += payloadLen;
 
             res = state->callback(ptr + 2, payloadLen,
                                   NULL, state->userdata);
@@ -116,15 +130,16 @@ ftdi_readstream_cb(struct libusb_transfer *transfer)
 }
 
 /**
-   Helper function to calculate (unix) time differences
+   Helper function to calculate time differences
 
    \param a timeval
    \param b timeval
+   \return (a - b) as double
 */
 static double
-TimevalDiff(const struct timeval *a, const struct timeval *b)
+timespec_diff(const struct timespec *a, const struct timespec *b)
 {
-    return (a->tv_sec - b->tv_sec) + 1e-6 * (a->tv_usec - b->tv_usec);
+    return (a->tv_sec - b->tv_sec) + 1e-9 * (a->tv_nsec - b->tv_nsec);
 }
 
 /**
@@ -142,19 +157,18 @@ TimevalDiff(const struct timeval *a, const struct timeval 
*b)
     \param  ftdi pointer to ftdi_context
     \param  callback to user supplied function for one block of data
     \param  userdata
-    \param  packetsPerTransfer number of packets per transfer
-    \param  numTransfers Number of transfers per callback
+    \param  packets_per_transfer number of packets per transfer
+    \param  num_transfers Number of transfers per callback
 
 */
-
 int
-ftdi_readstream(struct ftdi_context *ftdi,
-                FTDIStreamCallback *callback, void *userdata,
-                int packetsPerTransfer, int numTransfers)
+ftdi_stream_read(struct ftdi_context *ftdi,
+                ftdi_stream_callback *callback, void *userdata,
+                int packets_per_transfer, int num_transfers)
 {
     struct libusb_transfer **transfers;
     FTDIStreamState state = { callback, userdata, ftdi->max_packet_size, 1 };
-    int bufferSize = packetsPerTransfer * ftdi->max_packet_size;
+    int bufferSize = packets_per_transfer * ftdi->max_packet_size;
     int xferIndex;
     int err = 0;
 
@@ -183,14 +197,14 @@ ftdi_readstream(struct ftdi_context *ftdi,
      * Set up all transfers
      */
 
-    transfers = calloc(numTransfers, sizeof *transfers);
+    transfers = calloc(num_transfers, sizeof *transfers);
     if (!transfers)
     {
         err = LIBUSB_ERROR_NO_MEM;
         goto cleanup;
     }
 
-    for (xferIndex = 0; xferIndex < numTransfers; xferIndex++)
+    for (xferIndex = 0; xferIndex < num_transfers; xferIndex++)
     {
         struct libusb_transfer *transfer;
 
@@ -204,7 +218,7 @@ ftdi_readstream(struct ftdi_context *ftdi,
 
         libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->out_ep,
                                   malloc(bufferSize), bufferSize,
-                                  ftdi_readstream_cb,
+                                  ftdi_stream_read_cb,
                                   &state, 0);
 
         if (!transfer->buffer)
@@ -224,7 +238,7 @@ ftdi_readstream(struct ftdi_context *ftdi,
      * fetching data for several to several ten milliseconds
      * and we skip blocks
      */
-    if (ftdi_set_bitmode(ftdi,  0xff, BITMODE_SYNCFF) < 0)
+    if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_SYNCFF) < 0)
     {
         fprintf(stderr,"Can't set synchronous fifo mode: %s\n",
                 ftdi_get_error_string(ftdi));
@@ -235,15 +249,16 @@ ftdi_readstream(struct ftdi_context *ftdi,
      * Run the transfers, and periodically assess progress.
      */
 
-    gettimeofday(&state.progress.first.time, NULL);
+    timespec_get(&state.progress.first.time, TIME_UTC);
 
     do
     {
-        FTDIProgressInfo  *progress = &state.progress;
+        struct ftdi_stream_progress *progress = &state.progress;
+        // 1 second
         const double progressInterval = 1.0;
         struct timeval timeout = { ftdi->usb_read_timeout / 1000,
             (ftdi->usb_read_timeout % 1000) * 1000 };
-        struct timeval now;
+        struct timespec now;
 
         int xfer_err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout);
         if (xfer_err ==  LIBUSB_ERROR_INTERRUPTED)
@@ -259,27 +274,27 @@ ftdi_readstream(struct ftdi_context *ftdi,
             state.activity = 0;
 
         // If enough time has elapsed, update the progress
-        gettimeofday(&now, NULL);
-        if (TimevalDiff(&now, &progress->current.time) >= progressInterval)
+        timespec_get(&now, TIME_UTC);
+        if (timespec_diff(&now, &progress->current.time) >= progressInterval)
         {
             progress->current.time = now;
-            progress->totalTime = TimevalDiff(&progress->current.time,
-                                              &progress->first.time);
+            progress->total_time = timespec_diff(&progress->current.time,
+                                                 &progress->first.time);
 
-            if (progress->prev.totalBytes)
+            if (progress->prev.total_bytes)
             {
                 // We have enough information to calculate rates
 
                 double currentTime;
 
-                currentTime = TimevalDiff(&progress->current.time,
-                                          &progress->prev.time);
+                currentTime = timespec_diff(&progress->current.time,
+                                            &progress->prev.time);
 
-                progress->totalRate =
-                    progress->current.totalBytes /progress->totalTime;
-                progress->currentRate =
-                    (progress->current.totalBytes -
-                     progress->prev.totalBytes) / currentTime;
+                progress->total_rate =
+                    progress->current.total_bytes / progress->total_time;
+                progress->current_rate =
+                    (progress->current.total_bytes -
+                     progress->prev.total_bytes) / currentTime;
             }
 
             state.callback(NULL, 0, progress, state.userdata);
@@ -302,3 +317,22 @@ cleanup:
         return state.result;
 }
 
+uint64_t ftdi_stream_total_bytes(struct ftdi_stream_progress *progress)
+{
+    return progress->current.total_bytes;
+}
+
+double ftdi_stream_total_time(struct ftdi_stream_progress *progress)
+{
+    return progress->total_time;
+}
+
+double ftdi_stream_total_rate(struct ftdi_stream_progress *progress)
+{
+    return progress->total_rate;
+}
+
+double ftdi_stream_current_rate(struct ftdi_stream_progress *progress)
+{
+    return progress->current_rate;
+}
-- 
2.44.0.windows.1


--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Current Thread