get additional device data from udev

This commit is contained in:
Lennart Poettering 2009-03-01 20:34:07 +01:00
parent cc8d51ad62
commit 784ac5b0da
10 changed files with 268 additions and 11 deletions

View file

@ -977,6 +977,41 @@ AC_SUBST(HAL_LIBS)
AC_SUBST(HAVE_HAL)
AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1])
#### UDEV support (optional) ####
AC_ARG_ENABLE([udev],
AS_HELP_STRING([--disable-udev],[Disable optional UDEV support]),
[
case "${enableval}" in
yes) udev=yes ;;
no) udev=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-udev) ;;
esac
],
[udev=auto])
if test "x${udev}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
PKG_CHECK_MODULES(UDEV, [ libudev ],
[
HAVE_UDEV=1
AC_DEFINE([HAVE_UDEV], 1, [Have UDEV.])
],
[
HAVE_UDEV=0
if test "x$udev" = xyes ; then
AC_MSG_ERROR([*** UDEV support not found])
fi
])
else
HAVE_UDEV=0
fi
AC_SUBST(UDEV_CFLAGS)
AC_SUBST(UDEV_LIBS)
AC_SUBST(HAVE_UDEV)
AM_CONDITIONAL([HAVE_UDEV], [test "x$HAVE_UDEV" = x1])
AC_DEFINE([LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE], 1, [I know the API is subject to change.])
#### BlueZ support (optional) ####
AC_ARG_ENABLE([bluez],
@ -1340,6 +1375,11 @@ if test "x$HAVE_HAL" = "x1" ; then
ENABLE_HAL=yes
fi
ENABLE_UDEV=no
if test "x$HAVE_UDEV" = "x1" ; then
ENABLE_UDEV=yes
fi
ENABLE_TCPWRAP=no
if test "x${LIBWRAP_LIBS}" != x ; then
ENABLE_TCPWRAP=yes
@ -1399,6 +1439,7 @@ echo "
Enable Async DNS: ${ENABLE_LIBASYNCNS}
Enable LIRC: ${ENABLE_LIRC}
Enable HAL: ${ENABLE_HAL}
Enable udev: ${ENABLE_UDEV}
Enable BlueZ: ${ENABLE_BLUEZ}
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
Enable libsamplerate: ${ENABLE_LIBSAMPLERATE}

View file

@ -1313,6 +1313,12 @@ libalsa_util_la_LIBADD += $(HAL_LIBS)
libalsa_util_la_CFLAGS += $(HAL_CFLAGS)
endif
if HAVE_UDEV
libalsa_util_la_SOURCES += modules/udev-util.h modules/udev-util.c
libalsa_util_la_LIBADD += $(UDEV_LIBS)
libalsa_util_la_CFLAGS += $(UDEV_CFLAGS)
endif
if HAVE_DBUS
libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c modules/reserve-wrap.c modules/reserve-wrap.h
libalsa_util_la_LIBADD += $(DBUS_LIBS) libdbus-util.la

View file

@ -1667,6 +1667,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
}
pa_alsa_set_description(data.proplist);
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
pa_sink_new_data_done(&data);

View file

@ -1509,6 +1509,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
}
pa_alsa_set_description(data.proplist);
u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
pa_source_new_data_done(&data);

View file

@ -47,6 +47,10 @@
#include "hal-util.h"
#endif
#ifdef HAVE_UDEV
#include "udev-util.h"
#endif
struct pa_alsa_fdlist {
unsigned num_fds;
struct pollfd *fds;
@ -1362,6 +1366,35 @@ void pa_alsa_redirect_errors_dec(void) {
snd_lib_error_set_handler(NULL);
}
void pa_alsa_set_description(pa_proplist *p) {
const char *s;
pa_assert(p);
if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
return;
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
if (pa_streq(s, "internal")) {
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio"));
return;
}
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) {
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
return;
}
if ((s = pa_proplist_gets(p, "alsa.card_name"))) {
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
return;
}
if ((s = pa_proplist_gets(p, "alsa.name"))) {
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
return;
}
}
void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
char *cn, *lcn, *dn;
@ -1385,6 +1418,10 @@ void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
pa_xfree(dn);
}
#ifdef HAVE_UDEV
pa_udev_get_info(c, p, card);
#endif
#ifdef HAVE_HAL
pa_hal_get_info(c, p, card);
#endif
@ -1411,7 +1448,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
snd_pcm_class_t class;
snd_pcm_subclass_t subclass;
const char *n, *id, *sdn, *cn = NULL;
const char *n, *id, *sdn;
int card;
pa_assert(p);
@ -1426,6 +1463,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
if (alsa_class_table[class])
pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
}
subclass = snd_pcm_info_get_subclass(pcm_info);
if (subclass <= SND_PCM_SUBCLASS_LAST)
if (alsa_subclass_table[subclass])
@ -1443,17 +1481,8 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) {
if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
pa_alsa_init_proplist_card(c, p, card);
cn = pa_proplist_gets(p, "alsa.card_name");
}
if (cn && n && !strstr(cn, n) && !strstr(n, cn))
pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s, %s", cn, n);
else if (cn && (!n || strstr(cn, n)))
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, cn);
else if (n)
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n);
}
void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {

View file

@ -123,6 +123,7 @@ void pa_alsa_redirect_errors_dec(void);
void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info);
void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card);
void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm);
void pa_alsa_set_description(pa_proplist *p);
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);

