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