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 .