From: Brigham Campbell <me@brighamcampbell.com>
To: Jean Delvare <jdelvare@suse.de>, linux-i2c@vger.kernel.org
Cc: "Wolfram Sang" <wsa+renesas@sang-engineering.com>,
"Brigham Campbell" <me@brighamcampbell.com>,
"Gero Schwäricke" <gero.schwaericke@sevenlab.de>
Subject: [PATCH v4 1/2] i2c-tools: Allow passing device file paths
Date: Sun, 05 Jul 2026 22:27:53 -0600 [thread overview]
Message-ID: <20260705-accept-device-path-v4-1-c62caa708a9e@brighamcampbell.com> (raw)
In-Reply-To: <20260705-accept-device-path-v4-0-c62caa708a9e@brighamcampbell.com>
Make i2c-tools binaries accept a device file path or symlink directly.
This is useful, for example, for use with stable symlinks generated by
udev.
In the case of conflict, the bus parameter is parsed with the following
precedence in order to maintain backwards compatibility:
number -> name -> device path
Suggested-by: Gero Schwäricke <gero.schwaericke@sevenlab.de>
Signed-off-by: Brigham Campbell <me@brighamcampbell.com>
---
tools/i2cbusses.c | 40 ++++++++++++++++++++++++++++++++++------
tools/i2cbusses.h | 4 +++-
tools/i2cdetect.c | 12 ++++--------
tools/i2cdump.c | 12 ++++--------
tools/i2cget.c | 11 ++++-------
tools/i2cset.c | 11 ++++-------
tools/i2ctransfer.c | 11 ++++-------
7 files changed, 57 insertions(+), 44 deletions(-)
diff --git a/tools/i2cbusses.c b/tools/i2cbusses.c
index d687615..54f3238 100644
--- a/tools/i2cbusses.c
+++ b/tools/i2cbusses.c
@@ -65,7 +65,7 @@ static enum adt i2c_get_funcs(int i2cbus)
char filename[20];
enum adt ret;
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 1);
+ file = open_i2c_dev_num(i2cbus, filename, sizeof(filename), 1);
if (file < 0)
return adt_unknown;
@@ -348,10 +348,6 @@ static int lookup_i2c_bus_by_name(const char *bus_name)
}
}
- if (i2cbus == -1)
- fprintf(stderr, "Error: I2C bus name doesn't match any "
- "bus present!\n");
-
done:
free_adapters(adapters);
return i2cbus;
@@ -410,7 +406,7 @@ int parse_i2c_address(const char *address_arg, int all_addrs)
return address;
}
-int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
+int open_i2c_dev_num(int i2cbus, char *filename, size_t size, int quiet)
{
int file, len;
@@ -446,6 +442,38 @@ int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
return file;
}
+int open_i2c_dev_path(const char *i2cbus_arg, int quiet)
+{
+ int file = open(i2cbus_arg, O_RDWR);
+
+ if (file < 0 && !quiet) {
+ fprintf(stderr, "Error: Could not open file "
+ "`%s': %s\n", i2cbus_arg, strerror(errno));
+ if (errno == EACCES)
+ fprintf(stderr, "Run as root?\n");
+ }
+
+ return file;
+}
+
+int open_i2c_dev(char *i2cbus_arg, char **filename, size_t size, int quiet)
+{
+ int file, i2cbus;
+
+ i2cbus = lookup_i2c_bus(i2cbus_arg);
+
+ if (i2cbus < 0) {
+ *filename = i2cbus_arg;
+ file = open_i2c_dev_path(i2cbus_arg, quiet);
+ if (file < 0)
+ fprintf(stderr, "Failed to open `%s' as a bus name "
+ "and as a path.\n", i2cbus_arg);
+ return file;
+ }
+
+ return open_i2c_dev_num(i2cbus, *filename, size, quiet);
+}
+
int set_slave_addr(int file, int address, int force)
{
/* With force, let the user read from/write to the registers
diff --git a/tools/i2cbusses.h b/tools/i2cbusses.h
index 6f901b6..5de3056 100644
--- a/tools/i2cbusses.h
+++ b/tools/i2cbusses.h
@@ -31,7 +31,9 @@ void free_adapters(struct i2c_adap *adapters);
int lookup_i2c_bus(const char *i2cbus_arg);
int parse_i2c_address(const char *address_arg, int all_addrs);
-int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet);
+int open_i2c_dev(char *i2cbus_arg, char **filename, size_t size, int quiet);
+int open_i2c_dev_num(int i2cbus, char *filename, size_t size, int quiet);
+int open_i2c_dev_path(const char *i2cbus_arg, int quiet);
int set_slave_addr(int file, int address, int force);
#define MISSING_FUNC_FMT "Error: Adapter does not have %s capability\n"
diff --git a/tools/i2cdetect.c b/tools/i2cdetect.c
index 3c22f17..b62f395 100644
--- a/tools/i2cdetect.c
+++ b/tools/i2cdetect.c
@@ -213,8 +213,9 @@ static void print_i2c_busses(void)
int main(int argc, char *argv[])
{
char *end;
- int i2cbus, file, res;
- char filename[20];
+ int file, res;
+ char filename_buf[20];
+ char *filename = filename_buf;
unsigned long funcs;
int mode = MODE_AUTO;
int first = 0x08, last = 0x77;
@@ -277,11 +278,6 @@ int main(int argc, char *argv[])
help();
exit(1);
}
- i2cbus = lookup_i2c_bus(argv[optind]);
- if (i2cbus < 0) {
- help();
- exit(1);
- }
/* read address range if present */
if (argc == optind + 3 && mode != MODE_FUNC) {
@@ -321,7 +317,7 @@ int main(int argc, char *argv[])
exit(1);
}
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
+ file = open_i2c_dev(argv[optind], &filename, sizeof(filename_buf), 0);
if (file < 0) {
exit(1);
}
diff --git a/tools/i2cdump.c b/tools/i2cdump.c
index d315e2f..ce3be2c 100644
--- a/tools/i2cdump.c
+++ b/tools/i2cdump.c
@@ -100,9 +100,10 @@ static int check_funcs(int file, int size, int pec)
int main(int argc, char *argv[])
{
char *end;
- int i, j, res, i2cbus, address, size, file;
+ int i, j, res, address, size, file;
int bank = 0, bankreg = 0x4E, old_bank = 0;
- char filename[20];
+ char filename_buf[20];
+ char *filename = filename_buf;
int block[256];
int pec = 0, even = 0;
int opt;
@@ -135,11 +136,6 @@ int main(int argc, char *argv[])
help();
exit(1);
}
- i2cbus = lookup_i2c_bus(argv[optind]);
- if (i2cbus < 0) {
- help();
- exit(1);
- }
if (argc < optind + 2) {
fprintf(stderr, "Error: No address specified!\n");
@@ -235,7 +231,7 @@ int main(int argc, char *argv[])
}
}
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
+ file = open_i2c_dev(argv[optind], &filename, sizeof(filename_buf), 0);
if (file < 0
|| check_funcs(file, size, pec)
|| set_slave_addr(file, address, force))
diff --git a/tools/i2cget.c b/tools/i2cget.c
index 17d78bf..e08ee81 100644
--- a/tools/i2cget.c
+++ b/tools/i2cget.c
@@ -169,9 +169,10 @@ static int confirm(const char *filename, int address, int size, int daddress,
int main(int argc, char *argv[])
{
char *end;
- int res, i2cbus, address, size, file;
+ int res, address, size, file;
int daddress;
- char filename[20];
+ char filename_buf[20];
+ char *filename = filename_buf;
int pec = 0;
int opt;
int force = 0, yes = 0, version = 0, all_addrs = 0;
@@ -199,10 +200,6 @@ int main(int argc, char *argv[])
if (argc < optind + 2)
help(1);
- i2cbus = lookup_i2c_bus(argv[optind]);
- if (i2cbus < 0)
- help(1);
-
address = parse_i2c_address(argv[optind+1], all_addrs);
if (address < 0)
help(1);
@@ -251,7 +248,7 @@ int main(int argc, char *argv[])
length = I2C_SMBUS_BLOCK_MAX;
}
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
+ file = open_i2c_dev(argv[optind], &filename, sizeof(filename_buf), 0);
if (file < 0
|| check_funcs(file, size, daddress, pec)
|| set_slave_addr(file, address, force))
diff --git a/tools/i2cset.c b/tools/i2cset.c
index aaf7faf..8371570 100644
--- a/tools/i2cset.c
+++ b/tools/i2cset.c
@@ -151,9 +151,10 @@ int main(int argc, char *argv[])
{
char *end;
const char *maskp = NULL;
- int res, i2cbus, address, size, file;
+ int res, address, size, file;
int value, daddress, vmask = 0;
- char filename[20];
+ char filename_buf[20];
+ char *filename = filename_buf;
int pec = 0;
int opt;
int force = 0, yes = 0, version = 0, readback = 0, all_addrs = 0;
@@ -183,10 +184,6 @@ int main(int argc, char *argv[])
if (argc < optind + 3)
help(1);
- i2cbus = lookup_i2c_bus(argv[optind]);
- if (i2cbus < 0)
- help(1);
-
address = parse_i2c_address(argv[optind+1], all_addrs);
if (address < 0)
help(1);
@@ -301,7 +298,7 @@ int main(int argc, char *argv[])
}
}
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
+ file = open_i2c_dev(argv[optind], &filename, sizeof(filename_buf), 0);
if (file < 0
|| check_funcs(file, size, pec)
|| set_slave_addr(file, address, force))
diff --git a/tools/i2ctransfer.c b/tools/i2ctransfer.c
index a49b734..d9d1396 100644
--- a/tools/i2ctransfer.c
+++ b/tools/i2ctransfer.c
@@ -257,8 +257,9 @@ static enum supported_flags_retval
int main(int argc, char *argv[])
{
- char filename[20];
- int i2cbus, address = -1, file, opt, nmsgs = 0, nmsgs_sent, i;
+ char filename_buf[20];
+ char *filename = filename_buf;
+ int address = -1, file, opt, nmsgs = 0, nmsgs_sent, i;
int force = 0, yes = 0, version = 0, verbose = 0, all_addrs = 0, binary = 0;
struct i2c_msg msgs[I2C_RDRW_IOCTL_MAX_MSGS];
enum parse_state state = PARSE_GET_DESC;
@@ -293,11 +294,7 @@ int main(int argc, char *argv[])
exit(1);
}
- i2cbus = lookup_i2c_bus(argv[optind++]);
- if (i2cbus < 0)
- exit(1);
-
- file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
+ file = open_i2c_dev(argv[optind++], &filename, sizeof(filename_buf), 0);
if (file < 0 || get_funcs(file, &funcs) || check_funcs(funcs))
exit(1);
--
2.55.0
next prev parent reply other threads:[~2026-07-06 4:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 4:27 [PATCH v4 0/2] i2c-tools: Make tools accept bus path Brigham Campbell
2026-07-06 4:27 ` Brigham Campbell [this message]
2026-07-06 4:27 ` [PATCH v4 2/2] i2c-tools: Document device paths as I2CBUS arg Brigham Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260705-accept-device-path-v4-1-c62caa708a9e@brighamcampbell.com \
--to=me@brighamcampbell.com \
--cc=gero.schwaericke@sevenlab.de \
--cc=jdelvare@suse.de \
--cc=linux-i2c@vger.kernel.org \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox