Home | History | Annotate | Line # | Download | only in hdaudioctl
      1 /* $NetBSD: graph.c,v 1.6 2021/06/21 03:09:52 christos Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2009 Precedence Technologies Ltd <support (at) precedence.co.uk>
      5  * Copyright (c) 2009 Jared D. McNeill <jmcneill (at) invisible.ca>
      6  * All rights reserved.
      7  *
      8  * This code is derived from software contributed to The NetBSD Foundation
      9  * by Precedence Technologies Ltd
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/types.h>
     33 #include <sys/ioctl.h>
     34 
     35 #include <prop/proplib.h>
     36 
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <unistd.h>
     42 
     43 #include <dev/hdaudio/hdaudioio.h>
     44 #include <dev/hdaudio/hdaudioreg.h>
     45 
     46 #include "hdaudioctl.h"
     47 
     48 int
     49 hdaudioctl_graph(int fd, int argc, char *argv[])
     50 {
     51 	prop_dictionary_t request, response;
     52 	prop_object_iterator_t iter;
     53 	prop_number_t nnid;
     54 	prop_array_t connlist;
     55 	const char *name;
     56 	int error, index;
     57 	uint32_t cap, config;
     58 	uint16_t reqnid, reqcodecid;
     59 	uint16_t vendor, product;
     60 	uint8_t type, nid;
     61 	char buf[10] = "??h";
     62 
     63 	if (argc != 2)
     64 		usage();
     65 
     66 	reqcodecid = strtol(argv[0], NULL, 0);
     67 	reqnid = strtol(argv[1], NULL, 0);
     68 
     69 	request = prop_dictionary_create();
     70 	if (request == NULL) {
     71 		fprintf(stderr, "out of memory\n");
     72 		return ENOMEM;
     73 	}
     74 
     75 	prop_dictionary_set_uint16(request, "codecid", reqcodecid);
     76 	prop_dictionary_set_uint16(request, "nid", reqnid);
     77 
     78 	error = prop_dictionary_sendrecv_ioctl(request, fd,
     79 	    HDAUDIO_FGRP_CODEC_INFO, &response);
     80 	if (error != 0) {
     81 		perror("HDAUDIO_FGRP_CODEC_INFO failed");
     82 		prop_object_release(request);
     83 		return error;
     84 	}
     85 
     86 	prop_dictionary_get_uint16(response, "vendor-id", &vendor);
     87 	prop_dictionary_get_uint16(response, "product-id", &product);
     88 
     89 	printf("digraph \"HD Audio %04X:%04X\" {\n",
     90 	    vendor, product);
     91 
     92 	for (index = 0;; index++) {
     93 		prop_dictionary_set_uint16(request, "index", index);
     94 		error = prop_dictionary_sendrecv_ioctl(request, fd,
     95 		    HDAUDIO_FGRP_WIDGET_INFO, &response);
     96 		if (error != 0)
     97 			break;
     98 		prop_dictionary_get_string(response, "name", &name);
     99 		prop_dictionary_get_uint32(response, "cap", &cap);
    100 		prop_dictionary_get_uint32(response, "config", &config);
    101 		prop_dictionary_get_uint8(response, "type", &type);
    102 		prop_dictionary_get_uint8(response, "nid", &nid);
    103 
    104 		sprintf(buf, "widget%02Xh", nid);
    105 
    106 		switch (type) {
    107 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    108 			printf(" %s [label=\"%s\\naudio output\",shape=box,style=filled,fillcolor=\""
    109 			    "#88ff88\"];\n", buf, buf);
    110 			break;
    111 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    112 			printf(" %s [label=\"%s\\naudio input\",shape=box,style=filled,fillcolor=\""
    113 			    "#ff8888\"];\n", buf, buf);
    114 			break;
    115 		case COP_AWCAP_TYPE_AUDIO_MIXER:
    116 			printf(" %s [label=\"%s\\naudio mixer\","
    117 			    "shape=invhouse];\n", buf, buf);
    118 			break;
    119 		case COP_AWCAP_TYPE_AUDIO_SELECTOR:
    120 			printf(" %s [label=\"%s\\naudio selector\","
    121 			    "shape=invtrapezium];\n", buf, buf);
    122 			break;
    123 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    124 			printf(" %s [label=\"%s\\ndevice=%s\",style=filled",
    125 			    buf, buf,
    126 			    pin_devices[COP_CFG_DEFAULT_DEVICE(config)]);
    127 			if (cap & COP_PINCAP_OUTPUT_CAPABLE &&
    128 			    cap & COP_PINCAP_INPUT_CAPABLE)
    129 				puts(",shape=doublecircle,fillcolor=\""
    130 				    "#ffff88\"];");
    131 			else if (cap & COP_PINCAP_OUTPUT_CAPABLE)
    132 				puts(",shape=circle,fillcolor=\"#88ff88\"];");
    133 			else if (cap & COP_PINCAP_INPUT_CAPABLE)
    134 				puts(",shape=circle,fillcolor=\"#ff8888\"];");
    135 			else
    136 				puts(",shape=circle,fillcolor=\"#888888\"];");
    137 			break;
    138 		case COP_AWCAP_TYPE_POWER_WIDGET:
    139 			printf(" %s [label=\"%s\\npower widget\","
    140 			    "shape=box];\n", buf, buf);
    141 			break;
    142 		case COP_AWCAP_TYPE_VOLUME_KNOB:
    143 			printf(" %s [label=\"%s\\nvolume knob\","
    144 			    "shape=box];\n", buf, buf);
    145 			break;
    146 		case COP_AWCAP_TYPE_BEEP_GENERATOR:
    147 			printf(" %s [label=\"%s\\nbeep generator\","
    148 			    "shape=box];\n", buf, buf);
    149 			break;
    150 		case COP_AWCAP_TYPE_VENDOR_DEFINED:
    151 			printf(" %s [label=\"%s\\nvendor defined\","
    152 			    "shape=box];\n", buf, buf);
    153 			break;
    154 		}
    155 		connlist = prop_dictionary_get(response, "connlist");
    156 		if (connlist == NULL)
    157 			goto next;
    158 		iter = prop_array_iterator(connlist);
    159 		prop_object_iterator_reset(iter);
    160 		while ((nnid = prop_object_iterator_next(iter)) != NULL) {
    161 			nid = prop_number_unsigned_value(nnid);
    162 			printf(" widget%02Xh -> %s [sametail=widget%02Xh];\n",
    163 			    nid, buf, nid);
    164 		}
    165 		prop_object_iterator_release(iter);
    166 next:
    167 		prop_object_release(response);
    168 	}
    169 
    170 	printf(" {rank=min;");
    171 	for (index = 0;; index++) {
    172 		prop_dictionary_set_uint16(request, "index", index);
    173 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    174 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    175 		if (error != 0)
    176 			break;
    177 		prop_dictionary_get_string(response, "name", &name);
    178 		prop_dictionary_get_uint8(response, "type", &type);
    179 		prop_dictionary_get_uint8(response, "nid", &nid);
    180 
    181 		sprintf(buf, "widget%02Xh", nid);
    182 
    183 		switch (type) {
    184 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    185 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    186 			printf(" %s;", buf);
    187 			break;
    188 		}
    189 		prop_object_release(response);
    190 	}
    191 	printf("}\n");
    192 
    193 	printf(" {rank=max;");
    194 	for (index = 0;; index++) {
    195 		prop_dictionary_set_uint16(request, "index", index);
    196 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    197 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    198 		if (error != 0)
    199 			break;
    200 		prop_dictionary_get_string(response, "name", &name);
    201 		prop_dictionary_get_uint8(response, "type", &type);
    202 		prop_dictionary_get_uint8(response, "nid", &nid);
    203 
    204 		sprintf(buf, "widget%02Xh", nid);
    205 
    206 		switch (type) {
    207 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    208 			printf(" %s;", buf);
    209 			break;
    210 		}
    211 		prop_object_release(response);
    212 	}
    213 	printf("}\n");
    214 
    215 	printf("}\n");
    216 
    217 	prop_object_release(request);
    218 
    219 	return 0;
    220 }
    221