diff options
| author | pgoyette <pgoyette@NetBSD.org> | 2015-05-13 07:07:36 +0000 |
|---|---|---|
| committer | pgoyette <pgoyette@NetBSD.org> | 2015-05-13 07:07:36 +0000 |
| commit | ad7d712bc17eaab4ab4c122a50f3e963a7b68650 (patch) | |
| tree | 47c2e9c45d432acc44cdd21260b337bc6c21c6c4 /sys/modules/examples | |
| parent | 473ae0d0c350213199709b9ccd8676c022214c24 (diff) | |
A set of more comprehensive example kernel modules to replace our
previous single example.
These examples were provided by Kamil Rytarowski.
XXX These modules are built as part of a system build, but they
XXX are NOT installed in $DESTDIR.
Diffstat (limited to 'sys/modules/examples')
| -rw-r--r-- | sys/modules/examples/Makefile | 11 | ||||
| -rw-r--r-- | sys/modules/examples/Makefile.inc | 9 | ||||
| -rw-r--r-- | sys/modules/examples/README | 59 | ||||
| -rw-r--r-- | sys/modules/examples/hello/Makefile | 9 | ||||
| -rw-r--r-- | sys/modules/examples/hello/hello.c | 64 | ||||
| -rw-r--r-- | sys/modules/examples/luahello/luahello.lua | 47 | ||||
| -rw-r--r-- | sys/modules/examples/ping/Makefile | 18 | ||||
| -rw-r--r-- | sys/modules/examples/ping/cmd_ping.c | 61 | ||||
| -rw-r--r-- | sys/modules/examples/ping/ping.c | 131 | ||||
| -rw-r--r-- | sys/modules/examples/ping/ping.h | 8 | ||||
| -rw-r--r-- | sys/modules/examples/properties/Makefile | 9 | ||||
| -rw-r--r-- | sys/modules/examples/properties/properties.c | 75 | ||||
| -rw-r--r-- | sys/modules/examples/readhappy/Makefile | 9 | ||||
| -rw-r--r-- | sys/modules/examples/readhappy/readhappy.c | 195 |
14 files changed, 705 insertions, 0 deletions
diff --git a/sys/modules/examples/Makefile b/sys/modules/examples/Makefile new file mode 100644 index 00000000000..8d32be613df --- /dev/null +++ b/sys/modules/examples/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +.include <bsd.own.mk> + +SUBDIR+= hello +#SUBDIR+= luahello # Nothing to build here, only text files +SUBDIR+= ping # Needs an additional helper program +SUBDIR+= properties +SUBDIR+= readhappy + +.include <bsd.subdir.mk> diff --git a/sys/modules/examples/Makefile.inc b/sys/modules/examples/Makefile.inc new file mode 100644 index 00000000000..254e09d009c --- /dev/null +++ b/sys/modules/examples/Makefile.inc @@ -0,0 +1,9 @@ +# $NetBSD: Makefile.inc,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +# We only build the example modules; we don't want to install them anywhere + +kmodinstall: + +# Include parent's Makefile.inc + +.include "../Makefile.inc" diff --git a/sys/modules/examples/README b/sys/modules/examples/README new file mode 100644 index 00000000000..d6d43412c1c --- /dev/null +++ b/sys/modules/examples/README @@ -0,0 +1,59 @@ + $NetBSD: README,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + + Kernel Developer's Manual + +DESCRIPTION + The kernel example dynamic modules. + + This directory contains the following example modules: + * hello - the simplest `hello world' module + * properties - handle incoming properties during the module load + * readhappy - basic implementation of read(9) with happy numbers + * ping - basic ioctl(9) + * hellolua - the simplest `hello world' Lua module + + To build the examples you need a local copy of NetBSD sources. You also + need the comp set with toolchain. To build the module just enter a + directory with example modules and use make(1): + + # make + + To load, unload, and stat the module use modload(8), modunload(8) and + modstat(8). + + The S parameter in the Makefile files points to src/sys and it can be + overloaded in this way: + + # make S=/data/netbsd/src/sys + + The code of a module does not need to be in src/sys unless you use + the autoconf(9) framework. + + A cross-built of a module for a target platform is possible with the + build.sh framework. You need to generate the toolchain and set + appropriately PATH to point bin/ in the TOOLDIR path. An example command + to cross-build a module with the amd64 toolchain is as follows: + + # nbmake-amd64 S=/data/netbsd/src/sys + + + The example modules should not be used on a production machine. + + All modules that create a cdevsw should be verified that the major number + should not conflict with a real device. + +SEE ALSO + lua(9lua), modctl(2), modload(8), module(7), module(9), modstat(8), + modunload(8) + +HISTORY + An example of handling incoming properties first appeared in NetBSD 5.0 + and was written by Julio Merino with further modifications by Martin + Husemann, Adam Hamsik, John Nemeth and Mindaugas Rasiukevicius. + + This document and additional modules (hello, readhappy, properties, + and ping, hellolua) first appeared in NetBSD 8.0 and they were written + by Kamil Rytarowski. + +AUTHORS + This document was written by Kamil Rytarowski. diff --git a/sys/modules/examples/hello/Makefile b/sys/modules/examples/hello/Makefile new file mode 100644 index 00000000000..6c7aa1917bf --- /dev/null +++ b/sys/modules/examples/hello/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +.include "../Makefile.inc" + +#S?= /usr/src/sys +KMOD= hello +SRCS= hello.c + +.include <bsd.kmodule.mk> diff --git a/sys/modules/examples/hello/hello.c b/sys/modules/examples/hello/hello.c new file mode 100644 index 00000000000..7814642f83e --- /dev/null +++ b/sys/modules/examples/hello/hello.c @@ -0,0 +1,64 @@ +/* $NetBSD: hello.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: hello.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/module.h> + +/* + * Last parameter of MODULE macro is a list of names (as string; names are + * separated by commas) of dependencies. If module has no dependencies, + * then NULL should be passed. + */ + +MODULE(MODULE_CLASS_MISC, hello, NULL); + +static int +hello_modcmd(modcmd_t cmd, void *arg __unused) +{ + switch (cmd) { + case MODULE_CMD_INIT: + printf("Example module loaded.\n"); + break; + + case MODULE_CMD_FINI: + printf("Example module unloaded.\n"); + break; + + case MODULE_CMD_STAT: + printf("Example module status queried.\n"); + break; + + default: + return ENOTTY; + } + + return 0; +} diff --git a/sys/modules/examples/luahello/luahello.lua b/sys/modules/examples/luahello/luahello.lua new file mode 100644 index 00000000000..6a970fc3ed2 --- /dev/null +++ b/sys/modules/examples/luahello/luahello.lua @@ -0,0 +1,47 @@ +# $NetBSD: luahello.lua,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ +# +# +# Copyright (c) 2015 The NetBSD Foundation, Inc. +# 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. +# +# +# Print `Hello Lua world' in dmesg(8) +# +# Tutorial +# 1. Load the lua and luasystm modules. +# modload lua +# modload luasystm +# +# 2. Create Lua state for our code +# luactl create state1 +# +# 3. Require systm(9lua) for state1 +# luactl require state1 systm +# +# 4. Load our code in state1 +# luactl load state1 ./hellolua.lua +# +# NB. The path with our code must contain at least single '/' character + +systm.print("Hello Lua world!\n") diff --git a/sys/modules/examples/ping/Makefile b/sys/modules/examples/ping/Makefile new file mode 100644 index 00000000000..678c7a366bf --- /dev/null +++ b/sys/modules/examples/ping/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +.include "../Makefile.inc" + +#S?= /usr/src/sys + +KMOD= ping +SRCS= ping.c + +.include <bsd.kmodule.mk> + +# To make use of this module, you'll need to separately build the +# cmd_ping program, with a Makefile similar to +# +# MKMAN= NO +# PROG= cmd_ping +# .include <bsd.prog.mk> + diff --git a/sys/modules/examples/ping/cmd_ping.c b/sys/modules/examples/ping/cmd_ping.c new file mode 100644 index 00000000000..8576d3d0117 --- /dev/null +++ b/sys/modules/examples/ping/cmd_ping.c @@ -0,0 +1,61 @@ +/* $NetBSD: cmd_ping.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD $"); + +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include "ping.h" + +#define _PATH_DEV_PING "/dev/ping" + +int main(int argc, char **argv) +{ + int devfd; + + setprogname(argv[0]); + + if ((devfd = open(_PATH_DEV_PING, O_RDWR)) == -1) + err(EXIT_FAILURE, "Cannot open %s", _PATH_DEV_PING); + + if (ioctl(devfd, CMD_PING) == -1) + err(EXIT_FAILURE, "ping failed"); + + printf("%s: ping sent successfully\n", getprogname()); + + if (close(devfd) == -1) + err(EXIT_FAILURE, "Cannot close %s", _PATH_DEV_PING); + + return EXIT_SUCCESS; +} diff --git a/sys/modules/examples/ping/ping.c b/sys/modules/examples/ping/ping.c new file mode 100644 index 00000000000..dd22ac2e88a --- /dev/null +++ b/sys/modules/examples/ping/ping.c @@ -0,0 +1,131 @@ +/* $NetBSD: ping.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: ping.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include "ping.h" + +/* + * Create a device /dev/ping in order to test this module. + * + * To use this device you need to do: + * mknod /dev/ping c 210 0 + * + */ + +dev_type_open(ping_open); +dev_type_close(ping_close); +dev_type_ioctl(ping_ioctl); + +static struct cdevsw ping_cdevsw = { + .d_open = ping_open, + .d_close = ping_close, + .d_read = noread, + .d_write = nowrite, + .d_ioctl = ping_ioctl, + .d_stop = nostop, + .d_tty = notty, + .d_poll = nopoll, + .d_mmap = nommap, + .d_kqfilter = nokqfilter, + .d_discard = nodiscard, + .d_flag = D_OTHER +}; + + +struct ping_softc { + int refcnt; +}; + +static struct ping_softc sc; + +int +ping_open(dev_t self __unused, int flag __unused, int mode __unused, + struct lwp *l __unused) +{ + if (sc.refcnt > 0) + return EBUSY; + + ++sc.refcnt; + + return 0; +} + +int +ping_close(dev_t self __unused, int flag __unused, int mode __unused, + struct lwp *l __unused) +{ + --sc.refcnt; + + return 0; +} + +int +ping_ioctl(dev_t self __unused, u_long cmd, void *data, int flag, + struct lwp *l __unused) +{ + switch(cmd) { + case CMD_PING: + printf("ping: pong!\n"); + return 0; + default: + return 1; + } +} + +MODULE(MODULE_CLASS_MISC, ping, NULL); + +static int +ping_modcmd(modcmd_t cmd, void *arg __unused) +{ + /* The major should be verified and changed if needed to avoid + * conflicts with other devices. */ + int cmajor = 210, bmajor = -1; + + switch (cmd) { + case MODULE_CMD_INIT: + if (devsw_attach("ping", NULL, &bmajor, &ping_cdevsw, &cmajor)) + return ENXIO; + return 0; + case MODULE_CMD_FINI: + if (sc.refcnt > 0) + return EBUSY; + + devsw_detach(NULL, &ping_cdevsw); + return 0; + default: + return ENOTTY; + } +} diff --git a/sys/modules/examples/ping/ping.h b/sys/modules/examples/ping/ping.h new file mode 100644 index 00000000000..25691907bf8 --- /dev/null +++ b/sys/modules/examples/ping/ping.h @@ -0,0 +1,8 @@ +#ifndef _PING_H_ +#define _PING_H_ + +#include <sys/ioccom.h> + +#define CMD_PING _IO('p', 2) + +#endif /* _PING_H_ */ diff --git a/sys/modules/examples/properties/Makefile b/sys/modules/examples/properties/Makefile new file mode 100644 index 00000000000..9c2b341ee4d --- /dev/null +++ b/sys/modules/examples/properties/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +.include "../Makefile.inc" + +#S?= /usr/src/sys +KMOD= properties +SRCS= properties.c + +.include <bsd.kmodule.mk> diff --git a/sys/modules/examples/properties/properties.c b/sys/modules/examples/properties/properties.c new file mode 100644 index 00000000000..6af88a25943 --- /dev/null +++ b/sys/modules/examples/properties/properties.c @@ -0,0 +1,75 @@ +/* $NetBSD: properties.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: properties.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/module.h> + +MODULE(MODULE_CLASS_MISC, properties, NULL); + +static void +handle_props(prop_dictionary_t props) +{ + const char *msg; + prop_string_t str; + + if (props != NULL) { + str = prop_dictionary_get(props, "msg"); + } else { + printf("No property dictionary was provided.\n"); + str = NULL; + } + if (str == NULL) + printf("The 'msg' property was not given.\n"); + else if (prop_object_type(str) != PROP_TYPE_STRING) + printf("The 'msg' property is not a string.\n"); + else { + msg = prop_string_cstring_nocopy(str); + if (msg == NULL) + printf("Failed to process the 'msg' property.\n"); + else + printf("The 'msg' property is: %s\n", msg); + } +} + +static int +properties_modcmd(modcmd_t cmd, void *arg) +{ + switch (cmd) { + case MODULE_CMD_INIT: + handle_props(arg); + return 0; + case MODULE_CMD_FINI: + return 0; + default: + return ENOTTY; + } +} diff --git a/sys/modules/examples/readhappy/Makefile b/sys/modules/examples/readhappy/Makefile new file mode 100644 index 00000000000..857f0136583 --- /dev/null +++ b/sys/modules/examples/readhappy/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ + +.include "../Makefile.inc" + +#S?= /usr/src/sys +KMOD= readhappy +SRCS= readhappy.c + +.include <bsd.kmodule.mk> diff --git a/sys/modules/examples/readhappy/readhappy.c b/sys/modules/examples/readhappy/readhappy.c new file mode 100644 index 00000000000..637d28f7a35 --- /dev/null +++ b/sys/modules/examples/readhappy/readhappy.c @@ -0,0 +1,195 @@ +/* $NetBSD: readhappy.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: readhappy.c,v 1.1 2015/05/13 07:07:36 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/module.h> + +/* + * Create a device /dev/happy from which you can read sequential + * happy numbers. + * + * To use this device you need to do: + * mknod /dev/happy c 210 0 + * + * Commentary: + * A happy number is a number defined by the following process: Starting with + * any positive integer, replace the number by the sum of the squares of its + * digits, and repeat the process until the number equals 1 (where it will + * stay), or it loops endlessly in a cycle which does not include 1. Those + * numbers for which this process ends in 1 are happy numbers, while those that + * do not end in 1 are unhappy numbers (or sad numbers). + * + * For more information on happy numbers, and the algorithms, see + * http://en.wikipedia.org/wiki/Happy_number + * + * The happy number generator is here only to have something that the user + * can read from our device. Any other arbitrary data generator could + * have been used. The algorithm is not critical to the implementation + * of the module. + */ + + +#define HAPPY_NUMBER 1 + +/* If n is not happy then its sequence ends in the cycle: + * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */ +#define SAD_NUMBER 4 + +/* Calculate the sum of the squares of the digits of n */ +static unsigned +dsum(unsigned n) +{ + unsigned sum, x; + for (sum = 0; n; n /= 10) { + x = n % 10; + sum += x * x; + } + return sum; +} + +static int +check_happy(unsigned n) +{ + for (;;) { + unsigned total = dsum(n); + + if (total == HAPPY_NUMBER) + return 1; + if (total == SAD_NUMBER) + return 0; + + n = total; + } +} + +dev_type_open(happy_open); +dev_type_close(happy_close); +dev_type_read(happy_read); + +static struct cdevsw happy_cdevsw = { + .d_open = happy_open, + .d_close = happy_close, + .d_read = happy_read, + .d_write = nowrite, + .d_ioctl = noioctl, + .d_stop = nostop, + .d_tty = notty, + .d_poll = nopoll, + .d_mmap = nommap, + .d_kqfilter = nokqfilter, + .d_discard = nodiscard, + .d_flag = D_OTHER +}; + + +struct happy_softc { + int refcnt; + unsigned last; +}; + +static struct happy_softc sc; + +int +happy_open(dev_t self __unused, int flag __unused, int mode __unused, + struct lwp *l __unused) +{ + if (sc.refcnt > 0) + return EBUSY; + + sc.last = 0; + ++sc.refcnt; + + return 0; +} + +int +happy_close(dev_t self __unused, int flag __unused, int mode __unused, + struct lwp *l __unused) +{ + --sc.refcnt; + + return 0; +} + +int +happy_read(dev_t self __unused, struct uio *uio, int flags __unused) +{ + char line[80]; + + /* Get next happy number */ + while (check_happy(++sc.last) == 0) + continue; + + /* Print it into line[] with trailing \n */ + int len = snprintf(line, sizeof(line), "%u\n", sc.last); + + /* Is there room? */ + if (uio->uio_resid < len) { + --sc.last; /* Step back */ + return EINVAL; + } + + /* Send it to User-Space */ + int e; + if ((e = uiomove(line, len, uio))) + return e; + + return 0; +} + +MODULE(MODULE_CLASS_MISC, happy, NULL); + +static int +happy_modcmd(modcmd_t cmd, void *arg __unused) +{ + /* The major should be verified and changed if needed to avoid + * conflicts with other devices. */ + int cmajor = 210, bmajor = -1; + + switch (cmd) { + case MODULE_CMD_INIT: + if (devsw_attach("happy", NULL, &bmajor, &happy_cdevsw, + &cmajor)) + return ENXIO; + return 0; + case MODULE_CMD_FINI: + if (sc.refcnt > 0) + return EBUSY; + + devsw_detach(NULL, &happy_cdevsw); + return 0; + default: + return ENOTTY; + } +} |
