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