Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Aug 2004 17:00:59 +0200
From:      "Gert van der Plas" <snoyt@hotmail.com>
To:        doc@FreeBSD.org
Subject:   update for FreeBSD Architecture Handbook: 13.4 Character Devices
Message-ID:  <BAY17-F28uaYve5T7HV000d0ed0@hotmail.com>

next in thread | raw e-mail | index | archive | help
Hi doc@FreeBSD.org,

I wanted to write a kernel module and accessed your example 13-2: 'Example 
of a Sample Echo Pseudo-Device Driver for FreeBSD 5.X'. The source seems 
slightly outdated and did not work for FreeBSD 5.2-CURRENT of 30th of june.
I fixed it and submit to you the updated version.

Regards,

   Gert van der Plas

/*
* Simple  Echo pseudo-device KLD
*
* Murray Stokely
*
* Converted to 5.X by Søren (Xride) Straarup
* Updated 29 August 2004 by Gert van der Plas
*/

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */
#include <sys/errno.h>
#include <sys/param.h>  /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/uio.h>    /* uio struct */
#include <sys/malloc.h>

#define BUFFERSIZE 256
#define CDEV_MAJOR      33


/* Function prototypes */
static d_open_t      echo_open;
static d_close_t     echo_close;
static d_read_t      echo_read;
static d_write_t     echo_write;

/* Character device entry points */
static struct cdevsw echo_cdevsw = {
    .d_open = echo_open,
    .d_close = echo_close,
    .d_maj = CDEV_MAJOR,
    .d_name = "echo",
    .d_read = echo_read,
    .d_write = echo_write,
    .d_version = D_VERSION
};

typedef struct s_echo {
    char msg[BUFFERSIZE];
    int len;
} t_echo;

/* vars */
static struct cdev *echo_dev;
static int count;
static t_echo *echomsg;

MALLOC_DECLARE(M_ECHOBUF);
MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");

/*
* This function is called by the kld[un]load(2) system calls to
* determine what actions to take when a module is loaded or unloaded.
*/

static int
echo_loader(struct module *m, int what, void *arg)
{
    int err = 0;

    switch (what) {
    case MOD_LOAD:                /* kldload */
        echo_dev = make_dev(&echo_cdevsw,
            0,
            UID_ROOT,
            GID_WHEEL,
            0600,
            "echo");
        /* kmalloc memory for use by this driver */
        MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
        printf("Echo device loaded.\n");
        break;
    case MOD_UNLOAD:
        destroy_dev(echo_dev);
        FREE(echomsg,M_ECHOBUF);
        printf("Echo device unloaded.\n");
        break;
    default:
        err = EINVAL;
        break;
    }
    return(err);
}

static int
echo_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
{
    int err = 0;

    uprintf("Opened device \"echo\" successfully.\n");
    return(err);
}

static int
echo_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
{
    uprintf("Closing device \"echo.\"\n");
    return(0);
}

/*
* The read function just takes the buf that was saved via
* echo_write() and returns it to userland for accessing.
* uio(9)
*/

static int
echo_read(struct cdev *dev, struct uio *uio, int ioflag)
{
    int err = 0;
    int amt;

    /*
     * How big is this read operation?  Either as big as the user wants,
     * or as big as the remaining data
     */
     amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ?
         echomsg->len - uio->uio_offset : 0);
    if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
        uprintf("uiomove failed!\n");
    }
    return(err);
}

/*
* echo_write takes in a character string and saves it
* to buf for later accessing.
*/

static int
echo_write(struct cdev *dev, struct uio *uio, int ioflag)
{
    int err = 0;

    /* Copy the string in from user memory to kernel memory */
    err = copyin(uio->uio_iov->iov_base, echomsg->msg,
        MIN(uio->uio_iov->iov_len,BUFFERSIZE));

    /* Now we need to null terminate, then record the length */
    *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
    echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);

    if (err != 0) {
        uprintf("Write failed: bad address!\n");
    }
    count++;
    return(err);
}

DEV_MODULE(echo,echo_loader,NULL);

_________________________________________________________________
Talk with your online friends with MSN Messenger http://messenger.msn.nl/



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?BAY17-F28uaYve5T7HV000d0ed0>