Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package spi-tools for openSUSE:Factory 
checked in at 2026-08-01 19:57:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/spi-tools (Old)
 and      /work/SRC/openSUSE:Factory/.spi-tools.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "spi-tools"

Sat Aug  1 19:57:00 2026 rev:7 rq:1369015 version:1.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/spi-tools/spi-tools.changes      2023-01-03 
15:06:11.934801764 +0100
+++ /work/SRC/openSUSE:Factory/.spi-tools.new.16738/spi-tools.changes   
2026-08-01 19:57:02.075152981 +0200
@@ -1,0 +2,20 @@
+Tue Jul 21 08:44:53 UTC 2026 - Frantisek Simorda <[email protected]>
+
+- update to 1.1.0:
+  * [FIX] Parameter reading and parsing in `spi-pipe`.
+  * [FIX] parameter reading and parsing in `spi-config`.
+  * Update copyright dates.
+  * [FIX] wrong declaration of `-r` option in `spi-pipe`.
+  * [FIX] Some small errors in `spi-tools` detected by an AI.
+  * [FIX] Typo in `spi-config` man page.
+  * Merge pull request #33 from parsamajidi21/master
+  * README: Example of building binaries for Android devices
+  * add sample Android.bp to build within an Android tree
+  * [DOC] Working on `README.md`.
+  * [DEV] Add a `CMakeLists.txt` file for cmake build system.
+  * [DEV] Only write new configuration in `spi-pipe` if something changed.
+  * Merge pull request #32 from mjsir911/master
+  * Allow CFLAGS to be passed to ./configure
+  * [FIX] Typo in `spi-config` man page.
+
+-------------------------------------------------------------------

Old:
----
  spi-tools-1.0.2.tar.gz

New:
----
  spi-tools-1.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ spi-tools.spec ++++++
--- /var/tmp/diff_new_pack.FiGAL4/_old  2026-08-01 19:57:02.683173678 +0200
+++ /var/tmp/diff_new_pack.FiGAL4/_new  2026-08-01 19:57:02.687173815 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package spi-tools
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           spi-tools
-Version:        1.0.2
+Version:        1.1.0
 Release:        0
 Summary:        A set of SPI tools for Linux
 License:        GPL-2.0-or-later