View file

@ -318,6 +318,7 @@ int pa__init(pa_module *m) {
data.module = m;
pa_alsa_init_proplist_card(m->core, data.proplist, alsa_card_index);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
pa_alsa_set_description(data.proplist);
set_card_name(&data, ma, u->device_id);
if (reserve)

View file

@ -89,6 +89,9 @@ int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
pa_proplist_sets(p, "hal.udi", udis[i]);
/* The data HAL stores in info.product is not actually a product
* string but simply the ALSA card name. We will hence not write
* it to PA_PROP_DEVICE_PRODUCT_NAME */
t = libhal_device_get_property_string(hal, udis[i], "info.product", &error);
if (dbus_error_is_set(&error))
dbus_error_free(&error);

142
src/modules/udev-util.c Normal file
View file

@ -0,0 +1,142 @@
/***
This file is part of PulseAudio.
Copyright 2009 Lennart Poettering
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <libudev.h>
#include <pulse/xmalloc.h>
#include <pulse/proplist.h>
#include <pulsecore/log.h>
#include <pulsecore/core-util.h>
#include "udev-util.h"
static int read_id(struct udev_device *d, const char *n) {
const char *v;
unsigned u;
pa_assert(d);
pa_assert(n);
if (!(v = udev_device_get_property_value(d, n)))
return -1;
if (pa_startswith(v, "0x"))
v += 2;
if (!*v)
return -1;
if (sscanf(v, "%04x", &u) != 1)
return -1;
if (u > 0xFFFFU)
return -1;
return u;
}
int pa_udev_get_info(pa_core *core, pa_proplist *p, int card_idx) {
int r = -1;
struct udev *udev;
struct udev_device *card;
char *t;
const char *v;
int id;
pa_assert(core);
pa_assert(p);
pa_assert(card_idx >= 0);
if (!(udev = udev_new())) {
pa_log_error("Failed to allocate udev context.");
goto finish;
}
t = pa_sprintf_malloc("%s/class/sound/card%i", udev_get_sys_path(udev), card_idx);
card = udev_device_new_from_syspath(udev, t);
pa_xfree(t);
if (!card) {
pa_log_error("Failed to get card object.");
goto finish;
}
if (!pa_proplist_contains(p, PA_PROP_DEVICE_BUS))
if ((v = udev_device_get_property_value(card, "ID_BUS")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_BUS, v);
if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_ID))
if ((id = read_id(card, "ID_VENDOR_ID")) > 0 && *v)
pa_proplist_setf(p, PA_PROP_DEVICE_VENDOR_ID, "%04x", id);
if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_NAME)) {
if ((v = udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
else if ((v = udev_device_get_property_value(card, "ID_VENDOR")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
}
if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_ID))
if ((id = read_id(card, "ID_MODEL_ID")) >= 0)
pa_proplist_setf(p, PA_PROP_DEVICE_PRODUCT_ID, "%04x", id);
if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_NAME)) {
if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
else if ((v = udev_device_get_property_value(card, "ID_MODEL")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
}
if (!pa_proplist_contains(p, PA_PROP_DEVICE_SERIAL))
if ((v = udev_device_get_property_value(card, "ID_SERIAL")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_SERIAL, v);
if (!pa_proplist_contains(p, PA_PROP_DEVICE_FORM_FACTOR))
if ((v = udev_device_get_property_value(card, "SOUND_FORM_FACTOR")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_FORM_FACTOR, v);
if (!pa_proplist_contains(p, PA_PROP_DEVICE_BUS_PATH))
if ((v = udev_device_get_devpath(card)))
pa_proplist_sets(p, PA_PROP_DEVICE_BUS_PATH, v);
/* This is normaly not set by th udev rules but may be useful to
* allow administrators to overwrite the device description.*/
if (!pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
if ((v = udev_device_get_property_value(card, "SOUND_DESCRIPTION")) && *v)
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, v);
r = 0;
finish:
if (card)
udev_device_unref(card);
if (udev)
udev_unref(udev);
return r;
}

30
src/modules/udev-util.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef fooudevutilhfoo
#define fooudevutilhfoo
/***
This file is part of PulseAudio.
Copyright 2009 Lennart Poettering
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#include <pulsecore/core.h>
int pa_udev_get_info(pa_core *core, pa_proplist *p, int card);
#endif