summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/.nomake0
-rw-r--r--utils/Makefile17
-rw-r--r--utils/README60
-rw-r--r--utils/lin-inject.sh141
-rw-r--r--utils/mixgen.c800
-rw-r--r--utils/mixgen2.c1233
-rw-r--r--utils/ossmkdep.c234
-rwxr-xr-xutils/phpmake27
-rw-r--r--utils/readtimings.c61
-rw-r--r--utils/snoopy.c901
-rwxr-xr-xutils/vib9
-rwxr-xr-xutils/vif9
-rwxr-xr-xutils/vil9
-rwxr-xr-xutils/vil243
-rwxr-xr-xutils/vis9
-rwxr-xr-xutils/viu9
-rwxr-xr-xutils/viv9
17 files changed, 3531 insertions, 0 deletions
diff --git a/utils/.nomake b/utils/.nomake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utils/.nomake
diff --git a/utils/Makefile b/utils/Makefile
new file mode 100644
index 0000000..86fe4fa
--- /dev/null
+++ b/utils/Makefile
@@ -0,0 +1,17 @@
+CFLAGS=-I../include
+
+PROGRAMS=snoopy mixgen readtimings
+
+all: $(PROGRAMS)
+
+snoopy: snoopy.c ../kernel/drv/oss_hdaudio/hdaudio.h
+ $(CC) -o snoopy snoopy.c -I../kernel/drv/oss_hdaudio $(CFLAGS)
+
+mixgen: mixgen.c ../kernel/drv/oss_hdaudio/hdaudio.h
+ $(CC) -o mixgen mixgen.c -I../kernel/drv/oss_hdaudio $(CFLAGS)
+
+mixgen2: mixgen2.c ../kernel/drv/oss_hdaudio/hdaudio.h
+ $(CC) -o mixgen2 mixgen2.c -I../kernel/drv/oss_hdaudio $(CFLAGS)
+
+clean:
+ rm -f $(PROGRAMS) core core.* *.core *~ x y z *.o
diff --git a/utils/README b/utils/README
new file mode 100644
index 0000000..4ff708f
--- /dev/null
+++ b/utils/README
@@ -0,0 +1,60 @@
+This directory contains some utilities, diagnostic tools and helper
+scripts for developing, building and testing OSS.
+
+ossmkdep.c
+
+This is a simple utility that is used by "make dep". It lists the dependencies
+of each the source files given in the command line. This utility is used since
+GNU cpp is not available in all environments we support. It will be compiled
+and used automatically when OSS is built.
+
+readtimings.c
+
+This is an internal diagnostic tool that can be used to extract run-time tracing
+information produced by OSS. To use this feature you need to use
+the --enable-timings option when configuring OSS.
+Don't define this flag in production environment since it will cause
+significant amount of CPU overhead.
+
+Compile this program using "make readtimings" and then copy it to (say)
+/usr/local/bin.
+
+Then start readtimings>some_file.txt in one terminal window (or in backround).
+Run the program you would like to debug in another window. Kill the readtimings
+program as soon as the problem shows up (the listing may be very long).
+
+Now the produced file (say some_file.txt) will contain a trace of what
+happened. Don't ask what all this means?
+
+snoopy.c
+
+An utility program for displaying information about a HD audio codec chip.
+You need to edit hdaudio.conf and set the hdaudio_snoopy option to 1. The
+program tries to open /dev/oss/hdaudio0/pcm0 and to obtain the codec information
+from the driver. If the codec has some other codec number than 0 then you will
+need to edit the source and to change the "int cad=0;" line to match the
+codec number. This utility must be run as root.
+
+vif
+vib
+vil
+vis
+viu
+
+These are helper scripts for editing OSS files. Copy them to /usr/local.
+
+vif <file_mask> finds all files that match the given mask in the
+current directory and it's source trees. For example vif os_*.h will launch
+"vi" command for os.h files.
+
+vib, vil, vis, viu are similar commands for editing OS dependent files
+for Freebsd, Linux, Solaris and SCO UnixWare/OpenServer (respectively). These
+commands are usefull if you like to edit the build.sh file only for Linux (vil).
+The fif buils.sh script will open them for all operating systems.
+
+mixgen.c
+
+This is a tool to generate dedicated mixer modules for HDAudio based laptops
+and motherboards. Actually this program will generate just a template that
+needs to be edited and fine tuned manually. Full instructions are available
+at "http://developer.opensound.com/hdaudio_mixers.html".
diff --git a/utils/lin-inject.sh b/utils/lin-inject.sh
new file mode 100644
index 0000000..3d2126f
--- /dev/null
+++ b/utils/lin-inject.sh
@@ -0,0 +1,141 @@
+#!/bin/sh
+
+if test "$1 " = " "
+then
+ echo You need to give the Linux kernel directory as a argument.
+ exit 1
+fi
+
+TARGETDIR="$1"
+
+if ! test -d $TARGETDIR
+then
+ echo $TARGETDIR does not exist.
+ exit 1
+fi
+
+echo
+echo Kernel build directory is $TARGETDIR
+
+if test -d $TARGETDIR/sound/oss4
+then
+ echo error: $TARGETDIR/sound/oss4 already exists. Remove it and try again.
+ exit 1
+fi
+
+if ! test -d kernel/drv
+then
+ echo You need to run this script inside the OSS source directory
+ exit 1
+fi
+
+echo Copying OSS files
+if ! cp -R kernel $TARGETDIR/sound/oss4
+then
+ echo Failed to copy OSS files to $TARGETDIR/sound/oss4.
+ exit 1
+fi
+
+(cd $TARGETDIR/sound/oss4;mv OS/Linux linux_os;rm -rf OS)
+cp setup/Linux/oss/build/*.c $TARGETDIR/sound/oss4/linux_os
+cp setup/Linux/oss/build/*.h $TARGETDIR/sound/oss4/linux_os
+cp setup/Linux/oss/build/*.inc $TARGETDIR/sound/oss4/linux_os
+cp setup/Linux/oss/build/osscore.c $TARGETDIR/sound/oss4/framework/osscore/
+
+rm -rf $TARGETDIR/sound/oss4/drv/Makefile
+
+# Remove some non-Linux drivers
+rm -rf $TARGETDIR/sound/oss4/drv/oss_sadasupport
+rm -rf $TARGETDIR/sound/oss4/drv/osscore
+rm -rf $TARGETDIR/sound/oss4/drv/oss_audiocs
+rm -rf $TARGETDIR/sound/oss4/nonfree
+
+# Remove MIDI support that is not functional yet.
+rm -rf $TARGETDIR/sound/oss4/framework/midi
+
+# Remove all previous Makefiles that are bogus
+find $TARGETDIR/sound/oss4 -name Makefile -exec rm {} ';'
+
+# Remove the man files
+find $TARGETDIR/sound/oss4 -name '*.man' -exec rm {} ';'
+
+cat<<END_OF_CONFIG >$TARGETDIR/sound/oss4/Kconfig
+
+config OSS_VMIX
+ bool "Virtual audio mixer (vmix) suport"
+ default y
+
+config OSS_VMIX_FLOAT
+ bool "Use floating point arithmetic for vmix computations"
+ default y
+
+config OSS_MIDI
+ bool "MIDI support (partially functional)"
+ default n
+
+END_OF_CONFIG
+
+echo Generating drivers
+for n in $TARGETDIR/sound/oss4/drv/*
+do
+ N=`basename $n|tr 'a-z' 'A-Z'`
+ BN=`basename $n`
+
+ echo config $N >>$TARGETDIR/sound/oss4/Kconfig
+ echo " tristate" \"`head -1 $n/.name`\">>$TARGETDIR/sound/oss4/Kconfig
+ echo " depends on" OSS4 >>$TARGETDIR/sound/oss4/Kconfig
+ echo " default y" >>$TARGETDIR/sound/oss4/Kconfig
+ echo >>$TARGETDIR/sound/oss4/Kconfig
+
+ mv $TARGETDIR/sound/oss4/drv/$BN/$BN.c $TARGETDIR/sound/oss4/drv/$BN/"$BN"_main.c
+ cp target/build/$BN.c $TARGETDIR/sound/oss4/drv/$BN/"$BN"_stub.c
+
+ echo obj-\$\(CONFIG_OSS_$N\) += drv\/$BN/ >> $TARGETDIR/sound/oss4/Makefile
+ echo obj-\$\(CONFIG_OSS_$N\) := $BN.o > $TARGETDIR/sound/oss4/drv/$BN/Makefile
+ echo >> $TARGETDIR/sound/oss4/drv/$BN/Makefile
+
+ for fn in $TARGETDIR/sound/oss4/drv/$BN/*.c
+ do
+ fn=`basename $fn .c`.o
+ echo $BN-objs += $fn >> $TARGETDIR/sound/oss4/drv/$BN/Makefile
+ done
+done
+
+echo Done
+
+if ! grep -q OSS4 $TARGETDIR/sound/Kconfig
+then
+
+ echo
+ echo NOTICE
+ echo
+ echo As the final step you need to copy/paste the following lines to
+ echo $TARGETDIR/sound/Kconfig
+ echo The right location is just above the last endmenu line.
+
+ cat <<END_OF_CONFIG
+----- cut here ---
+menu "Open Sound System v4.x"
+
+config OSS4
+ tristate "Open Sound System v4.x support"
+ depends on SOUND!=n
+ depends on !SND
+ depends on !SOUND_PRIME
+ help
+ This is version 4.x of Open Sound System. It replaces
+ the older (DEPRECATED) OSS version that has been included
+ in the kernel during past 10 years.
+
+ You need to disabele both ALSA and the older OSS version
+ before being able to compile OSSv4.
+
+source "sound/oss4/Kconfig"
+endmenu
+----- cut here ---
+END_OF_CONFIG
+
+echo Finally append the following line to $TARGETDIR/sound/Makefile
+echo 'obj-$(CONFIG_OSS4) += oss4/'
+fi
+exit 0
diff --git a/utils/mixgen.c b/utils/mixgen.c
new file mode 100644
index 0000000..1aed9cd
--- /dev/null
+++ b/utils/mixgen.c
@@ -0,0 +1,800 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <soundcard.h>
+
+typedef int sound_os_info, mixer_create_controls_t, oss_device_t;
+
+#include <hdaudio.h>
+
+#define ioctl_arg int
+#define mixer_ext_init_fn int
+#include <hdaudio_codec.h>
+
+static int num_widgets = 0;
+
+static int print_widgets = 0;
+
+typedef struct
+{
+ int type;
+ int valid;
+ int used;
+
+ char name[32];
+
+ unsigned int wcaps;
+ unsigned int pincaps;
+ unsigned int inamp_caps;
+ unsigned int outamp_caps;
+ int nconn;
+ int connections[MAX_CONN];
+ widget_t widget_info;
+} mixgen_widget_t;
+
+static mixgen_widget_t widgets[256] = { {0} };
+
+static int errors = 0;
+
+static unsigned int default_outamp_caps = 0;
+static unsigned int default_inamp_caps = 0;
+static unsigned int subdevice = 0;
+
+#undef corb_read
+#undef corb_write
+
+int fd;
+void *mixer = NULL;
+int trace = 0;
+
+int cad = -1;
+
+int
+corb_write (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+ if (trace)
+ printf ("WRITE %08x\n", tmp);
+
+ if (ioctl (fd, HDA_IOCTL_WRITE, &tmp) == -1)
+ {
+ /* perror("HDA_IOCTL_WRITE"); */
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm, unsigned int *upper,
+ unsigned int *lower)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+
+ if (ioctl (fd, HDA_IOCTL_READ, &tmp) == -1)
+ {
+ /* perror("HDA_IOCTL_READ"); */
+ if (errno == EINVAL)
+ {
+ fprintf (stderr, "hdaudio_snoopy mode is not available\n");
+ exit (-1);
+ }
+ return 0;
+ }
+
+ *upper = tmp;
+ *lower = 0;
+ if (trace)
+ printf ("READ %08x\n", tmp);
+
+ return 1;
+}
+
+static int
+set_error (char *msg)
+{
+ fprintf (stderr, "%s");
+ errors++;
+
+ return 0;
+}
+
+static int
+gen_amps (mixgen_widget_t * widget, int wid)
+{
+ int i;
+ char *name;
+
+ if (widget->wcaps & WCAP_OUTPUT_AMP_PRESENT)
+ {
+ if (widget->outamp_caps & ~AMPCAP_MUTE) /* Has gain control */
+ {
+ name = "-";
+ if (widget->type == NT_PIN)
+ name = "invol";
+ printf ("\t\tHDA_OUTAMP(0x%02x, group, \"%s\", 90);\n", wid, name);
+ }
+ else if (widget->outamp_caps & AMPCAP_MUTE) /* Only mute control */
+ {
+ name = "mute";
+ if (widget->type == NT_PIN)
+ name = "inmute";
+ printf ("\t\tHDA_OUTMUTE(0x%02x, group, \"%s\", UNMUTE);\n", wid,
+ name);
+ }
+ }
+
+ if (widget->wcaps & WCAP_INPUT_AMP_PRESENT)
+ {
+ int n = widget->nconn;
+ if (widget->type == NT_PIN)
+ n = 1;
+
+ if (n > 1 && !(widget->inamp_caps & ~AMPCAP_MUTE))
+ { /* Create mute group */
+ printf ("\t\t{\n");
+ printf ("\t\t\tint amp_group;\n\n");
+ printf ("\t\t\tHDA_GROUP(amp_group, group, \"mute\");\n");
+ for (i = 0; i < widget->nconn; i++)
+ {
+ char *name;
+
+ name = widgets[widget->connections[i]].name;
+ if (widgets[widget->connections[i]].type == NT_PIN)
+ name = widgets[widget->connections[i]].widget_info.color;
+ printf
+ ("\t\t\tHDA_INMUTE(0x%02x, %d, amp_group, \"%s\", UNMUTE);\t/* From widget 0x%02x */\n",
+ wid, i, name, widget->connections[i]);
+ }
+ printf ("\t\t}\n");
+ }
+ else
+ {
+ for (i = 0; i < n; i++)
+ {
+ char *name;
+
+ name = widgets[widget->connections[i]].name;
+ if (widgets[widget->connections[i]].type == NT_PIN)
+ name = widgets[widget->connections[i]].widget_info.color;
+ if (widget->type == NT_PIN)
+ name = "out";
+ if (widget->inamp_caps & ~AMPCAP_MUTE) /* Has gain control */
+ {
+ printf
+ ("\t\tHDA_INAMP(0x%02x, %d, group, \"%s\", 90);\t/* From widget 0x%02x */\n",
+ wid, i, name, widget->connections[i]);
+ }
+ else
+ {
+ printf
+ ("\t\tHDA_INMUTE(0x%02x, %d, group, \"%smute\", UNMUTE);\t/* From widget 0x%02x */\n",
+ wid, i, name, widget->connections[i]);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+follow_widget_chain (int wid, int force)
+{
+ int i;
+ char choice_list[1024] = "", *s = choice_list;
+ mixgen_widget_t *widget;
+
+ if (!widgets[wid].valid || widgets[wid].used)
+ return 0;
+
+ widget = &widgets[wid];
+
+ if (widget->widget_info.refcount > 1 && !force)
+ return 0;
+
+ widget->used = 1;
+
+ printf ("\n\t\t/* Widget 0x%02x (%s) */\n", wid, widget->name);
+
+ for (i = 0; i < widget->nconn; i++)
+ {
+ char *name = widgets[widget->connections[i]].name;
+ if (widgets[widget->connections[i]].type == NT_PIN)
+ name = widgets[widget->connections[i]].widget_info.color;
+ if (i > 0)
+ *s++ = ' ';
+ if (widget->connections[i] < num_widgets)
+ strcpy (s, widgets[widget->connections[i]].name);
+ else
+ strcpy (s, "unknown");
+ printf ("\t\t/* Src 0x%x=%s */\n", widget->connections[i], name);
+ s += strlen (s);
+ }
+
+ if (widget->type == NT_SELECT && widget->nconn > 1)
+ {
+ printf ("\t\tif (HDA_SELECT(0x%02x, \"src\", ctl, group, -1))\n", wid);
+ printf ("\t\t {\n");
+ printf ("\t\t\tHDA_CHOICES(ctl, \"%s\");\n", choice_list);
+ printf ("\t\t }\n");
+ }
+
+ gen_amps (widget, wid);
+/*
+ * Follow the input connection chain.
+ */
+ if (widget->nconn == 1)
+ follow_widget_chain (widget->connections[0], force);
+
+ return 0;
+}
+
+static int
+handle_pin_widget (int wid, mixgen_widget_t * widget)
+{
+ int outselects = 0, inselects = 0, num_amps = 0;
+ char choice_list[1024] = "", *s = choice_list;
+ int i;
+
+ widget->used = 1;
+
+ if (widget->pincaps & PINCAP_INPUT_CAPABLE)
+ {
+ if (!(widget->wcaps & WCAP_DIGITAL)) /* Analog pin */
+ {
+ inselects = 1;
+ }
+ }
+
+ if (widget->pincaps & PINCAP_OUTPUT_CAPABLE)
+ {
+ if (!(widget->wcaps & WCAP_DIGITAL)) /* Analog pin */
+ {
+ outselects = widget->nconn;
+ }
+ }
+
+ if (widget->wcaps & WCAP_INPUT_AMP_PRESENT)
+ {
+ num_amps += widget->nconn;
+ }
+
+ if (widget->wcaps & WCAP_OUTPUT_AMP_PRESENT)
+ {
+ num_amps++;
+ }
+
+ if (inselects + outselects + num_amps == 0)
+ return 0;
+
+ printf
+ ("\n\tif (HDA_PIN_GROUP(0x%02x, group, pin_group, \"%s\", n, \"jack\", 4))\t/* Pin widget 0x%02x */\n",
+ wid, widget->widget_info.color, wid);
+ printf ("\t {\n");
+
+ for (i = 0; i < widget->nconn; i++)
+ {
+ if (i > 0)
+ *s++ = ' ';
+
+ if (widget->connections[i] < num_widgets)
+ sprintf (s, "%s-out", widgets[widget->connections[i]].name);
+ else
+ strcpy (s, "unknown");
+ printf ("\t\t/* Src 0x%x=%s */\n", widget->connections[i],
+ widgets[widget->connections[i]].name);
+ s += strlen (s);
+ }
+
+ if (widget->nconn > 0)
+ *s++ = ' ';
+ sprintf (s, "input");
+ s += strlen (s);
+
+ printf ("\t\tif (HDA_PINSELECT(0x%02x, ctl, group, \"mode\", -1))\n", wid);
+ printf ("\t\t\tHDA_CHOICES(ctl, \"%s\");\n", choice_list);
+
+ gen_amps (widget, wid);
+
+ for (i = 0; i < widget->nconn; i++)
+ follow_widget_chain (widget->connections[i], 0);
+
+ printf ("\t }\n");
+
+ return 0;
+}
+
+static int
+handle_adc_widget (int wid, mixgen_widget_t * widget)
+{
+ int outselects = 0, inselects = 0, num_amps = 0;
+ char choice_list[4000] = "", *s = choice_list;
+ int i;
+
+ widget->used = 1;
+
+ if (widget->wcaps & WCAP_INPUT_AMP_PRESENT)
+ {
+ num_amps += widget->nconn;
+ }
+
+ if (widget->wcaps & WCAP_OUTPUT_AMP_PRESENT)
+ {
+ num_amps++;
+ }
+
+ printf
+ ("\n\tif (HDA_ADC_GROUP(0x%02x, group, rec_group, \"%s\", n, \"record\", 4))\t/* ADC widget 0x%02x */\n",
+ wid, widget->name, wid);
+ printf ("\t {\n");
+
+ for (i = 0; i < widget->nconn; i++)
+ {
+ if (i > 0)
+ *s++ = ' ';
+ if (widget->connections[i] < num_widgets)
+ strcpy (s, widgets[widget->connections[i]].name);
+ else
+ strcpy (s, "unknown");
+ printf ("\t\t/* Src 0x%x=%s */\n", widget->connections[i],
+ widgets[widget->connections[i]].name);
+ s += strlen (s);
+ }
+
+ if (widget->nconn > 1)
+ {
+ printf ("\t\tif (HDA_SELECT(0x%02x, \"src\", ctl, group, -1))\n", wid);
+ printf ("\t\t {\n");
+ printf ("\t\t\tHDA_CHOICES(ctl, \"%s\");\n", choice_list);
+ printf ("\t\t }\n");
+ }
+
+ gen_amps (widget, wid);
+
+ for (i = 0; i < widget->nconn; i++)
+ follow_widget_chain (widget->connections[i], 0);
+
+ printf ("\t }\n");
+
+ return 0;
+}
+
+static int
+handle_misc_widget (int wid, mixgen_widget_t * widget)
+{
+ int outselects = 0, inselects = 0, num_amps = 0;
+ char choice_list[4000] = "", *s = choice_list;
+ int i;
+
+ widget->used = 1;
+
+ if (widget->wcaps & WCAP_INPUT_AMP_PRESENT)
+ {
+ num_amps += widget->nconn;
+ }
+
+ if (widget->wcaps & WCAP_OUTPUT_AMP_PRESENT)
+ {
+ num_amps++;
+ }
+
+ if (num_amps == 0)
+ return 0;
+
+ printf
+ ("\n\tif (HDA_MISC_GROUP(0x%02x, group, misc_group, \"%s\", n, \"misc\", 8))\t/* Misc widget 0x%02x */\n",
+ wid, widget->name, wid);
+ printf ("\t {\n");
+
+ for (i = 0; i < widget->nconn; i++)
+ {
+ if (i > 0)
+ *s++ = ' ';
+ if (widget->connections[i] < num_widgets)
+ strcpy (s, widgets[widget->connections[i]].name);
+ else
+ strcpy (s, "unknown");
+ printf ("\t\t/* Src 0x%x=%s */\n", widget->connections[i],
+ widgets[widget->connections[i]].name);
+ s += strlen (s);
+ }
+
+ if (widget->type == NT_SELECT && widget->nconn > 1)
+ {
+ printf ("\t\tif (HDA_SELECT(0x%02x, \"src\", ctl, group, -1))\n", wid);
+ printf ("\t\t {\n");
+ printf ("\t\t\tHDA_CHOICES(ctl, \"%s\");\n", choice_list);
+ printf ("\t\t }\n");
+ }
+
+ gen_amps (widget, wid);
+
+ for (i = 0; i < widget->nconn; i++)
+ follow_widget_chain (widget->connections[i], 1);
+
+ printf ("\t }\n");
+
+ return 0;
+}
+
+static int
+attach_widget (int wid)
+{
+ hda_name_t name;
+ hda_widget_info_t info;
+ unsigned int wcaps, b;
+ mixgen_widget_t *widget = &widgets[wid];
+ int type;
+ int i;
+ unsigned int nconn, connections[256];
+
+ memset (&name, 0, sizeof (name));
+ memset (&info, 0, sizeof (info));
+
+ name.cad = cad;
+ name.wid = wid;
+ if (ioctl (fd, HDA_IOCTL_NAME, &name) == -1)
+ strcpy (name.name, "Unknown_widget");
+
+ info.cad = cad;
+ info.wid = wid;
+ if (ioctl (fd, HDA_IOCTL_WIDGET, &info) != -1)
+ memcpy (&widget->widget_info, info.info, sizeof (widget->widget_info));
+
+ if (!corb_read
+ (mixer, cad, wid, 0, GET_PARAMETER, HDA_WIDGET_CAPS, &wcaps, &b))
+ return set_error ("Can't get widget capabilities\n");
+
+ type = (wcaps >> 20) & 0xf;
+
+ if (type == NT_PIN)
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_PIN_CAPS, &widget->pincaps, &b))
+ return set_error ("Can't get widget pin capabilities\n");
+
+ widget->valid = 1;
+ strcpy (widget->name, name.name);
+ widget->wcaps = wcaps;
+ widget->inamp_caps = default_inamp_caps;
+ widget->outamp_caps = default_outamp_caps;
+ widget->type = type;
+
+ /*
+ * Handle connection list.
+ */
+ nconn = 0;
+ if (wcaps & WCAP_CONN_LIST)
+ {
+
+ if (corb_read
+ (mixer, cad, wid, 0, GET_PARAMETER, HDA_CONNLIST_LEN, &nconn, &b))
+
+ if (nconn >= MAX_CONN)
+ {
+ fprintf (stderr,
+ "Too many input connections (%d) for widget %d\n", nconn,
+ wid);
+ exit (-1);
+ }
+ if (nconn != 0)
+ {
+ unsigned int clist;
+ int j;
+ int n = 0;
+
+ nconn &= 0x7f;
+
+ for (i = 0; i < nconn; i += 4)
+ if (corb_read
+ (mixer, cad, wid, 0, GET_CONNECTION_LIST_ENTRY, i, &clist,
+ &b))
+ for (j = 0; j < 4 && (i + j) < nconn; j++)
+ {
+ connections[n++] = (clist >> (j * 8)) & 0xff;
+ }
+ }
+ }
+
+ for (i = 0; i < nconn; i++)
+ widget->connections[i] = connections[i];
+ widget->nconn = nconn;
+
+ if ((wcaps & WCAP_AMP_CAP_OVERRIDE) && (wcaps & WCAP_OUTPUT_AMP_PRESENT))
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_OUTPUTAMP_CAPS,
+ &widget->outamp_caps, &b))
+ {
+ fprintf (stderr, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
+ return set_error ("Can't get outamp capabilities\n");
+ }
+
+ if ((wcaps & WCAP_AMP_CAP_OVERRIDE) && (wcaps & WCAP_INPUT_AMP_PRESENT))
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_INPUTAMP_CAPS,
+ &widget->inamp_caps, &b))
+ {
+ fprintf (stderr, "GET_PARAMETER HDA_INPUTTAMP_CAPS failed\n");
+ return set_error ("Can't get inamp capabilities\n");
+ }
+
+ return 0;
+}
+
+static void
+dump_node (int wid)
+{
+ int i;
+ unsigned int a, b, gtype, gcaps, wcaps, sizes, fmts, pincaps;
+ unsigned int inamp_caps, outamp_caps, clen, pstates, pcaps, gpio_count;
+ unsigned int vkcaps;
+ int first_node = 0, num_nodes = 0;
+ char *s;
+ int ntype = -1;
+
+ if (corb_read
+ (mixer, cad, wid, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gtype, &b))
+ if ((gtype & 0x1ff) != 0)
+ {
+ s = "Unknown";
+
+ switch (gtype & 0xff)
+ {
+ case 0:
+ s = "Reserved";
+ return;
+ break;
+ case 1:
+ s = "Audio function group";
+ break;
+ case 2:
+ s = "Vendor defined modem function group";
+ //return;
+ break;
+ }
+
+ }
+ if (corb_read (mixer, cad, wid, 0, GET_SUBSYSTEM_ID, 0, &a, &b))
+ {
+ printf ("/* Subsystem ID %08x */\n", a);
+ subdevice = a;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
+ {
+ fprintf (stderr, "GET_PARAMETER HDA_NODE_COUNT2 failed\n");
+ return;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_OUTPUTAMP_CAPS,
+ &default_outamp_caps, &b))
+ {
+ fprintf (stderr, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
+ return;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_INPUTAMP_CAPS, &default_inamp_caps, &b))
+ {
+ fprintf (stderr, "GET_PARAMETER HDA_INPUTTAMP_CAPS failed\n");
+ return;
+ }
+
+ printf ("/* Default amplifier caps: in=%08x, out=%08x */\n",
+ default_inamp_caps, default_outamp_caps);
+
+ first_node = (a >> 16) & 0xff;
+ num_nodes = a & 0xff;
+
+ for (wid = first_node; wid < first_node + num_nodes; wid++)
+ {
+ attach_widget (wid);
+ if (wid >= num_widgets)
+ num_widgets = wid + 1;
+ }
+}
+
+static void
+dump_widgets (void)
+{
+ int i;
+
+ for (i = 0; i < num_widgets; i++)
+ {
+ if (widgets[i].valid)
+ {
+ if (widgets[i].name[0] == 0) /* Empty string */
+ printf("\tES,\n");
+ else
+ printf ("\t\"%s\",\t\t/* 0x%02x */\n", widgets[i].name, i);
+ }
+ else
+ printf ("\tES,\t\t/* 0x%02x */\n", i);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ unsigned int a, b;
+ int first_node, num_nodes;
+ int i;
+ char codec_name[32] = "";
+
+ if (argc > 1)
+ strcpy (codec_name, argv[1]);
+
+ if ((fd = open ("/dev/oss/oss_hdaudio0/pcm0", O_RDWR | O_EXCL, 0)) == -1)
+ {
+ perror ("/dev/oss/oss_hdaudio0/pcm0");
+ exit (-1);
+ }
+
+ if (argc > 2)
+ cad = atoi (argv[2]);
+
+ for (i = 3; i < argc; i++)
+ switch (argv[i][0])
+ {
+ case 'w':
+ print_widgets = 1;
+ break;
+ }
+
+ if (cad == -1) /* Not given on command line so find it. */
+ for (cad = 0; cad < 16; cad++)
+ if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &a, &b))
+ break;
+ printf
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+ printf ("/* Codec index is %d */\n", cad);
+ printf ("/* Codec vendor %04x:%04x */\n", a >> 16, a & 0xffff);
+
+ if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &a, &b))
+ {
+ printf ("/* HD codec revision %d.%d (%d.%d) (0x%08x) */\n",
+ (a >> 20) & 0xf, (a >> 16) & 0xf, (a >> 8) & 0xff, a & 0xff, a);
+ }
+ else
+ printf ("hdaudio: Can't get codec revision\n");
+
+/*
+ * Find out the primary group list
+ */
+
+ if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
+ exit(1);
+
+ first_node = (a >> 16) & 0xff;
+ num_nodes = a & 0xff;
+
+ for (i = first_node; i < first_node + num_nodes; i++)
+ dump_node (i);
+
+/*
+ * Next produce the output
+ */
+
+ if (*codec_name == 0)
+ sprintf (codec_name, "subdevice%08x", subdevice);
+
+ printf ("#include \"oss_hdaudio_cfg.h\"\n");
+ printf ("#include \"hdaudio.h\"\n");
+ printf ("#include \"hdaudio_codec.h\"\n");
+ printf ("#include \"hdaudio_dedicated.h\"\n");
+ printf ("\n");
+
+ printf ("int\n");
+ printf
+ ("hdaudio_%s_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group)\n",
+ codec_name);
+ printf ("{\n");
+ //printf (" int wid;\n");
+ printf (" int ctl=0;\n");
+ //printf (" codec_t *codec = mixer->codecs[cad];\n");
+
+ printf ("\n");
+ printf
+ (" DDB(cmn_err(CE_CONT, \"hdaudio_%s_mixer_init got called.\\n\"));\n",
+ codec_name);
+ printf ("\n");
+
+/*
+ * Handle PIN widgets first
+ */
+ printf (" /* Handle PIN widgets */\n");
+ printf (" {\n");
+ printf ("\tint n, group, pin_group;\n");
+ printf ("\n\tn=0;\n");
+
+ printf ("\n\tHDA_GROUP(pin_group, top_group, \"jack\");\n");
+
+ for (i = 0; i < num_widgets; i++)
+ {
+ mixgen_widget_t *widget = &widgets[i];
+
+ if (!widget->valid)
+ continue;
+
+ if (widget->type != NT_PIN)
+ continue;
+
+ handle_pin_widget (i, widget);
+ }
+ printf (" }\n");
+
+/*
+ * Handle ADC widgets
+ */
+ printf (" /* Handle ADC widgets */\n");
+ printf (" {\n");
+ printf ("\tint n, group, rec_group;\n");
+ printf ("\n\tn=0;\n");
+
+ printf ("\n\tHDA_GROUP(rec_group, top_group, \"record\");\n");
+
+ for (i = 0; i < num_widgets; i++)
+ {
+ mixgen_widget_t *widget = &widgets[i];
+
+ if (!widget->valid || widget->used)
+ continue;
+
+ if (widget->type != NT_ADC)
+ continue;
+
+ handle_adc_widget (i, widget);
+ }
+ printf (" }\n");
+
+/*
+ * Handle the remaining widgets
+ */
+ printf (" /* Handle misc widgets */\n");
+ printf (" {\n");
+ printf ("\tint n, group, misc_group;\n");
+ printf ("\n\tn=0;\n");
+
+ printf ("\n\tHDA_GROUP(misc_group, top_group, \"misc\");\n");
+
+ for (i = 0; i < num_widgets; i++)
+ {
+ mixgen_widget_t *widget = &widgets[i];
+
+ if (!widget->valid || widget->used)
+ continue;
+
+ handle_misc_widget (i, widget);
+ }
+ printf (" }\n");
+
+ printf (" return 0;\n");
+ printf ("}\n");
+
+ if (print_widgets)
+ dump_widgets ();
+ exit (errors);
+}
diff --git a/utils/mixgen2.c b/utils/mixgen2.c
new file mode 100644
index 0000000..41a55a9
--- /dev/null
+++ b/utils/mixgen2.c
@@ -0,0 +1,1233 @@
+/*
+ * Temporary utility used to develop the next hdaudio driver
+ * version. Not usable.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <soundcard.h>
+#include <stdarg.h>
+
+#define DRIVER_NICK "hdaudio"
+#define CE_CONT 0
+#define CE_NOTE 1
+#define CE_WARN 2
+
+#define DDB(x)
+
+#define PMALLOC(osdev, s) malloc(s)
+
+typedef int sound_os_info, mixer_create_controls_t;
+
+typedef struct
+{
+ char *hw_info;
+} oss_device_t;
+
+#include <hdaudio.h>
+
+#define ioctl_arg int
+#define mixer_ext_init_fn int
+#include <hdaudio_codec.h>
+//#include <hdaudio_codecids.h>
+
+int fd;
+
+#undef corb_read
+#undef corb_write
+
+typedef struct
+{
+ int association, sequence;
+ int nwidgets;
+ int jack_count;
+
+#define PATH_MAXWID 8
+ widget_t *widgets[PATH_MAXWID];
+} path_t;
+
+#define MAX_PATHS 32
+path_t *paths[MAX_PATHS];
+int npaths=0;
+
+int
+corb_write (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+
+ if (ioctl (fd, HDA_IOCTL_WRITE, &tmp) == -1)
+ {
+ perror ("HDA_IOCTL_WRITE");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm, unsigned int *upper,
+ unsigned int *lower)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+
+ if (ioctl (fd, HDA_IOCTL_READ, &tmp) == -1)
+ {
+ /* perror("HDA_IOCTL_READ"); */
+ if (errno == EINVAL)
+ {
+ fprintf (stderr, "hdaudio_snoopy mode is not available\n");
+ exit (-1);
+ }
+ return 0;
+ }
+
+ *upper = tmp;
+ *lower = 0;
+
+ return 1;
+}
+
+void
+cmn_err (int level, char *s, ...)
+{
+ char tmp[1024], *a[6];
+ va_list ap;
+ int i, n = 0;
+
+ va_start (ap, s);
+
+ for (i = 0; i < strlen (s); i++)
+ if (s[i] == '%')
+ n++;
+
+ for (i = 0; i < n && i < 6; i++)
+ {
+ a[i] = va_arg (ap, char *);
+ }
+
+ for (i = n; i < 6; i++)
+ a[i] = NULL;
+
+ if (level == CE_CONT)
+ {
+ sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
+ NULL, NULL, NULL);
+ printf ("%s", tmp);
+ }
+ else
+ {
+ strcpy (tmp, DRIVER_NICK ": ");
+
+ sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
+ NULL, NULL, NULL, NULL);
+ printf ("%s", tmp);
+ }
+
+ va_end (ap);
+}
+
+/*
+ ********************************
+ */
+
+static const char *widget_id[16] = {
+ "pcm",
+ "rec",
+ "mix",
+ "select",
+ "jack",
+ "power",
+ "vol",
+ "beep",
+ "unkn",
+ "unkn",
+ "unkn",
+ "unkn",
+ "unkn",
+ "unkn",
+ "unkn",
+ "vendor"
+ };
+
+static int
+attach_pin_widget (hdaudio_mixer_t * mixer, codec_t * codec,
+ widget_t * widget, int cad, int wid, int group_type)
+{
+ unsigned int conf;
+ int num = codec->jack_number++;
+ unsigned int pincaps, b;
+ int association, sequence;
+ int default_device;
+ int default_loc;
+ int conn;
+
+ int color;
+ int no_color = 0;
+ char *name = NULL, *loc = "", *color_name = NULL;
+
+ if (!corb_read (mixer, cad, wid, 0, GET_CONFIG_DEFAULT, 0, &conf, &b))
+ return 0;
+
+ default_device = (conf >> 20) & 0x0f;
+ default_loc = (conf >> 24) & 0x3f;
+ conn = (conf >> 30) & 0x03;
+
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_PIN_CAPS, &pincaps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_PIN_CAPS failed\n");
+ return 0;
+ }
+
+ widget->pincaps = pincaps;
+
+ if (conf == 0)
+ {
+ cmn_err (CE_WARN,
+ "CONFIG_DEFAULT information not provided by BIOS for cad=%d, wid=%02x\n",
+ cad, wid);
+ cmn_err (CE_CONT, "Cannot work in this system.\n");
+ return 0;
+ }
+
+ color = (conf >> 12) & 0x0f;
+
+ association = (conf>>4) & 0xf;
+ sequence = conf & 0xf;
+
+ if (pincaps & (1 << 6))
+ cmn_err (CE_WARN, "Balanced I/O not supported\n");
+ if (!(pincaps & (1 << 5))) /* No input */
+ widget->pin_type = PIN_OUT;
+ if (!(pincaps & (1 << 4)))
+ widget->pin_type = PIN_IN;
+
+ DDB (cmn_err (CE_CONT, "\tConfig default %08x\n", conf));
+
+ if ((default_loc & 0x0f) == 0x1) /* Rear panel - default */
+ loc = "";
+ if ((default_loc & 0x0f) == 0x2) /* Front panel */
+ loc = "fp-";
+ if ((default_loc & 0xf0) == 0x10) /* Internal func - eg cd/tad/spk */
+ loc = "int-";
+
+ if (conn == 1) /* Pin not connected to anything */
+ {
+ widget->skip = 1;
+ widget->skip_output = 1;
+ }
+
+ widget->association = association;
+ widget->sequence = sequence;
+
+ switch (default_device)
+ {
+ case 0x0:
+ name = "lineout";
+ widget->pin_type = PIN_OUT;
+ break;
+ case 0x1:
+ name = "speaker";
+ no_color = 1;
+ widget->pin_type = PIN_OUT;
+ break;
+ case 0x2:
+ name = "headphone";
+ widget->pin_type = PIN_OUT;
+ break;
+ case 0x3:
+ name = "cd";
+ no_color = 1;
+ widget->pin_type = PIN_IN;
+ break;
+ case 0x4:
+ name = "spdifout";
+ no_color = 1;
+ widget->pin_type = PIN_OUT;
+ break;
+ case 0x5:
+ name = "digout";
+ no_color = 1;
+ widget->pin_type = PIN_OUT;
+ break;
+ case 0x6:
+ name = "modem";
+ no_color = 1;
+ break;
+ case 0x7:
+ name = "phone";
+ no_color = 1;
+ break;
+ case 0x8:
+ name = "linein";
+ widget->pin_type = PIN_IN;
+ break;
+ case 0x9:
+ name = "aux";
+ break;
+ case 0xa:
+ name = "mic";
+ widget->pin_type = PIN_MIC;
+ break;
+ case 0xb:
+ name = "telephony";
+ no_color = 1;
+ break;
+ case 0xc:
+ name = "spdifin";
+ no_color = 1;
+ break;
+ case 0xd:
+ name = "digin";
+ no_color = 1;
+ break;
+ case 0xe:
+ name = "reserved";
+ no_color = 1;
+ break;
+ case 0xf: /* Unused pin widget */
+ widget->skip = 1;
+ widget->skip_output = 1;
+ break;
+ }
+
+/* process only colored jacks and skip fixed function jacks */
+ switch (color)
+ {
+ case 0x1:
+ color_name = "black";
+ widget->rgbcolor = OSS_RGB_BLACK;
+ break;
+ case 0x2:
+ color_name = "gray";
+ widget->rgbcolor = OSS_RGB_GRAY;
+ break;
+ case 0x3:
+ color_name = "blue";
+ widget->rgbcolor = OSS_RGB_BLUE;
+ break;
+ case 0x4:
+ color_name = "green";
+ widget->rgbcolor = OSS_RGB_GREEN;
+ break;
+ case 0x5:
+ color_name = "red";
+ widget->rgbcolor = OSS_RGB_RED;
+ break;
+ case 0x6:
+ color_name = "orange";
+ widget->rgbcolor = OSS_RGB_ORANGE;
+ break;
+ case 0x7:
+ color_name = "yellow";
+ widget->rgbcolor = OSS_RGB_YELLOW;
+ break;
+ case 0x8:
+ color_name = "purple";
+ widget->rgbcolor = OSS_RGB_PURPLE;
+ break;
+ case 0x9:
+ color_name = "pink";
+ widget->rgbcolor = OSS_RGB_PINK;
+ break;
+ case 0xe:
+ color_name = "white";
+ widget->rgbcolor = OSS_RGB_WHITE;
+ break;
+
+ default:
+ if (name != NULL)
+ color_name = name;
+ else
+ color_name = "internal";
+ }
+
+ if (no_color)
+ widget->rgbcolor = 0;
+
+ if (default_device == 0xf) /* Not present */
+ {
+ widget->rgbcolor = 0;
+ color_name = "internal";
+ }
+
+ sprintf (widget->color, "%s%s", loc, color_name);
+
+ if (name == NULL || default_device == 0x00)
+ name = color_name;
+ sprintf (widget->name, "%s%s", loc, name);
+
+ DDB(cmn_err(CE_CONT, "\tJack name %s, color %s (%06x)\n",
+ widget->name, widget->color, widget->rgbcolor));
+ DDB(cmn_err(CE_CONT, "\tAssociation %x, sequence %x\n", association, sequence));
+
+printf("Widget %02x: default_device=%d, name=%s, color=%s\n", wid, default_device, widget->name, widget->color);
+ return 1;
+}
+
+static int
+attach_widget (hdaudio_mixer_t * mixer, int cad, int wid, int group_type)
+{
+ static const char *widget_types[16] = {
+ "Audio output",
+ "Audio input",
+ "Audio mixer",
+ "Audio selector",
+ "Pin complex",
+ "Power widget",
+ "Volume knob",
+ "Beep generator",
+ "Reserved8",
+ "Reserved9",
+ "ReservedA",
+ "ReservedB",
+ "ReservedC",
+ "ReservedD",
+ "ReservedE",
+ "Vendor defined audio"
+ };
+
+ static const int bit_sizes[] = {
+ 8,
+ 16,
+ 20,
+ 24,
+ 32
+ };
+
+ static const unsigned int bit_fmts[] = {
+ AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_S32_LE,
+ AFMT_S32_LE,
+ AFMT_S32_LE
+ };
+
+ static const int srates[] = {
+ 8000,
+ 11025,
+ 16000,
+ 22050,
+ 32000,
+ 44100,
+ 48000,
+ 88200,
+ 96000,
+ 176400,
+ 192000,
+ 384000
+ };
+
+ unsigned int widget_caps, b, pstate;
+ unsigned int inamp_caps, outamp_caps;
+ int wid_type;
+ int i;
+
+ codec_t *codec = mixer->codecs[cad];
+ widget_t *widget;
+
+ if (codec == NULL)
+ return 0;
+
+ if (wid >= MAX_WIDGETS)
+ {
+ cmn_err (CE_WARN, "Too many widgets for codec %d (%d/%d)\n", cad, wid,
+ MAX_WIDGETS);
+ return 0;
+ }
+
+ mixer->ncontrols++;
+
+ codec->nwidgets = wid + 1;
+ widget = &codec->widgets[wid];
+
+ widget->cad = cad;
+ widget->wid = wid;
+
+ widget->rgbcolor = 0;
+
+ widget->group_type = group_type;
+
+ DDB (cmn_err (CE_CONT, " * Widget %02x, type %d\n", wid, group_type));
+
+ if (!corb_read
+ (mixer, cad, wid, 0, GET_PARAMETER, HDA_WIDGET_CAPS, &widget_caps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_WIDGET_CAPS failed\n");
+ return 0;
+ }
+
+ if (widget_caps & WCAP_AMP_CAP_OVERRIDE) /* Amp param override? */
+ {
+ if (!corb_read (mixer, widget->cad, widget->wid, 0,
+ GET_PARAMETER, HDA_OUTPUTAMP_CAPS, &outamp_caps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
+ return -EIO;
+ }
+ widget->outamp_caps = outamp_caps;
+
+ if (!corb_read (mixer, widget->cad, widget->wid, 0,
+ GET_PARAMETER, HDA_INPUTAMP_CAPS, &inamp_caps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTAMP_CAPS failed\n");
+ return -EIO;
+ }
+ widget->inamp_caps = inamp_caps;
+ }
+ else
+ {
+ widget->outamp_caps = outamp_caps = codec->default_outamp_caps;
+ widget->inamp_caps = inamp_caps = codec->default_inamp_caps;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0, GET_POWER_STATE, 0, &pstate, &b))
+ return 0;
+
+ /* power up each of the widgets if there is a Power Capability (1<<10) */
+ if (widget_caps & WCAP_POWER_CTL)
+ corb_write (mixer, cad, wid, 0, SET_POWER_STATE, 0);
+
+ widget->widget_caps = widget_caps;
+
+ wid_type = (widget_caps >> 20) & 0x0f;
+ DDB (cmn_err
+ (CE_CONT, "\tWidget type %d (%s)(%s)\n", wid_type,
+ widget_types[wid_type], widget_id[wid_type]));
+ DDB (cmn_err (CE_CONT, "\tPower State %d\n", pstate));
+
+ if (widget_caps & WCAP_CONN_LIST)
+ {
+ unsigned int clen;
+ /* Handle connection list */
+
+ if (!corb_read
+ (mixer, cad, wid, 0, GET_PARAMETER, HDA_CONNLIST_LEN, &clen, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_CONNLIST_LEN failed\n");
+ return 0;
+ }
+
+ if (clen & 0x80)
+ {
+ cmn_err (CE_WARN, "Long form connection list not supported\n");
+ return 0;
+ }
+
+ if (clen > 0)
+ {
+ if (clen > MAX_CONN)
+ {
+ cmn_err (CE_WARN, "Too many connections\n");
+ return 0;
+ }
+
+ DDB (cmn_err (CE_CONT, "\tConn list (%d): ", clen));
+
+ for (i = 0; i < clen; i += 4)
+ {
+ int j;
+ unsigned int a;
+
+ if (!corb_read
+ (mixer, cad, wid, 0, GET_CONNECTION_LIST_ENTRY, i, &a, &b))
+ {
+ cmn_err (CE_WARN, "GET_CONNECTION_LIST_ENTRY failed\n");
+ return 0;
+ }
+
+ for (j = 0; j < 4 && (i + j) < clen; j++)
+ {
+ int v, is_range = 0;
+
+ if (widget->nconn >= MAX_CONN)
+ {
+ cmn_err (CE_WARN,
+ "Too many connections for widget %d (%d)\n",
+ widget->wid, widget->nconn);
+ break;
+ }
+
+ v = (a >> (j * 8)) & 0xff;
+ DDB (cmn_err (CE_CONT, "%d ", v));
+
+ if (v & 0x80)
+ {
+ is_range = 1;
+ v &= ~0x80;
+ }
+
+ if (v < 0 || v >= MAX_WIDGETS)
+ {
+ cmn_err (CE_NOTE,
+ "Connection %d for widget %d is out of range (%d) - Skipped\n",
+ j, widget->wid, v);
+ continue;
+ }
+
+ if (is_range) /* Range: prev...v */
+ {
+ int x;
+ codec->widgets[v].references[codec->widgets[v].
+ refcount++] = wid;
+
+ if (widget->nconn < 1)
+ {
+ cmn_err (CE_CONT,
+ "Bad range connection for widget %d\n",
+ widget->wid);
+ continue;
+ }
+
+ for (x = widget->connections[widget->nconn - 1] + 1;
+ x <= v; x++)
+ {
+ if (widget->nconn >= MAX_CONN)
+ {
+ cmn_err (CE_WARN,
+ "Too many connectionsi(B) for widget %d (%d)\n",
+ widget->wid, widget->nconn);
+ break;
+ }
+
+ widget->connections[widget->nconn++] = x;
+ codec->widgets[x].references[codec->widgets[x].
+ refcount++] = wid;
+ }
+ }
+ else
+ {
+ widget->connections[widget->nconn++] = v;
+ codec->widgets[v].references[codec->widgets[v].
+ refcount++] = wid;
+ }
+ }
+ }
+
+ DDB (cmn_err (CE_CONT, "\n"));
+ }
+ }
+
+ widget->wid_type = wid_type;
+ strcpy (widget->name, widget_id[wid_type]);
+
+/*
+ * Handle widget based on its type.
+ */
+
+ switch (wid_type)
+ {
+ case NT_PIN:
+ if (!attach_pin_widget (mixer, codec, widget, cad, wid, group_type))
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+ /*ARGSUSED*/ static int
+attach_function_group (hdaudio_mixer_t * mixer, int cad, int wid,
+ int group_type)
+{
+ unsigned int a, b, gt;
+ int i, first_node, num_nodes;
+ codec_t *codec = mixer->codecs[cad];
+
+ if (codec == NULL)
+ return 0;
+ cmn_err (CE_CONT, "Attach function group, cad=%02x, wid=%02x\n", cad, wid);
+
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_OUTPUTAMP_CAPS,
+ &codec->default_outamp_caps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
+ return 0;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0,
+ GET_PARAMETER, HDA_INPUTAMP_CAPS,
+ &codec->default_inamp_caps, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTTAMP_CAPS failed\n");
+ return 0;
+ }
+
+ if (!corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT2 failed\n");
+ return 0;
+ }
+
+ first_node = (a >> 16) & 0xff;
+ num_nodes = a & 0xff;
+
+ corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gt, &b);
+ gt &= 0xff;
+
+ DDB (cmn_err
+ (CE_CONT,
+ " * Function group %d First node %d, num nodes %d, group type %x\n",
+ wid, first_node, num_nodes, gt));
+/*
+ * Ignore other than audio function groups. Codecs probably allocate
+ * higher widget number for the modem group than the audio group. So in this
+ * way we can have smaller MAX_WIDGETS which in turn conserves memory.
+ */
+ if (gt != group_type)
+ return 0;
+
+ if (corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_PCM_SIZES, &a, &b))
+ {
+ codec->sizes = a;
+ }
+
+ if (first_node > 0)
+ for (i = first_node; i < first_node + num_nodes; i++)
+ if (!attach_widget (mixer, cad, i, gt))
+ return 0;
+
+ if (num_nodes >= 1)
+ codec->active = 1;
+ return 1;
+}
+static int
+attach_codec (hdaudio_mixer_t * mixer, int cad, char *hw_info,
+ unsigned int pci_subdevice, int group_type)
+{
+ unsigned int a, b, x;
+ int i;
+ int first_node, num_nodes;
+ int has_audio_group = 0;
+ codec_t *codec;
+
+ if (cad >= MAX_CODECS)
+ {
+ cmn_err (CE_WARN, "attach_codec: Too many codecs %d\n", cad);
+ return -EIO;
+ }
+
+ mixer->ncodecs = cad + 1;
+
+ if (mixer->codecs[cad] == NULL)
+ {
+ if ((codec = PMALLOC (mixer->osdev, sizeof (*codec))) == NULL)
+ {
+ cmn_err (CE_CONT, "Cannot allocate codec descriptor\n");
+ return -ENOMEM;
+ }
+
+ memset (codec, 0, sizeof (*codec));
+
+ mixer->codecs[cad] = codec;
+ }
+ else
+ {
+ codec = mixer->codecs[cad];
+ }
+
+ corb_write (mixer, cad, 0, 0, SET_POWER_STATE, 0); /* Power up everything */
+
+ if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &a, &b))
+ {
+ if (group_type == 1)
+ {
+ sprintf (hw_info, " Codec %2d: Not present\n", cad);
+ cmn_err (CE_NOTE,
+ "attach_codec: Codec #%d is not physically present\n",
+ cad);
+ }
+ return -EIO;
+ }
+
+ codec->vendor_id = a;
+
+/*
+ * Find out the primary group list
+ */
+
+ if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_NODE_COUNT, &x, &b))
+ {
+ cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT3 failed\n");
+ return -EIO;
+ }
+
+ codec->first_node = first_node = (x >> 16) & 0xff;
+ num_nodes = x & 0xff;
+
+/*
+ * Check if this one is an audio codec (has an audio function group)
+ */
+ for (i = first_node; i < first_node + num_nodes; i++)
+ {
+ unsigned int gt;
+
+ if (corb_read
+ (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gt, &b));
+ if ((gt & 0xff) != 1) /* Audio function group */
+ continue;
+
+ has_audio_group = 1;
+ }
+
+#if 0
+/*
+ * Find codec specific settings
+ */
+ for (ix = 0; codecs[ix].id != 0; ix++)
+ if (codecs[ix].id == a)
+ break;
+
+ DDB (cmn_err
+ (CE_CONT, "HD audio Codec ID: %08x (%s)\n", a, codecs[ix].name));
+
+ if (codecs[ix].id == 0) /* Unknown codec */
+ {
+ if (group_type == 1)
+ sprintf (hw_info, " Codec %2d: Unknown (0x%08x", cad, a);
+ cmn_err (CE_NOTE, "Unknown HDA codec 0x%08x\n", a);
+ /*
+ * Create hexadecimal codec ID
+ */
+ if (has_audio_group && mixer->chip_name == NULL)
+ if ((mixer->chip_name = PMALLOC (mixer->osdev, 32)) != NULL)
+ {
+ sprintf (mixer->chip_name, "0x%08x", a);
+ }
+ }
+ else
+ {
+ if (group_type == 1)
+ sprintf (hw_info, " Codec %2d: %s (0x%08x", cad, codecs[ix].name, a);
+ }
+
+ if (has_audio_group && mixer->chip_name == NULL)
+ {
+ mixer->chip_name = codecs[ix].name;
+
+ }
+
+ if (codecs[ix].remap != NULL)
+ codec->remap = codecs[ix].remap;
+
+ if (codecs[ix].flags != 0)
+ codec->vendor_flags = codecs[ix].flags;
+
+ if (codecs[ix].mixer_init != NULL)
+ codec->mixer_init = codecs[ix].mixer_init;
+
+ codec->multich_map = codecs[ix].multich_map;
+ codec->codec_desc = &codecs[ix];
+#endif
+
+ if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &a, &b))
+ {
+ DDB (cmn_err (CE_CONT, "HDA codec revision %d.%d (%d.%d) (0x%08x)\n",
+ (a >> 20) & 0xf,
+ (a >> 16) & 0xf, (a >> 8) & 0xff, a & 0xff, a));
+ }
+ else
+ DDB (cmn_err (CE_CONT, "Can't get codec revision\n"));
+
+ DDB (cmn_err (CE_CONT, "**** Codec %d ****\n", cad));
+ DDB (cmn_err
+ (CE_CONT, "First group node %d, num nodes %d\n", first_node,
+ num_nodes));
+
+ for (i = first_node; i < first_node + num_nodes; i++)
+ {
+ corb_read (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, &a, &b);
+ if ((a & 0xff) == group_type) /* Proper function group type */
+ {
+ codec->afg = i;
+
+ if (corb_read (mixer, cad, i, 0, GET_SUBSYSTEM_ID, 0, &a, &b))
+ {
+ DDB (cmn_err (CE_CONT, "Subsystem ID = 0x%08x\n", a));
+
+ if (group_type == 1)
+ {
+ /* Append subvendor ID to hw_info */
+ hw_info += strlen (hw_info);
+ sprintf (hw_info, "/0x%08x", a);
+ }
+
+ codec->subvendor_id = a;
+
+#if 0
+ for (subix = 0; subdevices[subix].id != 0; subix++)
+ if (subdevices[subix].id == a)
+ {
+ if (subdevices[subix].main_id != 0)
+ if (subdevices[subix].main_id != codec->vendor_id)
+ continue;
+
+ if (subdevices[subix].pci_subdevice != 0)
+ if (subdevices[subix].pci_subdevice != pci_subdevice)
+ continue;
+
+
+ DDB (cmn_err
+ (CE_CONT, "Subdevice known as %s\n",
+ subdevices[subix].name));
+ if (group_type == 1)
+ {
+ hw_info += strlen (hw_info);
+ sprintf (hw_info, " %s", subdevices[subix].name);
+ }
+ if (subdevices[subix].remap != NULL)
+ {
+ codec->remap = subdevices[subix].remap;
+ }
+
+ if (subdevices[subix].multich_map != 0)
+ codec->multich_map = subdevices[subix].multich_map;
+ if (subdevices[subix].flags != 0)
+ codec->vendor_flags = subdevices[subix].flags;
+ if (subdevices[subix].mixer_init != NULL)
+ {
+ codec->mixer_init = subdevices[subix].mixer_init;
+ }
+ }
+#endif
+ }
+ break;
+ }
+ }
+
+ hw_info += strlen (hw_info);
+ if (group_type == 1)
+ strcpy (hw_info, ")\n");
+
+ for (i = first_node; i < first_node + num_nodes; i++)
+ {
+ if (!attach_function_group (mixer, cad, i, group_type))
+ continue;
+
+ /* power up the AFG! */
+ corb_write (mixer, cad, i, 0, SET_POWER_STATE, 0);
+ }
+
+#if 0
+ if (has_audio_group)
+ {
+ polish_widget_list (mixer, cad);
+ }
+
+ copy_endpoints (mixer, codec, 0); /* Copy analog endpoints from codec to mixer */
+#endif
+
+ return (has_audio_group) ? 0 : -EIO;
+}
+
+static void
+follow_path(hdaudio_mixer_t *mixer, codec_t *codec, widget_t *widget, path_t *path, int use_force)
+{
+ int i;
+
+ if (widget->used)
+ return;
+
+ widget->used = 1;
+ path->widgets[path->nwidgets++] = widget;
+ if (widget->wid_type == NT_PIN)
+ {
+ path->jack_count++;
+ path->association=widget->association;
+ path->sequence=widget->sequence;
+
+ /*
+ * Stop at a pin widget that is not the first widget of the path.
+ * In this way we don't walk back the input chain from the pin.
+ */
+
+ if (path->nwidgets > 1)
+ return;
+ }
+
+ if (use_force || path->nwidgets == 1 || widget->nconn == 1 || (widget->nconn>0 && widget->wid_type == NT_SELECT))
+ {
+ for (i=0;i<widget->nconn;i++)
+ if (!codec->widgets[widget->connections[i]].used)
+ //if (codec->widgets[widget->connections[i]].refcount < 2)
+ {
+ follow_path(mixer, codec, &codec->widgets[widget->connections[i]], path, use_force);
+ return;
+ }
+ }
+}
+
+static void
+dump_path(hdaudio_mixer_t *mixer, path_t *path)
+{
+ int i, j;
+
+ if (path->nwidgets == 0)
+ return;
+
+ printf("Path (a=%x, s=%x, jc=%d):\n ", path->association, path->sequence, path->jack_count);
+
+ for (i=0;i<path->nwidgets;i++)
+ {
+ widget_t *widget = path->widgets[i];
+
+ printf("\t%02x(%s/%s/nc=%d/rc=%d", widget->wid, widget_id[widget->wid_type], widget->name, widget->nconn, widget->refcount);
+ printf(")\n");
+
+ if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT)
+ {
+ printf("\t\tOutput amp\n");
+ }
+
+ if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT)
+ {
+ printf("\t\t%d input amp(s)\n", widget->nconn);
+
+ for (j=0;j<widget->nconn;j++)
+ {
+ widget_t *in_widget;
+
+ in_widget = &mixer->codecs[widget->cad]->
+ widgets[widget->connections[j]];
+ printf("\t\t\t%02x(%s/%s/nc=%d/rc=%d)\n", in_widget->wid, widget_id[in_widget->wid_type], in_widget->name, in_widget->nconn, in_widget->refcount);
+
+ in_widget->used=1;
+ }
+ }
+ }
+ printf("\n");
+}
+
+static void
+store_path(hdaudio_mixer_t *mixer, path_t *path)
+{
+ if (npaths>=MAX_PATHS)
+ {
+ cmn_err(CE_WARN, "Too many paths\n");
+ return;
+ }
+
+ paths[npaths++]=path;
+}
+
+static void
+create_path_list(hdaudio_mixer_t *mixer, int cad, int node_type, int use_force)
+{
+ codec_t *codec;
+ int wid;
+
+ path_t *path;
+
+cmn_err(CE_CONT, "Create path list %d (%s)\n", node_type, widget_id[node_type]);
+ codec=mixer->codecs[cad];
+
+ for (wid=0;wid<codec->nwidgets;wid++)
+ if (codec->widgets[wid].wid_type == node_type)
+ if (!codec->widgets[wid].skip)
+ if (codec->widgets[wid].wid == wid)
+ {
+ path=malloc(sizeof(*path));
+
+ follow_path(mixer, codec, &codec->widgets[wid], path, use_force);
+
+ if (path->nwidgets>1)
+ store_path(mixer, path);
+ else
+ if (path->nwidgets>0)
+ path->widgets[0]->used=0;
+ }
+
+}
+
+static void
+create_path_list_for_pin(hdaudio_mixer_t *mixer, int cad, int association, int sequence)
+{
+ codec_t *codec;
+ int wid;
+
+ path_t *path;
+
+ codec=mixer->codecs[cad];
+
+ for (wid=0;wid<codec->nwidgets;wid++)
+ if (codec->widgets[wid].wid_type == NT_PIN && !codec->widgets[wid].skip)
+ if (codec->widgets[wid].pin_type == PIN_HEADPHONE || codec->widgets[wid].pin_type == PIN_OUT)
+ if (codec->widgets[wid].wid == wid)
+ if (codec->widgets[wid].nconn > 0)
+ if (!codec->widgets[wid].skip)
+ if (codec->widgets[wid].sequence == sequence)
+ if (codec->widgets[wid].association == association)
+ {
+ path=malloc(sizeof(*path));
+
+ follow_path(mixer, codec, &codec->widgets[wid], path, 0);
+
+ if (path->nwidgets>1)
+ store_path(mixer, path);
+ else
+ if (path->nwidgets>0)
+ path->widgets[0]->used=0;
+ }
+
+}
+
+hdaudio_mixer_t *
+hdaudio_mixer_create (char *name, void *devc,
+ oss_device_t * osdev,
+ hdmixer_write_t writefunc,
+ hdmixer_read_t readfunc, unsigned int codecmask,
+ unsigned int vendor_id, unsigned int subvendor_id)
+{
+ hdaudio_mixer_t *mixer;
+ int i, func;
+ int ncodecs = 0;
+ char tmp[128];
+ int mixer_dev;
+
+ char *hw_info = osdev->hw_info; /* For printing hardware information */
+
+ if ((mixer = PMALLOC (osdev, sizeof (*mixer))) == NULL)
+ {
+ cmn_err (CE_WARN, "hdaudio_mixer_create: Out of memory\n");
+ return NULL;
+ }
+
+ memset (mixer, 0, sizeof (*mixer));
+
+ mixer->devc = devc;
+ mixer->osdev = osdev;
+ mixer->mixer_dev = 0;
+ strncpy (mixer->name, name, sizeof (mixer->name) - 1);
+ mixer->name[sizeof (mixer->name) - 1] = 0;
+
+ for (i = 0; i < MAX_CODECS; i++)
+ mixer->codecs[i] = NULL;
+
+#ifdef _KERNEL
+ mixer->read = readfunc;
+ mixer->write = writefunc;
+#endif
+
+ mixer->codecmask = codecmask;
+
+ sprintf (hw_info, "HD Audio controller %s\n"
+ "Vendor ID 0x%08x\n"
+ "Subvendor ID 0x%08x\n", name, vendor_id, subvendor_id);
+ hw_info += strlen (hw_info);
+
+/*
+ * Search first all audio function groups for all codecs and then
+ * handle modem function groups.
+ */
+ for (func = 1; func <= 2; func++)
+ for (i = 0; i < 16; i++)
+ if (mixer->codecmask & (1 << i))
+ {
+ if (attach_codec (mixer, i, hw_info, subvendor_id, func) >= 0)
+ ncodecs++;
+ hw_info += strlen (hw_info);
+ }
+
+ for (i = 0; i < 16; i++)
+ if (mixer->codecmask & (1 << i))
+ {
+ int association, sequence;
+
+printf("*** Codec %d\n", i);
+ for (association=1;association<16;association++)
+ for (sequence=0;sequence<16;sequence++)
+ create_path_list_for_pin(mixer, i, association, sequence);
+
+ create_path_list(mixer, i, NT_ADC, 0);
+ create_path_list(mixer, i, NT_MIXER, 1);
+ create_path_list(mixer, i, NT_SELECT, 1);
+ }
+
+ for (i=0;i<npaths;i++)
+ dump_path(mixer, paths[i]);
+
+#if 1
+ printf("\n\nOther widgets:\n");
+
+ for (i = 0; i < 16; i++)
+ if (mixer->codecmask & (1 << i))
+ {
+ int wid;
+
+ for (wid=0;wid<mixer->codecs[i]->nwidgets;wid++)
+ {
+ widget_t *widget = &mixer->codecs[i]->widgets[wid];
+
+ if (widget->wid != wid)
+ continue;
+
+ if (widget->used || widget->skip)
+ continue;
+ printf("Codec %d, Widget %02x %s/%s/%d\n", widget->cad, widget->wid, widget_id[widget->wid_type], widget->name, widget->nconn);
+ }
+ }
+#endif
+
+ return mixer;
+}
+
+int
+main (int argc, char *argv[])
+{
+ unsigned int rev, b;
+ int first_node, num_nodes;
+ int i;
+ int cad = 0;
+
+ int codecmask = 0;
+
+ oss_device_t osdev = { 0 };
+
+ osdev.hw_info = malloc (256);
+
+ if ((fd = open ("/dev/oss/oss_hdaudio0/pcm0", O_RDWR | O_EXCL, 0)) == -1)
+ {
+ perror ("/dev/oss/oss_hdaudio0/pcm0");
+ exit (-1);
+ }
+
+ for (cad = 0; cad < 15; cad++)
+ if (corb_read (NULL, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &rev, &b))
+ {
+#if 1
+ printf ("Codec %2d: HD codec revision %d.%d (%d.%d) (0x%08x)\n", cad,
+ (rev >> 20) & 0xf, (rev >> 16) & 0xf, (rev >> 8) & 0xff,
+ rev & 0xff, rev);
+#endif
+ codecmask |= (1 << cad);
+ }
+
+ hdaudio_mixer_create ("ACME hdaudio", NULL,
+ &osdev, NULL, NULL, codecmask, 0x12345678, 0x8754321);
+
+ //printf("HW Info: %s\n", osdev.hw_info);
+ exit (0);
+}
diff --git a/utils/ossmkdep.c b/utils/ossmkdep.c
new file mode 100644
index 0000000..9d33da9
--- /dev/null
+++ b/utils/ossmkdep.c
@@ -0,0 +1,234 @@
+/*
+ * Purpose: Simple replacement for cpp -M (gcc)
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+int ndirs = 0;
+char *dirs[1024];
+
+int ndupes = 0;
+char *dupes[4096];
+
+static void
+add_includedir (char *d)
+{
+ dirs[ndirs++] = d;
+}
+
+static int
+dupe_file (char *name)
+{
+ int i;
+
+ for (i = 0; i < ndupes; i++)
+ if (strcmp (dupes[i], name) == 0)
+ return 1;
+
+ dupes[ndupes++] = strdup (name);
+ return 0;
+}
+
+static void parse_f (FILE * f, char *pathname);
+
+static void
+do_global_include (char *hdrname, char *pathname)
+{
+ FILE *f;
+ int i;
+
+ char tmp[512];
+ sprintf (tmp, "%s/%s", pathname, hdrname);
+
+ if (dupe_file (tmp))
+ return;
+ if ((f = fopen (tmp, "r")) != NULL)
+ {
+ printf ("%s ", tmp);
+ parse_f (f, pathname);
+ fclose (f);
+ return;
+ }
+
+ for (i = 0; i < ndirs; i++)
+ {
+ sprintf (tmp, "%s/%s", dirs[i], hdrname);
+ if (dupe_file (tmp))
+ return;
+
+ if ((f = fopen (tmp, "r")) == NULL)
+ continue;
+ printf ("\\\n %s ", tmp);
+
+ parse_f (f, dirs[i]);
+ fclose (f);
+ return;
+ }
+
+ fprintf (stderr, "Cannot locate <%s>\n", hdrname);
+ printf ("\n");
+ exit (-1);
+}
+
+static void
+do_local_include (char *hdrname, char *pathname)
+{
+ FILE *f;
+ char tmp[512];
+
+ sprintf (tmp, "%s/%s", pathname, hdrname);
+
+ if (dupe_file (tmp))
+ {
+ return;
+ }
+
+ if ((f = fopen (tmp, "r")) == NULL)
+ {
+#if 1
+ do_global_include (hdrname, pathname);
+ return;
+#else
+ perror (tmp);
+ printf ("\n");
+ exit (-1);
+#endif
+ }
+
+ sprintf (tmp, "%s ", tmp);
+ parse_f (f, pathname);
+ printf ("\\\n %s ", tmp);
+
+ fclose (f);
+}
+
+static void
+parse_f (FILE * f, char *pathname)
+{
+ char line[1024], *p, *s;
+
+ while (fgets (line, sizeof (line), f) != NULL)
+ {
+ if (*line != '#')
+ continue;
+
+ s = line + 1;
+
+ /* Skip space */
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+
+ /* Extract the preprocessor directive name (p) */
+ p = s;
+ while (*s && (*s != ' ' && *s != '\t'))
+ s++;
+ *s++ = 0;
+
+ if (strcmp (p, "include") != 0)
+ continue;
+
+ /* Skip space */
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+
+ if (*s == '"')
+ {
+ s++;
+
+ p = s;
+ while (*s && *s != '"')
+ s++;
+ *s = 0;
+ do_local_include (p, pathname);
+ continue;
+ }
+
+ if (*s == '<')
+ {
+ s++;
+
+ p = s;
+ while (*s && *s != '>')
+ s++;
+ *s = 0;
+ do_global_include (p, pathname);
+ continue;
+ }
+ }
+}
+
+static void
+parse_sourcefile (char *srcname)
+{
+ FILE *f;
+ char *s, *p;
+ char origname[64];
+
+ strcpy (origname, srcname);
+
+ s = NULL;
+
+ p = srcname;
+ while (*p)
+ {
+ if (*p == '.')
+ s = p;
+ p++;
+ }
+
+ if (*s != '.')
+ {
+ fprintf (stderr, "Bad file name %s\n", srcname);
+ printf ("\n");
+ exit (-1);
+ }
+
+ if ((f = fopen (srcname, "r")) == NULL)
+ {
+ perror (srcname);
+ printf ("\n");
+ exit (-1);
+ }
+
+ *s++ = 0;
+ printf ("%s.o: %s ", srcname, origname);
+
+ parse_f (f, ".");
+ printf ("\n");
+ fclose (f);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ add_includedir ("/usr/include");
+ add_includedir ("/usr/local/include");
+
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'I':
+ add_includedir (argv[i] + 2);
+ break;
+ }
+ else
+ parse_sourcefile (argv[i]);
+
+ exit (0);
+}
diff --git a/utils/phpmake b/utils/phpmake
new file mode 100755
index 0000000..4000c25
--- /dev/null
+++ b/utils/phpmake
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+if test ! -f Makefile.php
+then
+ echo No Makefile.php in this directory
+ exit 0
+fi
+
+if ! php Makefile.php > Makefile
+then
+ exit 1
+fi
+
+for n in */Makefile.php
+do
+ N=`dirname $n`
+
+ if test "$N " != '* '
+ then
+ if ! (cd $N && phpmake $*)
+ then
+ exit 1
+ fi
+ fi
+done
+
+exit 0
diff --git a/utils/readtimings.c b/utils/readtimings.c
new file mode 100644
index 0000000..99a385e
--- /dev/null
+++ b/utils/readtimings.c
@@ -0,0 +1,61 @@
+/*
+ * Purpose: OSS built in tracing reader
+ *
+ * Description:
+ * This program is used to read timing/tracing information produced by the
+ * built in tracing facility of OSS.
+ *
+ * To use this program you need to rebuild OSS with the DO_TIMINGS macro
+ * defined. This macro is located in the os.h file for the target operating
+ * system. Output is written to stdout. Tracing information is currently
+ * produced only for the audio devices.
+ *
+ * To understand the output you need to be familiar with the internals of OSS.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int
+main (void)
+{
+ int fd;
+ char buf[257 * 1024];
+ int l;
+
+ if ((fd = open ("/dev/mixer0", O_RDONLY, 0)) == -1)
+ {
+ perror ("/dev/mixer0");
+ exit (-1);
+ }
+
+ while (1)
+ {
+ if ((l = read (fd, buf, sizeof (buf))) < 0)
+ {
+ perror ("read");
+ exit (-1);
+ }
+
+ if (l)
+ write (1, buf, l);
+
+ usleep (100000);
+ }
+
+ close (fd);
+ exit (0);
+}
diff --git a/utils/snoopy.c b/utils/snoopy.c
new file mode 100644
index 0000000..fede0e4
--- /dev/null
+++ b/utils/snoopy.c
@@ -0,0 +1,901 @@
+/*
+ * snoopy.c
+ *
+ * Purpose: Unsupported and undocumented diagnostic tool for hdaudio devices.
+ *
+ * This utility is an in-house tool used for examining capabilities and
+ * implementation details of HD audio codec chips. Only the first codec
+ * attached to the HD audio controller will be shown.
+ *
+ * You need to set the hdaudio_snoopy config option to 1 in hdaudio.conf.
+ *
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <soundcard.h>
+
+typedef int sound_os_info, mixer_create_controls_t, oss_device_t;
+
+#include <hdaudio.h>
+
+#define ioctl_arg int
+#define mixer_ext_init_fn int
+#include <hdaudio_codec.h>
+
+#undef corb_read
+#undef corb_write
+
+int fd;
+void *mixer = NULL;
+int trace = 0;
+
+int cad = -1;
+
+int
+corb_write (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+ if (trace)
+ printf ("WRITE %08x\n", tmp);
+
+ if (ioctl (fd, HDA_IOCTL_WRITE, &tmp) == -1)
+ {
+ /* perror("HDA_IOCTL_WRITE"); */
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
+ unsigned int verb, unsigned int parm, unsigned int *upper,
+ unsigned int *lower)
+{
+ unsigned int tmp;
+
+ tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
+
+ if (ioctl (fd, HDA_IOCTL_READ, &tmp) == -1)
+ {
+ /* perror("HDA_IOCTL_READ"); */
+ if (errno == EINVAL)
+ {
+ fprintf (stderr, "hdaudio_snoopy mode is not available\n");
+ exit (-1);
+ }
+ return 0;
+ }
+
+ *upper = tmp;
+ *lower = 0;
+ if (trace)
+ printf ("READ %08x\n", tmp);
+
+ return 1;
+}
+
+static void
+dump_verbs (int ix, int ntype, int clen, unsigned int wcaps)
+{
+ int i;
+ unsigned int a, b, sel, state, fmt, spd, pstate, conv, sdi;
+ unsigned int unsol, pin, sense, eapd, beep, def, stripe;
+
+ static const int bits[8] = { 8, 16, 20, 24, 32 };
+ static const char *vrefs[8] =
+ { "Hi-Z", "50%", "Ground (0V)", "Reserved", "80%", "100%", "Reserved",
+ "Reserved"
+ };
+
+ if (ntype == NT_ADC || ntype == NT_SELECT || ntype == NT_PIN)
+ if (corb_read (mixer, cad, ix, 0, GET_SELECTOR, 0, &sel, &b))
+ printf ("\tConnection select (701) = %08x\n", sel);
+
+ if (ntype == NT_ADC || ntype == NT_DAC || ntype == NT_SELECT
+ || ntype == NT_PIN)
+ if (corb_read (mixer, cad, ix, 0, GET_PROCESSING_STATE, 0, &state, &b))
+ printf ("\tProcessing state (703) = %08x\n", state);
+
+ if (ntype == NT_ADC || ntype == NT_DAC)
+ if (corb_read (mixer, cad, ix, 0, GET_CONVERTER_FORMAT, 0, &fmt, &b))
+ {
+ printf ("\tConverter format (00A) = %04x\n", fmt);
+ printf ("\t\tNon-PCM %d\n", (fmt >> 15) & 0x01);
+ printf ("\t\tSR base 44.1 kHz %d\n", (fmt >> 14) & 0x01);
+ printf ("\t\tSR multiplier %d\n", ((fmt >> 11) & 0x07) + 1);
+ printf ("\t\tSR divider %d\n", ((fmt >> 8) & 0x07) + 1);
+ printf ("\t\tBits %d\n", bits[(fmt >> 4) & 0x07]);
+ printf ("\t\tChannels %d\n", (fmt & 0x0f) + 1);
+ }
+
+ if (ntype == NT_ADC || ntype == NT_DAC)
+ if (corb_read (mixer, cad, ix, 0, GET_CONVERTER, 0, &conv, &b))
+ {
+ printf ("\tConverter control (F06) %02x\n", conv);
+ printf ("\t\tStream %d\n", (conv >> 4) & 0xf);
+ printf ("\t\tChannel %d\n", (conv >> 0) & 0xf);
+ }
+
+ if (ntype == NT_PIN)
+ {
+ if (corb_read (mixer, cad, ix, 0, GET_PINCTL, 0, &pin, &b))
+ {
+ printf ("\tPin widget control (F07) %02x\n", pin);
+ printf ("\t\tOutput amp enable %d\n", (pin >> 7) & 1);
+ printf ("\t\tOutput enable %d\n", (pin >> 6) & 1);
+ printf ("\t\tInput enable %d\n", (pin >> 5) & 1);
+ printf ("\t\tVRef enable %d %s\n", pin & 7, vrefs[pin & 7]);
+ }
+
+ corb_write (mixer, cad, ix, 0, TRIGGER_PIN_SENSE, 0);
+ usleep (100 * 1000);
+
+ if (corb_read (mixer, cad, ix, 0, GET_PIN_SENSE, 0, &sense, &b))
+ {
+ printf ("\tPin sense (F09) %08x\n", sense);
+ printf ("\t\tPresence detect %d\n", (sense >> 31) & 1);
+ printf ("\t\tImpedance sense bits %08x\n", sense & ~0x80000000);
+ }
+
+ if (corb_read (mixer, cad, ix, 0, GET_CONFIG_DEFAULT, 0, &def, &b))
+ {
+ int v;
+
+ printf ("\tConfiguration default (F1C) %08x\n", def);
+
+ /* Port connectivity */
+ v = (def >> 30) & 3;
+ printf ("\t\tPort connectivity %d ", v);
+ switch (v)
+ {
+ case 0:
+ printf ("Jack (1/8\", ATAPI, etc)");
+ break;
+ case 1:
+ printf ("No physical connection for port");
+ break;
+ case 2:
+ printf
+ ("A fixed function device (integrated speaker, mic, etc)");
+ break;
+ case 3:
+ printf ("Both integrated device and a jack is connected");
+ break;
+ }
+ printf ("\n");
+
+ /* Location */
+ v = (def >> 24) & 0x3f;
+ printf ("\t\tLocation %02x ", v);
+ switch (v >> 4)
+ {
+ case 0:
+ printf ("External or primary chassis ");
+ break;
+ case 1:
+ printf ("Internal ");
+ break;
+ case 2:
+ printf ("Separate chassis ");
+ break;
+ case 3:
+ printf ("Other ");
+ break;
+ }
+ switch (v & 0xf)
+ {
+ case 0:
+ printf ("N/A");
+ break;
+ case 1:
+ printf ("rear");
+ break;
+ case 2:
+ printf ("front");
+ break;
+ case 3:
+ printf ("left");
+ break;
+ case 4:
+ printf ("right");
+ break;
+ case 5:
+ printf ("top");
+ break;
+ case 6:
+ printf ("bottom");
+ break;
+ case 7:
+ printf ("special");
+ break;
+ case 8:
+ printf ("special");
+ break;
+ case 9:
+ printf ("special");
+ break;
+ default:
+ printf ("reserved");
+ break;
+ }
+ printf ("\n");
+
+ /* Default device */
+ v = (def >> 20) & 0xf;
+ printf ("\t\tDefault device %d ", v);
+ switch (v)
+ {
+ case 0x0:
+ printf ("Line out");
+ break;
+ case 0x1:
+ printf ("Speaker");
+ break;
+ case 0x2:
+ printf ("Headphone out");
+ break;
+ case 0x3:
+ printf ("CD");
+ break;
+ case 0x4:
+ printf ("SPDIF out");
+ break;
+ case 0x5:
+ printf ("Digital other out");
+ break;
+ case 0x6:
+ printf ("Modem line side");
+ break;
+ case 0x7:
+ printf ("Modem handset side");
+ break;
+ case 0x8:
+ printf ("Line in");
+ break;
+ case 0x9:
+ printf ("AUX");
+ break;
+ case 0xa:
+ printf ("Mic in");
+ break;
+ case 0xb:
+ printf ("Telephony");
+ break;
+ case 0xc:
+ printf ("SPDIF in");
+ break;
+ case 0xd:
+ printf ("Digital other in");
+ break;
+ case 0xe:
+ printf ("Reserved");
+ break;
+ case 0xf:
+ printf ("Other");
+ break;
+ }
+ printf ("\n");
+
+ /* Cpnnection type */
+ v = (def >> 16) & 0x0f;
+ printf ("\t\tConnection type %x ", v);
+ switch (v)
+ {
+ case 0x0:
+ printf ("Unknown");
+ break;
+ case 0x1:
+ printf ("1/8\" stereo/mono");
+ break;
+ case 0x2:
+ printf ("1/4\" stereo/mono");
+ break;
+ case 0x3:
+ printf ("ATAPI internal");
+ break;
+ case 0x4:
+ printf ("RCA");
+ break;
+ case 0x5:
+ printf ("Optical");
+ break;
+ case 0x6:
+ printf ("Other digital");
+ break;
+ case 0x7:
+ printf ("Other analog");
+ break;
+ case 0x8:
+ printf ("Multichannel analog (DIN)");
+ break;
+ case 0x9:
+ printf ("XLR/professional");
+ break;
+ case 0xa:
+ printf ("RJ-11 (modem)");
+ break;
+ case 0xb:
+ printf ("Combination");
+ break;
+ case 0xc:
+ printf ("Reserved");
+ break;
+ case 0xd:
+ printf ("Reserved");
+ break;
+ case 0xe:
+ printf ("Reserved");
+ break;
+ case 0xf:
+ printf ("Other");
+ break;
+ }
+ printf ("\n");
+
+ /* Color */
+ v = (def >> 12) & 0xf;
+ printf ("\t\tColor %d ", v);
+ switch (v)
+ {
+ case 0x0:
+ printf ("Unknown");
+ break;
+ case 0x1:
+ printf ("Black");
+ break;
+ case 0x2:
+ printf ("Grey");
+ break;
+ case 0x3:
+ printf ("Blue");
+ break;
+ case 0x4:
+ printf ("Green");
+ break;
+ case 0x5:
+ printf ("Red");
+ break;
+ case 0x6:
+ printf ("Orange");
+ break;
+ case 0x7:
+ printf ("Yellow");
+ break;
+ case 0x8:
+ printf ("Purple");
+ break;
+ case 0x9:
+ printf ("Pink");
+ break;
+ case 0xa:
+ printf ("Reserved");
+ break;
+ case 0xb:
+ printf ("Reserved");
+ break;
+ case 0xc:
+ printf ("Reserved");
+ break;
+ case 0xd:
+ printf ("Reserved");
+ break;
+ case 0xe:
+ printf ("White");
+ break;
+ case 0xf:
+ printf ("Other");
+ break;
+ }
+ printf ("\n");
+
+ /* Mixc */
+ v = (def >> 8) & 0xf;
+ printf ("\t\tMisc 0x%x ", v);
+ if (v & 0x1)
+ printf ("JackDetectOverride ");
+ if (v & 0x2)
+ printf ("reserved1 ");
+ if (v & 0x4)
+ printf ("reserved2 ");
+ if (v & 0x8)
+ printf ("reserved3 ");
+ printf ("\n");
+
+ /* Default association */
+ v = (def >> 4) & 0xf;
+ printf ("\t\tDefault association %d ", v);
+ printf ("\n");
+
+ /* Sequence */
+ v = (def >> 0) & 0xf;
+ printf ("\t\tSequence %d ", v);
+ printf ("\n");
+ }
+ }
+
+ if (corb_read (mixer, cad, ix, 0, GET_EAPD, 0, &eapd, &b))
+ {
+ printf ("\tEAPD/BTL enable (F0C) %08x\n", eapd);
+ printf ("\t\tBTL %d\n", (eapd >> 0) & 1);
+ printf ("\t\tEAPD %d\n", (eapd >> 1) & 1);
+ printf ("\t\tL/R swap %d\n", (eapd >> 2) & 1);
+ }
+
+ if (ntype == NT_ADC)
+ if (corb_read (mixer, cad, ix, 0, GET_SDI_SELECT, 0, &sdi, &b))
+ {
+ printf ("\tSDI Select (F04) %d\n", sdi & 0x0f);
+ }
+
+ if (ntype == NT_DAC)
+ if (corb_read (mixer, cad, ix, 0, GET_STRIPE_CONTROL, 0, &stripe, &b))
+ {
+ printf ("\tStripe control (F24) %d\n", stripe);
+ }
+
+
+ if (ntype == NT_BEEP)
+ if (corb_read (mixer, cad, ix, 0, GET_BEEP, 0, &beep, &b))
+ {
+ beep &= 0xff;
+
+ if (beep == 0)
+ printf ("\tBeep OFF\n");
+ else
+ printf ("Beep %d Hz\n", 48000 / beep);
+ }
+
+ if (wcaps & (1 << 7))
+ if (corb_read (mixer, cad, ix, 0, GET_UNSOLICITED, 0, &unsol, &b))
+ {
+ printf ("\tUnsolicited response (F08) %02x\n", unsol);
+ printf ("\t\tEnabled %d\n", (unsol >> 7) & 1);
+ printf ("\t\tTag %d\n", unsol & 0x7f);
+ }
+
+ if (ntype == NT_ADC || ntype == NT_DAC)
+ if (wcaps & (1 << 9)) /* Digital capable */
+ if (corb_read (mixer, cad, ix, 0, GET_SPDIF_CONTROL, 0, &spd, &b))
+ {
+ printf ("\tS/PDIF converter control (F0D) %08x\n", spd);
+ printf ("\t\tCategory code (CC) %02x\n", (spd >> 8) & 0x3f);
+ printf ("\t\tGeneration level (L) %d\n", (spd >> 7) & 1);
+ printf ("\t\tPRO %d\n", (spd >> 6) & 1);
+ printf ("\t\t/AUDIO %d\n", (spd >> 5) & 1);
+ printf ("\t\tCOPY %d\n", (spd >> 4) & 1);
+ printf ("\t\tPreemphasis (PRE) %d\n", (spd >> 3) & 1);
+ printf ("\t\tValidity config (VCFG) %d\n", (spd >> 2) & 1);
+ printf ("\t\tValidity FLAG (V) %d\n", (spd >> 1) & 1);
+ printf ("\t\tDigital Enable (DigEn) %d\n", (spd >> 0) & 1);
+ }
+
+ if (corb_read (mixer, cad, ix, 0, GET_POWER_STATE, 0, &pstate, &b))
+ printf ("\tPower state (F05) D%d\n", pstate & 3);
+
+
+ if (wcaps & (1 << 2)) /* Output amp present */
+ {
+ if (corb_read (mixer, cad, ix, 0, GET_GAIN (1, 0), 0, &a, &b))
+ printf ("\tLeft output gain %02x\n", a);
+ else
+ printf ("\tLeft output gain read error\n");
+ if (corb_read (mixer, cad, ix, 0, GET_GAIN (1, 1), 0, &a, &b))
+ printf ("\tRight output gain %02x\n", a);
+ else
+ printf ("\tRight output gain read error\n");
+ }
+
+ if (wcaps & (1 << 1)) /* Input amp(s) present */
+ for (i = 0; i < clen; i++)
+ {
+ if (corb_read (mixer, cad, ix, 0, GET_GAIN (0, 0), 0, &a, &b))
+ printf ("\tInput gain %2d %02x", i, a);
+ else
+ printf ("\tInput gain %2d - Read error\n");
+ if (corb_read (mixer, cad, ix, 0, GET_GAIN (0, 1), 0, &a, &b))
+ printf (", %02x", a);
+ else
+ printf (", Read error");
+ printf ("\n");
+ }
+}
+
+static void
+dump_node (int ix)
+{
+ int i;
+ unsigned int a, b, gtype, gcaps, wcaps, sizes, fmts, pincaps;
+ unsigned int inamp_caps, outamp_caps, clen, pstates, pcaps, gpio_count;
+ unsigned int vkcaps;
+ hda_name_t name;
+ int first_node = 0, num_nodes = 0;
+ char *s;
+ int ntype = -1;
+
+ memset (&name, 0, sizeof (name));
+
+ name.cad = cad;
+ name.wid = ix;
+ ioctl (fd, HDA_IOCTL_NAME, &name);
+
+ printf ("\n*** Widget 0x%02x (%d) name=%s\n", ix, ix, name.name);
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gtype, &b))
+ if ((gtype & 0x1ff) != 0)
+ {
+ s = "Unknown";
+
+ switch (gtype & 0xff)
+ {
+ case 0:
+ s = "Reserved";
+ break;
+ case 1:
+ s = "Audio function group";
+ break;
+ case 2:
+ s = "Vendor defined modem function group";
+ break;
+ }
+
+ printf ("\tGroup type=%08x (%s), UnSol capable %d\n", gtype & 0xff, s,
+ (gtype >> 8) & 1);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_AUDIO_GROUP_CAPS, &gcaps, &b))
+ if ((gcaps & 0xffff) != 0)
+ {
+ printf ("\tAudio group capabilities %08x\n", gcaps);
+ printf ("\t\tBeep gen %d\n", (gcaps >> 16) & 1);
+ printf ("\t\tInput delay %d\n", (gcaps >> 8) & 0xf);
+ printf ("\t\tOutput delay %d\n", (gcaps) & 0xf);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_WIDGET_CAPS, &wcaps, &b))
+ if (wcaps != 0)
+ {
+ int type;
+
+ printf ("\tAudio widget capabilities %08x\n", wcaps);
+
+ type = (wcaps >> 20) & 0xf;
+ s = "Unknown";
+
+ switch (type)
+ {
+ case 0:
+ s = "Audio output converter (DAC)";
+ break;
+ case 1:
+ s = "Audio input converter (ADC)";
+ break;
+ case 2:
+ s = "Audio mixer";
+ break;
+ case 3:
+ s = "Audio selector";
+ break;
+ case 4:
+ s = "Pin complex";
+ break;
+ case 5:
+ s = "Power widget";
+ break;
+ case 6:
+ s = "Volume knob widget";
+ break;
+ case 7:
+ s = "Beep generator widget";
+ break;
+ case 0xf:
+ s = "Vendor defined";
+ break;
+ }
+
+ ntype = type;
+
+ printf ("\t\tType %x (%s)\n", type, s);
+ printf ("\t\tDelay %d\n", (wcaps >> 16) & 0xf);
+ printf ("\t\tL-R Swap %d\n", (wcaps >> 11) & 1);
+ printf ("\t\tPowerControl %d\n", (wcaps >> 10) & 1);
+ printf ("\t\tDigital %d\n", (wcaps >> 9) & 1);
+ printf ("\t\tConnList %d\n", (wcaps >> 8) & 1);
+ printf ("\t\tUnsol capable %d\n", (wcaps >> 7) & 1);
+ printf ("\t\tProc Widget %d\n", (wcaps >> 6) & 1);
+ printf ("\t\tStripe %d\n", (wcaps >> 5) & 1);
+ printf ("\t\tFormat Override %d\n", (wcaps >> 3) & 1);
+ printf ("\t\tAmp param Override %d\n", (wcaps >> 3) & 1);
+ printf ("\t\tOut amp present %d\n", (wcaps >> 2) & 1);
+ printf ("\t\tIn amp present %d\n", (wcaps >> 1) & 1);
+ printf ("\t\tStereo %d\n", (wcaps >> 0) & 1);
+
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_CONNLIST_LEN, &clen, &b))
+ if (clen != 0)
+ {
+ unsigned int clist;
+ int j;
+
+ printf ("\tConnection list len %d (longform=%d): ", clen & 0x7f,
+ clen >> 7);
+
+ clen &= 0x7f;
+
+ for (i = 0; i < clen; i += 4)
+ if (corb_read
+ (mixer, cad, ix, 0, GET_CONNECTION_LIST_ENTRY, i, &clist, &b))
+ for (j = 0; j < 4 && (i + j) < clen; j++)
+ {
+ printf ("0x%x ", (clist >> (j * 8)) & 0xff);
+ }
+
+ printf ("\n");
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_PIN_CAPS, &pincaps, &b))
+ if (pincaps != 0)
+ {
+ printf ("\tPin capabilities\n");
+ if (pincaps & (1 << 16))
+ printf ("\t\tEAPD capable\n");
+ printf ("\t\tVref control %02x\n", (pincaps >> 8) & 0xff);
+ if (pincaps & (1 << 6))
+ printf ("\t\tBalanced I/O pins\n");
+ if (pincaps & (1 << 5))
+ printf ("\t\tInput capable\n");
+ if (pincaps & (1 << 4))
+ printf ("\t\tOutput capable\n");
+ if (pincaps & (1 << 3))
+ printf ("\t\tHeadphone drive capable\n");
+ if (pincaps & (1 << 2))
+ printf ("\t\tPrecense detect capable\n");
+ if (pincaps & (1 << 1))
+ printf ("\t\tTrigger required\n");
+ if (pincaps & (1 << 0))
+ printf ("\t\tImpedance sense capable\n");
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_STREAM_FMTS, &fmts, &b))
+ if (fmts != 0)
+ {
+ printf ("\tSupported stream formats %08x\n", fmts);
+ if (fmts & 0x01)
+ printf ("\t\tPCM\n");
+ if (fmts & 0x02)
+ printf ("\t\tFloat32\n");
+ if (fmts & 0x04)
+ printf ("\t\tAC3\n");
+ }
+
+ if (corb_read (mixer, cad, ix, 0, GET_PARAMETER, HDA_PCM_SIZES, &sizes, &b))
+ if (sizes != 0)
+ {
+ printf ("\tSupported sample sizes/rates %08x\n", sizes);
+
+ if (sizes & (1 << 20))
+ printf ("\t\t32 bits\n");
+ if (sizes & (1 << 19))
+ printf ("\t\t24 bits\n");
+ if (sizes & (1 << 18))
+ printf ("\t\t20 bits\n");
+ if (sizes & (1 << 17))
+ printf ("\t\t16 bits\n");
+ if (sizes & (1 << 16))
+ printf ("\t\t8 bits\n");
+
+ if (sizes & (1 << 11))
+ printf ("\t\t384 kHz\n");
+ if (sizes & (1 << 10))
+ printf ("\t\t192 kHz\n");
+ if (sizes & (1 << 9))
+ printf ("\t\t176.4 kHz\n");
+ if (sizes & (1 << 8))
+ printf ("\t\t96 kHz\n");
+ if (sizes & (1 << 7))
+ printf ("\t\t88.2 kHz\n");
+ if (sizes & (1 << 6))
+ printf ("\t\t48 kHz\n");
+ if (sizes & (1 << 5))
+ printf ("\t\t44.1 kHz\n");
+ if (sizes & (1 << 4))
+ printf ("\t\t32 kHz\n");
+ if (sizes & (1 << 3))
+ printf ("\t\t22.05 kHz\n");
+ if (sizes & (1 << 2))
+ printf ("\t\t16 kHz\n");
+ if (sizes & (1 << 1))
+ printf ("\t\t11.025 kHz\n");
+ if (sizes & (1 << 0))
+ printf ("\t\t8 kHz\n");
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_INPUTAMP_CAPS, &inamp_caps, &b))
+ if (inamp_caps != 0)
+ {
+ printf ("\tInput amp caps %08x\n", inamp_caps);
+ printf ("\t\tMute Capable %d\n", (inamp_caps >> 31) & 0x1);
+ printf ("\t\tStep size %d\n", (inamp_caps >> 16) & 0x7f);
+ printf ("\t\tNum steps %d\n", (inamp_caps >> 8) & 0x7f);
+ printf ("\t\tOffset %d\n", (inamp_caps >> 0) & 0x7f);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_OUTPUTAMP_CAPS, &outamp_caps,
+ &b))
+ if (outamp_caps != 0)
+ {
+ printf ("\tOutput amp caps %08x\n", outamp_caps);
+ printf ("\t\tMute Capable %d\n", (outamp_caps >> 31) & 0x1);
+ printf ("\t\tStep size %d\n", (outamp_caps >> 16) & 0x7f);
+ printf ("\t\tNum steps %d\n", (outamp_caps >> 8) & 0x7f);
+ printf ("\t\tOffset %d\n", (outamp_caps >> 0) & 0x7f);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_SUPPORTED_POWER_STATES, &pstates,
+ &b))
+ if (pstates != 0)
+ {
+ printf ("\tSupported power states %08x\n", pstates);
+ if (pstates & (1 << 3))
+ printf ("\t\tD3\n");
+ if (pstates & (1 << 2))
+ printf ("\t\tD2\n");
+ if (pstates & (1 << 1))
+ printf ("\t\tD1\n");
+ if (pstates & (1 << 0))
+ printf ("\t\tD0\n");
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_PROCESSING_CAPS, &pcaps, &b))
+ if (pcaps != 0)
+ {
+ printf ("\tProcessing capabilities %08x\n", pcaps);
+ printf ("\t\tNumCoeff %d\n", (pcaps >> 8) & 0xff);
+ printf ("\t\tBening %d\n", pcaps & 1);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_GPIO_COUNT, &gpio_count, &b))
+ if (gpio_count != 0)
+ {
+ printf ("\tGPIO count %08x\n", gpio_count);
+ printf ("\t\tGPIWake %d\n", (gpio_count >> 31) & 0x1);
+ printf ("\t\tGPIUnsol %d\n", (gpio_count >> 30) & 0x1);
+ printf ("\t\tNumGPIs %d\n", (gpio_count >> 16) & 0xff);
+ printf ("\t\tNumGPOs %d\n", (gpio_count >> 8) & 0xff);
+ printf ("\t\tNumGPIOs %d\n", (gpio_count >> 0) & 0xff);
+ }
+
+ if (ntype >= 0)
+ dump_verbs (ix, ntype, clen, wcaps);
+ else
+ {
+ if (corb_read (mixer, cad, ix, 0, GET_SUBSYSTEM_ID, 0, &a, &b))
+ printf ("\tSubsystem ID %08x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPI_DATA, 0, &a, &b))
+ printf ("\tGPI data %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPI_WAKE, 0, &a, &b))
+ printf ("\tGPI wake mask %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPI_UNSOL, 0, &a, &b))
+ printf ("\tGPI unsolicited mask %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPI_STICKY, 0, &a, &b))
+ printf ("\tGPI sticky mask %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPO_DATA, 0, &a, &b))
+ printf ("\tGPO data %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_DATA, 0, &a, &b))
+ printf ("\tGPIO data %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_ENABLE, 0, &a, &b))
+ printf ("\tGPIO enable %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_DIR, 0, &a, &b))
+ printf ("\tGPIO direction %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_WKEN, 0, &a, &b))
+ printf ("\tGPIO wake enable %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_UNSOL, 0, &a, &b))
+ printf ("\tGPIO unsolicited enable mask %02x\n", a);
+ if (corb_read (mixer, cad, ix, 0, GET_GPIO_STICKY, 0, &a, &b))
+ printf ("\tGPIO sticky mask %02x\n", a);
+ }
+
+ if (corb_read
+ (mixer, cad, ix, 0, GET_PARAMETER, HDA_VOLUMEKNOB_CAPS, &vkcaps, &b))
+ if ((vkcaps & 0xff) != 0)
+ {
+ printf ("\tVolume knob capabilities %08x\n", vkcaps);
+ }
+
+ if (corb_read (mixer, cad, ix, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
+ {
+ first_node = (a >> 16) & 0xff;
+ num_nodes = a & 0xff;
+ }
+ else
+ num_nodes = 0;
+
+ if (num_nodes > 0)
+ {
+ printf ("\tFirst node %02x, num nodes %d\n", first_node, num_nodes);
+
+ for (i = first_node; i < first_node + num_nodes; i++)
+ dump_node (i);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ unsigned int a, b;
+ int first_node, num_nodes;
+ int i;
+
+ if ((fd = open ("/dev/oss/oss_hdaudio0/pcm0", O_RDWR | O_EXCL, 0)) == -1)
+ {
+ perror ("/dev/oss/oss_hdaudio0/pcm0");
+ exit (-1);
+ }
+
+ if (argc > 1)
+ cad = atoi (argv[1]);
+ if (cad == -1) /* Not given on command line so find it. */
+ for (cad = 0; cad < 16; cad++)
+ if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &a, &b))
+ break;
+
+ printf ("Codec index is %d\n", cad);
+ printf ("Codec vendor %04x:%04x\n", a >> 16, a & 0xffff);
+
+ if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &a, &b))
+ {
+ printf ("HD codec revision %d.%d (%d.%d) (0x%08x)\n",
+ (a >> 20) & 0xf, (a >> 16) & 0xf, (a >> 8) & 0xff, a & 0xff, a);
+ }
+ else
+ printf ("hdaudio: Can't get codec revision\n");
+
+/*
+ * Find out the primary group list
+ */
+
+ if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
+ exit(1);
+
+ first_node = (a >> 16) & 0xff;
+ num_nodes = a & 0xff;
+
+ printf ("First node %02x, num nodes %d\n", first_node, num_nodes);
+
+ for (i = first_node; i < first_node + num_nodes; i++)
+ dump_node (i);
+
+ exit (0);
+}
diff --git a/utils/vib b/utils/vib
new file mode 100755
index 0000000..1117197
--- /dev/null
+++ b/utils/vib
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir
+fi
+
+vi `find $TOP/kernel/OS/FreeBSD $TOP/setup/FreeBSD $TOP/os_cmd/FreeBSD -name $1`
diff --git a/utils/vif b/utils/vif
new file mode 100755
index 0000000..6b70707
--- /dev/null
+++ b/utils/vif
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir/
+fi
+
+vi `find $TOP -name $1`
diff --git a/utils/vil b/utils/vil
new file mode 100755
index 0000000..7ed0c94
--- /dev/null
+++ b/utils/vil
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir
+fi
+
+vi `find $TOP/kernel/OS/Linux $TOP/setup/Linux $TOP/os_cmd/Linux -name $1`
diff --git a/utils/vil24 b/utils/vil24
new file mode 100755
index 0000000..a657daf
--- /dev/null
+++ b/utils/vil24
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+vi `find ./kernel/OS/Linux24 setup/Linux24 os_cmd/Linux24 -name $1`
diff --git a/utils/vis b/utils/vis
new file mode 100755
index 0000000..572b786
--- /dev/null
+++ b/utils/vis
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir
+fi
+
+vi `find $TOP/kernel/OS/SunOS $TOP/setup/SunOS $TOP/os_cmd/SunOS -name $1`
diff --git a/utils/viu b/utils/viu
new file mode 100755
index 0000000..d6e322d
--- /dev/null
+++ b/utils/viu
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir
+fi
+
+vi `find $TOP/kernel/OS/SCO_SV $TOP/setup/SCO_SV $TOP/os_cmd/SCO_SV -name $1`
diff --git a/utils/viv b/utils/viv
new file mode 100755
index 0000000..3e0803d
--- /dev/null
+++ b/utils/viv
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TOP=.
+if test -d origdir
+then
+ TOP=origdir
+fi
+
+vi `find $TOP/kernel/OS/VxWorks $TOP/setup/VxWorks -name $1`