tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Adding pulse support to gpio(4), gpioctl(8)
> The attached diff adds the ability to pulse a pin with a set frequency
> and duty cycle. A new gpio(4) ioctl, "GPIOPULSE", and a new gpioctl(8)
> command line option "pulse" are added.
>
> Whereas the gpioctl(8) command line utility accepts the freqeuncy in
> hertz and the duty cycle in percent, these values are converted to two
> "struct timeval"s for the ioctl call. gpio(4) accepts an "on" and "off"
> period as "struct timeval" which are then converted to ticks using
> tvtohz(9).
>
> The pulsing in software is realised using callout(9)s, if the underlying
> hardware signals that it can pulse the pin in hardware, the pin is just
> set to GPIO_PIN_HIGH and no callouts are used. There is no way at the
> moment to program the "on" and "off" periods for pins that pulse in
> hardware (implementing that is left as an exercise to the reader...)
Find attached revised version that uses only one callout and clears
pending callouts on device detach. I also removed a few superflous
tests, as noticed by rmind.
If you have any GPIO drivers as modules, e.g. gpiosim(4), make sure to
rebuild them as internal data structures have changed. I can tell from
experience^Wpain that failing to do so leads to panics...
Comments?
Index: sys/sys/gpio.h
===================================================================
RCS file: /cvsroot/src/sys/sys/gpio.h,v
retrieving revision 1.8
diff -u -p -r1.8 gpio.h
--- sys/sys/gpio.h 23 Jun 2011 00:46:37 -0000 1.8
+++ sys/sys/gpio.h 21 Aug 2011 13:28:36 -0000
@@ -20,9 +20,12 @@
#ifndef _SYS_GPIO_H_
#define _SYS_GPIO_H_
+#include <sys/time.h>
+
/* GPIO pin states */
#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */
#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */
+#define GPIO_PIN_PULSE 0x02 /* pulsing, or-ed with state */
/* Max name length of a pin */
#define GPIOMAXNAME 64
@@ -51,25 +54,33 @@ struct gpio_info {
/* GPIO pin request (read/write/toggle) */
struct gpio_req {
- char gp_name[GPIOMAXNAME]; /* pin name */
- int gp_pin; /* pin number */
- int gp_value; /* value */
+ char gp_name[GPIOMAXNAME]; /* pin name */
+ int gp_pin; /* pin number */
+ int gp_value; /* value */
+};
+
+/* GPIO pulse request */
+struct gpio_pulse {
+ char gp_name[GPIOMAXNAME]; /* pin name */
+ int gp_pin; /* pin number */
+ struct timeval gp_pulse_on; /* "on" period */
+ struct timeval gp_pulse_off; /* "off" period */
};
/* GPIO pin configuration */
struct gpio_set {
- char gp_name[GPIOMAXNAME];
- int gp_pin;
- int gp_caps;
- int gp_flags;
- char gp_name2[GPIOMAXNAME]; /* new name */
+ char gp_name[GPIOMAXNAME];
+ int gp_pin;
+ int gp_caps;
+ int gp_flags;
+ char gp_name2[GPIOMAXNAME]; /* new name */
};
/* Attach/detach device drivers that use GPIO pins */
struct gpio_attach {
- char ga_dvname[16]; /* device name */
- int ga_offset; /* pin number */
- u_int32_t ga_mask; /* binary mask */
+ char ga_dvname[16]; /* device name */
+ int ga_offset; /* pin number */
+ u_int32_t ga_mask; /* binary mask */
};
/* GPIO pin control (old API) */
@@ -81,8 +92,8 @@ struct gpio_pin_ctl {
/* GPIO pin operation (read/write/toggle) (old API) */
struct gpio_pin_op {
- int gp_pin; /* pin number */
- int gp_value; /* value */
+ int gp_pin; /* pin number */
+ int gp_value; /* value */
};
#define GPIOINFO _IOR('G', 0, struct gpio_info)
@@ -101,5 +112,6 @@ struct gpio_pin_op {
#define GPIOTOGGLE _IOWR('G', 9, struct gpio_req)
#define GPIOATTACH _IOWR('G', 10, struct gpio_attach)
#define GPIODETACH _IOWR('G', 11, struct gpio_attach)
+#define GPIOPULSE _IOWR('G', 12, struct gpio_pulse)
#endif /* !_SYS_GPIO_H_ */
Index: sys/dev/gpio/gpiovar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpiovar.h,v
retrieving revision 1.11
diff -u -p -r1.11 gpiovar.h
--- sys/dev/gpio/gpiovar.h 12 Aug 2011 08:00:52 -0000 1.11
+++ sys/dev/gpio/gpiovar.h 21 Aug 2011 13:28:36 -0000
@@ -35,18 +35,22 @@ typedef struct gpio_chipset_tag {
/* GPIO pin description */
typedef struct gpio_pin {
- int pin_num; /* number */
- int pin_caps; /* capabilities */
- int pin_flags; /* current configuration */
- int pin_state; /* current state */
- int pin_mapped; /* is mapped */
+ int pin_num; /* number */
+ int pin_caps; /* capabilities */
+ int pin_flags; /* current configuration */
+ int pin_state; /* current state */
+ int pin_mapped; /* is mapped */
+ callout_t pin_pulse; /* for pulsing */
+ int pin_ticks_on; /* "on" period */
+ int pin_ticks_off; /* "off" period */
+ gpio_chipset_tag_t pin_gc; /* reference the controller */
} gpio_pin_t;
/* Attach GPIO framework to the controller */
struct gpiobus_attach_args {
- gpio_chipset_tag_t gba_gc; /* underlying controller */
+ gpio_chipset_tag_t gba_gc; /* underlying controller */
gpio_pin_t *gba_pins; /* pins array */
- int gba_npins; /* total number of pins */
+ int gba_npins; /* total number of pins */
};
int gpiobus_print(void *, const char *);
Index: sys/dev/gpio/gpio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpio.c,v
retrieving revision 1.35
diff -u -p -r1.35 gpio.c
--- sys/dev/gpio/gpio.c 12 Aug 2011 08:00:52 -0000 1.35
+++ sys/dev/gpio/gpio.c 21 Aug 2011 13:28:37 -0000
@@ -26,12 +26,14 @@ __KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.3
*/
#include <sys/param.h>
+#include <sys/callout.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/gpio.h>
+#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/kmem.h>
#include <sys/queue.h>
@@ -73,6 +75,7 @@ static int gpio_detach(device_t, int);
static int gpio_search(device_t, cfdata_t, const int *, void *);
static int gpio_print(void *, const char *);
static int gpio_pinbyname(struct gpio_softc *, char *);
+static void gpio_pulse(void *);
/* Old API */
static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int,
@@ -165,7 +168,17 @@ gpio_attach(device_t parent, device_t se
static int
gpio_detach(device_t self, int flags)
{
- int rc;
+ struct gpio_softc *sc;
+ int pin, rc;
+
+ sc = device_private(self);
+
+ for (pin = 0; pin < sc->sc_npins; pin++)
+ if (sc->sc_pins[pin].pin_state & GPIO_PIN_PULSE) {
+ callout_stop(&sc->sc_pins[pin].pin_pulse);
+ callout_destroy(&sc->sc_pins[pin].pin_pulse);
+ sc->sc_pins[pin].pin_state &= ~GPIO_PIN_PULSE;
+ }
if ((rc = config_detach_children(self, flags)) != 0)
return rc;
@@ -382,6 +395,26 @@ gpio_pinbyname(struct gpio_softc *sc, ch
return -1;
}
+static void
+gpio_pulse(void *arg)
+{
+ struct gpio_pin *pin;
+
+ pin = (struct gpio_pin *)arg;
+ if ((pin->pin_state & GPIO_PIN_PULSE) == 0)
+ return;
+
+ if (pin->pin_state & GPIO_PIN_HIGH) {
+ gpiobus_pin_write(pin->pin_gc, pin->pin_num, GPIO_PIN_LOW);
+ pin->pin_state &= ~GPIO_PIN_HIGH;
+ callout_schedule(&pin->pin_pulse, pin->pin_ticks_off);
+ } else {
+ gpiobus_pin_write(pin->pin_gc, pin->pin_num, GPIO_PIN_HIGH);
+ pin->pin_state |= GPIO_PIN_HIGH;
+ callout_schedule(&pin->pin_pulse, pin->pin_ticks_on);
+ }
+}
+
int
gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
@@ -392,6 +425,7 @@ gpioioctl(dev_t dev, u_long cmd, void *d
struct gpio_attach_args ga;
struct gpio_dev *gdev;
struct gpio_req *req;
+ struct gpio_pulse *pulse;
struct gpio_name *nm;
struct gpio_set *set;
device_t dv;
@@ -427,11 +461,9 @@ gpioioctl(dev_t dev, u_long cmd, void *d
case GPIOREAD:
req = (struct gpio_req *)data;
- if (req->gp_name[0] != '\0') {
+ if (req->gp_name[0] != '\0')
pin = gpio_pinbyname(sc, req->gp_name);
- if (pin == -1)
- return EINVAL;
- } else
+ else
pin = req->gp_pin;
if (pin < 0 || pin >= sc->sc_npins)
@@ -451,11 +483,9 @@ gpioioctl(dev_t dev, u_long cmd, void *d
req = (struct gpio_req *)data;
- if (req->gp_name[0] != '\0') {
+ if (req->gp_name[0] != '\0')
pin = gpio_pinbyname(sc, req->gp_name);
- if (pin == -1)
- return EINVAL;
- } else
+ else
pin = req->gp_pin;
if (pin < 0 || pin >= sc->sc_npins)
@@ -473,23 +503,75 @@ gpioioctl(dev_t dev, u_long cmd, void *d
if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
return EINVAL;
+ if (sc->sc_pins[pin].pin_state & GPIO_PIN_PULSE) {
+ callout_stop(&sc->sc_pins[pin].pin_pulse);
+ callout_destroy(&sc->sc_pins[pin].pin_pulse);
+ sc->sc_pins[pin].pin_state &= ~GPIO_PIN_PULSE;
+ }
gpiobus_pin_write(gc, pin, value);
/* return old value */
req->gp_value = sc->sc_pins[pin].pin_state;
/* update current value */
sc->sc_pins[pin].pin_state = value;
break;
+ case GPIOPULSE:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+
+ pulse = (struct gpio_pulse *)data;
+
+ if (pulse->gp_name[0] != '\0')
+ pin = gpio_pinbyname(sc, pulse->gp_name);
+ else
+ pin = pulse->gp_pin;
+
+ if (pin < 0 || pin >= sc->sc_npins)
+ return EINVAL;
+
+ if (sc->sc_pins[pin].pin_mapped)
+ return EBUSY;
+
+ if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
+ kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
+ NULL, NULL, NULL, NULL))
+ return EPERM;
+
+ if (sc->sc_pins[pin].pin_flags & GPIO_PIN_PULSATE) {
+ gpiobus_pin_write(gc, pin, GPIO_PIN_HIGH);
+ sc->sc_pins[pin].pin_state = GPIO_PIN_PULSE;
+ return 0;
+ }
+
+ if (sc->sc_pins[pin].pin_state & GPIO_PIN_PULSE) {
+ callout_stop(&sc->sc_pins[pin].pin_pulse);
+ callout_destroy(&sc->sc_pins[pin].pin_pulse);
+ }
+ sc->sc_pins[pin].pin_gc = gc;
+ callout_init(&sc->sc_pins[pin].pin_pulse, 0);
+
+ sc->sc_pins[pin].pin_ticks_on = tvtohz(&pulse->gp_pulse_on);
+ sc->sc_pins[pin].pin_ticks_off = tvtohz(&pulse->gp_pulse_off);
+ if (sc->sc_pins[pin].pin_ticks_on == 0
+ || sc->sc_pins[pin].pin_ticks_off == 0) {
+ sc->sc_pins[pin].pin_ticks_on = hz / 2;
+ sc->sc_pins[pin].pin_ticks_off = hz / 2;
+ }
+ callout_setfunc(&sc->sc_pins[pin].pin_pulse, gpio_pulse,
+ &sc->sc_pins[pin]);
+ gpiobus_pin_write(gc, pin, GPIO_PIN_HIGH);
+ sc->sc_pins[pin].pin_state = GPIO_PIN_HIGH | GPIO_PIN_PULSE;
+ callout_schedule(&sc->sc_pins[pin].pin_pulse,
+ sc->sc_pins[pin].pin_ticks_on);
+ break;
case GPIOTOGGLE:
if ((flag & FWRITE) == 0)
return EBADF;
req = (struct gpio_req *)data;
- if (req->gp_name[0] != '\0') {
+ if (req->gp_name[0] != '\0')
pin = gpio_pinbyname(sc, req->gp_name);
- if (pin == -1)
- return EINVAL;
- } else
+ else
pin = req->gp_pin;
if (pin < 0 || pin >= sc->sc_npins)
@@ -574,12 +656,11 @@ gpioioctl(dev_t dev, u_long cmd, void *d
set = (struct gpio_set *)data;
- if (set->gp_name[0] != '\0') {
+ if (set->gp_name[0] != '\0')
pin = gpio_pinbyname(sc, set->gp_name);
- if (pin == -1)
- return EINVAL;
- } else
+ else
pin = set->gp_pin;
+
if (pin < 0 || pin >= sc->sc_npins)
return EINVAL;
flags = set->gp_flags;
@@ -629,11 +710,9 @@ gpioioctl(dev_t dev, u_long cmd, void *d
return EPERM;
set = (struct gpio_set *)data;
- if (set->gp_name[0] != '\0') {
+ if (set->gp_name[0] != '\0')
pin = gpio_pinbyname(sc, set->gp_name);
- if (pin == -1)
- return EINVAL;
- } else
+ else
pin = set->gp_pin;
if (pin < 0 || pin >= sc->sc_npins)
Index: share/man/man4/gpio.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/gpio.4,v
retrieving revision 1.18
diff -u -p -r1.18 gpio.4
--- share/man/man4/gpio.4 22 Mar 2010 18:58:31 -0000 1.18
+++ share/man/man4/gpio.4 21 Aug 2011 13:28:37 -0000
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd September 27, 2009
+.Dd August 21, 2011
.Dt GPIO 4
.Os
.Sh NAME
@@ -123,6 +123,31 @@ Toggles the pin output value, i.e. chang
.Fa gp_value
field is ignored and on return contains the old pin state.
.Pp
+.It Dv GPIOPULSE (struct gpio_pulse)
+Starts pulsing the pin:
+.Bd -literal
+/* GPIO pulse request */
+struct gpio_pulse {
+ char gp_name[GPIOMAXNAME]; /* pin name */
+ int gp_pin; /* pin number */
+ struct timeval gp_pulse_on; /* "on" period */
+ struct timeval gp_pulse_off; /* "off" period */
+};
+.Ed
+.Pp
+The
+.Fa gp_name
+or
+.Fa gp_pin
+field must be set before calling.
+If
+.Fa gp_pulse_on
+or
+.Fa gp_pulse_off
+is set to zero, a default of
+.Xr hz 9 / 2
+is assumed for both periods.
+.Pp
.It Dv GPIOSET (struct gpio_set)
Changes pin configuration flags with the new ones provided in the
.Fa gpio_set
Index: usr.sbin/gpioctl/gpioctl.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/gpioctl/gpioctl.8,v
retrieving revision 1.8
diff -u -p -r1.8 gpioctl.8
--- usr.sbin/gpioctl/gpioctl.8 12 Aug 2011 08:02:33 -0000 1.8
+++ usr.sbin/gpioctl/gpioctl.8 21 Aug 2011 13:28:37 -0000
@@ -1,6 +1,6 @@
.\" $NetBSD: gpioctl.8,v 1.8 2011/08/12 08:02:33 mbalmer Exp $
.\"
-.\" Copyright (c) 2009, 2010 Marc Balmer <marc%msys.ch@localhost>
+.\" Copyright (c) 2009, 2010, 2011 Marc Balmer <marc%msys.ch@localhost>
.\" Copyright (c) 2004 Alexander Yurchenko <grange%openbsd.org@localhost>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd September 25, 2009
+.Dd August 21, 2011
.Dt GPIOCTL 8
.Os
.Sh NAME
@@ -48,6 +48,12 @@ detach
.Op Fl q
.Ar device
.Ar pin
+pulse
+.Op Ar frequency Op Ar duty cycle
+.Nm gpioctl
+.Op Fl q
+.Ar device
+.Ar pin
set
.Op Ar flags
.Op Ar name
@@ -92,7 +98,7 @@ To write to a pin, a value must be speci
.Ar pin
number.
Values can be either 0 or 1.
-A value of 2 has a special meaning: it
+A value of 2
.Dq toggles
the pin, i.e. changes its state to the opposite.
Instead of the numerical values, the word
@@ -102,6 +108,19 @@ or
.Ar toggle
can be used.
.Pp
+To
+.Dq pulse
+a pin, use the pulse command line option with an optional frequency value
+in hertz and an optional duty cycle in percent.
+If no frequency is specified, 1 Hz is assumed.
+If no duty cycle is specified, 50% are assumed.
+If the underlying hardware is not capable of pulsing in hardware,
+pulsing is done in software using the
+.Xr callout 9
+facility.
+The frequency and duty cycle arguments are ignored for pins that are able to
+pulse in hardware.
+.Pp
Only pins that have been configured at securelevel 0, typically during system
startup, are accessible once the securelevel has been raised.
Pins can be given symbolic names for easier use.
@@ -207,5 +226,5 @@ The
.Nm
program was written by
.An Alexander Yurchenko Aq grange%openbsd.org@localhost .
-Device attachment was added by
+Device attachment and pulsing was added by
.An Marc Balmer Aq marc%msys.ch@localhost .
Index: usr.sbin/gpioctl/gpioctl.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/gpioctl/gpioctl.c,v
retrieving revision 1.10
diff -u -p -r1.10 gpioctl.c
--- usr.sbin/gpioctl/gpioctl.c 12 Aug 2011 08:06:23 -0000 1.10
+++ usr.sbin/gpioctl/gpioctl.c 21 Aug 2011 13:28:37 -0000
@@ -32,6 +32,7 @@
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <string.h>
#include <unistd.h>
@@ -43,6 +44,7 @@ int quiet = 0;
static void getinfo(void);
static void gpioread(int, char *);
static void gpiowrite(int, char *, int);
+static void gpiopulse(int, char *, double, double);
static void gpioset(int pin, char *name, int flags, char *alias);
static void gpiounset(int pin, char *name);
static void devattach(char *, int, u_int32_t);
@@ -74,6 +76,7 @@ int
main(int argc, char *argv[])
{
const struct bitstr *bs;
+ double freq, dc;
int pin, ch, n, fl = 0, value = 0;
const char *errstr;
char *ep;
@@ -99,6 +102,8 @@ main(int argc, char *argv[])
usage();
dev = argv[0];
+ freq = dc = 0.0;
+
if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
(void)snprintf(devn, sizeof(devn), "%s%s", _PATH_DEV, dev);
dev = devn;
@@ -140,12 +145,12 @@ main(int argc, char *argv[])
devdetach(argv[2]);
} else {
char *nm = NULL;
-
+
/* expecting a pin number or name */
pin = strtonum(argv[1], 0, INT_MAX, &errstr);
if (errstr)
nm = argv[1]; /* try named pin */
- if (argc > 2) {
+ if (argc > 2) {
if (!strcmp(argv[2], "set")) {
for (n = 3; n < argc; n++) {
for (bs = pinflags; bs->string != NULL;
@@ -162,14 +167,24 @@ main(int argc, char *argv[])
gpioset(pin, nm, fl, nam);
} else if (!strcmp(argv[2], "unset")) {
gpiounset(pin, nm);
+ } else if (!strcmp(argv[2], "pulse")) {
+ if (argc == 4) {
+ freq = atof(argv[3]);
+ dc = 50.0;
+ } else if (argc == 5) {
+ freq = atof(argv[3]);
+ dc = atof(argv[4]);
+ } else
+ freq = dc = 0.0;
+ gpiopulse(pin, nm, freq, dc);
} else {
value = strtonum(argv[2], INT_MIN, INT_MAX,
&errstr);
if (errstr) {
if (!strcmp(argv[2], "on"))
- value = 1;
+ value = GPIO_PIN_HIGH;
else if (!strcmp(argv[2], "off"))
- value = 0;
+ value = GPIO_PIN_LOW;
else if (!strcmp(argv[2], "toggle"))
value = 2;
else
@@ -236,8 +251,9 @@ gpiowrite(int pin, char *gp_name, int va
strlcpy(req.gp_name, gp_name, sizeof(req.gp_name));
else
req.gp_pin = pin;
- req.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH);
- if (value < 2) {
+
+ if (value == GPIO_PIN_HIGH || value == GPIO_PIN_LOW) {
+ req.gp_value = value;
if (ioctl(devfd, GPIOWRITE, &req) == -1)
err(EXIT_FAILURE, "GPIOWRITE");
} else {
@@ -257,6 +273,62 @@ gpiowrite(int pin, char *gp_name, int va
}
static void
+gpiopulse(int pin, char *gp_name, double freq, double dc)
+{
+ struct gpio_pulse pulse;
+ suseconds_t period, on, off;
+
+ if (freq < 0.0 || (dc < 0.0 || dc >= 100.0))
+ errx(EXIT_FAILURE, "%.f Hz, %.f%% duty cycle: invalid value",
+ freq, dc);
+
+ memset(&pulse, 0, sizeof(pulse));
+ if (gp_name != NULL)
+ strlcpy(pulse.gp_name, gp_name, sizeof(pulse.gp_name));
+ else
+ pulse.gp_pin = pin;
+
+ if (freq > 0.0 && dc > 0.0) {
+ period = 1000000 / freq;
+ on = period * dc / 100;
+ off = period - on;
+
+ if (on >= 1000000) {
+ pulse.gp_pulse_on.tv_sec = on / 1000000;
+ on -= pulse.gp_pulse_on.tv_sec * 1000000;
+ pulse.gp_pulse_on.tv_usec = on;
+ } else {
+ pulse.gp_pulse_on.tv_sec = 0;
+ pulse.gp_pulse_on.tv_usec = on;
+ }
+ if (off >= 1000000) {
+ pulse.gp_pulse_off.tv_sec = off / 1000000;
+ off -= pulse.gp_pulse_off.tv_sec * 1000000;
+ pulse.gp_pulse_off.tv_usec = off;
+ } else {
+ pulse.gp_pulse_off.tv_sec = 0;
+ pulse.gp_pulse_off.tv_usec = off;
+ }
+ } else { /* gpio(4) defaults */
+ freq = 1.0;
+ dc = 50.0;
+ }
+
+ if (ioctl(devfd, GPIOPULSE, &pulse) == -1)
+ err(EXIT_FAILURE, "GPIOPULSE");
+
+ if (quiet)
+ return;
+
+ if (gp_name)
+ printf("pin %s: pulse at %.f Hz with a %.f%% duty cylce\n",
+ gp_name, freq, dc);
+ else
+ printf("pin %d: pulse at %.f Hz with a %.f%% duty cylce\n",
+ pin, freq, dc);
+}
+
+static void
gpioset(int pin, char *name, int fl, char *alias)
{
struct gpio_set set;
@@ -345,6 +417,8 @@ usage(void)
progname = getprogname();
fprintf(stderr, "usage: %s [-q] device [pin] [0 | 1 | 2 | "
"on | off | toggle]\n", progname);
+ fprintf(stderr, "usage: %s [-q] device pin pulse [frequency "
+ "[duty cycle]]\n", progname);
fprintf(stderr, " %s [-q] device pin set [flags] [name]\n",
progname);
fprintf(stderr, " %s [-q] device pin unset\n", progname);
Home |
Main Index |
Thread Index |
Old Index