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