[pulseaudio-discuss] [PATCH v2 1/3] alsa-util: Add a function to read ELD info

David Henningsson david.henningsson at canonical.com
Tue Feb 19 04:25:47 PST 2013


Currently, this function only reads the monitor name, but could
be extended to read e g supported formats as well.

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 src/modules/alsa/alsa-util.c |   69 ++++++++++++++++++++++++++++++++++++++++++
 src/modules/alsa/alsa-util.h |    8 +++++
 2 files changed, 77 insertions(+)

diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 114ab27..ca53c6f 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1462,6 +1462,21 @@ snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name)
     return snd_hctl_find_elem(hctl, id);
 }
 
+snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device)
+{
+    snd_ctl_elem_id_t *id;
+
+    /* See if we can find the ELD control */
+    snd_ctl_elem_id_alloca(&id);
+    snd_ctl_elem_id_clear(id);
+    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
+    snd_ctl_elem_id_set_name(id, "ELD");
+    snd_ctl_elem_id_set_device(id, device);
+
+    return snd_hctl_find_elem(hctl, id);
+}
+
+
 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
     int err;
 
@@ -1574,3 +1589,57 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_h
     snd_mixer_close(m);
     return NULL;
 }
+
+bool pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
+
+    /* The ELD format is specific to HDA Intel sound cards and defined in the
+       HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
+    int err;
+    snd_hctl_elem_t *elem;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_value_t *value;
+    uint8_t *elddata;
+    unsigned int eldsize, mnl;
+
+    pa_assert(eld != NULL);
+
+    /* See if we can find the ELD control */
+    elem = pa_alsa_find_eld_ctl(hctl, device);
+    if (elem == NULL) {
+        pa_log_debug("No ELD info control found (for device=%d)", device);
+        return false;
+    }
+
+    /* Does it have any contents? */
+    snd_ctl_elem_info_alloca(&info);
+    snd_ctl_elem_value_alloca(&value);
+    if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
+       (err = snd_hctl_elem_read(elem, value)) < 0) {
+        pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
+        return false;
+    }
+
+    eldsize = snd_ctl_elem_info_get_count(info);
+    elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
+    if (elddata == NULL || eldsize == 0) {
+        pa_log_debug("ELD info empty (for device=%d)", device);
+        return false;
+    }
+    if (eldsize < 20 || eldsize > 256) {
+        pa_log_debug("ELD info has wrong size (for device=%d)", device);
+        return false;
+    }
+
+    /* Try to fetch monitor name */
+    mnl = elddata[4] & 0x1f;
+    if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
+        pa_log_debug("No monitor name in ELD info (for device=%d)", device);
+        mnl = 0;
+    }
+    memcpy(eld->monitor_name, &elddata[20], mnl);
+    eld->monitor_name[mnl] = '\0';
+    if (mnl)
+        pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
+
+    return true;
+}
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 1326e64..518d578 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -143,7 +143,15 @@ const char* pa_alsa_strerror(int errnum);
 pa_bool_t pa_alsa_may_tsched(pa_bool_t want);
 
 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name);
+snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device);
 
 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl);
 
+typedef struct pa_hdmi_eld pa_hdmi_eld;
+struct pa_hdmi_eld {
+    char monitor_name[17];
+};
+
+bool pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld);
+
 #endif
-- 
1.7.9.5



More information about the pulseaudio-discuss mailing list