1 /* $NetBSD: graph.c,v 1.5 2020/06/15 13:06:39 sborrill Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk> 5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@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_cstring_nocopy(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_cstring_nocopy(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_cstring_nocopy(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