Module Name: src
Committed By: sborrill
Date: Sun Oct 11 08:57:55 UTC 2009
Modified Files:
src/distrib/sets/lists/base: mi
src/distrib/sets/lists/man: mi
src/doc: CHANGES
src/usr.sbin: Makefile
Added Files:
src/usr.sbin/hdaudioctl: Makefile graph.c hdaudioctl.8 hdaudioctl.c
hdaudioctl.h
Log Message:
Add hdaudioctl(8), a tool to manipulate hdaudio(4) devices.
It offer the following subcommands:
list - shows all child codec
get - get a plist of the chosen codec's widget configuration
set - forcibly reconfigure a specified codec from a plist
graph - generate a graphviz file for the specified codec
To generate a diff of this commit:
cvs rdiff -u -r1.832 -r1.833 src/distrib/sets/lists/base/mi
cvs rdiff -u -r1.1163 -r1.1164 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.1305 -r1.1306 src/doc/CHANGES
cvs rdiff -u -r1.242 -r1.243 src/usr.sbin/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.sbin/hdaudioctl/Makefile \
src/usr.sbin/hdaudioctl/graph.c src/usr.sbin/hdaudioctl/hdaudioctl.8 \
src/usr.sbin/hdaudioctl/hdaudioctl.c src/usr.sbin/hdaudioctl/hdaudioctl.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/base/mi
diff -u src/distrib/sets/lists/base/mi:1.832 src/distrib/sets/lists/base/mi:1.833
--- src/distrib/sets/lists/base/mi:1.832 Mon Oct 5 22:32:58 2009
+++ src/distrib/sets/lists/base/mi Sun Oct 11 08:57:54 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.832 2009/10/05 22:32:58 haad Exp $
+# $NetBSD: mi,v 1.833 2009/10/11 08:57:54 sborrill Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@@ -1068,6 +1068,7 @@
./usr/sbin/groupdel base-sysutil-bin
./usr/sbin/groupinfo base-sysutil-bin
./usr/sbin/groupmod base-sysutil-bin
+./usr/sbin/hdaudioctl base-sysutil-bin
./usr/sbin/hlfsd base-amd-bin
./usr/sbin/host base-obsolete obsolete
./usr/sbin/hostapd base-sysutil-bin
Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1163 src/distrib/sets/lists/man/mi:1.1164
--- src/distrib/sets/lists/man/mi:1.1163 Fri Oct 9 00:48:35 2009
+++ src/distrib/sets/lists/man/mi Sun Oct 11 08:57:54 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1163 2009/10/09 00:48:35 haad Exp $
+# $NetBSD: mi,v 1.1164 2009/10/11 08:57:54 sborrill Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -2118,6 +2118,7 @@
./usr/share/man/cat8/groupmod.0 man-sysutil-catman .cat
./usr/share/man/cat8/gspa.0 man-sysutil-catman .cat
./usr/share/man/cat8/halt.0 man-sysutil-catman .cat
+./usr/share/man/cat8/hdaudioctl.0 man-sysutil-catman .cat
./usr/share/man/cat8/hlfsd.0 man-amd-catman .cat
./usr/share/man/cat8/hostapd.0 man-sysutil-catman .cat
./usr/share/man/cat8/hostapd_cli.0 man-sysutil-catman .cat
@@ -4582,6 +4583,7 @@
./usr/share/man/html8/groupmod.html man-sysutil-htmlman html
./usr/share/man/html8/gspa.html man-sysutil-htmlman html
./usr/share/man/html8/halt.html man-sysutil-htmlman html
+./usr/share/man/html8/hdaudioctl.html man-sysutil-htmlman html
./usr/share/man/html8/hlfsd.html man-amd-htmlman html
./usr/share/man/html8/hostapd.html man-sysutil-htmlman html
./usr/share/man/html8/hostapd_cli.html man-sysutil-htmlman html
@@ -7143,6 +7145,7 @@
./usr/share/man/man8/groupmod.8 man-sysutil-man .man
./usr/share/man/man8/gspa.8 man-sysutil-man .man
./usr/share/man/man8/halt.8 man-sysutil-man .man
+./usr/share/man/man8/hdaudioctl.8 man-sysutil-man .man
./usr/share/man/man8/hlfsd.8 man-amd-man .man
./usr/share/man/man8/hostapd.8 man-sysutil-man .man
./usr/share/man/man8/hostapd_cli.8 man-sysutil-man .man
Index: src/doc/CHANGES
diff -u src/doc/CHANGES:1.1305 src/doc/CHANGES:1.1306
--- src/doc/CHANGES:1.1305 Wed Oct 7 08:47:47 2009
+++ src/doc/CHANGES Sun Oct 11 08:57:54 2009
@@ -1,4 +1,4 @@
-# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1305 $>
+# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1306 $>
#
#
# [Note: This file does not mention every change made to the NetBSD source tree.
@@ -419,3 +419,5 @@
dhcpcd(8): Import dhcpcd-5.1.1. [roy 20091002]
libm(3): Add f{dim,max,min}{,f,l} from FreeBSD [christos 20091004]
man(1): Display manpage when specified with a path [cegger 20091007]
+ hdaudioctl(8): Add tool to manipulate hdaudio(4) devices
+ [sborrill 20091011]
Index: src/usr.sbin/Makefile
diff -u src/usr.sbin/Makefile:1.242 src/usr.sbin/Makefile:1.243
--- src/usr.sbin/Makefile:1.242 Thu Jun 25 18:41:21 2009
+++ src/usr.sbin/Makefile Sun Oct 11 08:57:54 2009
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.242 2009/06/25 18:41:21 mbalmer Exp $
+# $NetBSD: Makefile,v 1.243 2009/10/11 08:57:54 sborrill Exp $
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
.include <bsd.own.mk>
@@ -8,7 +8,8 @@
chown chroot chrtbl cnwctl cpuctl crash cron dev_mkdb \
dhcp diskpart dumpfs dumplfs edquota eeprom \
envstat eshconfig etcupdate extattrctl fssconfig fusermount fwctl \
- gpioctl grfconfig grfinfo gspa hilinfo ifwatchd inetd installboot \
+ gpioctl grfconfig grfinfo gspa hdaudioctl hilinfo ifwatchd inetd \
+ installboot \
iopctl iostat ipwctl irdaattach isdn iteconfig iwictl\
kgmon lastlogin link lmcconfig lockstat lpr mailwrapper makefs \
map-mbone mdconfig memswitch mlxctl mmcformat mopd mountd moused \
Added files:
Index: src/usr.sbin/hdaudioctl/Makefile
diff -u /dev/null src/usr.sbin/hdaudioctl/Makefile:1.1
--- /dev/null Sun Oct 11 08:57:55 2009
+++ src/usr.sbin/hdaudioctl/Makefile Sun Oct 11 08:57:54 2009
@@ -0,0 +1,11 @@
+# $NetBSD: Makefile,v 1.1 2009/10/11 08:57:54 sborrill Exp $
+
+PROG= hdaudioctl
+SRCS= hdaudioctl.c
+SRCS+= graph.c
+MAN= hdaudioctl.8
+
+LDADD+= -lprop
+DPADD+= ${LIBPROP}
+
+.include <bsd.prog.mk>
Index: src/usr.sbin/hdaudioctl/graph.c
diff -u /dev/null src/usr.sbin/hdaudioctl/graph.c:1.1
--- /dev/null Sun Oct 11 08:57:55 2009
+++ src/usr.sbin/hdaudioctl/graph.c Sun Oct 11 08:57:54 2009
@@ -0,0 +1,209 @@
+/* $NetBSD: graph.c,v 1.1 2009/10/11 08:57:54 sborrill Exp $ */
+
+/*
+ * Copyright (c) 2009 Precedence Technologies Ltd <[email protected]>
+ * Copyright (c) 2009 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Precedence Technologies Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <prop/proplib.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <dev/pci/hdaudio/hdaudioio.h>
+#include <dev/pci/hdaudio/hdaudioreg.h>
+
+#include "hdaudioctl.h"
+
+static const char *pin_devices[16] = {
+ "Line Out", "Speaker", "HP Out", "CD",
+ "SPDIF Out", "Digital Out", "Modem Line", "Modem Handset",
+ "Line In", "AUX", "Mic In", "Telephony",
+ "SPDIF In", "Digital In", "Reserved", "Other"
+};
+
+int
+hdaudioctl_graph(int fd, int argc, char *argv[])
+{
+ prop_dictionary_t request, response;
+ prop_object_iterator_t iter;
+ prop_number_t nnid;
+ prop_array_t connlist;
+ const char *name;
+ int error, index;
+ uint32_t cap, config;
+ uint16_t reqnid, reqcodecid;
+ uint16_t vendor, product;
+ uint8_t type, nid;
+ char buf[10] = "??h";
+
+ if (argc != 2)
+ usage();
+
+ reqcodecid = strtol(argv[0], NULL, 0);
+ reqnid = strtol(argv[1], NULL, 0);
+
+ request = prop_dictionary_create();
+ if (request == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return ENOMEM;
+ }
+
+ prop_dictionary_set_uint16(request, "codecid", reqcodecid);
+ prop_dictionary_set_uint16(request, "nid", reqnid);
+
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_FGRP_CODEC_INFO, &response);
+ if (error != 0) {
+ perror("HDAUDIO_FGRP_CODEC_INFO failed");
+ prop_object_release(request);
+ return error;
+ }
+
+ prop_dictionary_get_uint16(response, "vendor-id", &vendor);
+ prop_dictionary_get_uint16(response, "product-id", &product);
+
+ printf("digraph \"HD Audio %04X:%04X\" {\n",
+ vendor, product);
+
+ for (index = 0;; index++) {
+ prop_dictionary_set_uint16(request, "index", index);
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_FGRP_WIDGET_INFO, &response);
+ if (error != 0)
+ break;
+ prop_dictionary_get_cstring_nocopy(response, "name", &name);
+ prop_dictionary_get_uint32(response, "cap", &cap);
+ prop_dictionary_get_uint32(response, "config", &config);
+ prop_dictionary_get_uint8(response, "type", &type);
+ prop_dictionary_get_uint8(response, "nid", &nid);
+
+ sprintf(buf, "widget%02Xh", nid);
+
+ switch (type) {
+ case COP_AWCAP_TYPE_AUDIO_OUTPUT:
+ printf(" %s [shape=box,style=filled,fillcolor=\""
+ "#88ff88\"];\n", buf);
+ break;
+ case COP_AWCAP_TYPE_AUDIO_INPUT:
+ printf(" %s [shape=box,style=filled,fillcolor=\""
+ "#ff8888\"];\n", buf);
+ break;
+ case COP_AWCAP_TYPE_AUDIO_MIXER:
+ printf(" %s [shape=invhouse];\n", buf);
+ break;
+ case COP_AWCAP_TYPE_AUDIO_SELECTOR:
+ printf(" %s [shape=invtrapezium];\n", buf);
+ break;
+ case COP_AWCAP_TYPE_PIN_COMPLEX:
+ printf(" %s [label=\"%s\\ndevice=%s\",style=filled",
+ buf, buf,
+ pin_devices[COP_CFG_DEFAULT_DEVICE(config)]);
+ if (cap & COP_PINCAP_OUTPUT_CAPABLE &&
+ cap & COP_PINCAP_INPUT_CAPABLE)
+ printf(",shape=doublecircle,fillcolor=\""
+ "#ffff88\"];\n");
+ else if (cap & COP_PINCAP_OUTPUT_CAPABLE)
+ printf(",shape=circle,fillcolor=\"#88ff88\"];\n");
+ else if (cap & COP_PINCAP_INPUT_CAPABLE)
+ printf(",shape=circle,fillcolor=\"#ff8888\"];\n");
+ else
+ printf(",shape=circle,fillcolor=\"#888888\"];\n");
+ break;
+ }
+ connlist = prop_dictionary_get(response, "connlist");
+ if (connlist == NULL)
+ goto next;
+ iter = prop_array_iterator(connlist);
+ prop_object_iterator_reset(iter);
+ while ((nnid = prop_object_iterator_next(iter)) != NULL) {
+ nid = prop_number_unsigned_integer_value(nnid);
+ printf(" widget%02Xh -> %s [sametail=widget%02Xh];\n",
+ nid, buf, nid);
+ }
+ prop_object_iterator_release(iter);
+next:
+ prop_object_release(response);
+ }
+
+ printf(" {rank=min;");
+ for (index = 0;; index++) {
+ prop_dictionary_set_uint16(request, "index", index);
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_AFG_WIDGET_INFO, &response);
+ if (error != 0)
+ break;
+ prop_dictionary_get_cstring_nocopy(response, "name", &name);
+ prop_dictionary_get_uint8(response, "type", &type);
+ prop_dictionary_get_uint8(response, "nid", &nid);
+
+ sprintf(buf, "widget%02Xh", nid);
+
+ switch (type) {
+ case COP_AWCAP_TYPE_AUDIO_OUTPUT:
+ case COP_AWCAP_TYPE_AUDIO_INPUT:
+ printf(" %s;", buf);
+ break;
+ }
+ prop_object_release(response);
+ }
+ printf("}\n");
+
+ printf(" {rank=max;");
+ for (index = 0;; index++) {
+ prop_dictionary_set_uint16(request, "index", index);
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_AFG_WIDGET_INFO, &response);
+ if (error != 0)
+ break;
+ prop_dictionary_get_cstring_nocopy(response, "name", &name);
+ prop_dictionary_get_uint8(response, "type", &type);
+ prop_dictionary_get_uint8(response, "nid", &nid);
+
+ sprintf(buf, "widget%02Xh", nid);
+
+ switch (type) {
+ case COP_AWCAP_TYPE_PIN_COMPLEX:
+ printf(" %s;", buf);
+ break;
+ }
+ prop_object_release(response);
+ }
+ printf("}\n");
+
+ printf("}\n");
+
+ prop_object_release(request);
+
+ return 0;
+}
Index: src/usr.sbin/hdaudioctl/hdaudioctl.8
diff -u /dev/null src/usr.sbin/hdaudioctl/hdaudioctl.8:1.1
--- /dev/null Sun Oct 11 08:57:55 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.8 Sun Oct 11 08:57:54 2009
@@ -0,0 +1,101 @@
+.\" $NetBSD: hdaudioctl.8,v 1.1 2009/10/11 08:57:54 sborrill Exp $
+.\"
+.\" Copyright (c) 2009 Precedence Technologies Ltd <[email protected]>
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Precedence Technologies Ltd
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October 6, 2009
+.Dt HDAUDIOCTL 8
+.Os
+.Sh NAME
+.Nm hdaudioctl
+.Nd program to manipulate
+.Xr hdaudio 4
+devices.
+.Sh SYNOPSIS
+.Nm hdaudioctl
+.Op Ar -f device
+.Ar command
+.Op Ar arguments
+.Sh DESCRIPTION
+The
+.Nm
+command can be used to inspect and reconfigure High Definition Audio devices
+and their child codecs.
+.Pp
+The mandatory
+.Ar command
+argument specifies the action to take.
+Valid commands are:
+.Bl -tag -width XgetXcodecidXnidX
+.It list
+For each child codec of the chosen
+.Xr hdaudio 4
+device, display the nid, vendor, product, subsystem and device IDs.
+.It get Ar codecid Ar nid
+Retrieve and display the current codec configuration as a
+.Xr proplib 3
+XML plist.
+.It set Ar codecid Ar nid Op Ar plist
+Detach the specified
+.Xr hdafg 4
+codec and then re-attach with its widgets explicitly configured according to
+the specified plist.
+If no plist is given, the in-built widget parsing rules based on the High
+Definition Audio specification will be used.
+.It graph Ar codecid Ar nid
+Output a DOT file suitable processing by graphviz.
+The resulting image will graphically show the structure and interconnections
+of the widgets that form the chosen
+.Xr hdafg 4
+codec.
+.El
+.Sh CAVEATS
+When a plist is loaded and the
+.Xr hdafg 4
+codec reattaches, all mixer controls will be returned to their default values.
+.Sh FILES
+.Bl -tag -width /dev/hdaudioX -compact
+.It Pa /dev/hdaudioX
+control devices
+.El
+.Sh AUTHORS
+.Nm
+is based on two separate programs written by
+.An Jared McNeill Aq [email protected]
+under contract by
+.An Precedence Technologies Ltd Aq http://www.precedence.co.uk/ .
+Integration into one program and writing this manual page was done by
+.An Stephen Borrill Aq [email protected]
+.Sh SEE ALSO
+.Xr hdaudio 4
+.Xr audio 4
+.Xr pkgsrc/graphics/graphviz
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Nx 5.1 .
Index: src/usr.sbin/hdaudioctl/hdaudioctl.c
diff -u /dev/null src/usr.sbin/hdaudioctl/hdaudioctl.c:1.1
--- /dev/null Sun Oct 11 08:57:55 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.c Sun Oct 11 08:57:54 2009
@@ -0,0 +1,255 @@
+/* $NetBSD: hdaudioctl.c,v 1.1 2009/10/11 08:57:54 sborrill Exp $ */
+
+/*
+ * Copyright (c) 2009 Precedence Technologies Ltd <[email protected]>
+ * Copyright (c) 2009 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Precedence Technologies Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <prop/proplib.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <dev/pci/hdaudio/hdaudioio.h>
+#include <dev/pci/hdaudio/hdaudioreg.h>
+
+#include "hdaudioctl.h"
+
+#define DEVPATH_HDAUDIO "/dev/hdaudio0"
+
+void
+usage(void)
+{
+ const char *prog;
+ prog = getprogname();
+
+ fprintf(stderr, "usage: %s [-f dev] list\n", prog);
+ fprintf(stderr, " %s [-f dev] get <codecid> <nid>\n", prog);
+ fprintf(stderr, " %s [-f dev] set <codecid> <nid> [plist]\n",
+ prog);
+ fprintf(stderr, " %s [-f dev] graph <codecid> <nid>\n", prog);
+ exit(EXIT_FAILURE);
+}
+
+static int
+hdaudioctl_list(int fd)
+{
+ prop_dictionary_t request, response;
+ prop_dictionary_t dict;
+ prop_object_iterator_t iter;
+ prop_object_t obj;
+ prop_array_t array;
+ uint16_t nid, codecid;
+ uint16_t vendor, product;
+ uint32_t subsystem;
+ const char *device = NULL;
+ int error;
+
+ request = prop_dictionary_create();
+ if (request == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return ENOMEM;
+ }
+
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_FGRP_INFO, &response);
+ if (error != 0) {
+ perror("HDAUDIO_FGRP_INFO failed");
+ return error;
+ }
+
+ array = prop_dictionary_get(response, "function-group-info");
+ iter = prop_array_iterator(array);
+ prop_object_iterator_reset(iter);
+ while ((obj = prop_object_iterator_next(iter)) != NULL) {
+ dict = (prop_dictionary_t)obj;
+ prop_dictionary_get_uint16(dict, "codecid", &codecid);
+ prop_dictionary_get_uint16(dict, "nid", &nid);
+ prop_dictionary_get_uint16(dict, "vendor-id", &vendor);
+ prop_dictionary_get_uint16(dict, "product-id", &product);
+ prop_dictionary_get_uint32(dict, "subsystem-id", &subsystem);
+ prop_dictionary_get_cstring_nocopy(dict, "device", &device);
+
+ printf("codecid 0x%02X nid 0x%02X vendor 0x%04X "
+ "product 0x%04X subsystem 0x%08X device %s\n",
+ codecid, nid, vendor, product, subsystem,
+ device ? device : "<none>");
+ }
+
+ prop_object_release(array);
+ prop_object_release(response);
+ prop_object_release(request);
+
+ return 0;
+}
+
+static int
+hdaudioctl_get(int fd, int argc, char *argv[])
+{
+ prop_dictionary_t request, response;
+ prop_array_t config;
+ uint16_t nid, codecid;
+ const char *xml;
+ int error;
+
+ if (argc != 2)
+ usage();
+
+ codecid = strtol(argv[0], NULL, 0);
+ nid = strtol(argv[1], NULL, 0);
+
+ request = prop_dictionary_create();
+ if (request == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return ENOMEM;
+ }
+
+ prop_dictionary_set_uint16(request, "codecid", codecid);
+ prop_dictionary_set_uint16(request, "nid", nid);
+
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_FGRP_GETCONFIG, &response);
+ if (error != 0) {
+ perror("HDAUDIO_FGRP_GETCONFIG failed");
+ return error;
+ }
+
+ config = prop_dictionary_get(response, "pin-config");
+ xml = prop_array_externalize(config);
+
+ printf("%s\n", xml);
+
+ prop_object_release(response);
+ prop_object_release(request);
+
+ return 0;
+}
+
+static int
+hdaudioctl_set(int fd, int argc, char *argv[])
+{
+ prop_dictionary_t request, response;
+ prop_array_t config = NULL;
+ uint16_t nid, codecid;
+ int error;
+
+ if (argc < 2 || argc > 3)
+ usage();
+
+ codecid = strtol(argv[0], NULL, 0);
+ nid = strtol(argv[1], NULL, 0);
+ if (argc == 3) {
+ config = prop_array_internalize_from_file(argv[2]);
+ if (config == NULL) {
+ fprintf(stderr,
+ "couldn't load configuration from %s\n", argv[2]);
+ return EIO;
+ }
+ }
+
+ request = prop_dictionary_create();
+ if (request == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return ENOMEM;
+ }
+
+ prop_dictionary_set_uint16(request, "codecid", codecid);
+ prop_dictionary_set_uint16(request, "nid", nid);
+ if (config)
+ prop_dictionary_set(request, "pin-config", config);
+
+ error = prop_dictionary_sendrecv_ioctl(request, fd,
+ HDAUDIO_FGRP_SETCONFIG, &response);
+ if (error != 0) {
+ perror("HDAUDIO_FGRP_SETCONFIG failed");
+ return error;
+ }
+
+ prop_object_release(response);
+ prop_object_release(request);
+
+ return 0;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int fd, error;
+ int ch;
+ const char *devpath = DEVPATH_HDAUDIO;
+
+ while ((ch = getopt(argc, argv, "f:h")) != -1) {
+ switch (ch) {
+ case 'f':
+ devpath = strdup(optarg);
+ break;
+ case 'h':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ fd = open(devpath, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Error opening %s: %s\n", devpath,
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ error = 0;
+ if (strcmp(argv[0], "list") == 0)
+ error = hdaudioctl_list(fd);
+ else if (strcmp(argv[0], "get") == 0)
+ error = hdaudioctl_get(fd, argc - 1, argv + 1);
+ else if (strcmp(argv[0], "set") == 0)
+ error = hdaudioctl_set(fd, argc - 1, argv + 1);
+ else if (strcmp(argv[0], "graph") == 0)
+ error = hdaudioctl_graph(fd, argc - 1, argv + 1);
+ else
+ usage();
+
+ close(fd);
+
+ if (error)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+}
Index: src/usr.sbin/hdaudioctl/hdaudioctl.h
diff -u /dev/null src/usr.sbin/hdaudioctl/hdaudioctl.h:1.1
--- /dev/null Sun Oct 11 08:57:55 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.h Sun Oct 11 08:57:54 2009
@@ -0,0 +1,2 @@
+extern int hdaudioctl_graph(int fd, int argc, char *argv[]);
+extern void usage(void);