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