++++++ spi-tools-1.0.2.tar.gz -> spi-tools-1.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/Android.bp 
new/spi-tools-1.1.0/Android.bp
--- old/spi-tools-1.0.2/Android.bp      1970-01-01 01:00:00.000000000 +0100
+++ new/spi-tools-1.1.0/Android.bp      2026-06-08 18:09:54.000000000 +0200
@@ -0,0 +1,96 @@
+# Android.bp for the spi-tools project.
+#
+# Copyright 2025  Parsa Majidi ([email protected])
+#
+# License  GPLv3+:  This is free software:  you are free to  change and
+# redistribute it.There is NO WARRANTY, to the extent permitted by law.
+
+// spi-tools
+
+
+genrule {
+    name: "generate_config_h",
+    srcs: [
+        "src/config.h.cmake.in"
+    ],
+    out: [
+        "config.h"
+    ],
+    cmd: "cp $(in) $(out)",
+}
+
+cc_library {
+    name: "spi-tools",
+    defaults: [
+        "spi_defaults",
+    ],
+    generated_headers: [
+        "generate_config_h",
+    ],
+    export_generated_headers: [
+        "generate_config_h",
+    ],
+}
+
+cc_defaults {
+    name: "spi_defaults",
+    device_specific: true,
+    cpp_std: "gnu++17",
+    cflags: [
+        // You may want to edit this with the version from configure.ac of
+        // the release you are using.
+        "-DGPIOD_VERSION_STR=\"unstable\"",
+    ],
+    cppflags: [
+        // Google C++ style is to not use exceptions, but this library does
+        // use them.
+        "-fexceptions",
+    ],
+    // Google C++ style is to not use runtime type information, but this
+    // library does use it.
+    rtti: true,
+}
+
+//
+// spi tools
+//
+
+phony {
+    name: "spi_tools",
+    required: [
+        "spi-config",
+       "spi-pipe",
+    ],
+}
+
+cc_binary {
+    name: "spi-config",
+    defaults: [
+        "spi_defaults",
+        "spi_tools_defaults",
+    ],
+    srcs: [
+        "src/spi-config.c",
+    ],
+}
+
+cc_binary {
+    name: "spi-pipe",
+    defaults: [
+        "spi_defaults",
+        "spi_tools_defaults",
+    ],
+    srcs: [
+        "src/spi-pipe.c",
+    ],
+}
+
+cc_defaults {
+    name: "spi_tools_defaults",
+    srcs: [
+        "src/spi-tools.c",
+    ],
+    shared_libs: [
+        "spi-tools",
+    ],
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/CMakeLists.txt 
new/spi-tools-1.1.0/CMakeLists.txt
--- old/spi-tools-1.0.2/CMakeLists.txt  1970-01-01 01:00:00.000000000 +0100
+++ new/spi-tools-1.1.0/CMakeLists.txt  2026-06-08 18:09:54.000000000 +0200
@@ -0,0 +1,20 @@
+#######################################################################
+# CMakeLists.txt for the spi-tools project.
+#
+# Copyright 2024  Christophe BLAESS (https://www.blaess.fr/christophe).
+#
+# License  GPLv3+:  This is free software:  you are free to  change and
+# redistribute it.There is NO WARRANTY, to the extent permitted by law.
+#
+#######################################################################
+
+cmake_minimum_required(VERSION 3.0)
+project(SPI_TOOLS VERSION 1.0.2)
+
+configure_file(src/config.h.cmake.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h)
+
+add_executable(spi-config src/spi-config.c src/spi-tools.c src/spi-tools.h)
+add_executable(spi-pipe src/spi-pipe.c src/spi-tools.c src/spi-tools.h)
+
+install(TARGETS spi-config DESTINATION /usr/bin)
+install(TARGETS spi-pipe DESTINATION /usr/bin)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/README.md 
new/spi-tools-1.1.0/README.md
--- old/spi-tools-1.0.2/README.md       2022-08-18 16:42:22.000000000 +0200
+++ new/spi-tools-1.1.0/README.md       2026-06-08 18:09:54.000000000 +0200
@@ -2,7 +2,7 @@
 
 This package contains some simple command line tools to help using Linux 
spidev devices.
 
-Version 1.0.2
+Version 1.1.0
 
 ## Content
 
@@ -25,6 +25,10 @@
 
 ## Installation
 
+There's two ways to install `spi-tools`: using Autotools or using Cmake.
+
+### Autotools
+
 First, get the latest version on https://github.com/cpb-/spi-tools.git.
 Then enter the directory and execute:
 
@@ -43,6 +47,8 @@
 
 You can use `make uninstall` (with `sudo`) to remove the installed files.
 
+### Cmake
+
 ## Usage
 
 ### spi-config usage
@@ -55,11 +61,15 @@
 * `-l --lsb={0,1}`     LSB first (1) or MSB first (0).
 * `-b --bits=[7...]`   bits per word.
 * `-s --speed=<int>`   set the speed in Hz.
-* `-r --spirdy={0,1}`   set the SPI_READY spi mode flag.
+* `-r --spirdy={0,1}`  set the SPI_READY spi mode flag.
 * `-w --wait`          block, keeping the file descriptor open.
 * `-h --help`          help screen.
 * `-v --version`       display the version number.
 
+* Some examples using a build folder under the source tree root:
+
+Android : `cmake 
-DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake
 -DANDROID_PLATFORM=android-21 -DANDROID_ABI=armeabi-v7a .. && make`
+
 #### Read the current configuration
 
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/configure.ac 
new/spi-tools-1.1.0/configure.ac
--- old/spi-tools-1.0.2/configure.ac    2022-08-18 16:42:22.000000000 +0200
+++ new/spi-tools-1.1.0/configure.ac    2026-06-08 18:09:54.000000000 +0200
@@ -61,13 +61,13 @@
 
 if test x"$debugit" = x"yes"; then
     AC_DEFINE([DEBUG],[],[Debug Mode])
-    AM_CFLAGS="-g -Wall -Werror -Wno-uninitialized -O0"
-    AM_CXXFLAGS="-g -Wall -Werror -Wno-uninitialized -O0"
+    AM_CFLAGS="$CFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
+    AM_CXXFLAGS="$CXXFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
     AC_MSG_NOTICE([Debug Mode on.])
 else
     AC_DEFINE([NDEBUG],[],[No-debug Mode])
-    AM_CFLAGS="-O0 $AM_CFLAGS"
-    AM_CXXFLAGS="-O0 $AM_CXXFLAGS"
+    AM_CFLAGS="-O0 $AM_CFLAGS $CFLAGS"
+    AM_CXXFLAGS="-O0 $AM_CXXFLAGS $CXXFLAGS"
     AC_MSG_NOTICE([Debug Mode off.])
 fi
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/man/spi-config.1 
new/spi-tools-1.1.0/man/spi-config.1
--- old/spi-tools-1.0.2/man/spi-config.1        2022-08-18 16:42:22.000000000 
+0200
+++ new/spi-tools-1.1.0/man/spi-config.1        2026-06-08 18:09:54.000000000 
+0200
@@ -29,7 +29,7 @@
 \fB\-r\fR, \fB\-\-spirdy\fR=\fI{0,1}\fR
 set the SPI READY mode flag.
 .TP
-\fB\-s\fR, \fB\-\-wait
+\fB\-w\fR, \fB\-\-wait
 block, keeping the file descriptor open. See \fBWAIT OPTION\fR below.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
@@ -41,16 +41,16 @@
 .SS "SPI MODES"
 .TP
 mode 0
-low iddle level, sample on leading edge.
+low idle level, sample on leading edge.
 .TP
 mode 1
-low iddle level, sample on trailing edge.
+low idle level, sample on trailing edge.
 .TP
 mode 2
-high iddle level, sample on leading edge.
+high idle level, sample on leading edge.
 .TP
 mode 3
-high iddle level, sample on trailing edge.
+high idle level, sample on trailing edge.
 
 .SS "WAIT OPTION"
 On some platforms, the speed is reset to a default value when the file 
descriptor is closed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/src/config.h.cmake.in 
new/spi-tools-1.1.0/src/config.h.cmake.in
--- old/spi-tools-1.0.2/src/config.h.cmake.in   1970-01-01 01:00:00.000000000 
+0100
+++ new/spi-tools-1.1.0/src/config.h.cmake.in   2026-06-08 18:09:54.000000000 
+0200
@@ -0,0 +1,6 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#define VERSION 
"@SPI_TOOLS_VERSION_MAJOR@.@SPI_TOOLS_VERSION_MINOR@.@SPI_TOOLS_VERSION_PATCH@"
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/src/spi-config.c 
new/spi-tools-1.1.0/src/spi-config.c
--- old/spi-tools-1.0.2/src/spi-config.c        2022-08-18 16:42:22.000000000 
+0200
+++ new/spi-tools-1.1.0/src/spi-config.c        2026-06-08 18:09:54.000000000 
+0200
@@ -1,7 +1,7 @@
 /*
  * spidev configuration tool.
  *
- * (c) 2014 Christophe BLAESS <[email protected]>
+ * (c) 2014-2026 Christophe BLAESS <[email protected]>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -18,40 +18,36 @@
  *
  */
 
+// ---------------------- System headers.
+
 #include <fcntl.h>
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include "config.h"
 
+
+// ---------------------- Project headers.
+
+#include "config.h"
 #include "spi-tools.h"
 
-static char *project = "spi-config";
 
+// ---------------------- Private macros declarations.
 
+// ---------------------- Private types and structures.
 
-static void display_usage(const char * name)
-{
-       fprintf(stderr, "usage: %s options...\n", name);
-       fprintf(stderr, "  options:\n");
-       fprintf(stderr, "    -d --device=<dev>  use the given spi-dev character 
device.\n");
-       fprintf(stderr, "    -q --query         print the current 
configuration.\n");
-       fprintf(stderr, "    -m --mode=[0-3]    use the selected spi mode:\n");
-       fprintf(stderr, "             0: low idle level, sample on leading 
edge,\n");
-       fprintf(stderr, "             1: low idle level, sample on trailing 
edge,\n");
-       fprintf(stderr, "             2: high idle level, sample on leading 
edge,\n");
-       fprintf(stderr, "             3: high idle level, sample on trailing 
edge.\n");
-       fprintf(stderr, "    -l --lsb={0,1}     LSB first (1) or MSB first 
(0).\n");
-       fprintf(stderr, "    -b --bits=[7...]   bits per word.\n");
-       fprintf(stderr, "    -s --speed=<int>   set the speed in Hz.\n");
-       fprintf(stderr, "    -r --spirdy={0,1}  consider SPI_RDY signal (1) or 
ignore it (0).\n");
-       fprintf(stderr, "    -w --wait          block keeping the file 
descriptor open to avoid speed reset.\n");
-       fprintf(stderr, "    -h --help          this screen.\n");
-       fprintf(stderr, "    -v --version       display the version number.\n");
+// ---------------------- Private method declarations.
 
-}
+static void display_usage(const char * name);
+
+
+// ---------------------- Private variables.
 
+static const char project[] = "spi-config";
+
+
+// ---------------------- Public methods
 
 int main (int argc, char * argv[])
 {
@@ -79,6 +75,7 @@
        int           val;
        int           query_only = 0;
        int           wait = 0;
+       int           changed = 0;
 
        new_config.spi_mode = -1;
        new_config.lsb_first = -1;
@@ -96,7 +93,7 @@
                                exit(EXIT_SUCCESS);
                        case 'v':
                                fprintf(stderr, "%s - %s\n", project, VERSION);
-                               fprintf(stderr, "Copyright (c) 2014-2021 
Christophe Blaess. (license GPLv2)\n");
+                               fprintf(stderr, "Copyright (c) 2014-2026 
Christophe Blaess. (license GPLv2)\n");
                                fprintf(stderr, "This is free software. You are 
free to change and redistribute it.\n");
                                fprintf(stderr, "There is NO WARRANTY, to the 
extent permitted by law.\n");
                                exit(EXIT_SUCCESS);
@@ -109,11 +106,13 @@
                        case 'm':
                                if (Parse_spi_mode(optarg, &new_config) != 0)
                                        exit(EXIT_FAILURE);
+                               changed = 1;
                                break;
 
                        case 'l':
                                if (Parse_lsb_first(optarg, &new_config) != 0)
                                        exit(EXIT_FAILURE);
+                               changed = 1;
                                break;
 
                        case 'b':
@@ -122,17 +121,20 @@
                                        fprintf(stderr, "%s: wrong bits per 
word value [7...]\n", argv[0]);
                                        exit(EXIT_FAILURE);
                                }
+                               changed = 1;
                                new_config.bits_per_word = val;
                                break;
 
                        case 's':
                                if (Parse_spi_speed(optarg, &new_config) != 0)
                                        exit(EXIT_FAILURE);
+                               changed = 1;
                                break;
 
                        case 'r':
                                if (Parse_spi_ready(optarg, &new_config) != 0)
                                        exit(EXIT_FAILURE);
+                               changed = 1;
                                break;
 
                        default:
@@ -141,6 +143,16 @@
                }
        }
 
+       if (optind < argc) {
+               fprintf(stderr, "%s: unexpected argument: %s\n", argv[0], 
argv[optind]);
+               exit(EXIT_FAILURE);
+       }
+
+       if (query_only && changed) {
+               fprintf(stderr, "%s: `-q` cannot be used with configuration 
options.\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
        if (device == NULL) {
                fprintf(stderr, "%s: no device specified (use option -h for 
help).\n", argv[0]);
                exit(EXIT_FAILURE);
@@ -187,3 +199,28 @@
        return EXIT_SUCCESS;
 }
 
+
+// ---------------------- Private methods
+
+static void display_usage(const char * name)
+{
+       fprintf(stderr, "usage: %s options...\n", name);
+       fprintf(stderr, "  options:\n");
+       fprintf(stderr, "    -d --device=<dev>  use the given spi-dev character 
device.\n");
+       fprintf(stderr, "    -q --query         print the current 
configuration.\n");
+       fprintf(stderr, "    -m --mode=[0-3]    use the selected spi mode:\n");
+       fprintf(stderr, "             0: low idle level, sample on leading 
edge,\n");
+       fprintf(stderr, "             1: low idle level, sample on trailing 
edge,\n");
+       fprintf(stderr, "             2: high idle level, sample on leading 
edge,\n");
+       fprintf(stderr, "             3: high idle level, sample on trailing 
edge.\n");
+       fprintf(stderr, "    -l --lsb={0,1}     LSB first (1) or MSB first 
(0).\n");
+       fprintf(stderr, "    -b --bits=[7...]   bits per word.\n");
+       fprintf(stderr, "    -s --speed=<int>   set the speed in Hz.\n");
+       fprintf(stderr, "    -r --spirdy={0,1}  consider SPI_RDY signal (1) or 
ignore it (0).\n");
+       fprintf(stderr, "    -w --wait          block keeping the file 
descriptor open to avoid speed reset.\n");
+       fprintf(stderr, "    -h --help          this screen.\n");
+       fprintf(stderr, "    -v --version       display the version number.\n");
+
+}
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/src/spi-pipe.c 
new/spi-tools-1.1.0/src/spi-pipe.c
--- old/spi-tools-1.0.2/src/spi-pipe.c  2022-08-18 16:42:22.000000000 +0200
+++ new/spi-tools-1.1.0/src/spi-pipe.c  2026-06-08 18:09:54.000000000 +0200
@@ -1,7 +1,7 @@
 /*
  * spidev data transfer tool.
  *
- * (c) 2014-2021 Christophe BLAESS <[email protected]>
+ * (c) 2014-2026 Christophe BLAESS <[email protected]>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -18,6 +18,9 @@
  *
  */
 
+// ---------------------- System headers.
+
+#include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <stdint.h>
@@ -25,32 +28,30 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+
+
+// ---------------------- Project headers.
+
 #include "config.h"
 #include "spi-tools.h"
 
-static char *project = "spi-pipe";
 
-static void display_usage(const char *name)
-{
-       fprintf(stderr, "usage: %s options...\n", name);
-       fprintf(stderr, "  options:\n");
-       fprintf(stderr, "    -d --device=<dev>    Use the given spi-dev 
character device.\n");
-       fprintf(stderr, "    -m --mode=[0-3]      Use the selected spi 
mode:\n");
-       fprintf(stderr, "             0: low idle level, sample on leading 
edge,\n");
-       fprintf(stderr, "             1: low idle level, sample on trailing 
edge,\n");
-       fprintf(stderr, "             2: high idle level, sample on leading 
edge,\n");
-       fprintf(stderr, "             3: high idle level, sample on trailing 
edge.\n");
-       fprintf(stderr, "    -s --speed=<speed>   Maximum SPI clock rate (in 
Hz).\n");
-       fprintf(stderr, "    -l --lsb={0,1}     LSB first (1) or MSB first 
(0).\n");
-       fprintf(stderr, "    -B --bits=[7...]     Bits per word.\n");
-       fprintf(stderr, "    -b --blocksize=<int> transfer block size in 
byte.\n");
-       fprintf(stderr, "    -n --number=<int>    number of blocks to transfer 
(-1 = infinite).\n");
-       fprintf(stderr, "    -h --help            this screen.\n");
-       fprintf(stderr, "    -v --version         display the version 
number.\n");
-}
+// ---------------------- Private macros declarations.
+
+// ---------------------- Private types and structures.
+
+// ---------------------- Private method declarations.
+
+static void display_usage(const char *name);
+static int full_write(int fd, const void *buffer, size_t length);
+
+
+// ---------------------- Private variables.
 
+static const char project[] = "spi-pipe";
 
 
+// ---------------------- Public methods
 
 int main (int argc, char *argv[])
 {
@@ -65,6 +66,7 @@
                {"lsb",       required_argument, NULL,  'l' },
                {"mode",      required_argument, NULL,  'm' },
                {"bits",      required_argument, NULL,  'B' },
+               {"ready",     required_argument, NULL,  'r' },
                {"help",      no_argument,       NULL,  'h' },
                {"version",   no_argument,       NULL,  'v' },
                {0,           0,                 0,  0 }
@@ -77,10 +79,10 @@
        spi_config_t prev_config;
        spi_config_t new_config;
 
-       int block_size    =  1;
-       int blocks_count  = -1;
-       int offset        =  0;
-       int nb            =  0;
+       size_t block_size    =  1;
+       int blocks_count     = -1;
+       size_t offset        =  0;
+       size_t nb            =  0;
 
        new_config.spi_mode = -1;
        new_config.lsb_first = -1;
@@ -89,7 +91,7 @@
        new_config.spi_ready = -1;
 
 
-       while ((opt = getopt_long(argc, argv, "d:s:b:l:m:n:B:rhv", options, 
&long_index)) >= 0) {
+       while ((opt = getopt_long(argc, argv, "d:s:b:l:m:n:B:r:hv", options, 
&long_index)) >= 0) {
                switch(opt) {
                        case 'h':
                                display_usage(argv[0]);
@@ -97,7 +99,7 @@
 
                        case 'v':
                                fprintf(stderr, "%s - %s\n", project, VERSION);
-                               fprintf(stderr, "Copyright (c) 2014-2021 
Christophe Blaess. (license GPLv2)\n");
+                               fprintf(stderr, "Copyright (c) 2014-2026 
Christophe Blaess. (license GPLv2)\n");
                                fprintf(stderr, "This is free software. You are 
free to change and redistribute it.\n");
                                fprintf(stderr, "There is NO WARRANTY, to the 
extent permitted by law.\n");
                                exit(EXIT_SUCCESS);
@@ -132,11 +134,8 @@
                                break;
 
                        case 'b':
-                               if ((sscanf(optarg, "%d", &block_size) != 1)
-                                || (block_size <= 0)) {
-                                       fprintf(stderr, "%s: wrong 
blocksize\n", argv[0]);
+                               if (Parse_spi_bits_per_word(optarg, 
&new_config) != 0)
                                        exit(EXIT_FAILURE);
-                               }
                                break;
 
                        case 'n':
@@ -155,20 +154,20 @@
 
        if (((rx_buffer = malloc(block_size)) == NULL)
         || ((tx_buffer = malloc(block_size)) == NULL)) {
-               fprintf(stderr, "%s: not enough memory to allocate two %d bytes 
buffers\n",
+               fprintf(stderr, "%s: not enough memory to allocate two %ld 
bytes buffers\n",
                                argv[0], block_size);
                exit(EXIT_FAILURE);
        }
 
-       memset(rx_buffer, 0, block_size);
-       memset(tx_buffer, 0, block_size);
-
        if (device == NULL) {
                fprintf(stderr, "%s: no device specified (use option -h for 
help).\n", argv[0]);
                exit(EXIT_FAILURE);
        }
 
-       fd = open(device, O_RDONLY);
+       memset(rx_buffer, 0, block_size);
+       memset(tx_buffer, 0, block_size);
+
+       fd = open(device, O_RDWR);
        if (fd < 0) {
                perror(device);
                exit(EXIT_FAILURE);
@@ -186,14 +185,15 @@
        if (new_config.bits_per_word == -1)
                new_config.bits_per_word = prev_config.bits_per_word;
 
-       if (new_config.spi_speed == -1)
+       if (new_config.spi_speed == 0)
                new_config.spi_speed = prev_config.spi_speed;
 
        if (new_config.spi_ready == -1)
                new_config.spi_ready = prev_config.spi_ready;
 
-       if (Write_spi_configuration(fd, &new_config) != 0)
-               exit(EXIT_FAILURE);
+       if (memcmp(&prev_config, &new_config, sizeof(spi_config_t)) != 0)
+               if (Write_spi_configuration(fd, &new_config) != 0)
+                       exit(EXIT_FAILURE);
 
        while ((blocks_count > 0) || (blocks_count == -1)) {
                for (offset = 0; offset < block_size; offset += nb) {
@@ -208,8 +208,10 @@
                        perror("SPI_IOC_MESSAGE");
                        break;
                }
-               if (write(STDOUT_FILENO, rx_buffer, offset) <= 0)
+               if (full_write(STDOUT_FILENO, rx_buffer, offset) < 0) {
+                       perror("write");
                        break;
+               }
                if (blocks_count > 0)
                        blocks_count --;
        }
@@ -217,11 +219,55 @@
        free(rx_buffer);
        free(tx_buffer);
 
-       if (Write_spi_configuration(fd, &prev_config) != 0)
-               exit(EXIT_FAILURE);
+       if (memcmp(&prev_config, &new_config, sizeof(spi_config_t)) != 0)
+               if (Write_spi_configuration(fd, &prev_config) != 0)
+                       exit(EXIT_FAILURE);
 
        if (blocks_count != 0)
                return EXIT_FAILURE;
 
        return EXIT_SUCCESS;
 }
+
+
+// ---------------------- Private methods
+
+static void display_usage(const char *name)
+{
+       fprintf(stderr, "usage: %s options...\n", name);
+       fprintf(stderr, "  options:\n");
+       fprintf(stderr, "    -d --device=<dev>    Use the given spi-dev 
character device.\n");
+       fprintf(stderr, "    -m --mode=[0-3]      Use the selected spi 
mode:\n");
+       fprintf(stderr, "             0: low idle level, sample on leading 
edge,\n");
+       fprintf(stderr, "             1: low idle level, sample on trailing 
edge,\n");
+       fprintf(stderr, "             2: high idle level, sample on leading 
edge,\n");
+       fprintf(stderr, "             3: high idle level, sample on trailing 
edge.\n");
+       fprintf(stderr, "    -s --speed=<speed>   Maximum SPI clock rate (in 
Hz).\n");
+       fprintf(stderr, "    -l --lsb={0,1}       LSB first (1) or MSB first 
(0).\n");
+       fprintf(stderr, "    -B --bits=[7...]     Bits per word.\n");
+       fprintf(stderr, "    -r --ready={0,1}     Spi ready mode.\n");
+       fprintf(stderr, "    -b --blocksize=<int> Transfer block size in 
byte.\n");
+       fprintf(stderr, "    -n --number=<int>    Number of blocks to transfer 
(-1 = infinite).\n");
+       fprintf(stderr, "    -h --help            This screen.\n");
+       fprintf(stderr, "    -v --version         Display the version 
number.\n");
+}
+
+
+
+static int full_write(int fd, const void *buffer, size_t length)
+{
+       const uint8_t *ptr = buffer;
+       size_t done = 0;
+
+       while (done < length) {
+               ssize_t n = write(fd, ptr + done, length - done);
+               if (n > 0) {
+                       done += (size_t)n;
+                       continue;
+               }
+               if ((n < 0) && (errno == EINTR))
+                       continue;
+               return -1;
+       }
+       return 0;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/src/spi-tools.c 
new/spi-tools-1.1.0/src/spi-tools.c
--- old/spi-tools-1.0.2/src/spi-tools.c 2022-08-18 16:42:22.000000000 +0200
+++ new/spi-tools-1.1.0/src/spi-tools.c 2026-06-08 18:09:54.000000000 +0200
@@ -1,7 +1,7 @@
 /*
  * spidev tools.
  *
- * (c) 2014-2021 Christophe BLAESS <[email protected]>
+ * (c) 2014-2026 Christophe BLAESS <[email protected]>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -19,27 +19,50 @@
  */
 
 
+// ---------------------- System headers.
+
+#include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <linux/spi/spidev.h>
 #include <sys/ioctl.h>
 
+
+// ---------------------- Project headers.
+
 #include "spi-tools.h"
 
 
+// ---------------------- Private macros declarations.
+
+// ---------------------- Private types and structures.
+
+// ---------------------- Private method declarations.
+
+static int parse_int_with_range(const char *s, int min, int max, int *value);
+
+// ---------------------- Private variables.
+
+// ---------------------- Public methods
 
 int Read_spi_configuration(int fd, spi_config_t *config)
 {
        uint8_t  u8;
        uint32_t u32;
 
+       if (config == NULL) {
+               errno = EINVAL;
+               return -1;
+       }
+
        if (ioctl(fd, SPI_IOC_RD_MODE, &u8) < 0) {
                perror("SPI_IOC_RD_MODE");
                return -1;
        }
        config->spi_mode = u8 & 0x03;
-       config->spi_ready = ((config->spi_mode & SPI_READY) ? 1 : 0);
+       config->spi_ready = ((u8 & SPI_READY) ? 1 : 0);
 
        if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &u8) < 0) {
                perror("SPI_IOC_RD_LSB_FIRST");
@@ -64,35 +87,61 @@
 
 
 
-int Write_spi_configuration(int fd, spi_config_t *config)
+int Write_spi_configuration(int fd, const spi_config_t *config)
 {
        uint8_t  u8;
        uint32_t u32;
 
-       u8 = config->spi_mode;
-       if (config->spi_ready == 1)
-               u8 |= SPI_READY;
-       if (ioctl(fd, SPI_IOC_WR_MODE, &u8) < 0) {
-               perror("SPI_IOC_WR_MODE");
+       if (config == NULL) {
+               errno = EINVAL;
                return -1;
        }
 
-       u8 = (config->lsb_first ? 1 : 0);
-       if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &u8) < 0) {
-       perror("SPI_IOC_WR_LSB_FIRST");
-       return -1;
-       }
-
-       u8 = config->bits_per_word;
-       if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &u8) < 0) {
-               perror("SPI_IOC_WR_BITS_PER_WORD");
-               return -1;
-       }
-
-       u32 = config->spi_speed;
-       if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &u32) < 0) {
-               perror("SPI_IOC_WR_MAX_SPEED_HZ");
-               return -1;
+       if (config->spi_mode >= 0 || config->spi_ready >= 0) {
+               if (ioctl(fd, SPI_IOC_RD_MODE, &u8) < 0) {
+                       perror("SPI_IOC_RD_MODE");
+                       return -1;
+               }
+               if (config->spi_mode >= 0) {
+                       u8 &= ~0x03;
+                       u8 |= config->spi_mode;
+               }
+
+               if (config->spi_ready >= 0) {
+                       if (config->spi_ready)
+                               u8 |= SPI_READY;
+                       else
+                               u8 &= ~SPI_READY;
+               }
+
+               if (ioctl(fd, SPI_IOC_WR_MODE, &u8) < 0) {
+                       perror("SPI_IOC_WR_MODE");
+                       return -1;
+               }
+       }
+
+       if (config->lsb_first >= 0) {
+               u8 = (config->lsb_first ? 1 : 0);
+               if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &u8) < 0) {
+                       perror("SPI_IOC_WR_LSB_FIRST");
+                       return -1;
+               }
+       }
+
+       if (config->bits_per_word >= 0) {
+               u8 = config->bits_per_word;
+               if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &u8) < 0) {
+                       perror("SPI_IOC_WR_BITS_PER_WORD");
+                       return -1;
+               }
+       }
+
+       if (config->spi_speed > 0) {
+               u32 = config->spi_speed;
+               if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &u32) < 0) {
+                       perror("SPI_IOC_WR_MAX_SPEED_HZ");
+                       return -1;
+               }
        }
 
        return 0;
@@ -101,9 +150,11 @@
 
 int Parse_spi_mode(const char *optarg, spi_config_t *config)
 {
-       if ((sscanf(optarg, "%d", &(config->spi_mode)) != 1)
-        || (config->spi_mode < 0) || (config->spi_mode > 3)) {
-               fprintf(stderr, "Error: wrong SPI mode ([0-3]): %s\n", optarg);
+       if (config == NULL)
+               return -1;
+
+       if (parse_int_with_range(optarg, 0, 3, &(config->spi_mode)) != 0) {
+               fprintf(stderr, "Error: wrong SPI mode ([0-3]): %s\n", optarg ? 
optarg : "(null)");
                return -1;
        }
        return 0;
@@ -113,9 +164,11 @@
 
 int Parse_lsb_first(const char *optarg, spi_config_t *config)
 {
-       if ((sscanf(optarg, "%d", &(config->lsb_first)) != 1)
-        || (config->lsb_first < 0) || (config->lsb_first > 1)) {
-               fprintf(stderr, "Error: wrong LSB value ([0,1]): %s\n", optarg);
+       if (config == NULL)
+               return -1;
+
+       if (parse_int_with_range(optarg, 0, 1, &(config->lsb_first)) != 0) {
+               fprintf(stderr, "Error: wrong LSB value ([0,1]): %s\n", optarg 
? optarg : "(null)");
                return -1;
        }
        return 0;
@@ -125,9 +178,11 @@
 
 int Parse_spi_speed(const char *optarg, spi_config_t *config)
 {
-       if ((sscanf(optarg, "%d", &(config->spi_speed)) != 1)
-        || (config->spi_speed < 0) || (config->spi_speed > 100000000)) {
-               fprintf(stderr, "Error: invalid SPI speed ([0-100000000]): 
%s\n", optarg);
+       if (config == NULL)
+               return -1;
+
+       if (parse_int_with_range(optarg, 0, 100000000, &(config->spi_speed)) != 
0) {
+               fprintf(stderr, "Error: invalid SPI speed ([0-100000000]): 
%s\n", optarg ? optarg : "(null)");
                return -1;
        }
        return 0;
@@ -137,9 +192,11 @@
 
 int Parse_spi_ready(const char *optarg, spi_config_t *config)
 {
-       if ((sscanf(optarg, "%d", &(config->spi_ready)) != 1)
-        || (config->spi_ready < 0) || (config->spi_ready > 1)) {
-               fprintf(stderr, "Error: wrong SPI-ready value ([0, 1]): %s\n", 
optarg);
+       if (config == NULL)
+               return -1;
+
+       if (parse_int_with_range(optarg, 0, 1, &(config->spi_ready)) != 0) {
+               fprintf(stderr, "Error: wrong SPI-ready value ([0, 1]): %s\n", 
optarg ? optarg : "(null)");
                return -1;
        }
        return 0;
@@ -149,9 +206,11 @@
 
 int Parse_spi_bits_per_word(const char *optarg, spi_config_t *config)
 {
-       if ((sscanf(optarg, "%d", &(config->bits_per_word)) != 1)
-        || (config->bits_per_word < 7)) {
-               fprintf(stderr, "Error: wrong bits-per-word value ([0, 1]): 
%s\n", optarg);
+       if (config == NULL)
+               return -1;
+
+       if (parse_int_with_range(optarg, 7, 255, &(config->bits_per_word)) != 
0) {
+               fprintf(stderr, "Error: wrong bits-per-word value ([7, 255]): 
%s\n", optarg ? optarg : "(null)");
                return -1;
        }
        return 0;
@@ -159,7 +218,7 @@
 
 
 
-int Transfer_spi_buffers(int fd, void *tx_buffer, void *rx_buffer, size_t 
length)
+int Transfer_spi_buffers(int fd, const void *tx_buffer, void *rx_buffer, 
size_t length)
 {
        struct spi_ioc_transfer transfer = {
                .tx_buf        = 0,
@@ -170,6 +229,17 @@
                .bits_per_word = 0,
        };
 
+
+       if (length > UINT32_MAX) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if ((length > 0) && (tx_buffer == NULL) && (rx_buffer == NULL)) {
+               errno = EINVAL;
+               return -1;
+       }
+
        transfer.rx_buf = (unsigned long)rx_buffer;
        transfer.tx_buf = (unsigned long)tx_buffer;
        transfer.len = length;
@@ -179,3 +249,28 @@
 
        return 0;
 }
+
+
+// ---------------------- Private methods
+
+static int parse_int_with_range(const char *str, int min, int max, int *value)
+{
+       char *end = NULL;
+       long tmpvalue;
+
+       if ((str == NULL) || (value == NULL))
+               return -1;
+
+       errno = 0;
+       tmpvalue = strtol(str, &end, 0);
+       if ((errno != 0) || (end == str) || (*end != '\0'))
+               return -1;
+
+       if ((tmpvalue < min) || (tmpvalue > max))
+               return -1;
+
+       *value = (int)tmpvalue;
+
+       return 0;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spi-tools-1.0.2/src/spi-tools.h 
new/spi-tools-1.1.0/src/spi-tools.h
--- old/spi-tools-1.0.2/src/spi-tools.h 2022-08-18 16:42:22.000000000 +0200
+++ new/spi-tools-1.1.0/src/spi-tools.h 2026-06-08 18:09:54.000000000 +0200
@@ -21,21 +21,23 @@
 #ifndef SPI_TOOLS_H
 #define SPI_TOOLS_H
 
+#include <stddef.h>
+
 
 typedef struct spi_config {
 
-    int        spi_mode;      // [0-3]  (-1 when not configured).
-    int        lsb_first;     // {0,1}  (-1 when not configured).
-    int        bits_per_word; // [7...] (-1 when not configured).
-    int        spi_speed;     // 0 when not configured.
-    int        spi_ready;     // {0,1}  (-1 when not configured).
+    int          spi_mode;      // [0-3]  (-1 when not configured).
+    int          lsb_first;     // {0,1}  (-1 when not configured).
+    int          bits_per_word; // [7...] (-1 when not configured).
+    unsigned int spi_speed;     // 0 when not configured.
+    int          spi_ready;     // {0,1}  (-1 when not configured).
 
 } spi_config_t;
 
 
 int Read_spi_configuration(int fd, spi_config_t *config);
 
-int Write_spi_configuration(int fd, spi_config_t *config);
+int Write_spi_configuration(int fd, const spi_config_t *config);
 
 int Parse_spi_mode(const char *optarg, spi_config_t *config);
 
@@ -47,7 +49,7 @@
 
 int Parse_spi_bits_per_word(const char *optarg, spi_config_t *config);
 
-int Transfer_spi_buffers(int fd, void *tx_buffer, void *rx_buffer, size_t 
length);
+int Transfer_spi_buffers(int fd, const void *tx_buffer, void *rx_buffer, 
size_t length);
 
 
 #endif

Reply via email to