[PATCH 6/6] add input.jack support
Guillem Jover
guillem.jover at nokia.com
Fri Oct 31 17:31:13 PDT 2008
A device with an input.jack capability supports sensing when a jack has
been inserted or removed from the socket. Additional capabilities might
be present depending on what the socket is able to sense. The device
will have a button to signal those events, and a property input.jack.type
listing the supported contacts in the currently plugged jack.
The supported jack types are: headphone, microphone and line-out.
---
doc/spec/hal-spec-properties.xml | 98 ++++++++++++++++++++++++++++++++++++++
hald/linux/addons/addon-input.c | 58 ++++++++++++++++++++--
hald/linux/device.c | 43 +++++++++++++++-
hald/linux/probing/probe-input.c | 27 ++++++-----
4 files changed, 205 insertions(+), 21 deletions(-)
diff --git a/doc/spec/hal-spec-properties.xml b/doc/spec/hal-spec-properties.xml
index a942513..b7ddcf9 100644
--- a/doc/spec/hal-spec-properties.xml
+++ b/doc/spec/hal-spec-properties.xml
@@ -4327,6 +4327,14 @@ org.freedesktop.Hal.Device.Volume.method_signatures = {'ssas', 'as', 'as'}
</entry>
</row>
<row>
+ <entry></entry>
+ <entry>jack_insert</entry>
+ <entry></entry>
+ <entry>
+ A jack socket triggering insertion and removal events
+ </entry>
+ </row>
+ <row>
<entry>
<literal>button.has_state</literal> (bool)
</entry>
@@ -4500,6 +4508,96 @@ org.freedesktop.Hal.Device.Volume.method_signatures = {'ssas', 'as', 'as'}
</informaltable>
</sect2>
+ <sect2 id="device-properties-input-jack">
+ <title>
+ input.jack namespace
+ </title>
+ <para>
+ Device objects with the capability <literal>input.jack</literal>
+ are jack sockets.
+ </para>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Key (type)</entry>
+ <entry>Values</entry>
+ <entry>Mandatory</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>input.jack.type</literal> (strlist)
+ </entry>
+ <entry></entry>
+ <entry>Yes</entry>
+ <entry>
+ The type of jack currently plugged. Several strings can be
+ present at the same time if the currently plugged jack
+ supports them.
+ </entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>headphone</entry>
+ <entry></entry>
+ <entry>
+ The inserted jack connects to a headphone.
+ </entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>microphone</entry>
+ <entry></entry>
+ <entry>
+ The inserted jack connects to a microphone.
+ </entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>line-out</entry>
+ <entry></entry>
+ <entry>
+ The inserted jack connects to a line-in.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect2>
+
+ <sect2 id="device-properties-input-jack-headphone">
+ <title>
+ input.jack.headphone namespace
+ </title>
+ <para>
+ The input device is a jack socket that supports headphone jacks.
+ No namespace specific properties.
+ </para>
+ </sect2>
+
+ <sect2 id="device-properties-input-jack-microphone">
+ <title>
+ input.jack.microphone namespace
+ </title>
+ <para>
+ The input device is a jack socket that supports microphone jacks.
+ No namespace specific properties.
+ </para>
+ </sect2>
+
+ <sect2 id="device-properties-input-jack-line-out">
+ <title>
+ input.jack.lineout namespace
+ </title>
+ <para>
+ The input device is a jack socket that supports line-out jacks.
+ No namespace specific properties.
+ </para>
+ </sect2>
+
<sect2 id="device-properties-input-joystick">
<title>
input.joystick namespace
diff --git a/hald/linux/addons/addon-input.c b/hald/linux/addons/addon-input.c
index a4a763f..087ce11 100644
--- a/hald/linux/addons/addon-input.c
+++ b/hald/linux/addons/addon-input.c
@@ -7,6 +7,7 @@
* Copyright (C) 2005 Ryan Lortie <desrt at desrt.ca>
* Copyright (C) 2006 Matthew Garrett <mjg59 at srcf.ucam.org>
* Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor at codethink.co.uk>
+ * Copyright (C) 2008 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -168,6 +169,8 @@ struct _InputData
char *button_type;
gboolean button_has_state;
gboolean button_state;
+ gboolean button_new_state;
+ gboolean is_jack;
char udi[1]; /*variable size*/
};
@@ -177,12 +180,13 @@ static GHashTable *inputs = NULL;
static GList *devices = NULL;
static void
-emit_switch_condition (InputData *input_data, gboolean new_state)
+emit_switch_condition (InputData *input_data)
{
- if (new_state != input_data->button_state) {
+ if (input_data->button_new_state != input_data->button_state) {
DBusError error;
- input_data->button_state = new_state;
+ input_data->button_state = input_data->button_new_state;
+ input_data->button_new_state = 0;
dbus_error_init (&error);
libhal_device_set_property_bool (ctx, input_data->udi, "button.state.value",
@@ -197,6 +201,19 @@ emit_switch_condition (InputData *input_data, gboolean new_state)
}
}
+static void
+set_jack_switch_type (const char *udi, const char *name, gboolean state)
+{
+ DBusError error;
+
+ dbus_error_init (&error);
+ if (state)
+ libhal_device_property_strlist_append (ctx, udi, "input.jack.type", name, &error);
+ else
+ libhal_device_property_strlist_remove (ctx, udi, "input.jack.type", name, &error);
+ dbus_error_free (&error);
+}
+
static gboolean
event_io (GIOChannel *channel, GIOCondition condition, gpointer data)
{
@@ -230,7 +247,6 @@ event_io (GIOChannel *channel, GIOCondition condition, gpointer data)
switch (event.code) {
case SW_LID:
case SW_TABLET_MODE:
- case SW_HEADPHONE_INSERT:
case SW_RFKILL_ALL:
/* check switch state - cuz apparently we get spurious events (or I don't know
* how to use the input layer correctly)
@@ -246,16 +262,38 @@ event_io (GIOChannel *channel, GIOCondition condition, gpointer data)
* 19:08:26.868 [I] event.value=0 ; event.code=0 (0x00)
* 19:08:26.955 [I] event.value=0 ; event.code=0 (0x00)
* 19:08:26.960 [I] event.value=0 ; event.code=0 (0x00)
+ *
+ * XXX: with latest kernels we should be able
+ * to just use event.value, as the input layer
+ * removes those duped events.
+ *
+ * XXX: in older kernels and devices SW_LID is
+ * not always followed by an EV_SYN event, so
+ * this code cannot be refactored just yet.
*/
if (ioctl (g_io_channel_unix_get_fd(channel), EVIOCGSW(sizeof (bitmask)), bitmask) < 0) {
HAL_DEBUG (("ioctl EVIOCGSW failed"));
} else {
- int new_state = test_bit (event.code, bitmask);
- emit_switch_condition (input_data, new_state);
+ input_data->button_new_state = test_bit (event.code, bitmask);
+ emit_switch_condition (input_data);
}
break;
+ case SW_HEADPHONE_INSERT:
+ input_data->button_new_state |= event.value;
+ set_jack_switch_type (input_data->udi, "headphone", event.value);
+ break;
+ case SW_MICROPHONE_INSERT:
+ input_data->button_new_state |= event.value;
+ set_jack_switch_type (input_data->udi, "microphone", event.value);
+ break;
+ case SW_LINEOUT_INSERT:
+ input_data->button_new_state |= event.value;
+ set_jack_switch_type (input_data->udi, "line-out", event.value);
+ break;
}
+ } else if (event.type == EV_SYN && input_data->is_jack) {
+ emit_switch_condition (input_data);
} else if (event.type == EV_KEY && key_name[event.code] != NULL && event.value) {
dbus_error_init (&error);
libhal_device_emit_condition (ctx, input_data->udi,
@@ -315,6 +353,7 @@ add_device (LibHalContext *ctx,
int len = strlen (udi);
const char* device_file;
const char *button_type;
+ long bitmask[NBITS(SW_MAX)];
data = (InputData*) g_malloc (sizeof (InputData) + len);
@@ -330,6 +369,8 @@ add_device (LibHalContext *ctx,
button_type = "unknown";
data->button_type = g_strdup (button_type);
+ data->is_jack = strcmp (data->button_type, "jack_insert") == 0;
+
/* button_has_state will be false if the key isn't available*/
data->button_has_state = libhal_ps_get_bool (properties, "button.has_state");
if (data->button_has_state)
@@ -341,6 +382,11 @@ add_device (LibHalContext *ctx,
return;
}
+ if (data->is_jack && ioctl (eventfp, EVIOCGSW (sizeof (bitmask)), bitmask) < 0) {
+ set_jack_switch_type (udi, "headphone", test_bit (SW_HEADPHONE_INSERT, bitmask));
+ set_jack_switch_type (udi, "microphone", test_bit (SW_MICROPHONE_INSERT, bitmask));
+ set_jack_switch_type (udi, "line-out", test_bit (SW_LINEOUT_INSERT, bitmask));
+ }
HAL_DEBUG (("%s: Listening on %s", udi, device_file));
diff --git a/hald/linux/device.c b/hald/linux/device.c
index ffa68b4..97b6cfb 100644
--- a/hald/linux/device.c
+++ b/hald/linux/device.c
@@ -5,6 +5,7 @@
* Copyright (C) 2005 Richard Hughes, <richard at hughsie.com>
* Copyright (C) 2005 Danny Kukawka, <danny.kukawka at web.de>
* Copyright (C) 2006 Kay Sievers <kay.sievers at vrfy.org>
+ * Copyright (C) 2007, 2008 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1000,6 +1001,23 @@ out:
;
}
+static int
+input_count_jack_switches (long *bitmask)
+{
+ int jack_sw[] = {
+ SW_HEADPHONE_INSERT,
+ SW_MICROPHONE_INSERT,
+ SW_LINEOUT_INSERT,
+ };
+ int i, found = 0;
+
+ for (i = 0; i < (int)(sizeof (jack_sw) / sizeof (jack_sw[0])); i++)
+ if (test_bit (jack_sw[i], bitmask))
+ found++;
+
+ return found;
+}
+
static void
input_test_switch (HalDevice *d, const char *sysfs_path)
{
@@ -1016,7 +1034,9 @@ input_test_switch (HalDevice *d, const char *sysfs_path)
goto out;
hal_device_add_capability (d, "input.switch");
- if (num_bits == 1) {
+ if (num_bits == 1 || num_bits == input_count_jack_switches (bitmask)) {
+ gboolean is_jack_switch = FALSE;
+
hal_device_add_capability (d, "button");
hal_device_property_set_bool (d, "button.has_state", TRUE);
/* NOTE: button.state.value will be set from our prober in hald/linux/probing/probe-input.c */
@@ -1026,11 +1046,28 @@ input_test_switch (HalDevice *d, const char *sysfs_path)
_have_sysfs_lid_button = TRUE;
} else if (test_bit (SW_TABLET_MODE, bitmask)) {
hal_device_property_set_string (d, "button.type", "tablet_mode");
- } else if (test_bit (SW_HEADPHONE_INSERT, bitmask)) {
- hal_device_property_set_string (d, "button.type", "headphone_insert");
} else if (test_bit (SW_RFKILL_ALL, bitmask)) {
hal_device_property_set_string (d, "button.type", "radio");
}
+
+ if (test_bit (SW_HEADPHONE_INSERT, bitmask)) {
+ is_jack_switch = TRUE;
+ hal_device_add_capability (d, "input.jack.headphone");
+ }
+ if (test_bit (SW_MICROPHONE_INSERT, bitmask)) {
+ is_jack_switch = TRUE;
+ hal_device_add_capability (d, "input.jack.microphone");
+ }
+ if (test_bit (SW_LINEOUT_INSERT, bitmask)) {
+ is_jack_switch = TRUE;
+ hal_device_add_capability (d, "input.jack.lineout");
+ }
+
+ if (is_jack_switch) {
+ hal_device_add_capability (d, "input.jack");
+ hal_device_property_set_strlist (d, "input.jack.type", NULL);
+ hal_device_property_set_string (d, "button.type", "jack_insert");
+ }
}
out:
diff --git a/hald/linux/probing/probe-input.c b/hald/linux/probing/probe-input.c
index e860b5e..8617498 100644
--- a/hald/linux/probing/probe-input.c
+++ b/hald/linux/probing/probe-input.c
@@ -4,6 +4,7 @@
* probe-input.c : Probe input devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2008 Nokia Corporation
*
* Licensed under the Academic Free License version 2.1
*
@@ -71,17 +72,6 @@ main (int argc, char *argv[])
if (button_type == NULL)
goto out;
- if (strcmp (button_type, "lid") == 0)
- sw = SW_LID;
- else if (strcmp (button_type, "tablet_mode") == 0)
- sw = SW_TABLET_MODE;
- else if (strcmp (button_type, "headphone_insert") == 0)
- sw = SW_HEADPHONE_INSERT;
- else if (strcmp (button_type, "radio") == 0)
- sw = SW_RFKILL_ALL;
- else
- goto out;
-
device_file = getenv ("HAL_PROP_INPUT_DEVICE");
if (device_file == NULL)
goto out;
@@ -107,8 +97,21 @@ main (int argc, char *argv[])
goto out;
}
+ if (strcmp (button_type, "lid") == 0)
+ sw = test_bit (SW_LID, bitmask);
+ else if (strcmp (button_type, "tablet_mode") == 0)
+ sw = test_bit (SW_TABLET_MODE, bitmask);
+ else if (strcmp (button_type, "radio") == 0)
+ sw = test_bit (SW_RADIO, bitmask);
+ else if (strcmp (button_type, "jack_insert") == 0) {
+ sw = test_bit (SW_HEADPHONE_INSERT, bitmask) ||
+ test_bit (SW_MICROPHONE_INSERT, bitmask) ||
+ test_bit (SW_LINEOUT_INSERT, bitmask);
+ } else
+ goto out;
+
dbus_error_init (&error);
- libhal_device_set_property_bool (ctx, udi, "button.state.value", test_bit (sw, bitmask), &error);
+ libhal_device_set_property_bool (ctx, udi, "button.state.value", sw, &error);
ret = 0;
--
1.6.0.2
More information about the hal
mailing list