xref: /minix3/minix/usr.bin/trace/ioctl/char.c (revision 4f89addcc198bff2fc614da2f8f4a7beb4b6cb7d)
1 
2 #include "inc.h"
3 
4 #include <dev/pci/pciio.h>
5 
6 #include <minix/fb.h>
7 #include <minix/i2c.h>
8 #include <minix/keymap.h>
9 #include <minix/sound.h>
10 
11 #include <sys/fcntl.h>
12 #include <sys/ioctl.h>
13 #include <sys/kbdio.h>
14 #include <sys/termios.h>
15 #include <sys/time.h>
16 
17 const char *
18 char_ioctl_name(unsigned long req)
19 {
20 
21 	switch (req) {
22 	NAME(MINIX_I2C_IOCTL_EXEC);
23 	NAME(FBIOGET_VSCREENINFO);
24 	NAME(FBIOPUT_VSCREENINFO);
25 	NAME(FBIOGET_FSCREENINFO);	/* TODO: print argument */
26 	NAME(FBIOPAN_DISPLAY);
27 	NAME(DSPIORATE);
28 	NAME(DSPIOSTEREO);
29 	NAME(DSPIOSIZE);
30 	NAME(DSPIOBITS);
31 	NAME(DSPIOSIGN);
32 	NAME(DSPIOMAX);
33 	NAME(DSPIORESET);		/* no argument */
34 	NAME(DSPIOFREEBUF);
35 	NAME(DSPIOSAMPLESINBUF);
36 	NAME(DSPIOPAUSE);		/* no argument */
37 	NAME(DSPIORESUME);		/* no argument */
38 	NAME(MIXIOGETVOLUME);
39 	NAME(MIXIOGETINPUTLEFT);
40 	NAME(MIXIOGETINPUTRIGHT);
41 	NAME(MIXIOGETOUTPUT);
42 	NAME(MIXIOSETVOLUME);
43 	NAME(MIXIOSETINPUTLEFT);
44 	NAME(MIXIOSETINPUTRIGHT);
45 	NAME(MIXIOSETOUTPUT);
46 	NAME(TIOCEXCL);			/* no argument */
47 	NAME(TIOCNXCL);			/* no argument */
48 	NAME(TIOCFLUSH);
49 	NAME(TIOCGETA);
50 	NAME(TIOCSETA);
51 	NAME(TIOCSETAW);
52 	NAME(TIOCSETAF);
53 	NAME(TIOCGETD);
54 	NAME(TIOCSETD);
55 	NAME(TIOCGLINED);
56 	NAME(TIOCSLINED);
57 	NAME(TIOCSBRK);			/* no argument */
58 	NAME(TIOCCBRK);			/* no argument */
59 	NAME(TIOCSDTR);			/* no argument */
60 	NAME(TIOCCDTR);			/* no argument */
61 	NAME(TIOCGPGRP);
62 	NAME(TIOCSPGRP);
63 	NAME(TIOCOUTQ);
64 	NAME(TIOCSTI);
65 	NAME(TIOCNOTTY);		/* no argument */
66 	NAME(TIOCPKT);
67 	NAME(TIOCSTOP);			/* no argument */
68 	NAME(TIOCSTART);		/* no argument */
69 	NAME(TIOCMSET);			/* TODO: print argument */
70 	NAME(TIOCMBIS);			/* TODO: print argument */
71 	NAME(TIOCMBIC);			/* TODO: print argument */
72 	NAME(TIOCMGET);			/* TODO: print argument */
73 	NAME(TIOCREMOTE);
74 	NAME(TIOCGWINSZ);
75 	NAME(TIOCSWINSZ);
76 	NAME(TIOCUCNTL);
77 	NAME(TIOCSTAT);
78 	NAME(TIOCGSID);
79 	NAME(TIOCCONS);
80 	NAME(TIOCSCTTY);		/* no argument */
81 	NAME(TIOCEXT);
82 	NAME(TIOCSIG);			/* no argument */
83 	NAME(TIOCDRAIN);		/* no argument */
84 	NAME(TIOCGFLAGS);		/* TODO: print argument */
85 	NAME(TIOCSFLAGS);		/* TODO: print argument */
86 	NAME(TIOCDCDTIMESTAMP);		/* TODO: print argument */
87 	NAME(TIOCRCVFRAME);		/* TODO: print argument */
88 	NAME(TIOCXMTFRAME);		/* TODO: print argument */
89 	NAME(TIOCPTMGET);		/* TODO: print argument */
90 	NAME(TIOCGRANTPT);		/* no argument */
91 	NAME(TIOCPTSNAME);		/* TODO: print argument */
92 	NAME(TIOCSQSIZE);
93 	NAME(TIOCGQSIZE);
94 	NAME(TIOCSFON);			/* big IOCTL, not printing argument */
95 	NAME(KIOCBELL);
96 	NAME(KIOCSLEDS);
97 	NAME(KIOCSMAP);			/* not worth interpreting */
98 	NAME(PCI_IOC_CFGREAD);
99 	NAME(PCI_IOC_CFGWRITE);
100 	NAME(PCI_IOC_BDF_CFGREAD);
101 	NAME(PCI_IOC_BDF_CFGWRITE);
102 	NAME(PCI_IOC_BUSINFO);
103 	NAME(PCI_IOC_MAP);
104 	NAME(PCI_IOC_UNMAP);
105 	NAME(PCI_IOC_RESERVE);
106 	NAME(PCI_IOC_RELEASE);
107 	}
108 
109 	return NULL;
110 }
111 
112 static void
113 put_i2c_op(struct trace_proc * proc, const char *name, i2c_op_t op)
114 {
115 	const char *text = NULL;
116 
117 	if (!valuesonly) {
118 		switch (op) {
119 		TEXT(I2C_OP_READ);
120 		TEXT(I2C_OP_READ_WITH_STOP);
121 		TEXT(I2C_OP_WRITE);
122 		TEXT(I2C_OP_WRITE_WITH_STOP);
123 		TEXT(I2C_OP_READ_BLOCK);
124 		TEXT(I2C_OP_WRITE_BLOCK);
125 		}
126 	}
127 
128 	if (text != NULL)
129 		put_field(proc, name, text);
130 	else
131 		put_value(proc, name, "%d", op);
132 }
133 
134 static void
135 put_sound_device(struct trace_proc * proc, const char * name, int device)
136 {
137 	const char *text = NULL;
138 
139 	if (!valuesonly) {
140 		switch (device) {
141 		TEXT(Master);
142 		TEXT(Dac);
143 		TEXT(Fm);
144 		TEXT(Cd);
145 		TEXT(Line);
146 		TEXT(Mic);
147 		TEXT(Speaker);
148 		TEXT(Treble);
149 		TEXT(Bass);
150 		}
151 	}
152 
153 	if (text != NULL)
154 		put_field(proc, name, text);
155 	else
156 		put_value(proc, name, "%d", device);
157 }
158 
159 static void
160 put_sound_state(struct trace_proc * proc, const char * name, int state)
161 {
162 
163 	if (!valuesonly && state == ON)
164 		put_field(proc, name, "ON");
165 	else if (!valuesonly && state == OFF)
166 		put_field(proc, name, "OFF");
167 	else
168 		put_value(proc, name, "%d", state);
169 }
170 
171 static const struct flags flush_flags[] = {
172 	FLAG(FREAD),
173 	FLAG(FWRITE),
174 };
175 
176 static const struct flags tc_iflags[] = {
177 	FLAG(IGNBRK),
178 	FLAG(BRKINT),
179 	FLAG(IGNPAR),
180 	FLAG(PARMRK),
181 	FLAG(INPCK),
182 	FLAG(ISTRIP),
183 	FLAG(INLCR),
184 	FLAG(IGNCR),
185 	FLAG(ICRNL),
186 	FLAG(IXON),
187 	FLAG(IXOFF),
188 	FLAG(IXANY),
189 	FLAG(IMAXBEL),
190 };
191 
192 static const struct flags tc_oflags[] = {
193 	FLAG(OPOST),
194 	FLAG(ONLCR),
195 	FLAG(OXTABS),
196 	FLAG(ONOEOT),
197 	FLAG(OCRNL),
198 	FLAG(ONOCR),
199 	FLAG(ONLRET),
200 };
201 
202 static const struct flags tc_cflags[] = {
203 	FLAG(CIGNORE),
204 	FLAG_MASK(CSIZE, CS5),
205 	FLAG_MASK(CSIZE, CS6),
206 	FLAG_MASK(CSIZE, CS7),
207 	FLAG_MASK(CSIZE, CS8),
208 	FLAG(CSTOPB),
209 	FLAG(CREAD),
210 	FLAG(PARENB),
211 	FLAG(PARODD),
212 	FLAG(HUPCL),
213 	FLAG(CLOCAL),
214 	FLAG(CRTSCTS),
215 	FLAG(CDTRCTS),
216 	FLAG(MDMBUF),
217 };
218 
219 static const struct flags tc_lflags[] = {
220 	FLAG(ECHOKE),
221 	FLAG(ECHOE),
222 	FLAG(ECHOK),
223 	FLAG(ECHO),
224 	FLAG(ECHONL),
225 	FLAG(ECHOPRT),
226 	FLAG(ECHOCTL),
227 	FLAG(ISIG),
228 	FLAG(ICANON),
229 	FLAG(ALTWERASE),
230 	FLAG(IEXTEN),
231 	FLAG(EXTPROC),
232 	FLAG(TOSTOP),
233 	FLAG(FLUSHO),
234 	FLAG(NOKERNINFO),
235 	FLAG(PENDIN),
236 	FLAG(NOFLSH),
237 };
238 
239 static void
240 put_tty_disc(struct trace_proc * proc, const char * name, int disc)
241 {
242 	const char *text = NULL;
243 
244 	if (!valuesonly) {
245 		switch (disc) {
246 		TEXT(TTYDISC);
247 		TEXT(TABLDISC);
248 		TEXT(SLIPDISC);
249 		TEXT(PPPDISC);
250 		TEXT(STRIPDISC);
251 		TEXT(HDLCDISC);
252 		}
253 	}
254 
255 	if (text != NULL)
256 		put_field(proc, name, text);
257 	else
258 		put_value(proc, name, "%d", disc);
259 }
260 
261 static const struct flags kbd_leds[] = {
262 	FLAG(KBD_LEDS_NUM),
263 	FLAG(KBD_LEDS_CAPS),
264 	FLAG(KBD_LEDS_SCROLL),
265 };
266 
267 int
268 char_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr,
269 	int dir)
270 {
271 	minix_i2c_ioctl_exec_t *iie;
272 	struct fb_var_screeninfo *fbvs;
273 	struct volume_level *level;
274 	struct inout_ctrl *inout;
275 	struct termios *tc;
276 	struct winsize *ws;
277 	struct kio_bell *bell;
278 	struct kio_leds *leds;
279 	struct pciio_cfgreg *pci_cfgreg;
280 	struct pciio_bdf_cfgreg *pci_bdf_cfgreg;
281 	struct pciio_businfo *pci_businfo;
282 	struct pciio_map *pci_iomap;
283 	struct pciio_acl *pci_acl;
284 
285 
286 	switch (req) {
287 	case MINIX_I2C_IOCTL_EXEC:
288 		if ((iie = (minix_i2c_ioctl_exec_t *)ptr) == NULL)
289 			return IF_OUT; /* we print only the request for now */
290 
291 		put_i2c_op(proc, "iie_op", iie->iie_op);
292 		put_value(proc, "iie_addr", "0x%04x", iie->iie_addr);
293 		return 0; /* TODO: print command/data/result */
294 
295 	case FBIOGET_VSCREENINFO:
296 		if ((fbvs = (struct fb_var_screeninfo *)ptr) == NULL)
297 			return IF_IN;
298 
299 		put_value(proc, "xres", "%"PRIu32, fbvs->xres);
300 		put_value(proc, "yres", "%"PRIu32, fbvs->yres);
301 		put_value(proc, "xres_virtual", "%"PRIu32, fbvs->xres_virtual);
302 		put_value(proc, "yres_virtual", "%"PRIu32, fbvs->yres_virtual);
303 		put_value(proc, "xoffset", "%"PRIu32, fbvs->xoffset);
304 		put_value(proc, "yoffset", "%"PRIu32, fbvs->yoffset);
305 		put_value(proc, "bits_per_pixel", "%"PRIu32,
306 		    fbvs->bits_per_pixel);
307 		return 0;
308 
309 	case FBIOPUT_VSCREENINFO:
310 	case FBIOPAN_DISPLAY:
311 		if ((fbvs = (struct fb_var_screeninfo *)ptr) == NULL)
312 			return IF_OUT;
313 
314 		put_value(proc, "xoffset", "%"PRIu32, fbvs->xoffset);
315 		put_value(proc, "yoffset", "%"PRIu32, fbvs->yoffset);
316 		return 0;
317 
318 	case DSPIORATE:
319 	case DSPIOSTEREO:
320 	case DSPIOSIZE:
321 	case DSPIOBITS:
322 	case DSPIOSIGN:
323 	case DSPIOMAX:
324 	case DSPIOFREEBUF:
325 	case DSPIOSAMPLESINBUF:
326 		if (ptr == NULL)
327 			return dir;
328 
329 		put_value(proc, NULL, "%u", *(unsigned int *)ptr);
330 		return IF_ALL;
331 
332 	case MIXIOGETVOLUME:
333 		if ((level = (struct volume_level *)ptr) == NULL)
334 			return dir;
335 
336 		if (dir == IF_OUT)
337 			put_sound_device(proc, "device", level->device);
338 		else {
339 			put_value(proc, "left", "%d", level->left);
340 			put_value(proc, "right", "%d", level->right);
341 		}
342 		return IF_ALL;
343 
344 	case MIXIOSETVOLUME:
345 		/* Print the corrected volume levels only with verbosity on. */
346 		if ((level = (struct volume_level *)ptr) == NULL)
347 			return IF_OUT | ((verbose > 0) ? IF_IN : 0);
348 
349 		if (dir == IF_OUT)
350 			put_sound_device(proc, "device", level->device);
351 		put_value(proc, "left", "%d", level->left);
352 		put_value(proc, "right", "%d", level->right);
353 		return IF_ALL;
354 
355 	case MIXIOGETINPUTLEFT:
356 	case MIXIOGETINPUTRIGHT:
357 	case MIXIOGETOUTPUT:
358 		if ((inout = (struct inout_ctrl *)ptr) == NULL)
359 			return dir;
360 
361 		if (dir == IF_OUT)
362 			put_sound_device(proc, "device", inout->device);
363 		else {
364 			put_sound_state(proc, "left", inout->left);
365 			put_sound_state(proc, "right", inout->right);
366 		}
367 		return IF_ALL;
368 
369 	case MIXIOSETINPUTLEFT:
370 	case MIXIOSETINPUTRIGHT:
371 	case MIXIOSETOUTPUT:
372 		if ((inout = (struct inout_ctrl *)ptr) == NULL)
373 			return IF_OUT;
374 
375 		put_sound_device(proc, "device", inout->device);
376 		put_sound_state(proc, "left", inout->left);
377 		put_sound_state(proc, "right", inout->right);
378 		return IF_ALL;
379 
380 	case TIOCFLUSH:
381 		if (ptr == NULL)
382 			return IF_OUT;
383 
384 		put_flags(proc, NULL, flush_flags, COUNT(flush_flags), "0x%x",
385 		    *(int *)ptr);
386 		return IF_ALL;
387 
388 	case TIOCGETA:
389 	case TIOCSETA:
390 	case TIOCSETAW:
391 	case TIOCSETAF:
392 		if ((tc = (struct termios *)ptr) == NULL)
393 			return dir;
394 
395 		/*
396 		 * These are fairly common IOCTLs, so printing everything by
397 		 * default would create a lot of noise.  By default we limit
398 		 * ourselves to printing the field that contains what I
399 		 * consider to be the most important flag: ICANON.
400 		 * TODO: see if we can come up with a decent format for
401 		 * selectively printing (relatively important) flags.
402 		 */
403 		if (verbose > 0) {
404 			put_flags(proc, "c_iflag", tc_iflags, COUNT(tc_iflags),
405 			    "0x%x", tc->c_iflag);
406 			put_flags(proc, "c_oflag", tc_oflags, COUNT(tc_oflags),
407 			    "0x%x", tc->c_oflag);
408 			put_flags(proc, "c_cflag", tc_cflags, COUNT(tc_cflags),
409 			    "0x%x", tc->c_cflag);
410 		}
411 		put_flags(proc, "c_lflag", tc_lflags, COUNT(tc_lflags), "0x%x",
412 			tc->c_lflag);
413 		if (verbose > 0) {
414 			put_value(proc, "c_ispeed", "%d", tc->c_ispeed);
415 			put_value(proc, "c_ospeed", "%d", tc->c_ospeed);
416 		}
417 		return 0; /* TODO: print the c_cc fields */
418 
419 	case TIOCGETD:
420 	case TIOCSETD:
421 		if (ptr == NULL)
422 			return dir;
423 
424 		put_tty_disc(proc, NULL, *(int *)ptr);
425 		return IF_ALL;
426 
427 	case TIOCGLINED:
428 	case TIOCSLINED:
429 		if (ptr == NULL)
430 			return dir;
431 
432 		put_buf(proc, NULL, PF_LOCADDR | PF_STRING, (vir_bytes)ptr,
433 		    sizeof(linedn_t));
434 		return IF_ALL;
435 
436 	case TIOCGPGRP:
437 	case TIOCSPGRP:
438 	case TIOCOUTQ:
439 	case TIOCPKT:
440 	case TIOCREMOTE:
441 	case TIOCUCNTL:
442 	case TIOCSTAT:		/* argument seems unused? */
443 	case TIOCGSID:
444 	case TIOCCONS:		/* argument seems unused? */
445 	case TIOCEXT:
446 	case TIOCSQSIZE:
447 	case TIOCGQSIZE:
448 		/* Print a simple integer. */
449 		if (ptr == NULL)
450 			return dir;
451 
452 		put_value(proc, NULL, "%d", *(int *)ptr);
453 		return IF_ALL;
454 
455 	case TIOCSTI:
456 		if (ptr == NULL)
457 			return dir;
458 
459 		if (!valuesonly)
460 			put_value(proc, NULL, "'%s'",
461 			    get_escape(*(char *)ptr));
462 		else
463 			put_value(proc, NULL, "%u", *(char *)ptr);
464 		return IF_ALL;
465 
466 	case TIOCGWINSZ:
467 	case TIOCSWINSZ:
468 		if ((ws = (struct winsize *)ptr) == NULL)
469 			return dir;
470 
471 		/* This is a stupid order, but we follow the struct layout. */
472 		put_value(proc, "ws_row", "%u", ws->ws_row);
473 		put_value(proc, "ws_col", "%u", ws->ws_col);
474 		if (verbose > 0) {
475 			put_value(proc, "ws_xpixel", "%u", ws->ws_xpixel);
476 			put_value(proc, "ws_ypixel", "%u", ws->ws_ypixel);
477 		}
478 		return (verbose > 0) ? IF_ALL : 0;
479 
480 	case KIOCBELL:
481 		if ((bell = (struct kio_bell *)ptr) == NULL)
482 			return IF_OUT;
483 
484 		put_value(proc, "kb_pitch", "%u", bell->kb_pitch);
485 		put_value(proc, "kb_volume", "%lu", bell->kb_volume);
486 		put_struct_timeval(proc, "kb_duration", PF_LOCADDR,
487 		    (vir_bytes)&bell->kb_duration);
488 
489 		return IF_ALL;
490 
491 	case KIOCSLEDS:
492 		if ((leds = (struct kio_leds *)ptr) == NULL)
493 			return IF_OUT;
494 
495 		put_flags(proc, "kl_bits", kbd_leds, COUNT(kbd_leds), "0x%x",
496 		    leds->kl_bits);
497 		return IF_ALL;
498 
499 	case PCI_IOC_CFGREAD:
500 		if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL)
501 			return IF_IN;
502 
503 		put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg);
504 		put_value(proc, "val", "%08x", pci_cfgreg->val);
505 		return IF_ALL;
506 
507 	case PCI_IOC_CFGWRITE:
508 		if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL)
509 			return IF_OUT;
510 
511 		put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg);
512 		put_value(proc, "val", "%08x", pci_cfgreg->val);
513 		return IF_ALL;
514 
515 	case PCI_IOC_BDF_CFGREAD:
516 		if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL)
517 			return IF_IN;
518 
519 		put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus);
520 		put_value(proc, "device", "%u", pci_bdf_cfgreg->device);
521 		put_value(proc, "function", "%u", pci_bdf_cfgreg->function);
522 		put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg);
523 		put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val);
524 		return IF_ALL;
525 
526 	case PCI_IOC_BDF_CFGWRITE:
527 		if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL)
528 			return IF_OUT;
529 
530 		put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus);
531 		put_value(proc, "device", "%u", pci_bdf_cfgreg->device);
532 		put_value(proc, "function", "%u", pci_bdf_cfgreg->function);
533 		put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg);
534 		put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val);
535 		return IF_ALL;
536 
537 	case PCI_IOC_BUSINFO:
538 		if ((pci_businfo = (struct pciio_businfo *)ptr) == NULL)
539 			return IF_IN;
540 
541 		put_value(proc, "busno", "%u", pci_businfo->busno);
542 		put_value(proc, "maxdevs", "%u", pci_businfo->maxdevs);
543 		return IF_ALL;
544 
545 	case PCI_IOC_MAP:
546 		if ((pci_iomap = (struct pciio_map *)ptr) == NULL)
547 			return IF_OUT|IF_IN;
548 
549 		put_value(proc, "flags", "%x", pci_iomap->flags);
550 		put_value(proc, "phys_offset", "%08x", pci_iomap->phys_offset);
551 		put_value(proc, "size", "%zu", pci_iomap->size);
552 		put_value(proc, "readonly", "%x", pci_iomap->readonly);
553 
554 		if (IF_IN == dir)
555 			put_ptr(proc, "vaddr_ret", (vir_bytes)pci_iomap->vaddr_ret);
556 
557 		return IF_ALL;
558 
559 	case PCI_IOC_UNMAP:
560 		if ((pci_iomap = (struct pciio_map *)ptr) == NULL)
561 			return IF_OUT;
562 
563 		put_ptr(proc, "vaddr", (vir_bytes)pci_iomap->vaddr);
564 
565 		return IF_ALL;
566 
567 	case PCI_IOC_RESERVE:
568 		if ((pci_acl = (struct pciio_acl *)ptr) == NULL)
569 			return IF_OUT;
570 
571 		put_value(proc, "domain", "%u", pci_acl->domain);
572 		put_value(proc, "bus", "%u", pci_acl->bus);
573 		put_value(proc, "device", "%u", pci_acl->device);
574 		put_value(proc, "function", "%u", pci_acl->function);
575 
576 		return IF_ALL;
577 	case PCI_IOC_RELEASE:
578 		if ((pci_acl = (struct pciio_acl *)ptr) == NULL)
579 			return IF_OUT;
580 
581 		put_value(proc, "domain", "%u", pci_acl->domain);
582 		put_value(proc, "bus", "%u", pci_acl->bus);
583 		put_value(proc, "device", "%u", pci_acl->device);
584 		put_value(proc, "function", "%u", pci_acl->function);
585 
586 		return IF_ALL;
587 
588 	default:
589 		return 0;
590 	}
591 }
592