Captain's Universe Home
Captain's Universe Home
Cosmic Ray Muon DetectorTeleGarden Pages
Time on MarsBryophyllum Plants
Jupiter Radio AstronomyAncient Pages
Salzburg Tourist GuideEarth Magnetometer
  H O M E     AJAX & MORE     LINUX & MORE     RTAI     XENOMAI     ADEOS IPIPE      
    JAVA & BROWSERS     *NIX     ELECTRONICS     REVIEWS     ARTEMIA     FAIRY SHRIMP      



FreeBSD Kernel Module Example - Sample Echo Pseudo-Device Driver for FreeBSD 5.2 and FreeBSD 5.3:

There are two examples presented at:
http://freebsd.active-venture.com/arch-handbook/driverbasics-char.html

One for FreeBSD 4.x and one for FreeBSD 5.x, but the 5.x doesn't compile on 5.2 and 5.3. See error messages below. Gert van der Plas has modified it to compile on recent versions of FreeBSD and sent it to the freebsd-doc list.

Compile the module with "# make" and insert the module with:
# kldload -v ./echodev.ko
and test with:
# echo -n "Test Data" > /dev/echo
# cat /dev/echo
Test Data
Remove the module with:
# kldunload echodev
Tested on FreeBSD 5.3.

Example "echodev.c"
/*
* 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

test with:
# echo -n "Test Data" > /dev/echo
# cat /dev/echo
Test Data

*/

#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);

Makefile
SRCS=echodev.c
KMOD=echodev

.include <bsd.kmod.mk>
Compiler errors with the original 5.x source with FreeBSD 5.3 in the arch-handbook:
echodev.c: In function `echo_loader':
echodev.c:69: warning: assignment makes integer from pointer without a cast
echodev.c:75: warning: passing arg 1 of `destroy_dev' makes pointer from integer without a cast
echodev.c: At top level:
echodev.c:88: error: conflicting types for 'echo_open'
echodev.c:24: error: previous declaration of 'echo_open' was here
echodev.c:88: error: conflicting types for 'echo_open'
echodev.c:24: error: previous declaration of 'echo_open' was here
echodev.c:97: error: conflicting types for 'echo_close'
echodev.c:25: error: previous declaration of 'echo_close' was here
echodev.c:97: error: conflicting types for 'echo_close'
echodev.c:25: error: previous declaration of 'echo_close' was here
echodev.c:110: error: conflicting types for 'echo_read'
echodev.c:26: error: previous declaration of 'echo_read' was here
echodev.c:110: error: conflicting types for 'echo_read'
echodev.c:26: error: previous declaration of 'echo_read' was here
echodev.c:133: error: conflicting types for 'echo_write'
echodev.c:27: error: previous declaration of 'echo_write' was here
echodev.c:133: error: conflicting types for 'echo_write'
echodev.c:27: error: previous declaration of 'echo_write' was here
echodev.c:24: warning: 'echo_open' used but never defined
echodev.c:25: warning: 'echo_close' used but never defined
echodev.c:26: warning: 'echo_read' used but never defined
echodev.c:27: warning: 'echo_write' used but never defined
echodev.c:88: warning: 'echo_open' defined but not used
echodev.c:97: warning: 'echo_close' defined but not used
echodev.c:110: warning: 'echo_read' defined but not used
echodev.c:133: warning: 'echo_write' defined but not used
*** Error code 1


Last-Modified: Sat, 04 Feb 2006 16:12:34 GMT

Google
 
Web www.captain.at
go to top
© 1996-2010 . All rights reserved.
No reproduction, distribution, publishing or transmission of the copyrighted materials at this site is permitted. Policy
go to top