On Wed, Jul 07, 2021 at 03:13:37PM +0100, Edd Barrett wrote:
> 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.
>
[...]
> @@ -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++) {
azalia(4) fetches all codecs, but uses (and supports) only one of
them. You should copy the name of the one in use, ie
az->codecs[az->codecno].
> + 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/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;
>
The intent of the "name" field was to be human-readable as well. You
could just replace it. There's no benefit in having two fields for the
same thing.