random

:-)
git clone read: git://git.margiolis.net/random.git
Log | Files | Refs | LICENSE

commit 18693b9b2654b84d0913df54ed27c57510120f9f
parent 159798155e8ac5a3543bd29aed523ba0f2b4b831
Author: Christos Margiolis <christos@margiolis.net>
Date:   Mon,  6 Mar 2023 16:37:20 +0200

improve mydev

Diffstat:
Mmydev_freebsd/mydev.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mmydev_freebsd/mydev.h | 9+++++----
Mmydev_freebsd/mydev_test.c | 42+++++++++++++++++++++++++-----------------
3 files changed, 87 insertions(+), 36 deletions(-)

diff --git a/mydev_freebsd/mydev.c b/mydev_freebsd/mydev.c @@ -1,12 +1,24 @@ +#include <sys/types.h> #include <sys/param.h> #include <sys/conf.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> +#include <sys/malloc.h> #include <sys/uio.h> #include "mydev.h" +#define BUFSIZE (1 << 16) + +MALLOC_DECLARE(M_MYDEV); +MALLOC_DEFINE(M_MYDEV, "mydev", "test device"); + +typedef struct { + char buf[BUFSIZE + 1]; + size_t len; +} foo_t; + static d_open_t mydev_open; static d_close_t mydev_close; static d_read_t mydev_read; @@ -26,6 +38,7 @@ static struct cdevsw mydev_cdevsw = { }; static struct cdev *mydev_cdev; +static foo_t *foo; static int mydev_open(struct cdev *dev, int flags, int devtype, struct thread *td) @@ -46,11 +59,23 @@ mydev_close(struct cdev *dev, int flags, int devtype, struct thread *td) static int mydev_read(struct cdev *dev, struct uio *uio, int ioflag) { - char buf[32]; - int error = 0; + size_t amnt; + int v, error = 0; + + /* + * Determine how many bytes we have to read. We'll either read the + * remaining bytes (uio->uio_resid) or the number of bytes requested by + * the caller. + */ + v = uio->uio_offset >= foo->len + 1 ? 0 : foo->len + 1 - uio->uio_offset; + amnt = MIN(uio->uio_resid, v); - strlcpy(buf, "reading from mydev", sizeof(buf)); - error = uiomove(buf, sizeof(buf), uio); + /* Move the bytes from foo->buf to uio. */ + if ((error = uiomove(foo->buf, amnt, uio)) != 0) + uprintf("uiomove failed\n"); + + if (!foo->len) + uprintf("nothing to read\n"); return (error); } @@ -58,9 +83,23 @@ mydev_read(struct cdev *dev, struct uio *uio, int ioflag) static int mydev_write(struct cdev *dev, struct uio *uio, int ioflag) { + size_t amnt; int error = 0; - uprintf("mydev: %s\n", (char *)uio->uio_iov->iov_base); + /* Do not allow random access. */ + if (uio->uio_offset != 0 && (uio->uio_offset != foo->len)) + return (EINVAL); + + /* We're not appending, reset length. */ + else if (uio->uio_offset == 0) + foo->len = 0; + + amnt = MIN(uio->uio_resid, (BUFSIZE - foo->len)); + if ((error = uiomove(foo->buf + uio->uio_offset, amnt, uio)) != 0) + uprintf("uiomove failed"); + + foo->len = uio->uio_offset; + foo->buf[foo->len] = '\0'; return (error); } @@ -69,24 +108,23 @@ static int mydev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) { - foo_t *fp; + bar_t *bp; int error = 0; switch (cmd) { case MYDEVIOC_READ: - fp = (foo_t *)addr; - fp->x = 10; - fp->y = 20; + bp = (bar_t *)addr; + bp->x = 100; + bp->y = 300; break; case MYDEVIOC_WRITE: - fp = (foo_t *)addr; - uprintf("mydev: x=%d, y=%d\n", fp->x, fp->y); + bp = (bar_t *)addr; + uprintf("/dev/mydev: x=%d, y=%d\n", bp->x, bp->y); break; case MYDEVIOC_RDWR: - fp = (foo_t *)addr; - uprintf("mydev: received: x=%d, y=%d\n", fp->x, fp->y); - fp->x += 5; - fp->y += 5; + bp = (bar_t *)addr; + bp->x += 15; + bp->y += 30; break; default: error = ENOTTY; @@ -105,9 +143,13 @@ mydev_modevent(module_t mod, int type, void *arg) case MOD_LOAD: mydev_cdev = make_dev(&mydev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "mydev"); + foo = malloc(sizeof(foo_t), M_MYDEV, M_WAITOK | M_ZERO); + foo->buf[0] = '\0'; + foo->len = 0; break; case MOD_UNLOAD: /* FALLTHROUGH */ case MOD_SHUTDOWN: + free(foo, M_MYDEV); destroy_dev(mydev_cdev); break; default: diff --git a/mydev_freebsd/mydev.h b/mydev_freebsd/mydev.h @@ -1,15 +1,16 @@ #ifndef _MYDEV_H_ #define _MYDEV_H_ +#include <sys/types.h> #include <sys/ioccom.h> typedef struct { int x; int y; -} foo_t; +} bar_t; -#define MYDEVIOC_READ _IOR('a', 1, foo_t) -#define MYDEVIOC_WRITE _IOW('a', 2, foo_t) -#define MYDEVIOC_RDWR _IOWR('a', 3, foo_t) +#define MYDEVIOC_READ _IOR('a', 1, bar_t) +#define MYDEVIOC_WRITE _IOW('a', 2, bar_t) +#define MYDEVIOC_RDWR _IOWR('a', 3, bar_t) #endif /* _MYDEV_H_ */ diff --git a/mydev_freebsd/mydev_test.c b/mydev_freebsd/mydev_test.c @@ -10,35 +10,43 @@ int main(int argc, char *argv[]) { - foo_t foo; - char buf[32]; - int dev; + bar_t bar; + char buf[BUFSIZ]; + int fd; - if ((dev = open("/dev/mydev", O_RDWR)) < 0) + if ((fd = open("/dev/mydev", O_RDWR)) < 0) err(1, "open(/dev/mydev)"); - if (ioctl(dev, MYDEVIOC_READ, &foo) != 0) + if (ioctl(fd, MYDEVIOC_READ, &bar) != 0) err(1, "ioctl(MYDEVIOC_READ)"); - printf("%s: x=%d, y=%d\n", getprogname(), foo.x, foo.y); + printf("%s: ioctl(MYDEVIOC_READ)\t-> x=%d, y=%d\n", + getprogname(), bar.x, bar.y); - foo.x = 1; - foo.y = 2; - if (ioctl(dev, MYDEVIOC_WRITE, &foo) != 0) + printf("%s: ioctl(MYDEVIOC_WRITE)\t-> ", getprogname()); + fflush(stdout); + + bar.x = 10; + bar.y = 20; + if (ioctl(fd, MYDEVIOC_WRITE, &bar) != 0) err(1, "ioctl(MYDEVIOC_WRITE)"); - if (ioctl(dev, MYDEVIOC_RDWR, &foo) != 0) + if (ioctl(fd, MYDEVIOC_RDWR, &bar) != 0) err(1, "ioctl(MYDEVIOC_RDWR)"); - printf("%s received: x=%d, y=%d\n", getprogname(), foo.x, foo.y); + printf("%s: ioctl(MYDEVIOC_RDWR)\t-> x=%d, y=%d\n", + getprogname(), bar.x, bar.y); - if (read(dev, buf, sizeof(buf)) < 0) - err(1, "read"); - printf("%s: %s\n", getprogname(), buf); + (void)strlcpy(buf, "hello from test program", sizeof(buf)); - strlcpy(buf, "writing to mydev", sizeof(buf)); - if (write(dev, buf, sizeof(buf)) < 0) + printf("%s: write()\t\t\t-> %s\n", getprogname(), buf); + fflush(stdout); + + if (write(fd, buf, sizeof(buf)) < 0) err(1, "write"); + if (read(fd, buf, sizeof(buf)) < 0) + err(1, "read"); + printf("%s: read()\t\t\t-> %s\n", getprogname(), buf); - close(dev); + close(fd); return (0); }