Home | History | Annotate | Line # | Download | only in intro
intro.c revision 1.1
      1 /*	$NetBSD: intro.c,v 1.1 2007/11/20 18:58:17 pooka Exp $	*/
      2 
      3 /*
      4  * El extra-simplo example of the userspace driver framework.
      5  *
      6  * Eventually there will be a library a la libpuffs (perhaps,
      7  * gasp, even the same lib), but for now it's all manual until
      8  * I get it figured out.
      9  *
     10  * So how to run this?
     11  * 0) sh MAKEDEV putter (if you don't have a freshly created /dev)
     12  * 1) run this program with the argument "/dev/pud"
     13  * 2) mknod a char device with the major 377 (see sources below)
     14  * 3) echo ascii art and jokes into device created in previous step
     15  *    or read the device
     16  */
     17 
     18 #include <sys/types.h>
     19 
     20 #include <dev/pud/pud_msgif.h>
     21 
     22 #include <err.h>
     23 #include <errno.h>
     24 #include <fcntl.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <unistd.h>
     29 
     30 #define DEFALLOC 1024*1024
     31 #define ECHOSTR "Would you like some sauce diable with that?\n"
     32 
     33 #ifndef MIN
     34 #define MIN(a,b) ((a)<(b)?(a):(b))
     35 #endif
     36 
     37 int
     38 main(int argc, char *argv[])
     39 {
     40 	struct pud_req *pdr = malloc(DEFALLOC);
     41 	struct pud_conf_reg pcr;
     42 	int fd;
     43 	ssize_t n;
     44 
     45 	if (argc != 2)
     46 		errx(1, "args");
     47 
     48 	/*
     49 	 * open pud device
     50 	 */
     51 	fd = open(argv[1], O_RDWR);
     52 	if (fd == -1)
     53 		err(1, "open");
     54 
     55 	/*
     56 	 * register our major number
     57 	 */
     58 	memset(&pcr, 0, sizeof(pcr));
     59 	pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
     60 	pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
     61 	pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
     62 
     63 	pcr.pm_regdev = makedev(377, 0);
     64 	pcr.pm_flags = 0;
     65 	strlcpy(pcr.pm_devname, "testdev", sizeof(pcr.pm_devname));
     66 
     67 	n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
     68 	if (n == -1)
     69 		err(1, "configure write");
     70 
     71 	/*
     72 	 * process requests
     73 	 */
     74 	for (;;) {
     75 		n = read(fd, pdr, DEFALLOC);
     76 		printf("read %d\n", n);
     77 
     78 		if (pdr->pdr_reqclass != PUD_REQ_CDEV) {
     79 			printf("class %d not supported\n", pdr->pdr_reqclass);
     80 			abort();
     81 		}
     82 
     83 		switch (pdr->pdr_reqtype) {
     84 		case PUD_CDEV_OPEN:
     85 		case PUD_CDEV_CLOSE:
     86 			printf("got openclose %d\n", pdr->pdr_reqtype);
     87 			pdr->pdr_rv = 0;
     88 			break;
     89 
     90 		case PUD_CDEV_READ:
     91 		{
     92 			struct pud_creq_read *pc_read;
     93 			size_t clen;
     94 
     95 			pc_read = (void *)pdr;
     96 			clen = MIN(strlen(ECHOSTR), pc_read->pm_resid);
     97 			strncpy(pc_read->pm_data, ECHOSTR, clen);
     98 			pc_read->pm_resid -= clen;
     99 			pdr->pdr_pth.pth_framelen =
    100 			    sizeof(struct pud_creq_read) + clen;
    101 		}
    102 			break;
    103 
    104 		case PUD_CDEV_WRITE:
    105 		{
    106 			struct pud_creq_write *pc_write;
    107 
    108 			pc_write = (void *)pdr;
    109 			pc_write->pm_data[pc_write->pm_resid] = '\0';
    110 			printf("got via write: %s", pc_write->pm_data);
    111 			pdr->pdr_pth.pth_framelen =
    112 			    sizeof(struct pud_creq_write);
    113 			pc_write->pm_resid = 0;
    114 		}
    115 			break;
    116 
    117 		default:
    118 			abort();
    119 		}
    120 
    121 		n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
    122 		printf("wrote %d %d\n", n, errno);
    123 	}
    124 }
    125