Hi,

This diff is an attempt to make identifying audio devices easier by
giving each device a human-readable description that can be read from
userspace (and without scraping dmesg).

This is implemented on a per-audio-device basis using a new `descr`
interface to `audio_hw_if`. For now I've only implemented this on:

 - azalia(4), which uses the codec info, e.g. `Realtek ALC1150`

 - uaudio(4), which uses the USB vendor and model info, e.g.
   `Logitech HD Pro Webcam C920`.

For drivers, which currently don't implement this interface, the
description string defaults to the audio device node name, e.g.
`uaudio2`.

The string is exposed to userspace via the AUDIO_GETDEV ioctl(2). I've
reclaimed the space currently occupied by the (unused) `version` and
`config` fields in `audio_device_t` and used it for a new `descr` field.
Thus the size of `audio_device_t` remains the same for now.

I've also made audioctl(8) display the description string, e.g.:
```
# audioctl                                                       
name=azalia1
descr=Realtek ALC1150
...
# audioctl -f /dev/audioctl1 
name=uaudio0
descr=SteelSeries SteelSeries Arctis 
...
```

I'm hoping that later we can have sndiod read these strings and expose
them to its clients. For example, I'd like for sndioctl(1) to allow
choosing a device based on the device description string (instead of the
sndio device index), and for xfce4-mixer to allow choosing a device via
its description in the GUI using a drop-down box.

Diff follows.



Index: sys/dev/audio.c
===================================================================
RCS file: /cvs/src/sys/dev/audio.c,v
retrieving revision 1.193
diff -u -p -r1.193 audio.c
--- sys/dev/audio.c     16 May 2021 15:12:37 -0000      1.193
+++ sys/dev/audio.c     7 Jul 2021 10:21:25 -0000
@@ -1791,6 +1791,11 @@ audio_getdev(struct audio_softc *sc, str
        if (sc->dev.dv_parent == NULL)
                return EIO;
        strlcpy(adev->name, sc->dev.dv_parent->dv_xname, MAX_AUDIO_DEV_LEN);
+       if (sc->ops->descr != NULL)
+               sc->ops->descr(sc->arg, adev->descr, MAX_AUDIO_DESCR_LEN);
+       else
+               strlcpy(adev->descr, sc->dev.dv_parent->dv_xname,
+                   MAX_AUDIO_DESCR_LEN);
        return 0;
 }
 
Index: sys/dev/audio_if.h
===================================================================
RCS file: /cvs/src/sys/dev/audio_if.h,v
retrieving revision 1.36
diff -u -p -r1.36 audio_if.h
--- sys/dev/audio_if.h  5 Sep 2019 05:33:57 -0000       1.36
+++ sys/dev/audio_if.h  2 Jul 2021 19:15:53 -0000
@@ -137,6 +137,8 @@ struct audio_hw_if {
            struct audio_params *, struct audio_params *, unsigned int);
        unsigned int (*set_nblks)(void *, int,
            struct audio_params *, unsigned int, unsigned int);
