graph.c revision 1.1 1 1.1 sborrill /* $NetBSD: graph.c,v 1.1 2009/10/11 08:57:54 sborrill 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.1 sborrill #include <dev/pci/hdaudio/hdaudioio.h>
44 1.1 sborrill #include <dev/pci/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.1 sborrill printf(" %s [shape=box,style=filled,fillcolor=\""
116 1.1 sborrill "#88ff88\"];\n", buf);
117 1.1 sborrill break;
118 1.1 sborrill case COP_AWCAP_TYPE_AUDIO_INPUT:
119 1.1 sborrill printf(" %s [shape=box,style=filled,fillcolor=\""
120 1.1 sborrill "#ff8888\"];\n", buf);
121 1.1 sborrill break;
122 1.1 sborrill case COP_AWCAP_TYPE_AUDIO_MIXER:
123 1.1 sborrill printf(" %s [shape=invhouse];\n", buf);
124 1.1 sborrill break;
125 1.1 sborrill case COP_AWCAP_TYPE_AUDIO_SELECTOR:
126 1.1 sborrill printf(" %s [shape=invtrapezium];\n", buf);
127 1.1 sborrill break;
128 1.1 sborrill case COP_AWCAP_TYPE_PIN_COMPLEX:
129 1.1 sborrill printf(" %s [label=\"%s\\ndevice=%s\",style=filled",
130 1.1 sborrill buf, buf,
131 1.1 sborrill pin_devices[COP_CFG_DEFAULT_DEVICE(config)]);
132 1.1 sborrill if (cap & COP_PINCAP_OUTPUT_CAPABLE &&
133 1.1 sborrill cap & COP_PINCAP_INPUT_CAPABLE)
134 1.1 sborrill printf(",shape=doublecircle,fillcolor=\""
135 1.1 sborrill "#ffff88\"];\n");
136 1.1 sborrill else if (cap & COP_PINCAP_OUTPUT_CAPABLE)
137 1.1 sborrill printf(",shape=circle,fillcolor=\"#88ff88\"];\n");
138 1.1 sborrill else if (cap & COP_PINCAP_INPUT_CAPABLE)
139 1.1 sborrill printf(",shape=circle,fillcolor=\"#ff8888\"];\n");
140 1.1 sborrill else
141 1.1 sborrill printf(",shape=circle,fillcolor=\"#888888\"];\n");
142 1.1 sborrill break;
143 1.1 sborrill }
144 1.1 sborrill connlist = prop_dictionary_get(response, "connlist");
145 1.1 sborrill if (connlist == NULL)
146 1.1 sborrill goto next;
147 1.1 sborrill iter = prop_array_iterator(connlist);
148 1.1 sborrill prop_object_iterator_reset(iter);
149 1.1 sborrill while ((nnid = prop_object_iterator_next(iter)) != NULL) {
150 1.1 sborrill nid = prop_number_unsigned_integer_value(nnid);
151 1.1 sborrill printf(" widget%02Xh -> %s [sametail=widget%02Xh];\n",
152 1.1 sborrill nid, buf, nid);
153 1.1 sborrill }
154 1.1 sborrill prop_object_iterator_release(iter);
155 1.1 sborrill next:
156 1.1 sborrill prop_object_release(response);
157 1.1 sborrill }
158 1.1 sborrill
159 1.1 sborrill printf(" {rank=min;");
160 1.1 sborrill for (index = 0;; index++) {
161 1.1 sborrill prop_dictionary_set_uint16(request, "index", index);
162 1.1 sborrill error = prop_dictionary_sendrecv_ioctl(request, fd,
163 1.1 sborrill HDAUDIO_AFG_WIDGET_INFO, &response);
164 1.1 sborrill if (error != 0)
165 1.1 sborrill break;
166 1.1 sborrill prop_dictionary_get_cstring_nocopy(response, "name", &name);
167 1.1 sborrill prop_dictionary_get_uint8(response, "type", &type);
168 1.1 sborrill prop_dictionary_get_uint8(response, "nid", &nid);
169 1.1 sborrill
170 1.1 sborrill sprintf(buf, "widget%02Xh", nid);
171 1.1 sborrill
172 1.1 sborrill switch (type) {
173 1.1 sborrill case COP_AWCAP_TYPE_AUDIO_OUTPUT:
174 1.1 sborrill case COP_AWCAP_TYPE_AUDIO_INPUT:
175 1.1 sborrill printf(" %s;", buf);
176 1.1 sborrill break;
177 1.1 sborrill }
178 1.1 sborrill prop_object_release(response);
179 1.1 sborrill }
180 1.1 sborrill printf("}\n");
181 1.1 sborrill
182 1.1 sborrill printf(" {rank=max;");
183 1.1 sborrill for (index = 0;; index++) {
184 1.1 sborrill prop_dictionary_set_uint16(request, "index", index);
185 1.1 sborrill error = prop_dictionary_sendrecv_ioctl(request, fd,
186 1.1 sborrill HDAUDIO_AFG_WIDGET_INFO, &response);
187 1.1 sborrill if (error != 0)
188 1.1 sborrill break;
189 1.1 sborrill prop_dictionary_get_cstring_nocopy(response, "name", &name);
190 1.1 sborrill prop_dictionary_get_uint8(response, "type", &type);
191 1.1 sborrill prop_dictionary_get_uint8(response, "nid", &nid);
192 1.1 sborrill
193 1.1 sborrill sprintf(buf, "widget%02Xh", nid);
194 1.1 sborrill
195 1.1 sborrill switch (type) {
196 1.1 sborrill case COP_AWCAP_TYPE_PIN_COMPLEX:
197 1.1 sborrill printf(" %s;", buf);
198 1.1 sborrill break;
199 1.1 sborrill }
200 1.1 sborrill prop_object_release(response);
201 1.1 sborrill }
202 1.1 sborrill printf("}\n");
203 1.1 sborrill
204 1.1 sborrill printf("}\n");
205 1.1 sborrill
206 1.1 sborrill prop_object_release(request);
207 1.1 sborrill
208 1.1 sborrill return 0;
209 1.1 sborrill }
210