Home | History | Annotate | Line # | Download | only in intro
intro.c revision 1.4.4.2
      1  1.4.4.2  matt /*	$NetBSD: intro.c,v 1.4.4.2 2008/01/09 01:38:58 matt Exp $	*/
      2  1.4.4.2  matt 
      3  1.4.4.2  matt /*
      4  1.4.4.2  matt  * El extra-simplo example of the userspace driver framework.
      5  1.4.4.2  matt  *
      6  1.4.4.2  matt  * Eventually there will be a library a la libpuffs (perhaps,
      7  1.4.4.2  matt  * gasp, even the same lib), but for now it's all manual until
      8  1.4.4.2  matt  * I get it figured out.
      9  1.4.4.2  matt  *
     10  1.4.4.2  matt  * So how to run this?
     11  1.4.4.2  matt  * 0) sh MAKEDEV putter (if you don't have a freshly created /dev)
     12  1.4.4.2  matt  * 1) run this program with the argument "/dev/pud"
     13  1.4.4.2  matt  * 2) mknod a char device with the major 377 (see sources below)
     14  1.4.4.2  matt  * 3) echo ascii art and jokes into device created in previous step
     15  1.4.4.2  matt  *    or read the device
     16  1.4.4.2  matt  */
     17  1.4.4.2  matt 
     18  1.4.4.2  matt #include <sys/types.h>
     19  1.4.4.2  matt 
     20  1.4.4.2  matt #include <dev/pud/pud_msgif.h>
     21  1.4.4.2  matt 
     22  1.4.4.2  matt #include <err.h>
     23  1.4.4.2  matt #include <errno.h>
     24  1.4.4.2  matt #include <fcntl.h>
     25  1.4.4.2  matt #include <stdio.h>
     26  1.4.4.2  matt #include <stdlib.h>
     27  1.4.4.2  matt #include <string.h>
     28  1.4.4.2  matt #include <unistd.h>
     29  1.4.4.2  matt 
     30  1.4.4.2  matt #include "common.h"
     31  1.4.4.2  matt 
     32  1.4.4.2  matt #define DEFALLOC 1024*1024
     33  1.4.4.2  matt #define ECHOSTR1 "Would you like some sauce diable with that?\n"
     34  1.4.4.2  matt #define ECHOSTR2 "Nej tack, you fool, I'm happy with my tournedos Rossini\n"
     35  1.4.4.2  matt #define NSTR 2
     36  1.4.4.2  matt 
     37  1.4.4.2  matt const char *curstr = ECHOSTR1;
     38  1.4.4.2  matt 
     39  1.4.4.2  matt #ifndef MIN
     40  1.4.4.2  matt #define MIN(a,b) ((a)<(b)?(a):(b))
     41  1.4.4.2  matt #endif
     42  1.4.4.2  matt 
     43  1.4.4.2  matt int
     44  1.4.4.2  matt main(int argc, char *argv[])
     45  1.4.4.2  matt {
     46  1.4.4.2  matt 	struct pud_req *pdr = malloc(DEFALLOC);
     47  1.4.4.2  matt 	struct pud_conf_reg pcr;
     48  1.4.4.2  matt 	int fd;
     49  1.4.4.2  matt 	ssize_t n;
     50  1.4.4.2  matt 
     51  1.4.4.2  matt 	if (argc != 2)
     52  1.4.4.2  matt 		errx(1, "args");
     53  1.4.4.2  matt 
     54  1.4.4.2  matt 	/*
     55  1.4.4.2  matt 	 * open pud device
     56  1.4.4.2  matt 	 */
     57  1.4.4.2  matt 	fd = open(argv[1], O_RDWR);
     58  1.4.4.2  matt 	if (fd == -1)
     59  1.4.4.2  matt 		err(1, "open");
     60  1.4.4.2  matt 
     61  1.4.4.2  matt 	/*
     62  1.4.4.2  matt 	 * register our major number
     63  1.4.4.2  matt 	 */
     64  1.4.4.2  matt 	memset(&pcr, 0, sizeof(pcr));
     65  1.4.4.2  matt 	pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
     66  1.4.4.2  matt 	pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION;
     67  1.4.4.2  matt 	pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
     68  1.4.4.2  matt 	pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
     69  1.4.4.2  matt 
     70  1.4.4.2  matt 	pcr.pm_regdev = makedev(377, 0);
     71  1.4.4.2  matt 	pcr.pm_flags = PUD_CONFFLAG_BDEV;
     72  1.4.4.2  matt 	strlcpy(pcr.pm_devname, "testdev", sizeof(pcr.pm_devname));
     73  1.4.4.2  matt 
     74  1.4.4.2  matt 	n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
     75  1.4.4.2  matt 	if (n == -1)
     76  1.4.4.2  matt 		err(1, "configure write");
     77  1.4.4.2  matt 
     78  1.4.4.2  matt 	/*
     79  1.4.4.2  matt 	 * process requests
     80  1.4.4.2  matt 	 */
     81  1.4.4.2  matt 	for (;;) {
     82  1.4.4.2  matt 		n = read(fd, pdr, DEFALLOC);
     83  1.4.4.2  matt 		printf("read %d %d\n", n, errno);
     84  1.4.4.2  matt 
     85  1.4.4.2  matt 		switch (pdr->pdr_reqtype) {
     86  1.4.4.2  matt 		case PUD_CDEV_OPEN:
     87  1.4.4.2  matt 		case PUD_CDEV_CLOSE:
     88  1.4.4.2  matt 			printf("got openclose %d\n", pdr->pdr_reqtype);
     89  1.4.4.2  matt 			pdr->pdr_rv = 0;
     90  1.4.4.2  matt 			break;
     91  1.4.4.2  matt 
     92  1.4.4.2  matt 		case PUD_CDEV_READ:
     93  1.4.4.2  matt 		/* uh oh case PUD_BDEV_STRATREAD: */
     94  1.4.4.2  matt 		{
     95  1.4.4.2  matt 			struct pud_creq_read *pc_read;
     96  1.4.4.2  matt 			size_t clen;
     97  1.4.4.2  matt 
     98  1.4.4.2  matt 			pc_read = (void *)pdr;
     99  1.4.4.2  matt 			printf("read from offset %llu, resid %zu\n",
    100  1.4.4.2  matt 			    (unsigned long long)pc_read->pm_offset,
    101  1.4.4.2  matt 			    pc_read->pm_resid);
    102  1.4.4.2  matt 
    103  1.4.4.2  matt 			clen = MIN(strlen(curstr), pc_read->pm_resid);
    104  1.4.4.2  matt 			strncpy(pc_read->pm_data, curstr, clen);
    105  1.4.4.2  matt 			if (pdr->pdr_reqclass == PUD_REQ_BDEV) {
    106  1.4.4.2  matt 				clen = pc_read->pm_resid;
    107  1.4.4.2  matt 				pc_read->pm_resid = 0;
    108  1.4.4.2  matt 			} else {
    109  1.4.4.2  matt 				pc_read->pm_resid -= clen;
    110  1.4.4.2  matt 			}
    111  1.4.4.2  matt 			pdr->pdr_pth.pth_framelen =
    112  1.4.4.2  matt 			    sizeof(struct pud_creq_read) + clen;
    113  1.4.4.2  matt 		}
    114  1.4.4.2  matt 			break;
    115  1.4.4.2  matt 
    116  1.4.4.2  matt 		case PUD_CDEV_WRITE:
    117  1.4.4.2  matt 		/* uh uh oh case PUD_BDEV_STRATWRITE: */
    118  1.4.4.2  matt 		{
    119  1.4.4.2  matt 			struct pud_creq_write *pc_write;
    120  1.4.4.2  matt 
    121  1.4.4.2  matt 			pc_write = (void *)pdr;
    122  1.4.4.2  matt 			printf("write to offset %llu, resid %zu\n",
    123  1.4.4.2  matt 			    (unsigned long long)pc_write->pm_offset,
    124  1.4.4.2  matt 			    pc_write->pm_resid);
    125  1.4.4.2  matt 
    126  1.4.4.2  matt 			pc_write->pm_data[pc_write->pm_resid] = '\0';
    127  1.4.4.2  matt 			printf("got via write: %s", pc_write->pm_data);
    128  1.4.4.2  matt 			pdr->pdr_pth.pth_framelen =
    129  1.4.4.2  matt 			    sizeof(struct pud_creq_write);
    130  1.4.4.2  matt 			pc_write->pm_resid = 0;
    131  1.4.4.2  matt 		}
    132  1.4.4.2  matt 			break;
    133  1.4.4.2  matt 
    134  1.4.4.2  matt 		case PUD_CDEV_IOCTL:
    135  1.4.4.2  matt 		{
    136  1.4.4.2  matt 			struct pud_req_ioctl *pc_ioctl;
    137  1.4.4.2  matt 			int *iocval;
    138  1.4.4.2  matt 
    139  1.4.4.2  matt 			pc_ioctl = (void *)pdr;
    140  1.4.4.2  matt 			switch (pc_ioctl->pm_iocmd) {
    141  1.4.4.2  matt 			case INTROTOGGLE:
    142  1.4.4.2  matt 			case INTROTOGGLE_R:
    143  1.4.4.2  matt 				iocval = (int *)pc_ioctl->pm_data;
    144  1.4.4.2  matt 				if (*iocval < 0 || *iocval > 2) {
    145  1.4.4.2  matt 					pdr->pdr_rv = ERANGE;
    146  1.4.4.2  matt 					break;
    147  1.4.4.2  matt 				}
    148  1.4.4.2  matt 
    149  1.4.4.2  matt 				if (*iocval == 1)
    150  1.4.4.2  matt 					curstr = ECHOSTR1;
    151  1.4.4.2  matt 				else
    152  1.4.4.2  matt 					curstr = ECHOSTR2;
    153  1.4.4.2  matt 
    154  1.4.4.2  matt 				*iocval = 0;
    155  1.4.4.2  matt 				break;
    156  1.4.4.2  matt 			default:
    157  1.4.4.2  matt 				abort();
    158  1.4.4.2  matt 			}
    159  1.4.4.2  matt 		}
    160  1.4.4.2  matt 			break;
    161  1.4.4.2  matt 
    162  1.4.4.2  matt 		default:
    163  1.4.4.2  matt 			abort();
    164  1.4.4.2  matt 		}
    165  1.4.4.2  matt 
    166  1.4.4.2  matt 		n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
    167  1.4.4.2  matt 		printf("wrote %d %d\n", n, errno);
    168  1.4.4.2  matt 	}
    169  1.4.4.2  matt }
    170