mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-16 15:11:52 +00:00
This is smbmsg(8), a small utility to send/receive SMBus messages.
Also included is a `bus-probe' modus of operation to help scanning an I2C bus.
This commit is contained in:
parent
a6af156093
commit
325bf22bbd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/JOERG/; revision=129330
8
usr.sbin/smbmsg/Makefile
Normal file
8
usr.sbin/smbmsg/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= smbmsg
|
||||
MAN8= smbmsg.8
|
||||
WARNS= 6
|
||||
|
||||
.include <bsd.prog.mk>
|
29
usr.sbin/smbmsg/pathnames.h
Normal file
29
usr.sbin/smbmsg/pathnames.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*-
|
||||
* Copyright (C) 2004 Joerg Wunsch
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define PATH_DEFAULTSMBDEV "/dev/smb0"
|
286
usr.sbin/smbmsg/smbmsg.8
Normal file
286
usr.sbin/smbmsg/smbmsg.8
Normal file
@ -0,0 +1,286 @@
|
||||
.\" Copyright (c) 2004 Joerg Wunsch
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 16, 2004
|
||||
.Dt SMBMSG 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm smbmsg
|
||||
.Nd "send or receive messages over an SMBus"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f Ar dev
|
||||
.Fl p
|
||||
.Pp
|
||||
.Nm
|
||||
.Op Fl f Ar dev
|
||||
.Fl s Ar slave
|
||||
.Op Fl F Ar fmt
|
||||
.Op Fl c Ar cmd
|
||||
.Op Fl w
|
||||
.Op Fl i Ar incnt
|
||||
.Op Fl o Ar outcnt
|
||||
.Op Ar outdata ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command can be used to send or receive messages over an
|
||||
SMBus, see
|
||||
.Xr smbus 4 .
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
command has two different modi of operation.
|
||||
The first form shown in the synopsis can be used to
|
||||
.Dq probe
|
||||
the devices on the SMBus.
|
||||
This is done by sending each valid device address one
|
||||
receive byte, and one quick read message, respectively.
|
||||
Devices that respond to these requests will by displayed
|
||||
by their device address, followed by the strings
|
||||
.Ql r ,
|
||||
.Ql w ,
|
||||
or
|
||||
.Ql rw ,
|
||||
for devices that are readable, writeable, or both, readable
|
||||
and writeable, respectively.
|
||||
The only valid additional option for this modus of operation (besides
|
||||
the
|
||||
.Fl p
|
||||
option that choses the modus) is
|
||||
.Fl f Ar dev .
|
||||
See below for a description.
|
||||
.Pp
|
||||
Note that probing the bus is risky, since individual devices could
|
||||
perform unwanted actions upon receiving one of the mentioned messages.
|
||||
For example, if a particular SMBus device considers
|
||||
.Em any
|
||||
write operation issued to it as a request to power off the system,
|
||||
the probing would trigger this action.
|
||||
.Pp
|
||||
The second form shown in the synopsis can be used to send or receive
|
||||
arbitrary messages to or from individual devices.
|
||||
This might be useful to explore individual devices on the SMBus, or
|
||||
maybe even to write short shell scripts performing maintenance
|
||||
operations on the bus.
|
||||
.Pp
|
||||
Any data values on the command-line are integer values in the
|
||||
range 0 through 255 for byte values, or 0 through 65535 for
|
||||
word values.
|
||||
They can be specified using standard
|
||||
.Ql C
|
||||
notation (prefix 0 for octal interpretation, or 0x for
|
||||
hexadecimal interpretation).
|
||||
.Pp
|
||||
Since the low-order bit of the device address of SMBus devices
|
||||
selects between read and write operations, only even-numbered
|
||||
slave addresses can exist on the bus.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width ".Fl o Ar outcnt"
|
||||
.It Fl F Ar fmt
|
||||
Specify the
|
||||
.Xr printf 3
|
||||
format to be used for displaying input data.
|
||||
This option is ignored in messages that do not read any input
|
||||
from the SMBus device.
|
||||
The format defaults to
|
||||
.Ql 0x%02x
|
||||
for byte input operations, and to
|
||||
.Ql 0x%04x
|
||||
for word input operations.
|
||||
For multi-byte input (block read), the same format is used for
|
||||
each individual byte read from the SMBus.
|
||||
.It Fl c Ar cmd
|
||||
This is the value of the
|
||||
.Em command
|
||||
byte to be issued as part of the SMBus message.
|
||||
.It Fl f Ar dev
|
||||
This specifies that
|
||||
.Ar dev
|
||||
should be used as the connection to the SMBus, rather than the
|
||||
default of
|
||||
.Pa /dev/smb0 .
|
||||
.It Fl i Ar incnt
|
||||
An SMBus message should be generated to read
|
||||
.Ar incnt
|
||||
bytes from the device.
|
||||
.It Fl o Ar outcnt
|
||||
An SMBus message should be generated to write
|
||||
.Ar outcnt
|
||||
bytes to the device.
|
||||
The data values to write are expected to follow all of the options
|
||||
(and their arguments) on the command-line, where the number of data
|
||||
bytes must match the
|
||||
.Ar outcnt
|
||||
value.
|
||||
.It Fl p
|
||||
This selects the
|
||||
.Em probe bus
|
||||
modus of operation.
|
||||
.It Fl s Ar slave
|
||||
The
|
||||
.Ar slave
|
||||
parameter specifies which SMBus device to connect to.
|
||||
This option also selects the
|
||||
.Em transfer messages from/to device
|
||||
modus of operation, where a slave address is mandatory.
|
||||
.It Fl w
|
||||
This option specifies that IO operations are word operations,
|
||||
rather than byte operations.
|
||||
Either
|
||||
.Ar incnt ,
|
||||
or
|
||||
.Ar outcnt
|
||||
(or both) must be equal 2 in this case.
|
||||
Note that the SMBus byte order is defined to be little-endian
|
||||
(low byte first, high byte follows).
|
||||
.El
|
||||
.Pp
|
||||
Not all argument combinations make sense in order to form valid SMBus
|
||||
messages.
|
||||
If no
|
||||
.Fl c Ar cmd
|
||||
option has been provided, the following messages can be
|
||||
issued:
|
||||
.Pp
|
||||
.Bd -unfilled -offset indent
|
||||
.TS
|
||||
l r r.
|
||||
\fBmessage incnt outcnt\fR
|
||||
quick read 0 \&-
|
||||
quick write \&- 0
|
||||
receive byte 1 \&-
|
||||
send byte \&- 1
|
||||
.TE
|
||||
.Ed
|
||||
.Pp
|
||||
Note in particular that specifying 0 as a count value
|
||||
has a different meaning than omitting the respective
|
||||
option entirely.
|
||||
.Pp
|
||||
If a command value has been given using the
|
||||
.Fl c Ar cmd
|
||||
option, the following messages can be generated:
|
||||
.Pp
|
||||
.Bd -unfilled -offset indent
|
||||
.TS
|
||||
l l r r.
|
||||
\fBmessage \&-w incnt outcnt\fR
|
||||
read byte no 1 \&-
|
||||
write byte no \&- 1
|
||||
read word yes 2 \&-
|
||||
write word yes \&- 2
|
||||
process call yes 2 2
|
||||
block read no \*(Ge 2 \&-
|
||||
block write no \&- \*(Ge 2
|
||||
.TE
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /dev/smb0" -compact
|
||||
.It Pa /dev/smb0
|
||||
The default device to connect to, unless
|
||||
.Fl f Ar dev
|
||||
has been provided.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Typical usage examples of the
|
||||
.Nm
|
||||
command include:
|
||||
.Pp
|
||||
.Dl "smbmsg -f /dev/smb1 -p"
|
||||
.Pp
|
||||
Probe all devices on the SMBus attached to
|
||||
.Pa /dev/smb1 .
|
||||
.Pp
|
||||
.Dl "smbmsg -s 0x70 -i 1"
|
||||
.Pp
|
||||
Issue a
|
||||
.Em receive byte
|
||||
message to the device at address 0x70, and display
|
||||
the received byte using the default format.
|
||||
.Pp
|
||||
.Dl "smbmsg -s 0x70 -c 0xff -i 1 -F %d"
|
||||
.Pp
|
||||
Issue a
|
||||
.Em read byte
|
||||
message to the device at slave address 0x70, using
|
||||
255 (0xff) as the command-byte to send to the device,
|
||||
and display the result using the custom format %d.
|
||||
.Pp
|
||||
.Dl "smbmsg -s 0xa0 -c 0 -o 1 0x80"
|
||||
.Pp
|
||||
Send a
|
||||
.Em write byte
|
||||
message to the slave device at address 0xa0, using
|
||||
0 as the command-byte value, and 0x80 as the byte to
|
||||
send (after the command).
|
||||
Assuming this might be a Philips PCF8583 real-time clock,
|
||||
this would stop the clock.
|
||||
.Pp
|
||||
.Dl "smbmsg -s 0xa0 -c 1 -i 6 -F %02x"
|
||||
.Pp
|
||||
Send a
|
||||
.Em block read
|
||||
command to device at address 0xa0, and read 6 bytes from
|
||||
it, using hexadecimal display.
|
||||
Again, assuming a PCF8583 RTC, this would display the
|
||||
fractions of second, seconds, minutes, hours, year/date,
|
||||
and weekday/month values.
|
||||
Since this RTC uses BCD notation, the actual values displayed
|
||||
were decimal then.
|
||||
.Pp
|
||||
.Dl "smbmsg -s 0xa0 -c 2 -o 5 0x00 0x07 0x22 0x16 0x05"
|
||||
.Pp
|
||||
Send a
|
||||
.Em block write
|
||||
command to device at address 0xa0.
|
||||
For the PCF8583 RTC, this would set the clock to Sunday (2004%4)-05-16
|
||||
22:07:00.
|
||||
.Sh DIAGNOSTICS
|
||||
Exit status is 0 on success, or according to
|
||||
.Xr sysexits 3
|
||||
in case of failure.
|
||||
Diagnostic messages issued are supposed to be self-explanatory.
|
||||
.Sh SEE ALSO
|
||||
.Xr printf 3 ,
|
||||
.Xr sysexits 3 ,
|
||||
.Xr smb 4 ,
|
||||
.Xr smbus 4
|
||||
.Rs
|
||||
.%T "The SMBus specification"
|
||||
.%O http://www.smbus.org/specs/
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility and this manual page were written by
|
||||
.An J\(:org Wunsch .
|
339
usr.sbin/smbmsg/smbmsg.c
Normal file
339
usr.sbin/smbmsg/smbmsg.c
Normal file
@ -0,0 +1,339 @@
|
||||
/*-
|
||||
* Copyright (C) 2004 Joerg Wunsch
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send or receive messages over an SMBus.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <dev/smbus/smb.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
static const char *dev = PATH_DEFAULTSMBDEV;
|
||||
static const char *bytefmt = "0x%02x";
|
||||
static const char *wordfmt = "0x%04x";
|
||||
static const char *fmt;
|
||||
|
||||
static int fd; /* file descriptor for /dev/smbX */
|
||||
static int cflag = -1; /* SMBus cmd */
|
||||
static int iflag = -1; /* input data */
|
||||
static int oflag = -1; /* output data */
|
||||
static int pflag; /* probe bus */
|
||||
static int slave = -1; /* slave address */
|
||||
static int wflag; /* word IO */
|
||||
|
||||
static unsigned char ibuf[SMB_MAXBLOCKSIZE];
|
||||
static unsigned char obuf[SMB_MAXBLOCKSIZE];
|
||||
static unsigned short oword, iword;
|
||||
|
||||
/*
|
||||
* The I2C specs say that all addresses below 16 and above or equal
|
||||
* 240 are reserved. Address 0 is the global address, but we do not
|
||||
* care for this detail.
|
||||
*/
|
||||
#define MIN_I2C_ADDR 16
|
||||
#define MAX_I2C_ADDR 240
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: smbmsg [-f dev] -p\n"
|
||||
" smbmsg [-f dev] -s slave [-F fmt] [-c cmd] [-w] "
|
||||
"[-i incnt] [-o outcnt] [outdata ...]\n");
|
||||
exit (EX_USAGE);
|
||||
}
|
||||
|
||||
static int
|
||||
getnum(const char *s)
|
||||
{
|
||||
char *endp;
|
||||
unsigned long l;
|
||||
|
||||
l = strtoul(s, &endp, 0);
|
||||
if (*s != '\0' && *endp == '\0')
|
||||
return (int)l;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
probe_i2c(void)
|
||||
{
|
||||
unsigned char addr;
|
||||
int flags;
|
||||
#define IS_READABLE 1
|
||||
#define IS_WRITEABLE 2
|
||||
struct smbcmd c;
|
||||
|
||||
printf("Probing for devices on %s:\n", dev);
|
||||
|
||||
for (addr = MIN_I2C_ADDR; addr < MAX_I2C_ADDR; addr += 2) {
|
||||
c.slave = addr;
|
||||
flags = 0;
|
||||
if (ioctl(fd, SMB_RECVB, &c) != -1)
|
||||
flags = IS_READABLE;
|
||||
if (ioctl(fd, SMB_QUICK_WRITE, &c) != -1)
|
||||
flags |= IS_WRITEABLE;
|
||||
if (flags != 0) {
|
||||
printf("Device @0x%02x: ", addr);
|
||||
if (flags & IS_READABLE)
|
||||
putchar('r');
|
||||
if (flags & IS_WRITEABLE)
|
||||
putchar('w');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_io(void)
|
||||
{
|
||||
struct smbcmd c;
|
||||
int i;
|
||||
|
||||
c.slave = slave;
|
||||
c.cmd = cflag;
|
||||
|
||||
if (fmt == NULL && iflag > 0)
|
||||
fmt = wflag? wordfmt: bytefmt;
|
||||
|
||||
if (cflag == -1) {
|
||||
/* operations that do not require a command byte */
|
||||
if (iflag == -1 && oflag == 0)
|
||||
/* 0 bytes output: quick write operation */
|
||||
return (ioctl(fd, SMB_QUICK_WRITE, &c));
|
||||
else if (iflag == 0 && oflag == -1)
|
||||
/* 0 bytes input: quick read operation */
|
||||
return (ioctl(fd, SMB_QUICK_READ, &c));
|
||||
else if (iflag == 1 && oflag == -1) {
|
||||
/* no command, 1 byte input: receive byte op. */
|
||||
if (ioctl(fd, SMB_RECVB, &c) == -1)
|
||||
return (-1);
|
||||
printf(fmt, (unsigned char)c.cmd);
|
||||
putchar('\n');
|
||||
return (0);
|
||||
} else if (iflag == -1 && oflag == 1) {
|
||||
/* no command, 1 byte output: send byte op. */
|
||||
c.cmd = obuf[0];
|
||||
return (ioctl(fd, SMB_SENDB, &c));
|
||||
} else
|
||||
return (-2);
|
||||
}
|
||||
if (iflag == 1 && oflag == -1) {
|
||||
/* command + 1 byte input: read byte op. */
|
||||
c.data.byte_ptr = ibuf;
|
||||
if (ioctl(fd, SMB_READB, &c) == -1)
|
||||
return (-1);
|
||||
printf(fmt, (int)(unsigned char)ibuf[0]);
|
||||
putchar('\n');
|
||||
return (0);
|
||||
} else if (iflag == -1 && oflag == 1) {
|
||||
/* command + 1 byte output: write byte op. */
|
||||
c.data.byte = obuf[0];
|
||||
return (ioctl(fd, SMB_WRITEB, &c));
|
||||
} else if (wflag && iflag == 2 && oflag == -1) {
|
||||
/* command + 2 bytes input: read word op. */
|
||||
c.data.word_ptr = &iword;
|
||||
if (ioctl(fd, SMB_READW, &c) == -1)
|
||||
return (-1);
|
||||
printf(fmt, (int)(unsigned short)iword);
|
||||
putchar('\n');
|
||||
return (0);
|
||||
} else if (wflag && iflag == -1 && oflag == 2) {
|
||||
/* command + 2 bytes output: write word op. */
|
||||
c.data.word = oword;
|
||||
return (ioctl(fd, SMB_WRITEW, &c));
|
||||
} else if (wflag && iflag == 2 && oflag == 2) {
|
||||
/*
|
||||
* command + 2 bytes output + 2 bytes input:
|
||||
* "process call" op.
|
||||
*/
|
||||
c.data.process.sdata = oword;
|
||||
c.data.process.rdata = &iword;
|
||||
if (ioctl(fd, SMB_PCALL, &c) == -1)
|
||||
return (-1);
|
||||
printf(fmt, (int)(unsigned short)iword);
|
||||
putchar('\n');
|
||||
return (0);
|
||||
} else if (iflag > 1 && oflag == -1) {
|
||||
/* command + > 1 bytes of input: block read */
|
||||
c.data.byte_ptr = ibuf;
|
||||
c.count = iflag;
|
||||
if (ioctl(fd, SMB_BREAD, &c) == -1)
|
||||
return (-1);
|
||||
for (i = 0; i < iflag; i++) {
|
||||
if (i != 0)
|
||||
putchar(' ');
|
||||
printf(fmt, ibuf[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
return (0);
|
||||
} else if (iflag == -1 && oflag > 1) {
|
||||
/* command + > 1 bytes of output: block write */
|
||||
c.data.byte_ptr = obuf;
|
||||
c.count = oflag;
|
||||
return (ioctl(fd, SMB_BWRITE, &c));
|
||||
}
|
||||
|
||||
return (-2);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i, n, errs = 0;
|
||||
int savederrno;
|
||||
|
||||
while ((i = getopt(argc, argv, "F:c:f:i:o:ps:w")) != -1)
|
||||
switch (i) {
|
||||
case 'F':
|
||||
fmt = optarg;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if ((cflag = getnum(optarg)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", optarg);
|
||||
if (cflag < 0 || cflag >= 256)
|
||||
errx(EX_USAGE,
|
||||
"CMD out of range: %d",
|
||||
cflag);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
dev = optarg;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if ((iflag = getnum(optarg)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", optarg);
|
||||
if (iflag < 0 || iflag >= SMB_MAXBLOCKSIZE)
|
||||
errx(EX_USAGE,
|
||||
"# input bytes out of range: %d",
|
||||
iflag);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if ((oflag = getnum(optarg)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", optarg);
|
||||
if (oflag < 0 || oflag >= SMB_MAXBLOCKSIZE)
|
||||
errx(EX_USAGE,
|
||||
"# output bytes out of range: %d",
|
||||
oflag);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if ((slave = getnum(optarg)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", optarg);
|
||||
|
||||
if (slave < MIN_I2C_ADDR || slave >= MAX_I2C_ADDR)
|
||||
errx(EX_USAGE,
|
||||
"Slave address out of range: %d",
|
||||
slave);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
errs++;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (errs || (slave != -1 && pflag) || (slave == -1 && !pflag))
|
||||
usage();
|
||||
if (wflag &&
|
||||
!((iflag == 2 && oflag == -1) ||
|
||||
(iflag == -1 && oflag == 2) ||
|
||||
(iflag == 2 && oflag == 2)))
|
||||
errx(EX_USAGE, "Illegal # IO bytes for word IO");
|
||||
if (!pflag && iflag == -1 && oflag == -1)
|
||||
errx(EX_USAGE, "Nothing to do");
|
||||
if (pflag && (cflag != -1 || iflag != -1 || oflag != -1 || wflag != 0))
|
||||
usage();
|
||||
if (oflag > 0) {
|
||||
if (oflag == 2 && wflag) {
|
||||
if (argc == 0)
|
||||
errx(EX_USAGE, "Too few arguments for -o count");
|
||||
if ((n = getnum(*argv)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", *argv);
|
||||
if (n < 0 || n >= 65535)
|
||||
errx(EX_USAGE, "Value out of range: %d", n);
|
||||
oword = n;
|
||||
argc--;
|
||||
argv++;
|
||||
} else for (i = 0; i < oflag; i++, argv++, argc--) {
|
||||
if (argc == 0)
|
||||
errx(EX_USAGE, "Too few arguments for -o count");
|
||||
if ((n = getnum(*argv)) == -1)
|
||||
errx(EX_USAGE, "Invalid number: %s", *argv);
|
||||
if (n < 0 || n >= 256)
|
||||
errx(EX_USAGE, "Value out of range: %d", n);
|
||||
obuf[i] = n;
|
||||
}
|
||||
}
|
||||
if (argc != 0)
|
||||
usage();
|
||||
|
||||
if ((fd = open(dev, O_RDWR)) == -1)
|
||||
err(EX_UNAVAILABLE, "Cannot open %s", dev);
|
||||
|
||||
i = 0;
|
||||
if (pflag)
|
||||
probe_i2c();
|
||||
else
|
||||
i = do_io();
|
||||
|
||||
savederrno = errno;
|
||||
close(fd);
|
||||
errno = savederrno;
|
||||
|
||||
if (i == -1)
|
||||
err(EX_UNAVAILABLE, "Error performing SMBus IO");
|
||||
else if (i == -2)
|
||||
errx(EX_USAGE, "Invalid option combination");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user