Index: sys/dev/gpiosim.c =================================================================== RCS file: sys/dev/gpiosim.c diff -N sys/dev/gpiosim.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/gpiosim.c 6 Jan 2008 11:01:50 -0000 @@ -0,0 +1,147 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2008 Marc Balmer + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* 32 bit wide GPIO simulator */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define GPIOSIM_NPINS 32 + +struct gpiosim_softc { + struct device sc_dev; + u_int32_t sc_state; + struct gpio_chipset_tag sc_gpio_gc; + gpio_pin_t sc_gpio_pins[GPIOSIM_NPINS]; +}; + +int gpiosim_match(struct device *, void *, void *); +void gpiosim_attach(struct device *, struct device *, void *); +int gpiosim_ioctl(struct device *, u_long cmd, caddr_t data); + +int gpiosim_pin_read(void *, int); +void gpiosim_pin_write(void *, int, int); +void gpiosim_pin_ctl(void *, int, int); + +struct cfattach gpiosim_ca = { + sizeof(struct gpiosim_softc), gpiosim_match, gpiosim_attach +}; + +struct cfdriver gpiosim_cd = { + NULL, "gpiosim", DV_DULL +}; + +int +gpiosim_match(struct device *parent, void *match, void *aux) +{ + return 1; +} + +void +gpiosim_attach(struct device *parent, struct device *self, void *aux) +{ + struct gpiosim_softc *sc = (void *)self; + struct gpiobus_attach_args gba; + int i; + + /* initialize pin array */ + for (i = 0; i < GPIOSIM_NPINS; i++) { + sc->sc_gpio_pins[i].pin_num = i; + sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | + GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | + GPIO_PIN_INVIN | GPIO_PIN_INVOUT; + + /* read initial state */ + sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT; + sc->sc_state = 0; + + /* create controller tag */ + sc->sc_gpio_gc.gp_cookie = sc; + sc->sc_gpio_gc.gp_pin_read = gpiosim_pin_read; + sc->sc_gpio_gc.gp_pin_write = gpiosim_pin_write; + sc->sc_gpio_gc.gp_pin_ctl = gpiosim_pin_ctl; + + gba.gba_name = "gpio"; + gba.gba_gc = &sc->sc_gpio_gc; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = GPIOSIM_NPINS; + } + printf("\n"); + config_found(&sc->sc_dev, &gba, gpiobus_print); + bio_register(&sc->sc_dev, gpiosim_ioctl); +} + +int +gpiosim_ioctl(struct device *self, u_long cmd, caddr_t data) +{ + struct gpiosim_softc *sc = (void *)self; + struct gpiosim_op *op = (void *)data; + + switch (cmd) { + case GPIOSIMREAD: + op->state = sc->sc_state; + break; + case GPIOSIMWRITE: + sc->sc_state = (sc->sc_state & ~op->mask) | + (op->state & op->mask); + break; + default: + return ENOTTY; + } + return 0; +} + +int +gpiosim_pin_read(void *arg, int pin) +{ + struct gpiosim_softc *sc = (struct gpiosim_softc *)arg; + + if (sc->sc_state & (1 << pin)) + return GPIO_PIN_HIGH; + else + return GPIO_PIN_LOW; +} + +void +gpiosim_pin_write(void *arg, int pin, int value) +{ + struct gpiosim_softc *sc = (struct gpiosim_softc *)arg; + + if (value == 0) + sc->sc_state &= ~(1 << pin); + else + sc->sc_state |= (1 << pin); +} + +void +gpiosim_pin_ctl(void *arg, int pin, int flags) +{ + struct gpiosim_softc *sc = (struct gpiosim_softc *)arg; + + sc->sc_gpio_pins[pin].pin_flags = flags; +} Index: sys/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/conf/GENERIC,v retrieving revision 1.139 diff -u -p -r1.139 GENERIC --- sys/conf/GENERIC 5 Jan 2008 17:33:28 -0000 1.139 +++ sys/conf/GENERIC 6 Jan 2008 11:01:53 -0000 @@ -66,6 +66,9 @@ option MROUTING # Multicast router softraid0 at root # Software RAID scsibus* at softraid? +gpiosim0 at root disable # GPIO Simulator +gpio* at gpiosim? + pseudo-device pf # packet filter pseudo-device pflog # pf log if pseudo-device pfsync # pf sync if Index: sys/conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.422 diff -u -p -r1.422 files --- sys/conf/files 5 Jan 2008 17:33:28 -0000 1.422 +++ sys/conf/files 6 Jan 2008 11:01:54 -0000 @@ -445,6 +445,10 @@ file dev/softraid.c softraid needs-fla file dev/softraid_raid1.c softraid file dev/softraid_crypto.c softraid & crypto +device gpiosim: gpiobus +attach gpiosim at root +file dev/gpiosim.c gpiosim needs-flag + # legitimate pseudo-devices pseudo-device vnd: disk pseudo-device ccd: disk Index: share/man/man4/Makefile =================================================================== RCS file: /cvs/src/share/man/man4/Makefile,v retrieving revision 1.441 diff -u -p -r1.441 Makefile --- share/man/man4/Makefile 5 Jan 2008 17:33:28 -0000 1.441 +++ share/man/man4/Makefile 6 Jan 2008 11:01:54 -0000 @@ -20,7 +20,7 @@ MAN= aac.4 ac97.4 acphy.4 \ eso.4 ess.4 et.4 etphy.4 ex.4 exphy.4 \ faith.4 fd.4 fdc.4 fintek.4 fms.4 fpa.4 fxp.4 gdt.4 \ gentbi.4 gem.4 gif.4 \ - glenv.4 gpio.4 gpioiic.4 gpioow.4 gpr.4 gre.4 gscsio.4 gtp.4 \ + glenv.4 gpio.4 gpioiic.4 gpioow.4 gpiosim.4 gpr.4 gre.4 gscsio.4 gtp.4 \ hifn.4 hil.4 hilid.4 hilkbd.4 hilms.4 hme.4 hotplug.4 hsq.4 \ ichiic.4 ichwdt.4 icmp.4 icmp6.4 icsphy.4 ifmedia.4 \ iha.4 iic.4 inet.4 inet6.4 inphy.4 iop.4 iophy.4 ioprbs.4 \ --- /dev/null Sun Jan 6 12:03:38 2008 +++ usr.sbin/gpiosim/Makefile Sun Jan 6 11:15:52 2008 @@ -0,0 +1,13 @@ +# $OpenBSD$ + +PROG= gpiosim +SRCS= gpiosim.c + +CFLAGS+=-Wall +CFLAGS+=-Wstrict-prototypes -Wmissing-prototypes +CFLAGS+=-Wmissing-declarations -Wredundant-decls +CFLAGS+=-Wshadow -Wpointer-arith -Wcast-qual + +MAN= gpiosim.8 + +.include --- /dev/null Sun Jan 6 12:03:38 2008 +++ usr.sbin/gpiosim/gpiosim.8 Sun Jan 6 11:59:33 2008 @@ -0,0 +1,88 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2008 Marc Balmer +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate$ +.Dt GPIOSIM 8 +.Os +.Sh NAME +.Nm gpiosim +.Nd control GPIO simulator devices +.Sh SYNOPSIS +.Nm gpiosim +.Op Fl d Ar device +.Op Ar pin +.Op Ar 0 | 1 +.Nm gpiosim +.Op Fl d Ar device +.Op Fl s Ar state +.Nm gpiosim +.Op Fl d Ar device +.Sh DESCRIPTION +The +.Nm +program allows "behind the scene" manipulation of +.Tn GPIO +(General Purpose Input/Output) simulator device pins. +.Pp +The +.Xr gpiosim 4 +device behaves like an ordinary +.Xr gpio 4 +device that can be controlled using the +.Xr gpioctl 8 +command. +Additionally the +.Xr gpiosim 4 +pins can be controlled independently using the +.Nm +command. +.Pp +.Tn GPIO +simulator pins can be either +.Dq read +or +.Dq written +with the values of logical 0 or 1. +If only a +.Ar pin +number is specified on the command line, the pin state will be read +from the device. +If no arguments are specified, the current state of the simulator will +be output as a single 32-bit hexadecimal value. +.Pp +To write to a pin, a value must be specified after the +.Ar pin +number. +Values can be either 0 or 1. +.Pp +Using the +.Op Fl s Ar state +synopsis, the state of all pins can be set at once using a decimal or +hexadecimal value (prefixed with 0x in the latter case). +.Sh SEE ALSO +.Xr gpio 4 , +.Xr gpiosim 4 , +.Xr gpioctl 8 +.Sh HISTORY +The +.Nm +command first appeared in +.Ox 4.3 . +.Sh AUTHORS +The +.Nm +program was written by +.An Marc Balmer Aq mbalmer@openbsd.org . --- /dev/null Sun Jan 6 12:03:38 2008 +++ usr.sbin/gpiosim/gpiosim.c Sun Jan 6 11:57:18 2008 @@ -0,0 +1,177 @@ +/* $OpenBSD*/ +/* + * Copyright (c) 2008 Marc Balmer + * Copyright (c) 2004 Alexander Yurchenko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Program to control GPIO simulator devices. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define _PATH_DEV_BIO "/dev/bio" + +char *device = "gpiosim0"; +int devfd = -1; +void *cookie; + +void pinread(int); +void pinwrite(int, int); +u_int32_t stateget(void); +void stateset(u_int32_t state); + +__dead void usage(void); + +int +main(int argc, char *argv[]) +{ + struct bio_locate loc; + u_int32_t state = 0L; + int ch; + const char *errstr; + int pin = 0, value = 0, setstat = 0; + + while ((ch = getopt(argc, argv, "d:s:")) != -1) + switch (ch) { + case 'd': + device = optarg; + break; + case 's': + state = strtol(optarg, NULL, 0); + setstat = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + if (argc > 0) { + pin = strtonum(argv[0], 0, INT_MAX, &errstr); + if (errstr) + errx(1, "%s: invalid pin", argv[0]); + } + + if ((devfd = open(_PATH_DEV_BIO, O_RDWR)) == -1) + err(1, "%s", device); + loc.bl_name = device; + if (ioctl(devfd, BIOCLOCATE, &loc)) + err(1, "%s", device); + cookie = loc.bl_cookie; + if (argc == 0) { + if (setstat) + stateset(state); + else + printf("0x%08x\n", stateget()); + } else if (argc == 1) + pinread(pin); + else if (argc > 1) { + value = strtonum(argv[1], INT_MIN, INT_MAX, &errstr); + if (errstr) + errx(1, "%s: invalid value", argv[1]); + pinwrite(pin, value); + } else + usage(); + /* NOTREACHED */ + + return 0; +} + +void +pinread(int pin) +{ + struct gpiosim_op op; + + bzero(&op, sizeof(op)); + op.cookie = cookie; + if (ioctl(devfd, GPIOSIMREAD, &op) == -1) + err(1, "GPIOSIMREAD"); + + printf("pin %d: state %d\n", pin, op.state & (1 << pin) ? 1 : 0); +} + +void +pinwrite(int pin, int value) +{ + struct gpiosim_op op; + + if (value < 0 || value > 2) + errx(1, "%d: invalid value", value); + + bzero(&op, sizeof(op)); + op.cookie = cookie; + if (value) + op.state = 1 << pin; + else + op.state = 0; + op.mask = 1 << pin; + + if (value < 2) + if (ioctl(devfd, GPIOSIMWRITE, &op) == -1) + err(1, "GPIOSIMWRITE"); +} + +u_int32_t +stateget(void) +{ + struct gpiosim_op op; + + bzero(&op, sizeof(op)); + op.cookie = cookie; + if (ioctl(devfd, GPIOSIMREAD, &op) == -1) + err(1, "GPIOSIMREAD"); + + return op.state; +} + +void +stateset(u_int32_t state) +{ + struct gpiosim_op op; + + bzero(&op, sizeof(op)); + op.cookie = cookie; + op.state = state; + op.mask = 0xffffffff; + + if (ioctl(devfd, GPIOSIMWRITE, &op) == -1) + err(1, "GPIOSIMWRITE"); +} + +__dead void +usage(void) +{ + extern char *__progname; + + fprintf(stderr, "usage: %s [-d device] [pin] [0 | 1]\n", + __progname); + + exit(1); +}