Home | History | Annotate | Line # | Download | only in hdaudioctl
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