Home | History | Annotate | Line # | Download | only in hdaudioctl
graph.c revision 1.1.4.2
      1 /* $NetBSD: graph.c,v 1.1.4.2 2010/04/21 05:27:21 matt Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2009 Precedence Technologies Ltd <support (at) precedence.co.uk>
      5  * Copyright (c) 2009 Jared D. McNeill <jmcneill (at) 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/pci/hdaudio/hdaudioio.h>
     44 #include <dev/pci/hdaudio/hdaudioreg.h>
     45 
     46 #include "hdaudioctl.h"
     47 
     48 static const char *pin_devices[16] = {
     49 	"Line Out", "Speaker", "HP Out", "CD",
     50 	"SPDIF Out", "Digital Out", "Modem Line", "Modem Handset",
     51 	"Line In", "AUX", "Mic In", "Telephony",
     52 	"SPDIF In", "Digital In", "Reserved", "Other"
     53 };
     54 
     55 int
     56 hdaudioctl_graph(int fd, int argc, char *argv[])
     57 {
     58 	prop_dictionary_t request, response;
     59 	prop_object_iterator_t iter;
     60 	prop_number_t nnid;
     61 	prop_array_t connlist;
     62 	const char *name;
     63 	int error, index;
     64 	uint32_t cap, config;
     65 	uint16_t reqnid, reqcodecid;
     66 	uint16_t vendor, product;
     67 	uint8_t type, nid;
     68 	char buf[10] = "??h";
     69 
     70 	if (argc != 2)
     71 		usage();
     72 
     73 	reqcodecid = strtol(argv[0], NULL, 0);
     74 	reqnid = strtol(argv[1], NULL, 0);
     75 
     76 	request = prop_dictionary_create();
     77 	if (request == NULL) {
     78 		fprintf(stderr, "out of memory\n");
     79 		return ENOMEM;
     80 	}
     81 
     82 	prop_dictionary_set_uint16(request, "codecid", reqcodecid);
     83 	prop_dictionary_set_uint16(request, "nid", reqnid);
     84 
     85 	error = prop_dictionary_sendrecv_ioctl(request, fd,
     86 	    HDAUDIO_FGRP_CODEC_INFO, &response);
     87 	if (error != 0) {
     88 		perror("HDAUDIO_FGRP_CODEC_INFO failed");
     89 		prop_object_release(request);
     90 		return error;
     91 	}
     92 
     93 	prop_dictionary_get_uint16(response, "vendor-id", &vendor);
     94 	prop_dictionary_get_uint16(response, "product-id", &product);
     95 
     96 	printf("digraph \"HD Audio %04X:%04X\" {\n",
     97 	    vendor, product);
     98 
     99 	for (index = 0;; index++) {
    100 		prop_dictionary_set_uint16(request, "index", index);
    101 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    102 		    HDAUDIO_FGRP_WIDGET_INFO, &response);
    103 		if (error != 0)
    104 			break;
    105 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    106 		prop_dictionary_get_uint32(response, "cap", &cap);
    107 		prop_dictionary_get_uint32(response, "config", &config);
    108 		prop_dictionary_get_uint8(response, "type", &type);
    109 		prop_dictionary_get_uint8(response, "nid", &nid);
    110 
    111 		sprintf(buf, "widget%02Xh", nid);
    112 
    113 		switch (type) {
    114 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    115 			printf(" %s [shape=box,style=filled,fillcolor=\""
    116 			    "#88ff88\"];\n", buf);
    117 			break;
    118 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    119 			printf(" %s [shape=box,style=filled,fillcolor=\""
    120 			    "#ff8888\"];\n", buf);
    121 			break;
    122 		case COP_AWCAP_TYPE_AUDIO_MIXER:
    123 			printf(" %s [shape=invhouse];\n", buf);
    124 			break;
    125 		case COP_AWCAP_TYPE_AUDIO_SELECTOR:
    126 			printf(" %s [shape=invtrapezium];\n", buf);
    127 			break;
    128 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    129 			printf(" %s [label=\"%s\\ndevice=%s\",style=filled",
    130 			    buf, buf,
    131 			    pin_devices[COP_CFG_DEFAULT_DEVICE(config)]);
    132 			if (cap & COP_PINCAP_OUTPUT_CAPABLE &&
    133 			    cap & COP_PINCAP_INPUT_CAPABLE)
    134 				printf(",shape=doublecircle,fillcolor=\""
    135 				    "#ffff88\"];\n");
    136 			else if (cap & COP_PINCAP_OUTPUT_CAPABLE)
    137 				printf(",shape=circle,fillcolor=\"#88ff88\"];\n");
    138 			else if (cap & COP_PINCAP_INPUT_CAPABLE)
    139 				printf(",shape=circle,fillcolor=\"#ff8888\"];\n");
    140 			else
    141 				printf(",shape=circle,fillcolor=\"#888888\"];\n");
    142 			break;
    143 		}
    144 		connlist = prop_dictionary_get(response, "connlist");
    145 		if (connlist == NULL)
    146 			goto next;
    147 		iter = prop_array_iterator(connlist);
    148 		prop_object_iterator_reset(iter);
    149 		while ((nnid = prop_object_iterator_next(iter)) != NULL) {
    150 			nid = prop_number_unsigned_integer_value(nnid);
    151 			printf(" widget%02Xh -> %s [sametail=widget%02Xh];\n",
    152 			    nid, buf, nid);
    153 		}
    154 		prop_object_iterator_release(iter);
    155 next:
    156 		prop_object_release(response);
    157 	}
    158 
    159 	printf(" {rank=min;");
    160 	for (index = 0;; index++) {
    161 		prop_dictionary_set_uint16(request, "index", index);
    162 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    163 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    164 		if (error != 0)
    165 			break;
    166 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    167 		prop_dictionary_get_uint8(response, "type", &type);
    168 		prop_dictionary_get_uint8(response, "nid", &nid);
    169 
    170 		sprintf(buf, "widget%02Xh", nid);
    171 
    172 		switch (type) {
    173 		case COP_AWCAP_TYPE_AUDIO_OUTPUT:
    174 		case COP_AWCAP_TYPE_AUDIO_INPUT:
    175 			printf(" %s;", buf);
    176 			break;
    177 		}
    178 		prop_object_release(response);
    179 	}
    180 	printf("}\n");
    181 
    182 	printf(" {rank=max;");
    183 	for (index = 0;; index++) {
    184 		prop_dictionary_set_uint16(request, "index", index);
    185 		error = prop_dictionary_sendrecv_ioctl(request, fd,
    186 		    HDAUDIO_AFG_WIDGET_INFO, &response);
    187 		if (error != 0)
    188 			break;
    189 		prop_dictionary_get_cstring_nocopy(response, "name", &name);
    190 		prop_dictionary_get_uint8(response, "type", &type);
    191 		prop_dictionary_get_uint8(response, "nid", &nid);
    192 
    193 		sprintf(buf, "widget%02Xh", nid);
    194 
    195 		switch (type) {
    196 		case COP_AWCAP_TYPE_PIN_COMPLEX:
    197 			printf(" %s;", buf);
    198 			break;
    199 		}
    200 		prop_object_release(response);
    201 	}
    202 	printf("}\n");
    203 
    204 	printf("}\n");
    205 
    206 	prop_object_release(request);
    207 
    208 	return 0;
    209 }
    210