Module Name:    src
Committed By:   bouyer
Date:           Sun Oct 18 16:50:14 UTC 2009

Modified Files:
        src/distrib/sets/lists/base [netbsd-5]: mi
        src/distrib/sets/lists/man [netbsd-5]: mi
        src/sys/dev/pci/hdaudio [netbsd-5]: hdaudio.c hdaudio_afg.c hdaudioio.h
            hdaudiovar.h
        src/usr.sbin [netbsd-5]: Makefile
Added Files:
        src/usr.sbin/hdaudioctl [netbsd-5]: Makefile graph.c hdaudioctl.8
            hdaudioctl.c hdaudioctl.h

Log Message:
Pull up following revision(s) (requested by sborrill in ticket #1086):
        usr.sbin/hdaudioctl/Makefile: revision 1.1 via patch
        usr.sbin/hdaudioctl/graph.c: revision 1.1
        sys/dev/pci/hdaudio/hdaudio.c: revision 1.5
        distrib/sets/lists/base/mi: revision 1.833
        sys/dev/pci/hdaudio/hdaudio_afg.c: revision 1.17
        sys/dev/pci/hdaudio/hdaudiovar.h: revision 1.5
        distrib/sets/lists/man/mi: revision 1.1164
        sys/dev/pci/hdaudio/hdaudioio.h: revision 1.3
        usr.sbin/hdaudioctl/hdaudioctl.c: revision 1.1
        usr.sbin/hdaudioctl/hdaudioctl.h: revision 1.1
        usr.sbin/hdaudioctl/hdaudioctl.8: revision 1.1, 1.2
        usr.sbin/Makefile: revision 1.243
Add ioctls required by hdaudioctl. This involves some refactoring of the
hdaudio_afg ioctl code.
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
Sort sections, fix SEE ALSO. End sentence with dot.


To generate a diff of this commit:
cvs rdiff -u -r1.780.2.14 -r1.780.2.15 src/distrib/sets/lists/base/mi
cvs rdiff -u -r1.1109.2.11 -r1.1109.2.12 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.4.4.2 -r1.4.4.3 src/sys/dev/pci/hdaudio/hdaudio.c \
    src/sys/dev/pci/hdaudio/hdaudiovar.h
cvs rdiff -u -r1.14.2.4 -r1.14.2.5 src/sys/dev/pci/hdaudio/hdaudio_afg.c
cvs rdiff -u -r1.2.4.2 -r1.2.4.3 src/sys/dev/pci/hdaudio/hdaudioio.h
cvs rdiff -u -r1.237.4.1 -r1.237.4.2 src/usr.sbin/Makefile
cvs rdiff -u -r0 -r1.1.2.2 src/usr.sbin/hdaudioctl/Makefile \
    src/usr.sbin/hdaudioctl/graph.c src/usr.sbin/hdaudioctl/hdaudioctl.c \
    src/usr.sbin/hdaudioctl/hdaudioctl.h
cvs rdiff -u -r0 -r1.2.2.2 src/usr.sbin/hdaudioctl/hdaudioctl.8

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.780.2.14 src/distrib/sets/lists/base/mi:1.780.2.15
--- src/distrib/sets/lists/base/mi:1.780.2.14	Wed Oct 14 18:10:21 2009
+++ src/distrib/sets/lists/base/mi	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.780.2.14 2009/10/14 18:10:21 snj Exp $
+# $NetBSD: mi,v 1.780.2.15 2009/10/18 16:50:13 bouyer Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -1382,6 +1382,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.1109.2.11 src/distrib/sets/lists/man/mi:1.1109.2.12
--- src/distrib/sets/lists/man/mi:1.1109.2.11	Fri Oct 16 11:56:10 2009
+++ src/distrib/sets/lists/man/mi	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1109.2.11 2009/10/16 11:56:10 sborrill Exp $
+# $NetBSD: mi,v 1.1109.2.12 2009/10/18 16:50:13 bouyer Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -2088,6 +2088,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
@@ -4471,6 +4472,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
@@ -6951,6 +6953,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/sys/dev/pci/hdaudio/hdaudio.c
diff -u src/sys/dev/pci/hdaudio/hdaudio.c:1.4.4.2 src/sys/dev/pci/hdaudio/hdaudio.c:1.4.4.3
--- src/sys/dev/pci/hdaudio/hdaudio.c:1.4.4.2	Sat Sep 26 19:52:10 2009
+++ src/sys/dev/pci/hdaudio/hdaudio.c	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio.c,v 1.4.4.2 2009/09/26 19:52:10 snj Exp $ */
+/* $NetBSD: hdaudio.c,v 1.4.4.3 2009/10/18 16:50:13 bouyer Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.4.4.2 2009/09/26 19:52:10 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.4.4.3 2009/10/18 16:50:13 bouyer Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -1339,6 +1339,48 @@
 	return 0;
 }
 
+static int
+hdaudio_dispatch_fgrp_ioctl(struct hdaudio_softc *sc, u_long cmd,
+    prop_dictionary_t request, prop_dictionary_t response)
+{
+	struct hdaudio_function_group *fg;
+	int16_t codecid, nid;
+	void *fgrp_sc; 
+	int err;
+
+	if (!prop_dictionary_get_int16(request, "codecid", &codecid) ||
+	    !prop_dictionary_get_int16(request, "nid", &nid))
+		return EINVAL;
+
+	fg = hdaudioioctl_fgrp_lookup(sc, codecid, nid);
+	if (fg == NULL)
+		return ENODEV;
+	fgrp_sc = device_private(fg->fg_device);
+
+	switch (fg->fg_type) {
+	case HDAUDIO_GROUP_TYPE_AFG:
+		switch (cmd) {
+		case HDAUDIO_FGRP_CODEC_INFO:
+			err = hdaudio_afg_codec_info(fgrp_sc,
+			    request, response);
+			break;
+		case HDAUDIO_FGRP_WIDGET_INFO:
+			err = hdaudio_afg_widget_info(fgrp_sc,
+			    request, response);
+			break;
+		default:
+			err = EINVAL;
+			break;
+		}
+		break;
+
+	default:
+		err = EINVAL;
+		break;
+	}
+	return err;
+}
+
 int
 hdaudioopen(dev_t dev, int flag, int mode, struct lwp *l)
 {
@@ -1389,6 +1431,10 @@
 	case HDAUDIO_FGRP_SETCONFIG:
 		err = hdaudioioctl_fgrp_setconfig(sc, request, response);
 		break;
+	case HDAUDIO_FGRP_CODEC_INFO:
+	case HDAUDIO_FGRP_WIDGET_INFO:
+		err = hdaudio_dispatch_fgrp_ioctl(sc, cmd, request, response);
+		break;
 	default:
 		err = EINVAL;
 		break;
Index: src/sys/dev/pci/hdaudio/hdaudiovar.h
diff -u src/sys/dev/pci/hdaudio/hdaudiovar.h:1.4.4.2 src/sys/dev/pci/hdaudio/hdaudiovar.h:1.4.4.3
--- src/sys/dev/pci/hdaudio/hdaudiovar.h:1.4.4.2	Sat Sep 26 19:52:10 2009
+++ src/sys/dev/pci/hdaudio/hdaudiovar.h	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudiovar.h,v 1.4.4.2 2009/09/26 19:52:10 snj Exp $ */
+/* $NetBSD: hdaudiovar.h,v 1.4.4.3 2009/10/18 16:50:13 bouyer Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -178,4 +178,7 @@
 int	hdaudio_stream_tag(struct hdaudio_stream *);
 uint16_t hdaudio_stream_param(struct hdaudio_stream *, const audio_params_t *);
 
+int	hdaudio_afg_widget_info(void *, prop_dictionary_t, prop_dictionary_t);
+int	hdaudio_afg_codec_info(void *, prop_dictionary_t, prop_dictionary_t);
+
 #endif /* !_HDAUDIOVAR_H */

Index: src/sys/dev/pci/hdaudio/hdaudio_afg.c
diff -u src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.4 src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.5
--- src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.4	Fri Oct 16 05:43:38 2009
+++ src/sys/dev/pci/hdaudio/hdaudio_afg.c	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_afg.c,v 1.14.2.4 2009/10/16 05:43:38 snj Exp $ */
+/* $NetBSD: hdaudio_afg.c,v 1.14.2.5 2009/10/18 16:50:13 bouyer Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.14.2.4 2009/10/16 05:43:38 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.14.2.5 2009/10/18 16:50:13 bouyer Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3644,19 +3644,71 @@
 	return 0;
 }
 
+int
+hdaudio_afg_widget_info(void *opaque, prop_dictionary_t request,
+    prop_dictionary_t response)
+{
+	struct hdaudio_afg_softc *sc = opaque;
+	struct hdaudio_widget *w;
+	prop_array_t connlist;
+	uint32_t config, wcap;
+	uint16_t index;
+	int nid;
+	int i;
+
+	if (prop_dictionary_get_uint16(request, "index", &index) == false)
+		return EINVAL;
+
+	nid = sc->sc_startnode + index;
+	if (nid >= sc->sc_endnode)
+		return EINVAL;
+
+	w = hdaudio_afg_widget_lookup(sc, nid);
+	if (w == NULL)
+		return ENXIO;
+	wcap = hda_get_wparam(w, PIN_CAPABILITIES);
+	config = hdaudio_command(sc->sc_codec, w->w_nid,
+	    CORB_GET_CONFIGURATION_DEFAULT, 0);
+	prop_dictionary_set_cstring_nocopy(response, "name", w->w_name);
+	prop_dictionary_set_bool(response, "enable", w->w_enable);
+	prop_dictionary_set_uint8(response, "nid", w->w_nid);
+	prop_dictionary_set_uint8(response, "type", w->w_type);
+	prop_dictionary_set_uint32(response, "config", config);
+	prop_dictionary_set_uint32(response, "cap", wcap);
+	if (w->w_nconns == 0)
+		return 0;
+	connlist = prop_array_create();
+	for (i = 0; i < w->w_nconns; i++) {
+		if (w->w_conns[i] == 0)
+			continue;
+		prop_array_add(connlist,
+		    prop_number_create_unsigned_integer(w->w_conns[i]));
+	}
+	prop_dictionary_set(response, "connlist", connlist);
+	prop_object_release(connlist);
+	return 0;
+}
+
+int
+hdaudio_afg_codec_info(void *opaque, prop_dictionary_t request,
+    prop_dictionary_t response)
+{
+	struct hdaudio_afg_softc *sc = opaque;
+	prop_dictionary_set_uint16(response, "vendor-id",
+	    sc->sc_vendor);
+	prop_dictionary_set_uint16(response, "product-id",
+	    sc->sc_product);
+	return 0;
+}
+
 static int
 hdaudio_afg_dev_ioctl(void *opaque, u_long cmd, void *addr, int flag, lwp_t *l)
 {
 	struct hdaudio_audiodev *ad = opaque;
 	struct hdaudio_afg_softc *sc = ad->ad_sc;
 	struct plistref *pref = addr;
-	struct hdaudio_widget *w;
 	prop_dictionary_t request, response;
-	prop_array_t connlist;
-	uint32_t config, wcap;
-	uint16_t index;
-	int err, nid;
-	int i;
+	int err;
 
 	response = prop_dictionary_create();
 	if (response == NULL)
@@ -3667,60 +3719,22 @@
 		prop_object_release(response);
 		return err;
 	}
-
-	if (prop_dictionary_get_uint16(request, "index", &index) == false) {
-		err = EINVAL;
-		goto out;
-	}
-
-	nid = sc->sc_startnode + index;
-	if (nid >= sc->sc_endnode) {
-		err = EINVAL;
-		goto out;
-	}
-
+	err = 0;
 	switch (cmd) {
 	case HDAUDIO_AFG_WIDGET_INFO:
-		w = hdaudio_afg_widget_lookup(sc, nid);
-		if (w == NULL) {
-			err = ENXIO;
-			goto out;
-		}
-		wcap = hda_get_wparam(w, PIN_CAPABILITIES);
-		config = hdaudio_command(sc->sc_codec, w->w_nid,
-		    CORB_GET_CONFIGURATION_DEFAULT, 0);
-		prop_dictionary_set_cstring_nocopy(response, "name", w->w_name);
-		prop_dictionary_set_bool(response, "enable", w->w_enable);
-		prop_dictionary_set_uint8(response, "nid", w->w_nid);
-		prop_dictionary_set_uint8(response, "type", w->w_type);
-		prop_dictionary_set_uint32(response, "config", config);
-		prop_dictionary_set_uint32(response, "cap", wcap);
-		if (w->w_nconns == 0)
-			break;
-		connlist = prop_array_create();
-		for (i = 0; i < w->w_nconns; i++) {
-			if (w->w_conns[i] == 0)
-				continue;
-			prop_array_add(connlist,
-			    prop_number_create_unsigned_integer(w->w_conns[i]));
-		}
-		prop_dictionary_set(response, "connlist", connlist);
-		prop_object_release(connlist);
+		err = hdaudio_afg_widget_info(sc, request, response);
 		break;
 	case HDAUDIO_AFG_CODEC_INFO:
-		prop_dictionary_set_uint16(response, "vendor-id",
-		    sc->sc_vendor);
-		prop_dictionary_set_uint16(response, "product-id",
-		    sc->sc_product);
+		err = hdaudio_afg_codec_info(sc, request, response);
 		break;
 	default:
 		err = EINVAL;
-		goto out;
+		break;
 	}
 
-	err = prop_dictionary_copyout_ioctl(pref, cmd, response);
+	if (!err)
+		err = prop_dictionary_copyout_ioctl(pref, cmd, response);
 
-out:
 	if (response)
 		prop_object_release(response);
 	prop_object_release(request);

Index: src/sys/dev/pci/hdaudio/hdaudioio.h
diff -u src/sys/dev/pci/hdaudio/hdaudioio.h:1.2.4.2 src/sys/dev/pci/hdaudio/hdaudioio.h:1.2.4.3
--- src/sys/dev/pci/hdaudio/hdaudioio.h:1.2.4.2	Sat Sep 26 19:52:10 2009
+++ src/sys/dev/pci/hdaudio/hdaudioio.h	Sun Oct 18 16:50:13 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudioio.h,v 1.2.4.2 2009/09/26 19:52:10 snj Exp $ */
+/* $NetBSD: hdaudioio.h,v 1.2.4.3 2009/10/18 16:50:13 bouyer Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -38,6 +38,8 @@
 #define	HDAUDIO_FGRP_INFO	_IOWR('h', 0, struct plistref)
 #define	HDAUDIO_FGRP_GETCONFIG	_IOWR('h', 1, struct plistref)
 #define	HDAUDIO_FGRP_SETCONFIG	_IOWR('h', 2, struct plistref)
+#define	HDAUDIO_FGRP_WIDGET_INFO	_IOWR('h', 3, struct plistref)
+#define	HDAUDIO_FGRP_CODEC_INFO	_IOWR('h', 4, struct plistref)
 
 #define	HDAUDIO_AFG_WIDGET_INFO	_IOWR('H', 0, struct plistref)
 #define	HDAUDIO_AFG_CODEC_INFO	_IOWR('H', 1, struct plistref)

Index: src/usr.sbin/Makefile
diff -u src/usr.sbin/Makefile:1.237.4.1 src/usr.sbin/Makefile:1.237.4.2
--- src/usr.sbin/Makefile:1.237.4.1	Fri Jan 16 21:41:11 2009
+++ src/usr.sbin/Makefile	Sun Oct 18 16:50:14 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.237.4.1 2009/01/16 21:41:11 bouyer Exp $
+#	$NetBSD: Makefile,v 1.237.4.2 2009/10/18 16:50:14 bouyer Exp $
 #	from: @(#)Makefile	5.20 (Berkeley) 6/12/93
 
 .include <bsd.own.mk>
@@ -8,7 +8,7 @@
 	chown chroot chrtbl cnwctl cpuctl cron dev_mkdb \
 	dhcp diskpart dumpfs dumplfs edquota eeprom \
 	envstat eshconfig etcupdate extattrctl fssconfig fwctl gpioctl \
-	grfconfig grfinfo gspa hilinfo ifwatchd inetd installboot \
+	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.2.2
--- /dev/null	Sun Oct 18 16:50:14 2009
+++ src/usr.sbin/hdaudioctl/Makefile	Sun Oct 18 16:50:13 2009
@@ -0,0 +1,11 @@
+# $NetBSD: Makefile,v 1.1.2.2 2009/10/18 16:50:13 bouyer 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.2.2
--- /dev/null	Sun Oct 18 16:50:14 2009
+++ src/usr.sbin/hdaudioctl/graph.c	Sun Oct 18 16:50:13 2009
@@ -0,0 +1,209 @@
+/* $NetBSD: graph.c,v 1.1.2.2 2009/10/18 16:50:13 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
+ * Copyright (c) 2009 Jared D. McNeill <jmcne...@invisible.ca>
+ * 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.c
diff -u /dev/null src/usr.sbin/hdaudioctl/hdaudioctl.c:1.1.2.2
--- /dev/null	Sun Oct 18 16:50:14 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.c	Sun Oct 18 16:50:13 2009
@@ -0,0 +1,255 @@
+/* $NetBSD: hdaudioctl.c,v 1.1.2.2 2009/10/18 16:50:13 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
+ * Copyright (c) 2009 Jared D. McNeill <jmcne...@invisible.ca>
+ * 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.2.2
--- /dev/null	Sun Oct 18 16:50:14 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.h	Sun Oct 18 16:50:13 2009
@@ -0,0 +1,2 @@
+extern int hdaudioctl_graph(int fd, int argc, char *argv[]);
+extern void usage(void);

Index: src/usr.sbin/hdaudioctl/hdaudioctl.8
diff -u /dev/null src/usr.sbin/hdaudioctl/hdaudioctl.8:1.2.2.2
--- /dev/null	Sun Oct 18 16:50:14 2009
+++ src/usr.sbin/hdaudioctl/hdaudioctl.8	Sun Oct 18 16:50:13 2009
@@ -0,0 +1,101 @@
+.\"	$NetBSD: hdaudioctl.8,v 1.2.2.2 2009/10/18 16:50:13 bouyer Exp $
+.\"
+.\" Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
+.\" 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 jmcne...@netbsd.org
+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 sborr...@netbsd.org
+.Sh SEE ALSO
+.Xr hdaudio 4
+.Xr audio 4
+.Xr pkgsrc/graphics/graphviz
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Nx 5.1 .

Reply via email to