All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Henningsson <david.henningsson@canonical.com>
To: tiwai@suse.de, alsa-devel@alsa-project.org
Cc: David Henningsson <david.henningsson@canonical.com>
Subject: [PATCH v2] alsa-tools: Add a small "hdajacksensetest" helper
Date: Mon,  6 Oct 2014 15:30:03 +0200	[thread overview]
Message-ID: <1412602203-15787-1-git-send-email-david.henningsson@canonical.com> (raw)

I previously had a small python script doing the same thing,
but it depended on hda-analyzer, which always breaks when something
new is added to the codec proc file.

I got tired and rewrote it as a small C program instead, which I
hope will be a useful addition to alsa-tools.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
---

v2 changes:
 * s/hda-verb/hdajacksensetest in configure.ac
 * added g_option_context_free

 Makefile                            |   2 +-
 hdajacksensetest/Makefile.am        |  12 +++
 hdajacksensetest/configure.ac       |  10 +++
 hdajacksensetest/gitcompile         |  13 ++++
 hdajacksensetest/hdajacksensetest.c | 146 ++++++++++++++++++++++++++++++++++++
 5 files changed, 182 insertions(+), 1 deletion(-)
 create mode 100644 hdajacksensetest/Makefile.am
 create mode 100644 hdajacksensetest/configure.ac
 create mode 100755 hdajacksensetest/gitcompile
 create mode 100644 hdajacksensetest/hdajacksensetest.c

diff --git a/Makefile b/Makefile
index b2da046..72f95e2 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ TOP = .
 SUBDIRS = as10k1 envy24control hdsploader hdspconf hdspmixer \
 	  mixartloader pcxhrloader rmedigicontrol sb16_csp seq sscape_ctl \
 	  us428control usx2yloader vxloader echomixer ld10k1 qlo10k1 \
-	  hwmixvolume hdajackretask hda-verb
+	  hwmixvolume hdajackretask hda-verb hdajacksensetest
 
 all:
 	@for i in $(SUBDIRS); do \
