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