Module Name: src Committed By: mbalmer Date: Sun Oct 2 09:33:19 UTC 2011
Modified Files: src/share/man/man4: gpio.4 gpioiic.4 src/sys/dev/gpio: gpio.c gpioiic.c gpiovar.h src/sys/sys: gpio.h src/usr.sbin/gpioctl: gpioctl.8 gpioctl.c Log Message: Add a ga_flags field to the gpio_attach structure to hand driver specific flags to drivers being attached at gpio pins. gpioiic(4) uses this to reverse the SDA/SCL signal order. gpioctl(8) accepts the flag values as optional argument to the attach command. While here, make sure we retain backwards compatability and wrap compat code in #ifdef COMPAT_50/#endif. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/share/man/man4/gpio.4 cvs rdiff -u -r1.2 -r1.3 src/share/man/man4/gpioiic.4 cvs rdiff -u -r1.41 -r1.42 src/sys/dev/gpio/gpio.c cvs rdiff -u -r1.4 -r1.5 src/sys/dev/gpio/gpioiic.c cvs rdiff -u -r1.13 -r1.14 src/sys/dev/gpio/gpiovar.h cvs rdiff -u -r1.9 -r1.10 src/sys/sys/gpio.h cvs rdiff -u -r1.10 -r1.11 src/usr.sbin/gpioctl/gpioctl.8 cvs rdiff -u -r1.13 -r1.14 src/usr.sbin/gpioctl/gpioctl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/gpio.4 diff -u src/share/man/man4/gpio.4:1.19 src/share/man/man4/gpio.4:1.20 --- src/share/man/man4/gpio.4:1.19 Sun Aug 28 07:48:50 2011 +++ src/share/man/man4/gpio.4 Sun Oct 2 09:33:18 2011 @@ -1,4 +1,4 @@ -.\" $NetBSD: gpio.4,v 1.19 2011/08/28 07:48:50 mbalmer Exp $ +.\" $NetBSD: gpio.4,v 1.20 2011/10/02 09:33:18 mbalmer Exp $ .\" $OpenBSD: gpio.4,v 1.5 2004/11/23 09:39:29 reyk Exp $ .\" .\" Copyright (c) 2004 Alexander Yurchenko <gra...@openbsd.org> @@ -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 August 21, 2011 +.Dd October 2, 2011 .Dt GPIO 4 .Os .Sh NAME @@ -216,18 +216,19 @@ structure on this gpio device. struct gpio_attach { char ga_dvname[16]; /* device name */ int ga_offset; /* pin number */ - u_int32_t ga_mask; /* binary mask */ + uint32_t ga_mask; /* binary mask */ + uint32_t ga_flags; /* driver dependent */ }; .Ed -.Pp .It Dv GPIODETACH (struct gpio_attach) Detach a device from this gpio device that was previously attached using the .Dv GPIOATTACH .Xr ioctl 2 . The -.Fa ga_offset +.Fa ga_offset , +.Fa ga_mask , and -.Fa ga_mask +.Fa ga_flags fields of the .Fa gpio_attach structure are ignored. Index: src/share/man/man4/gpioiic.4 diff -u src/share/man/man4/gpioiic.4:1.2 src/share/man/man4/gpioiic.4:1.3 --- src/share/man/man4/gpioiic.4:1.2 Sun Aug 9 08:44:30 2009 +++ src/share/man/man4/gpioiic.4 Sun Oct 2 09:33:18 2011 @@ -1,4 +1,4 @@ -.\" $NetBSD: gpioiic.4,v 1.2 2009/08/09 08:44:30 wiz Exp $ +.\" $NetBSD: gpioiic.4,v 1.3 2011/10/02 09:33:18 mbalmer Exp $ .\" $OpenBSD: gpioiic.4,v 1.6 2008/11/24 15:30:21 jmc Exp $ .\" .\" Copyright (c) 2006 Alexander Yurchenko <gra...@openbsd.org> @@ -15,22 +15,24 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd August 8, 2009 +.Dd October 2, 2011 .Dt GPIOIIC 4 .Os .Sh NAME .Nm gpioiic .Nd GPIO I2C controller .Sh SYNOPSIS -.Cd "gpioiic* at gpio? offset 0 mask 0x3" +.Cd "gpioiic* at gpio? offset 0 mask 0x3 flags 0x0" .Cd "gpioiic* at gpio?" .Cd "iic* at gpioiic?" .Sh DESCRIPTION The .Nm driver allows bit-banging an I2C bus as a master using two GPIO pins. -The first pin is used as a serial data (SDA) signal and the second as -a serial clock (SCL). +By default the first pin is used as a serial data (SDA) signal and the +second as a serial clock (SCL). +If the flags locator is set to 0x01, the order of the SDA and SCL signals +is reversed. Both GPIO pins must be able to drive an output and the SDA pin must be also able to read an input. .Pp Index: src/sys/dev/gpio/gpio.c diff -u src/sys/dev/gpio/gpio.c:1.41 src/sys/dev/gpio/gpio.c:1.42 --- src/sys/dev/gpio/gpio.c:1.41 Fri Sep 2 06:50:20 2011 +++ src/sys/dev/gpio/gpio.c Sun Oct 2 09:33:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: gpio.c,v 1.41 2011/09/02 06:50:20 mbalmer Exp $ */ +/* $NetBSD: gpio.c,v 1.42 2011/10/02 09:33:19 mbalmer Exp $ */ /* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */ /* @@ -19,7 +19,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.41 2011/09/02 06:50:20 mbalmer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.42 2011/10/02 09:33:19 mbalmer Exp $"); /* * General Purpose Input/Output framework. @@ -83,9 +83,11 @@ static void gpio_pulse(void *); static int gpio_ioctl(struct gpio_softc *, u_long, void *, int, struct lwp *); +#ifdef COMPAT_50 /* Old API */ static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int, kauth_cred_t); +#endif CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc), gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan, @@ -255,6 +257,7 @@ gpio_search(device_t parent, cfdata_t cf ga.ga_gpio = aux; ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET]; ga.ga_mask = cf->cf_loc[GPIOCF_MASK]; + ga.ga_flags = cf->cf_loc[GPIOCF_FLAG]; if (config_match(parent, cf, &ga) > 0) config_attach(parent, cf, &ga, gpio_print); @@ -516,6 +519,7 @@ gpio_ioctl(struct gpio_softc *sc, u_long int error, pin, value, flags, npins; gc = sc->sc_gc; + ga.ga_flags = 0; if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) { DPRINTF(("%s: device is not active\n", @@ -667,12 +671,24 @@ gpio_ioctl(struct gpio_softc *sc, u_long sc->sc_pins[pin].pin_state = value; break; case GPIOATTACH: + attach = (struct gpio_attach *)data; + ga.ga_flags = attach->ga_flags; +#ifdef COMPAT_50 + /* FALLTHROUGH */ + case GPIOATTACH50: + /* + * The double assignment to 'attach' in case of GPIOATTACH + * and COMPAT_50 is on purpose. It ensures backward + * compatability in case we are called through the old + * GPIOATTACH50 ioctl(2), which had not the ga_flags field + * in struct gpio_attach. + */ + attach = (struct gpio_attach *)data; +#endif if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) return EPERM; - attach = (struct gpio_attach *)data; - /* do not try to attach if the pins are already mapped */ if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask)) return EBUSY; @@ -691,15 +707,17 @@ gpio_ioctl(struct gpio_softc *sc, u_long return EBUSY; ga.ga_gpio = sc; + /* Don't access attach->ga_flags here. */ ga.ga_dvname = attach->ga_dvname; ga.ga_offset = attach->ga_offset; ga.ga_mask = attach->ga_mask; - DPRINTF(("%s: attach %s with offset %d and mask " - "0x%02x\n", device_xname(sc->sc_dev), ga.ga_dvname, - ga.ga_offset, ga.ga_mask)); + DPRINTF(("%s: attach %s with offset %d, mask " + "0x%02x, and flags 0x%02x\n", device_xname(sc->sc_dev), + ga.ga_dvname, ga.ga_offset, ga.ga_mask, ga.ga_flags)); locs[GPIOCF_OFFSET] = ga.ga_offset; locs[GPIOCF_MASK] = ga.ga_mask; + locs[GPIOCF_FLAG] = ga.ga_flags; cf = config_search_loc(NULL, sc->sc_dev, "gpio", locs, &ga); if (cf != NULL) { @@ -719,6 +737,10 @@ gpio_ioctl(struct gpio_softc *sc, u_long cv_signal(&sc->sc_attach); mutex_exit(&sc->sc_mtx); return error; +#ifdef COMPAT_50 + case GPIODETACH50: + /* FALLTHOUGH */ +#endif case GPIODETACH: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) @@ -841,13 +863,18 @@ gpio_ioctl(struct gpio_softc *sc, u_long sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET; break; default: +#ifdef COMPAT_50 /* Try the old API */ DPRINTF(("%s: trying the old API\n", device_xname(sc->sc_dev))); return gpio_ioctl_oapi(sc, cmd, data, flag, cred); +#else + return ENOTTY; +#endif } return 0; } +#ifdef COMPAT_50 static int gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag, kauth_cred_t cred) @@ -965,6 +992,7 @@ gpio_ioctl_oapi(struct gpio_softc *sc, u } return 0; } +#endif /* COMPAT_50 */ MODULE(MODULE_CLASS_DRIVER, gpio, NULL); Index: src/sys/dev/gpio/gpioiic.c diff -u src/sys/dev/gpio/gpioiic.c:1.4 src/sys/dev/gpio/gpioiic.c:1.5 --- src/sys/dev/gpio/gpioiic.c:1.4 Wed Aug 31 12:25:05 2011 +++ src/sys/dev/gpio/gpioiic.c Sun Oct 2 09:33:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: gpioiic.c,v 1.4 2011/08/31 12:25:05 mbalmer Exp $ */ +/* $NetBSD: gpioiic.c,v 1.5 2011/10/02 09:33:19 mbalmer Exp $ */ /* $OpenBSD: gpioiic.c,v 1.8 2008/11/24 12:12:12 mbalmer Exp $ */ /* @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gpioiic.c,v 1.4 2011/08/31 12:25:05 mbalmer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gpioiic.c,v 1.5 2011/10/02 09:33:19 mbalmer Exp $"); /* * I2C bus bit-banging through GPIO pins. @@ -29,6 +29,7 @@ __KERNEL_RCSID(0, "$NetBSD: gpioiic.c,v #include <sys/device.h> #include <sys/gpio.h> #include <sys/rwlock.h> +#include <sys/module.h> #include <dev/gpio/gpiovar.h> @@ -42,6 +43,8 @@ __KERNEL_RCSID(0, "$NetBSD: gpioiic.c,v #define GPIOIIC_SDA 0x01 #define GPIOIIC_SCL 0x02 +#define GPIOIIC_PIN_REVERSE 0x01 + struct gpioiic_softc { void * sc_gpio; struct gpio_pinmap sc_map; @@ -51,6 +54,9 @@ struct gpioiic_softc { device_t sc_i2c_dev; krwlock_t sc_i2c_lock; + int sc_pin_sda; + int sc_pin_scl; + int sc_sda; int sc_scl; }; @@ -114,14 +120,24 @@ gpioiic_attach(struct device *parent, st /* Map pins */ sc->sc_gpio = ga->ga_gpio; sc->sc_map.pm_map = sc->_map; + + if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, &sc->sc_map)) { aprint_error(": can't map pins\n"); return; } + if (ga->ga_flags & GPIOIIC_PIN_REVERSE) { + sc->sc_pin_sda = GPIOIIC_PIN_SCL; + sc->sc_pin_scl = GPIOIIC_PIN_SDA; + } else { + sc->sc_pin_sda = GPIOIIC_PIN_SDA; + sc->sc_pin_scl = GPIOIIC_PIN_SCL; + } + /* Configure SDA pin */ - caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA); + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda); if (!(caps & GPIO_PIN_OUTPUT)) { aprint_error(": SDA pin is unable to drive output\n"); goto fail; @@ -130,7 +146,7 @@ gpioiic_attach(struct device *parent, st aprint_error(": SDA pin is unable to read input\n"); goto fail; } - aprint_normal(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]); + aprint_normal(": SDA[%d]", sc->sc_map.pm_map[sc->sc_pin_sda]); sc->sc_sda = GPIO_PIN_OUTPUT; if (caps & GPIO_PIN_OPENDRAIN) { aprint_normal(" open-drain"); @@ -143,15 +159,15 @@ gpioiic_attach(struct device *parent, st aprint_normal(" pull-up"); sc->sc_sda |= GPIO_PIN_PULLUP; } - gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda); + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda, sc->sc_sda); /* Configure SCL pin */ - caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL); + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, sc->sc_pin_scl); if (!(caps & GPIO_PIN_OUTPUT)) { aprint_error(": SCL pin is unable to drive output\n"); goto fail; } - aprint_normal(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]); + aprint_normal(", SCL[%d]", sc->sc_map.pm_map[sc->sc_pin_scl]); sc->sc_scl = GPIO_PIN_OUTPUT; if (caps & GPIO_PIN_OPENDRAIN) { aprint_normal(" open-drain"); @@ -164,7 +180,7 @@ gpioiic_attach(struct device *parent, st aprint_normal(" push-pull"); sc->sc_scl |= GPIO_PIN_PUSHPULL; } - gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl); + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_scl, sc->sc_scl); aprint_normal("\n"); @@ -268,10 +284,10 @@ gpioiic_bb_set_bits(void *cookie, uint32 { struct gpioiic_softc *sc = cookie; - gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, + gpio_pin_write(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda, bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW); gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, - bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW); + bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : sc->sc_pin_scl); } void @@ -286,7 +302,7 @@ gpioiic_bb_set_dir(void *cookie, uint32_ sda |= GPIO_PIN_TRISTATE; if (sc->sc_sda != sda) { sc->sc_sda = sda; - gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda, sc->sc_sda); } } @@ -298,11 +314,45 @@ gpioiic_bb_read_bits(void *cookie) uint32_t bits = 0; if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, - GPIOIIC_PIN_SDA) == GPIO_PIN_HIGH) + sc->sc_pin_sda) == GPIO_PIN_HIGH) bits |= GPIOIIC_SDA; if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, - GPIOIIC_PIN_SCL) == GPIO_PIN_HIGH) + sc->sc_pin_scl) == GPIO_PIN_HIGH) bits |= GPIOIIC_SCL; return bits; } + +MODULE(MODULE_CLASS_DRIVER, gpioiic, "gpio,iic"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +gpioiic_modcmd(modcmd_t cmd, void *opaque) +{ + int error; + + error = 0; + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_gpioiic, + cfattach_ioconf_gpioiic, cfdata_ioconf_gpioiic); + if (error) + aprint_error("%s: unable to init component\n", + gpioiic_cd.cd_name); +#endif + break; + case MODULE_CMD_FINI: +#ifdef _MODULE + config_fini_component(cfdriver_ioconf_gpioiic, + cfattach_ioconf_gpioiic, cfdata_ioconf_gpioiic); +#endif + break; + default: + error = ENOTTY; + } + return error; +} Index: src/sys/dev/gpio/gpiovar.h diff -u src/sys/dev/gpio/gpiovar.h:1.13 src/sys/dev/gpio/gpiovar.h:1.14 --- src/sys/dev/gpio/gpiovar.h:1.13 Wed Aug 31 12:20:35 2011 +++ src/sys/dev/gpio/gpiovar.h Sun Oct 2 09:33:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: gpiovar.h,v 1.13 2011/08/31 12:20:35 mbalmer Exp $ */ +/* $NetBSD: gpiovar.h,v 1.14 2011/10/02 09:33:19 mbalmer Exp $ */ /* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */ /* @@ -73,6 +73,7 @@ struct gpio_attach_args { int ga_offset; uint32_t ga_mask; char *ga_dvname; + uint32_t ga_flags; }; /* GPIO pin map */ Index: src/sys/sys/gpio.h diff -u src/sys/sys/gpio.h:1.9 src/sys/sys/gpio.h:1.10 --- src/sys/sys/gpio.h:1.9 Sun Aug 28 07:48:50 2011 +++ src/sys/sys/gpio.h Sun Oct 2 09:33:19 2011 @@ -1,7 +1,7 @@ -/* $NetBSD: gpio.h,v 1.9 2011/08/28 07:48:50 mbalmer Exp $ */ +/* $NetBSD: gpio.h,v 1.10 2011/10/02 09:33:19 mbalmer Exp $ */ /* $OpenBSD: gpio.h,v 1.7 2008/11/26 14:51:20 mbalmer Exp $ */ /* - * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * Copyright (c) 2009, 2011 Marc Balmer <m...@msys.ch> * Copyright (c) 2004 Alexander Yurchenko <gra...@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any @@ -81,6 +81,26 @@ struct gpio_attach { char ga_dvname[16]; /* device name */ int ga_offset; /* pin number */ uint32_t ga_mask; /* binary mask */ + uint32_t ga_flags; /* driver dependent flags */ +}; + +/* gpio(4) API */ +#define GPIOINFO _IOR('G', 0, struct gpio_info) +#define GPIOSET _IOWR('G', 5, struct gpio_set) +#define GPIOUNSET _IOWR('G', 6, struct gpio_set) +#define GPIOREAD _IOWR('G', 7, struct gpio_req) +#define GPIOWRITE _IOWR('G', 8, struct gpio_req) +#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) + +#ifdef COMPAT_50 +/* Old structure to attach/detach devices */ +struct gpio_attach50 { + char ga_dvname[16]; /* device name */ + int ga_offset; /* pin number */ + uint32_t ga_mask; /* binary mask */ }; /* GPIO pin control (old API) */ @@ -96,22 +116,13 @@ struct gpio_pin_op { int gp_value; /* value */ }; -#define GPIOINFO _IOR('G', 0, struct gpio_info) - -/* the old API, kept for backwards compatibility */ +/* the old API */ #define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op) #define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op) #define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op) #define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl) - -/* the new API */ -#define GPIOSET _IOWR('G', 5, struct gpio_set) -#define GPIOUNSET _IOWR('G', 6, struct gpio_set) -#define GPIOREAD _IOWR('G', 7, struct gpio_req) -#define GPIOWRITE _IOWR('G', 8, struct gpio_req) -#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) +#define GPIOATTACH50 _IOWR('G', 10, struct gpio_attach50) +#define GPIODETACH50 _IOWR('G', 11, struct gpio_attach50) +#endif /* COMPAT_50 */ #endif /* !_SYS_GPIO_H_ */ Index: src/usr.sbin/gpioctl/gpioctl.8 diff -u src/usr.sbin/gpioctl/gpioctl.8:1.10 src/usr.sbin/gpioctl/gpioctl.8:1.11 --- src/usr.sbin/gpioctl/gpioctl.8:1.10 Sun Aug 28 17:10:37 2011 +++ src/usr.sbin/gpioctl/gpioctl.8 Sun Oct 2 09:33:19 2011 @@ -1,4 +1,4 @@ -.\" $NetBSD: gpioctl.8,v 1.10 2011/08/28 17:10:37 wiz Exp $ +.\" $NetBSD: gpioctl.8,v 1.11 2011/10/02 09:33:19 mbalmer Exp $ .\" .\" Copyright (c) 2009, 2010, 2011 Marc Balmer <m...@msys.ch> .\" Copyright (c) 2004 Alexander Yurchenko <gra...@openbsd.org> @@ -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 August 21, 2011 +.Dd October 2, 2011 .Dt GPIOCTL 8 .Os .Sh NAME @@ -29,6 +29,7 @@ .Ar device .Ar offset .Ar mask +.Op Ar flags .Nm gpioctl .Op Fl q .Ar device Index: src/usr.sbin/gpioctl/gpioctl.c diff -u src/usr.sbin/gpioctl/gpioctl.c:1.13 src/usr.sbin/gpioctl/gpioctl.c:1.14 --- src/usr.sbin/gpioctl/gpioctl.c:1.13 Thu Sep 15 11:46:32 2011 +++ src/usr.sbin/gpioctl/gpioctl.c Sun Oct 2 09:33:19 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: gpioctl.c,v 1.13 2011/09/15 11:46:32 mbalmer Exp $ */ +/* $NetBSD: gpioctl.c,v 1.14 2011/10/02 09:33:19 mbalmer Exp $ */ /* * Copyright (c) 2008, 2010, 2011 Marc Balmer <mbal...@netbsd.org> @@ -46,7 +46,7 @@ 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, uint32_t); +static void devattach(char *, int, uint32_t, uint32_t); static void devdetach(char *); __dead static void usage(void); @@ -81,8 +81,10 @@ main(int argc, char *argv[]) char *ep; int ga_offset = -1; uint32_t ga_mask = 0; + uint32_t ga_flags = 0; long lval; char *nam = NULL; + char *flags; char devn[32]; while ((ch = getopt(argc, argv, "q")) != -1) @@ -119,12 +121,13 @@ main(int argc, char *argv[]) if (!strcmp(argv[1], "attach")) { char *driver, *offset, *mask; - if (argc != 5) + if (argc != 5 && argc != 6) usage(); driver = argv[2]; offset = argv[3]; mask = argv[4]; + flags = argc == 6 ? argv[5] : NULL; ga_offset = strtonum(offset, 0, INT_MAX, &errstr); if (errstr) @@ -136,7 +139,18 @@ main(int argc, char *argv[]) || lval == LONG_MIN)) || (unsigned long)lval > UINT_MAX) errx(EXIT_FAILURE, "mask out of range"); ga_mask = lval; - devattach(driver, ga_offset, ga_mask); + if (flags != NULL) { + lval = strtol(flags, &ep, 0); + if (*flags == '\0' || *ep != '\0') + errx(EXIT_FAILURE, + "invalid flags (not a number)"); + if ((errno == ERANGE && (lval == LONG_MAX + || lval == LONG_MIN)) + || (unsigned long)lval > UINT_MAX) + errx(EXIT_FAILURE, "flags out of range"); + ga_flags = lval; + } + devattach(driver, ga_offset, ga_mask, ga_flags); return EXIT_SUCCESS; } else if (!strcmp(argv[1], "detach")) { if (argc != 3) @@ -385,7 +399,7 @@ gpiounset(int pin, char *name) } static void -devattach(char *dvname, int offset, uint32_t mask) +devattach(char *dvname, int offset, uint32_t mask, uint32_t flags) { struct gpio_attach attach; @@ -393,6 +407,7 @@ devattach(char *dvname, int offset, uint strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname)); attach.ga_offset = offset; attach.ga_mask = mask; + attach.ga_flags = flags; if (ioctl(devfd, GPIOATTACH, &attach) == -1) err(EXIT_FAILURE, "GPIOATTACH"); } @@ -421,7 +436,8 @@ usage(void) fprintf(stderr, " %s [-q] device pin set [flags] [name]\n", progname); fprintf(stderr, " %s [-q] device pin unset\n", progname); - fprintf(stderr, " %s [-q] device attach device offset mask\n", + fprintf(stderr, " %s [-q] device attach device offset mask " + "[flags]\n", progname); fprintf(stderr, " %s [-q] device detach device\n", progname);