diff --git a/hdajacksensetest/Makefile.am b/hdajacksensetest/Makefile.am
new file mode 100644
index 0000000..795373c
--- /dev/null
+++ b/hdajacksensetest/Makefile.am
@@ -0,0 +1,12 @@
+MYNAME = hdajacksensetest
+AUTOMAKE_OPTIONS = foreign
+bin_PROGRAMS = hdajacksensetest
+AM_CFLAGS = @GLIB_CFLAGS@ -I "../hdajackretask/" -I "../hda-verb/"
+hdajacksensetest_SOURCES = hdajacksensetest.c ../hdajackretask/sysfs-pin-configs.c
+hdajacksensetest_LDADD = @GLIB_LIBS@
+
+alsa-dist: distdir
+	@rm -rf ../distdir/$(MYNAME)
+	@mkdir -p ../distdir/$(MYNAME)
+	@cp -RLpv $(distdir)/* ../distdir/$(MYNAME)
+	@rm -rf $(distdir)
diff --git a/hdajacksensetest/configure.ac b/hdajacksensetest/configure.ac
new file mode 100644
index 0000000..fa9ae8e
--- /dev/null
+++ b/hdajacksensetest/configure.ac
@@ -0,0 +1,10 @@
+AC_INIT(hdajacksensetest, 0.20141006)
+AM_INIT_AUTOMAKE(subdir-objects)
+AM_MAINTAINER_MODE([enable])
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_HEADER_STDC
+
+PKG_CHECK_MODULES([GLIB], [glib-2.0])
+
+AC_OUTPUT(Makefile)
diff --git a/hdajacksensetest/gitcompile b/hdajacksensetest/gitcompile
new file mode 100755
index 0000000..58328bd
--- /dev/null
+++ b/hdajacksensetest/gitcompile
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+aclocal $ACLOCAL_FLAGS || exit 1
+automake --foreign --add-missing || exit 1
+autoconf || exit 1
+export CFLAGS='-O2 -Wall -pipe -g'
+echo "CFLAGS=$CFLAGS"
+echo "./configure $@"
+./configure $@ || exit 1
+unset CFLAGS
+if [ -z "$GITCOMPILE_NO_MAKE" ]; then
+  make || exit 1
+fi
diff --git a/hdajacksensetest/hdajacksensetest.c b/hdajacksensetest/hdajacksensetest.c
new file mode 100644
index 0000000..cb8d9cd
--- /dev/null
+++ b/hdajacksensetest/hdajacksensetest.c
@@ -0,0 +1,146 @@
+/*
+ * Checks the current pin/jack status of the codec
+ *
+ * Copyright (c) 2014 David Henningsson, Canonical Ltd. <david.henningsson@canonical.com>
+ * (With some minor pieces copy-pasted from hda-verb by Takashi Iwai)
+ *
+ * Licensed under GPL v2 or later.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <glib.h>
+#include <errno.h>
+#include "sysfs-pin-configs.h"
+
+#include <sys/ioctl.h>
+#include <stdint.h>
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+#include "hda_hwdep.h"
+
+gint card_index, codec_index;
+gboolean try_all_pins, set_pin_sense;
+
+static GOptionEntry arg_entries[] =
+{
+  { "card", 'c', 0, G_OPTION_ARG_INT, &card_index, "card index (as can be seen in /proc/asound/cards)", "X" },
+  { "codec", 'd', 0, G_OPTION_ARG_INT, &codec_index, "codec device index (as can be seen in /proc/asound/cardX/codecY)", "Y" },
+  { "allpins", 'a', 0, G_OPTION_ARG_NONE, &try_all_pins, "try all pins, even those who (probably) does not have a physical jack", NULL },
+  { "setpinsense", 's', 0, G_OPTION_ARG_NONE, &set_pin_sense, "execute 'Set pin sense' before the pin sense is measured", NULL },
+  { NULL }
+};
+
+static void parse_command_line(int argc, char **argv)
+{
+	GError *error = NULL;
+	GOptionContext *context = g_option_context_new("- check current jack/pin sense");
+	g_option_context_add_main_entries(context, arg_entries, NULL);
+	if (!g_option_context_parse (context, &argc, &argv, &error)) {
+		fprintf(stderr, "Option parsing failed: %s\n", error->message);
+		exit(1);
+	}
+	g_option_context_free(context);
+}
+
+
+static gboolean should_check_pin(pin_configs_t *pin)
+{
+	unsigned long defcfg = actual_pin_config(pin);
+	if (try_all_pins)
+		return TRUE;
+	if (get_port_conn(defcfg) != 0)
+		return FALSE; // Not a jack
+	if (defcfg & (1 << 8)) // Jack has NO_PRESENCE set
+		return FALSE;
+	return TRUE;
+}
+
+int fd;
+
+static void codec_open()
+{
+	char filename[64];
+	int version = 0;
+
+	snprintf(filename, 64, "/dev/snd/hwC%dD%d", card_index, codec_index);
+	fd = open(filename, O_RDWR);
+	if (fd < 0) {
+		if (errno == EACCES)
+			fprintf(stderr, "Permission error (hint: this program usually requires root)\n");
+		else
+			fprintf(stderr, "Ioctl call failed with error %d\n", errno);
+		exit(1);
+	}
+
+	if (ioctl(fd, HDA_IOCTL_PVERSION, &version) < 0) {
+		fprintf(stderr, "Ioctl call failed with error %d\n", errno);
+		fprintf(stderr, "Looks like an invalid hwdep device...\n");
+		close(fd);
+		exit(1);
+	}
+	if (version < HDA_HWDEP_VERSION) {
+		fprintf(stderr, "Invalid version number 0x%x\n", version);
+		fprintf(stderr, "Looks like an invalid hwdep device...\n");
+		close(fd);
+		exit(1);
+	}
+}
+
+static unsigned long codec_rw(int nid, int verb, int param)
+{
+	struct hda_verb_ioctl val;
+
+	val.verb = HDA_VERB(nid, verb, param);
+	if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0) {
+		fprintf(stderr, "Ioctl call failed with error %d\n", errno);
+		close(fd);
+		exit(1);
+	}
+	return val.res;
+}
+
+#define AC_VERB_GET_PIN_SENSE	0x0f09
+#define AC_VERB_SET_PIN_SENSE	0x709
+
+#define MAX_PINS 32
+
+pin_configs_t pin_configs[MAX_PINS];
+
+int main(int argc, char **argv)
+{
+	int pin_count, i;
+
+	parse_command_line(argc, argv);
+	pin_count = get_pin_configs_list(pin_configs, MAX_PINS, card_index, codec_index);
+	if (pin_count == 0) {
+		fprintf(stderr, "No pins found for card %d codec %d, did you pick the right one?\n", card_index, codec_index);
+		exit(1);
+	}
+
+	codec_open();
+
+	if (set_pin_sense) {
+		for (i = 0; i < pin_count; i++)
+			if (should_check_pin(&pin_configs[i])) {
+				codec_rw(pin_configs[i].nid, AC_VERB_SET_PIN_SENSE, 0);
+			}
+		sleep(1);
+	}
+
+	for (i = 0; i < pin_count; i++)
+		if (should_check_pin(&pin_configs[i])) {
+			gchar *desc = get_config_description(actual_pin_config(&pin_configs[i]));
+			unsigned long present = codec_rw(pin_configs[i].nid, AC_VERB_GET_PIN_SENSE, 0);
+			printf("Pin 0x%.2x (%s): present = %s\n", pin_configs[i].nid, desc, present & 0x80000000 ? "Yes" : "No");
+			g_free(desc);
+		}
+
+	close(fd);
+	return 0;
+}
-- 
1.9.1

             reply	other threads:[~2014-10-06 13:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-06 13:30 David Henningsson [this message]
2014-10-06 14:25 ` [PATCH v2] alsa-tools: Add a small "hdajacksensetest" helper Takashi Iwai
2014-10-06 14:56 ` Raymond Yau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1412602203-15787-1-git-send-email-david.henningsson@canonical.com \
    --to=david.henningsson@canonical.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.