+
+       void    (*descr)(void*, char *, size_t); /* the device's description */
 };
 
 struct audio_attach_args {
Index: sys/dev/pci/azalia.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/azalia.c,v
retrieving revision 1.263
diff -u -p -r1.263 azalia.c
--- sys/dev/pci/azalia.c        11 Jun 2021 15:46:09 -0000      1.263
+++ sys/dev/pci/azalia.c        2 Jul 2021 19:15:53 -0000
@@ -256,6 +256,7 @@ unsigned int azalia_set_blksz(void *, in
        struct audio_params *, struct audio_params *, unsigned int);
 unsigned int azalia_set_nblks(void *, int,
        struct audio_params *, unsigned int, unsigned int);
+void   azalia_descr(void *, char *, size_t);
 int    azalia_halt_output(void *);
 int    azalia_halt_input(void *);
 int    azalia_set_port(void *, mixer_ctrl_t *);
@@ -315,7 +316,8 @@ struct audio_hw_if azalia_hw_if = {
        NULL,                   /* copy_output */
        NULL,                   /* underrun */
        azalia_set_blksz,
-       azalia_set_nblks
+       azalia_set_nblks,
+       azalia_descr            /* descr */
 };
 
 static const char *pin_devices[16] = {
@@ -4019,6 +4021,37 @@ azalia_set_nblks(void *v, int mode,
                nblks = HDA_BDL_MAX;
 
        return nblks;
+}
+
+void
+azalia_descr(void *arg, char *descr, size_t len)
+{
+       azalia_t *az = arg;
+       codec_t *codec;
+       const char *vendor;
+       char buf[MAX_AUDIO_DESCR_LEN];
+       int i;
+
+       *descr = '\0';
+       for (i = 0; i < az->ncodecs; i++) {
+               codec = &az->codecs[i];
+               /* adapted from azalia_print_codec() */
+               if (codec->name == NULL) {
+                       vendor = pci_findvendor(codec->vid >> 16);
+                       if (vendor == NULL)
+                               snprintf(buf, MAX_AUDIO_DESCR_LEN,
+                                   "0x%04x/0x%04x", codec->vid >> 16,
+                                   codec->vid & 0xffff);
+                       else
+                               snprintf(buf, MAX_AUDIO_DESCR_LEN, "%s/0x%04x",
+                                   vendor, codec->vid & 0xffff);
+               } else
+                       snprintf(buf, MAX_AUDIO_DESCR_LEN, "%s", codec->name);
+
+               if (i > 0)
+                       strlcat(descr, ", ", len);
+               strlcat(descr, buf, len);
+       }
 }
 
 int
Index: sys/dev/usb/uaudio.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uaudio.c,v
retrieving revision 1.161
diff -u -p -r1.161 uaudio.c
--- sys/dev/usb/uaudio.c        18 May 2021 10:02:00 -0000      1.161
+++ sys/dev/usb/uaudio.c        2 Jul 2021 19:15:53 -0000
@@ -431,6 +431,7 @@ int uaudio_query_devinfo(void *, struct 
 int uaudio_get_port(void *, struct mixer_ctrl *);
 int uaudio_set_port(void *, struct mixer_ctrl *);
 int uaudio_get_props(void *);
+void uaudio_descr(void *, char *, size_t);
 
 int uaudio_process_unit(struct uaudio_softc *,
     struct uaudio_unit *, int,
@@ -493,7 +494,9 @@ struct audio_hw_if uaudio_hw_if = {
        uaudio_trigger_input,   /* trigger_input */
        uaudio_copy_output,     /* copy_output */
        uaudio_underrun,        /* underrun */
-       uaudio_set_blksz        /* set_blksz */
+       uaudio_set_blksz,       /* set_blksz */
+       NULL,                   /* set_nblks */
+       uaudio_descr,           /* descr */
 };
 
 /*
@@ -4189,6 +4192,14 @@ int
 uaudio_get_props(void *self)
 {
        return AUDIO_PROP_FULLDUPLEX;
+}
+
+
+void
+uaudio_descr(void *arg, char *descr, size_t len)
+{
+       struct uaudio_softc *sc = arg;
+       snprintf(descr, len, "%s %s", sc->udev->vendor, sc->udev->product);
 }
 
 int
Index: sys/sys/audioio.h
===================================================================
RCS file: /cvs/src/sys/sys/audioio.h,v
retrieving revision 1.27
diff -u -p -r1.27 audioio.h
--- sys/sys/audioio.h   14 Sep 2016 06:12:20 -0000      1.27
+++ sys/sys/audioio.h   7 Jul 2021 10:23:09 -0000
@@ -76,10 +76,10 @@ struct audio_status {
  * audio devices.
  */
 #define MAX_AUDIO_DEV_LEN      16
+#define MAX_AUDIO_DESCR_LEN    32
 typedef struct audio_device {
        char name[MAX_AUDIO_DEV_LEN];
-       char version[MAX_AUDIO_DEV_LEN];
-       char config[MAX_AUDIO_DEV_LEN];
+       char descr[MAX_AUDIO_DESCR_LEN]; /* device description string */
 } audio_device_t;
 
 struct audio_pos {
Index: usr.bin/audioctl/audioctl.c
===================================================================
RCS file: /cvs/src/usr.bin/audioctl/audioctl.c,v
retrieving revision 1.42
diff -u -p -r1.42 audioctl.c
--- usr.bin/audioctl/audioctl.c 2 Feb 2020 05:25:41 -0000       1.42
+++ usr.bin/audioctl/audioctl.c 2 Jul 2021 19:15:53 -0000
@@ -46,6 +46,7 @@ struct field {
        int set;
 } fields[] = {
        {"name",                &rname.name,            NULL,           STR},
+       {"descr",               &rname.descr,           NULL,           STR},
        {"mode",                &rstatus.mode,          NULL,           MODE},
        {"pause",               &rstatus.pause,         NULL,           NUM},
        {"active",              &rstatus.active,        NULL,           NUM},
Index: share/man/man4/audio.4
===================================================================
RCS file: /cvs/src/share/man/man4/audio.4,v
retrieving revision 1.86
diff -u -p -r1.86 audio.4
--- share/man/man4/audio.4      1 Nov 2020 21:32:03 -0000       1.86
+++ share/man/man4/audio.4      7 Jul 2021 13:41:38 -0000
@@ -112,8 +112,7 @@ argument.
 .Bd -literal
 typedef struct audio_device {
         char name[MAX_AUDIO_DEV_LEN];
-        char version[MAX_AUDIO_DEV_LEN];
-        char config[MAX_AUDIO_DEV_LEN];
+        char descr[MAX_AUDIO_DESCR_LEN];
 } audio_device_t;
 .Ed
 .Pp


-- 
Best Regards
Edd Barrett

http://www.theunixzoo.co.uk

Reply via email to