Home | History | Annotate | Line # | Download | only in hdaudioctl
graph.c revision 1.3
      1 /* $NetBSD: graph.c,v 1.3 2015/03/28 14:09:59 jmcneill 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 static const char *pin_devices[16] = {
     49 	"Line Out", "Speaker", "HP Out", "CD",
     50 	"SPDIF Out", "Digital Out", "Modem Line", "Modem Handset",
     51 	"Line In", "AUX", "Mic In", "Telephony",
     52 	"SPDIF In", "Digital In", "Reserved", "Other"
     53 };
     54 
     55 int
     56 hdaudioctl_graph(int fd, int argc, char *argv[])
     57 {
     58 	prop_dictionary_t request, response;
     59 	prop_object_iterator_t iter;
     60 	prop_number_t nnid;
     61 	prop_array_t connlist;
     62 	const char *name;
     63 	int error, index;
     64 	uint32_t cap, config;
     65 	uint16_t reqnid, reqcodecid;
     66 	uint16_t vendor, product;
     67 	uint8_t type, nid;
     68 	char buf[10] = "??h";
     69 
     70 	if (argc != 2)
     71 		usage();
     72 
     73 	reqcodecid = strtol(argv[0], NULL, 0);
     74 	reqnid = strtol(argv[1], NULL, 0);
     75 
     76 	request = prop_dictionary_create();
     77 	if (request == NULL) {
     78 		fprintf(stderr, "out of memory\n");
     79 		return ENOMEM;
     80 	}
     81 
     82 	prop_dictionary_set_uint16(request, "codecid", reqcodecid);
     83 	prop_dictionary_set_uint16(request, "nid", reqnid);
     84 
     85 	error = prop_dictionary_sendrecv_ioctl(request, fd,
     86 	    HDAUDIO_FGRP_CODEC_INFO, &response);
     87 	if (error != 0) {
     88 		perror("HDAUDIO_FGRP_CODEC_INFO failed");
     89 		prop_object_release(request);
     90 		return error;
     91 	}
     92 
     93 	prop_dictionary_get_uint16(response, "vendor-id", &vendor);
     94 	prop_dictionary_get_uint16(response, "product-id", &product);
     95 
     96 	printf("digraph \"HD Audio %04X:%04X\" {\n",
     97 	    vendor, product);
     98 
     99 	for (index = 0;; index++) {
    100 		prop_dictionary_set_uint16(request, "index", index);
    101 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    102 		    HDAUDIO_FGRP_WIDGET_INFO, &response);
    103 		if (error != 0)
    104 			break;
    105 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    106 		prop_dictionary_get_uint32(response, "cap", &cap);
    107 		prop_dictionary_get_uint32(response, "config", &config);
    108 		prop_dictionary_get_uint8(response, "type", &type);
    109 		prop_dictionary_get_uint8(response, "nid", &nid);
    110 
    111 		sprintf(buf, "widget%02Xh", nid);
    112 
    113 		switch (type) {
    114 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    115 			printf(" %s [label=\"%s\\naudio output\",shape=box,style=filled,fillcolor=\""
    116 			    "#88ff88\"];\n", buf, buf);
    117 			break;
    118 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    119 			printf(" %s [label=\"%s\\naudio input\",shape=box,style=filled,fillcolor=\""
    120 			    "#ff8888\"];\n", buf, buf);
    121 			break;
    122 		case COP_AWCAP_TYPE_AUDIO_MIXER:
    123 			printf(" %s [label=\"%s\\naudio mixer\","
    124 			    "shape=invhouse];\n", buf, buf);
    125 			break;
    126 		case COP_AWCAP_TYPE_AUDIO_SELECTOR:
    127 			printf(" %s [label=\"%s\\naudio selector\","
    128 			    "shape=invtrapezium];\n", buf, buf);
    129 			break;
    130 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    131 			printf(" %s [label=\"%s\\ndevice=%s\",style=filled",
    132 			    buf, buf,
    133 			    pin_devices[COP_CFG_DEFAULT_DEVICE(config)]);
    134 			if (cap & COP_PINCAP_OUTPUT_CAPABLE &&
    135 			    cap & COP_PINCAP_INPUT_CAPABLE)
    136 				puts(",shape=doublecircle,fillcolor=\""
    137 				    "#ffff88\"];");
    138 			else if (cap & COP_PINCAP_OUTPUT_CAPABLE)
    139 				puts(",shape=circle,fillcolor=\"#88ff88\"];");
    140 			else if (cap & COP_PINCAP_INPUT_CAPABLE)
    141 				puts(",shape=circle,fillcolor=\"#ff8888\"];");
    142 			else
    143 				puts(",shape=circle,fillcolor=\"#888888\"];");
    144 			break;
    145 		case COP_AWCAP_TYPE_POWER_WIDGET:
    146 			printf(" %s [label=\"%s\\npower widget\","
    147 			    "shape=box];\n", buf, buf);
    148 			break;
    149 		case COP_AWCAP_TYPE_VOLUME_KNOB:
    150 			printf(" %s [label=\"%s\\nvolume knob\","
    151 			    "shape=box];\n", buf, buf);
    152 			break;
    153 		case COP_AWCAP_TYPE_BEEP_GENERATOR:
    154 			printf(" %s [label=\"%s\\nbeep generator\","
    155 			    "shape=box];\n", buf, buf);
    156 			break;
    157 		case COP_AWCAP_TYPE_VENDOR_DEFINED:
    158 			printf(" %s [label=\"%s\\nvendor defined\","
    159 			    "shape=box];\n", buf, buf);
    160 			break;
    161 		}
    162 		connlist = prop_dictionary_get(response, "connlist");
    163 		if (connlist == NULL)
    164 			goto next;
    165 		iter = prop_array_iterator(connlist);
    166 		prop_object_iterator_reset(iter);
    167 		while ((nnid = prop_object_iterator_next(iter)) != NULL) {
    168 			nid = prop_number_unsigned_integer_value(nnid);
    169 			printf(" widget%02Xh -> %s [sametail=widget%02Xh];\n",
    170 			    nid, buf, nid);
    171 		}
    172 		prop_object_iterator_release(iter);
    173 next:
    174 		prop_object_release(response);
    175 	}
    176 
    177 	printf(" {rank=min;");
    178 	for (index = 0;; index++) {
    179 		prop_dictionary_set_uint16(request, "index", index);
    180 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    181 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    182 		if (error != 0)
    183 			break;
    184 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    185 		prop_dictionary_get_uint8(response, "type", &type);
    186 		prop_dictionary_get_uint8(response, "nid", &nid);
    187 
    188 		sprintf(buf, "widget%02Xh", nid);
    189 
    190 		switch (type) {
    191 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    192 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    193 			printf(" %s;", buf);
    194 			break;
    195 		}
    196 		prop_object_release(response);
    197 	}
    198 	printf("}\n");
    199 
    200 	printf(" {rank=max;");
    201 	for (index = 0;; index++) {
    202 		prop_dictionary_set_uint16(request, "index", index);
    203 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    204 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    205 		if (error != 0)
    206 			break;
    207 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    208 		prop_dictionary_get_uint8(response, "type", &type);
    209 		prop_dictionary_get_uint8(response, "nid", &nid);
    210 
    211 		sprintf(buf, "widget%02Xh", nid);
    212 
    213 		switch (type) {
    214 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    215 			printf(" %s;", buf);
    216 			break;
    217 		}
    218 		prop_object_release(response);
    219 	}
    220 	printf("}\n");
    221 
    222 	printf("}\n");
    223 
    224 	prop_object_release(request);
    225 
    226 	return 0;
    227 }
    228