xref: /minix/minix/usr.bin/trace/ioctl/char.c (revision 0a6a1f1d)
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 ptmget *pm;
277 	struct winsize *ws;
278 	struct kio_bell *bell;
279 	struct kio_leds *leds;
280 	struct pciio_cfgreg *pci_cfgreg;
281 	struct pciio_bdf_cfgreg *pci_bdf_cfgreg;
282 	struct pciio_businfo *pci_businfo;
283 	struct pciio_map *pci_iomap;
284 	struct pciio_acl *pci_acl;
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 TIOCPTSNAME:
456 		if ((pm = (struct ptmget *)ptr) == NULL)
457 			return IF_IN;
458 
459 		put_buf(proc, "sn", PF_LOCADDR | PF_STRING, (vir_bytes)pm->sn,
460 		    sizeof(pm->sn));
461 		return IF_ALL;
462 
463 	case TIOCSTI:
464 		if (ptr == NULL)
465 			return dir;
466 
467 		if (!valuesonly)
468 			put_value(proc, NULL, "'%s'",
469 			    get_escape(*(char *)ptr));
470 		else
471 			put_value(proc, NULL, "%u", *(char *)ptr);
472 		return IF_ALL;
473 
474 	case TIOCGWINSZ:
475 	case TIOCSWINSZ:
476 		if ((ws = (struct winsize *)ptr) == NULL)
477 			return dir;
478 
479 		/* This is a stupid order, but we follow the struct layout. */
480 		put_value(proc, "ws_row", "%u", ws->ws_row);
481 		put_value(proc, "ws_col", "%u", ws->ws_col);
482 		if (verbose > 0) {
483 			put_value(proc, "ws_xpixel", "%u", ws->ws_xpixel);
484 			put_value(proc, "ws_ypixel", "%u", ws->ws_ypixel);
485 		}
486 		return (verbose > 0) ? IF_ALL : 0;
487 
488 	case KIOCBELL:
489 		if ((bell = (struct kio_bell *)ptr) == NULL)
490 			return IF_OUT;
491 
492 		put_value(proc, "kb_pitch", "%u", bell->kb_pitch);
493 		put_value(proc, "kb_volume", "%lu", bell->kb_volume);
494 		put_struct_timeval(proc, "kb_duration", PF_LOCADDR,
495 		    (vir_bytes)&bell->kb_duration);
496 
497 		return IF_ALL;
498 
499 	case KIOCSLEDS:
500 		if ((leds = (struct kio_leds *)ptr) == NULL)
501 			return IF_OUT;
502 
503 		put_flags(proc, "kl_bits", kbd_leds, COUNT(kbd_leds), "0x%x",
504 		    leds->kl_bits);
505 		return IF_ALL;
506 
507 	case PCI_IOC_CFGREAD:
508 		if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL)
509 			return IF_IN;
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_CFGWRITE:
516 		if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL)
517 			return IF_OUT;
518 
519 		put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg);
520 		put_value(proc, "val", "%08x", pci_cfgreg->val);
521 		return IF_ALL;
522 
523 	case PCI_IOC_BDF_CFGREAD:
524 		if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL)
525 			return IF_IN;
526 
527 		put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus);
528 		put_value(proc, "device", "%u", pci_bdf_cfgreg->device);
529 		put_value(proc, "function", "%u", pci_bdf_cfgreg->function);
530 		put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg);
531 		put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val);
532 		return IF_ALL;
533 
534 	case PCI_IOC_BDF_CFGWRITE:
535 		if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL)
536 			return IF_OUT;
537 
538 		put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus);
539 		put_value(proc, "device", "%u", pci_bdf_cfgreg->device);
540 		put_value(proc, "function", "%u", pci_bdf_cfgreg->function);
541 		put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg);
542 		put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val);
543 		return IF_ALL;
544 
545 	case PCI_IOC_BUSINFO:
546 		if ((pci_businfo = (struct pciio_businfo *)ptr) == NULL)
547 			return IF_IN;
548 
549 		put_value(proc, "busno", "%u", pci_businfo->busno);
550 		put_value(proc, "maxdevs", "%u", pci_businfo->maxdevs);
551 		return IF_ALL;
552 
553 	case PCI_IOC_MAP:
554 		if ((pci_iomap = (struct pciio_map *)ptr) == NULL)
555 			return IF_OUT|IF_IN;
556 
557 		put_value(proc, "flags", "%x", pci_iomap->flags);
558 		put_value(proc, "phys_offset", "%08x", pci_iomap->phys_offset);
559 		put_value(proc, "size", "%zu", pci_iomap->size);
560 		put_value(proc, "readonly", "%x", pci_iomap->readonly);
561 
562 		if (IF_IN == dir)
563 			put_ptr(proc, "vaddr_ret", (vir_bytes)pci_iomap->vaddr_ret);
564 
565 		return IF_ALL;
566 
567 	case PCI_IOC_UNMAP:
568 		if ((pci_iomap = (struct pciio_map *)ptr) == NULL)
569 			return IF_OUT;
570 
571 		put_ptr(proc, "vaddr", (vir_bytes)pci_iomap->vaddr);
572 
573 		return IF_ALL;
574 
575 	case PCI_IOC_RESERVE:
576 		if ((pci_acl = (struct pciio_acl *)ptr) == NULL)
577 			return IF_OUT;
578 
579 		put_value(proc, "domain", "%u", pci_acl->domain);
580 		put_value(proc, "bus", "%u", pci_acl->bus);
581 		put_value(proc, "device", "%u", pci_acl->device);
582 		put_value(proc, "function", "%u", pci_acl->function);
583 
584 		return IF_ALL;
585 	case PCI_IOC_RELEASE:
586 		if ((pci_acl = (struct pciio_acl *)ptr) == NULL)
587 			return IF_OUT;
588 
589 		put_value(proc, "domain", "%u", pci_acl->domain);
590 		put_value(proc, "bus", "%u", pci_acl->bus);
591 		put_value(proc, "device", "%u", pci_acl->device);
592 		put_value(proc, "function", "%u", pci_acl->function);
593 
594 		return IF_ALL;
595 
596 	default:
597 		return 0;
598 	}
599 }
600