spi: "-S" option for continuous stream from standard input to bus

created to allow addressable leds to be driven by abusing spi bus as waveform generator. this might have other uses for similar "permanent" spi transfers

Differential Revision:	https://reviews.freebsd.org/D54734
Reviewed by:	adrian
This commit is contained in:
Sulev-Madis Silber
2026-01-16 19:29:19 -08:00
committed by Adrian Chadd
parent 325baf0073
commit 6dc12ecfb2
2 changed files with 38 additions and 10 deletions
+7
View File
@@ -38,6 +38,7 @@
.Op Fl d Cm r Ns | Ns Cm w Ns | Ns Cm rw
.Op Fl f Ar device
.Op Fl m Ar mode
.Op Fl S
.Op Fl s Ar max-speed
.Nm
.Op Fl i
@@ -145,6 +146,12 @@ caused the LSB to be transmitted and read first.
SPI mode, 0 through 3.
This defines the clock phase and timing with respect to reading and writing
data, as per the SPI specification.
.It Fl S
Constantly stream from
.Xr stdin 3
to the
.Nm
bus.
.It Fl s Ar speed
Specify the maximum speed, in Hz, for the SPI clock.
The bus will operate at its highest available speed which does not
+31 -10
View File
@@ -129,7 +129,7 @@ usage(void)
fputs(" - communicate on SPI bus with slave devices\n"
"Usage:\n"
" spi [-f device] [-d r|w|rw] [-m mode] [-s max-speed] [-c count]\n"
" [-C \"command bytes\"] [-A] [-b] [-L] [-v]\n"
" [-C \"command bytes\"] [-A] [-b] [-L] [-S] [-v]\n"
" spi -i [-f device] [-v]\n"
" spi -h\n"
" where\n"
@@ -145,6 +145,7 @@ usage(void)
" -i query information about the device\n"
" -A uses ASCII for input/output as 2-digit hex values\n"
" -b Override output format as binary (only valid with '-A')\n"
" -S constantly stream from stdin to bus\n"
" -v verbose output\n"
" -h prints this message\n"
"\n"
@@ -158,11 +159,12 @@ int
main(int argc, char *argv[], char *envp[] __unused)
{
struct spi_options opt;
int err, ch, hdev, finfo, fdir;
int err, ch, hdev, finfo, stream, fdir;
char *pstr;
char dev_name[PATH_MAX * 2 + 5];
finfo = 0;
stream = 0;
fdir = DIR_NONE;
hdev = -1;
@@ -180,7 +182,7 @@ main(int argc, char *argv[], char *envp[] __unused)
opt.ncmd = 0;
opt.pcmd = NULL;
while (!err && (ch = getopt(argc, argv, "f:d:m:s:c:C:AbLvih")) != -1) {
while (!err && (ch = getopt(argc, argv, "f:d:m:s:c:C:AbLviSh")) != -1) {
switch (ch) {
case 'd':
if (optarg[0] == 'r') {
@@ -275,6 +277,10 @@ main(int argc, char *argv[], char *envp[] __unused)
finfo = 1;
break;
case 'S':
stream = 1;
break;
default:
err = 1;
/* FALLTHROUGH */
@@ -358,14 +364,29 @@ main(int argc, char *argv[], char *envp[] __unused)
/* do data transfer */
if (fdir == DIR_READ) {
err = perform_read(hdev, &opt);
if (stream) {
while (!err && !feof(stdin)) {
if (fdir == DIR_READ) {
err = perform_read(hdev, &opt);
}
else if (fdir == DIR_WRITE) {
err = perform_write(hdev, &opt);
}
else if (fdir == DIR_READWRITE) {
err = perform_readwrite(hdev, &opt);
}
}
}
else if (fdir == DIR_WRITE) {
err = perform_write(hdev, &opt);
}
else if (fdir == DIR_READWRITE) {
err = perform_readwrite(hdev, &opt);
else {
if (fdir == DIR_READ) {
err = perform_read(hdev, &opt);
}
else if (fdir == DIR_WRITE) {
err = perform_write(hdev, &opt);
}
else if (fdir == DIR_READWRITE) {
err = perform_readwrite(hdev, &opt);
}
}
the_end: