Download raw body.
Expose better display names for audio(4) devices
On Sun, Jul 13, 2025 at 06:37:28PM +0200, Alexandre Ratchov wrote:
> If there are multiple uaudio(4) devices, it is difficult to know which
> sndioctl(1) selector corresponds to which hardware interface without
> searching in the dmesg output. Example:
>
> $ sndioctl -i server.device
> server.device=0(azalia0),1(envy0),2(cmpci0),3(uaudio0),4(uaudio1),5(uaudio2),6,7
>
> The diff below makes the kernel expose a slightly more useful string
> instead of the device->dv_xname as the device display name. Ex., the
> product name for uaudio(4), the codec type for azalia(4), the card
> name for envy(4) and cmpci(4). The result:
>
> $ sndioctl -i server.device
> server.device=0(HDA: Analog),1(ESI Julia),2(CMI8738),3(U-24),4(Webcam C310),5(AudioBox Go),6,7
>
> These are short strings mainly intended for GUIs or as simple hints.
>
> OK?
>
Like this. ok mvs.
> Index: share/man/man9/audio.9
> ===================================================================
> RCS file: /cvs/src/share/man/man9/audio.9,v
> diff -u -p -r1.35 audio.9
> --- share/man/man9/audio.9 15 Oct 2023 15:49:47 -0000 1.35
> +++ share/man/man9/audio.9 8 Jul 2025 17:00:51 -0000
> @@ -79,6 +79,7 @@ struct audio_hw_if {
> struct audio_params *, struct audio_params *, int);
> int (*set_nblks)(void *, int, int,
> struct audio_params *, int);
> + size_t (*display_name)(void *, char *, size_t);
> };
>
> struct audio_params {
> @@ -453,6 +454,22 @@ function.
> is the desired number of blocks in the ring buffer.
> It may be lowered to at least two, to match hardware constraints.
> This function returns the adjusted number of blocks.
> +.It Ft size_t Fn (*display_name) "void *hdl" "char *buf" "size_t size"
> +This function produces a string suitable for user interfaces and
> +intended to help the user to identify the hardware.
> +Like
> +.Xr snprintf 3 ,
> +this function returns the total length of the string it tried to create
> +(excluding the final
> +.Ql \e0 ) .
> +Unless
> +.Fa size
> +is 0, it writes at most
> +.Fa size Ns \-1
> +characters followed by a terminating
> +.Ql \e0
> +at the location pointed by
> +.Fa buf .
> .El
> .Pp
> If the audio hardware is capable of input from more
> Index: sys/dev/audio.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/audio.c,v
> diff -u -p -r1.211 audio.c
> --- sys/dev/audio.c 14 Feb 2025 13:29:00 -0000 1.211
> +++ sys/dev/audio.c 8 Jul 2025 17:00:52 -0000
> @@ -1735,12 +1735,22 @@ audio_write(struct audio_softc *sc, stru
> }
>
> int
> -audio_getdev(struct audio_softc *sc, struct audio_device *adev)
> +audio_getdev(struct audio_softc *sc, struct audio_device *p)
> {
> - memset(adev, 0, sizeof(struct audio_device));
> - if (sc->dev.dv_parent == NULL)
> - return EIO;
> - strlcpy(adev->name, sc->dev.dv_parent->dv_xname, MAX_AUDIO_DEV_LEN);
> + size_t sz;
> +
> + memset(p, 0, sizeof(struct audio_device));
> + sz = 0;
> +
> + if (sc->ops->display_name)
> + sz = sc->ops->display_name(sc->arg, p->name, sizeof(p->name));
> +
> + if (sz == 0) {
> + if (sc->dev.dv_parent == NULL)
> + return EIO;
> + strlcpy(p->name, sc->dev.dv_parent->dv_xname, sizeof(p->name));
> + }
> +
> return 0;
> }
>
> Index: sys/dev/audio_if.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/audio_if.h,v
> diff -u -p -r1.42 audio_if.h
> --- sys/dev/audio_if.h 2 Nov 2022 10:41:34 -0000 1.42
> +++ sys/dev/audio_if.h 8 Jul 2025 17:00:52 -0000
> @@ -125,6 +125,7 @@ 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);
> + size_t (*display_name)(void *, char *, size_t);
> };
>
> struct audio_attach_args {
> Index: sys/dev/pci/azalia.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/azalia.c,v
> diff -u -p -r1.290 azalia.c
> --- sys/dev/pci/azalia.c 18 Aug 2024 14:42:56 -0000 1.290
> +++ sys/dev/pci/azalia.c 8 Jul 2025 17:00:54 -0000
> @@ -269,6 +269,7 @@ int azalia_trigger_output(void *, void *
> void (*)(void *), void *, audio_params_t *);
> int azalia_trigger_input(void *, void *, void *, int,
> void (*)(void *), void *, audio_params_t *);
> +size_t azalia_display_name(void *, char *, size_t);
>
> int azalia_params2fmt(const audio_params_t *, uint16_t *);
>
> @@ -305,6 +306,7 @@ const struct audio_hw_if azalia_hw_if =
> .trigger_input = azalia_trigger_input,
> .set_blksz = azalia_set_blksz,
> .set_nblks = azalia_set_nblks,
> + .display_name = azalia_display_name,
> };
>
> static const char *pin_devices[16] = {
> @@ -4208,6 +4210,30 @@ azalia_trigger_input(void *v, void *star
> az->rstream.swpos = 0;
>
> return azalia_stream_start(&az->rstream);
> +}
> +
> +size_t
> +azalia_display_name(void *self, char *buf, size_t size)
> +{
> + azalia_t *az = (azalia_t *)self;
> + codec_t *codec = &az->codecs[az->codecno];
> + const char *name;
> +
> + switch (codec->codec_type) {
> + case AZ_CODEC_TYPE_ANALOG:
> + name = "HDA: Analog";
> + break;
> + case AZ_CODEC_TYPE_DIGITAL:
> + name = "HDA: Digital";
> + break;
> + case AZ_CODEC_TYPE_HDMI:
> + name = "HDA: HDMI";
> + break;
> + default:
> + return 0;
> + }
> +
> + return strlcpy(buf, name, size);
> }
>
> /* --------------------------------
> Index: sys/dev/pci/cmpci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/cmpci.c,v
> diff -u -p -r1.54 cmpci.c
> --- sys/dev/pci/cmpci.c 24 May 2024 06:02:53 -0000 1.54
> +++ sys/dev/pci/cmpci.c 8 Jul 2025 17:00:54 -0000
> @@ -145,6 +145,7 @@ int cmpci_trigger_output(void *, void *,
> int cmpci_trigger_input(void *, void *, void *, int,
> void (*)(void *), void *,
> struct audio_params *);
> +size_t cmpci_display_name(void *, char *, size_t);
>
> const struct audio_hw_if cmpci_hw_if = {
> .open = cmpci_open,
> @@ -161,6 +162,7 @@ const struct audio_hw_if cmpci_hw_if = {
> .round_buffersize = cmpci_round_buffersize,
> .trigger_output = cmpci_trigger_output,
> .trigger_input = cmpci_trigger_input,
> + .display_name = cmpci_display_name,
> };
>
> /*
> @@ -1860,6 +1862,31 @@ cmpci_trigger_input(void *handle, void *
> cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
> mtx_leave(&audio_lock);
> return 0;
> +}
> +
> +size_t
> +cmpci_display_name(void *self, char *buf, size_t size)
> +{
> + struct cmpci_softc *sc = (struct cmpci_softc *)self;
> + const char *name;
> +
> + switch (PCI_PRODUCT(sc->sc_id)) {
> + case PCI_PRODUCT_CMI_CMI8338A:
> + name = "CMI8338A";
> + break;
> + case PCI_PRODUCT_CMI_CMI8338B:
> + name = "CMI8338B";
> + break;
> + case PCI_PRODUCT_CMI_CMI8738:
> + name = "CMI8738";
> + break;
> + case PCI_PRODUCT_CMI_CMI8738B:
> + name = "CMI8738B";
> + break;
> + default:
> + name = sc->sc_dev.dv_xname;
> + }
> + return strlcpy(buf, name, size);
> }
>
> /* end of file */
> Index: sys/dev/pci/envy.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/envy.c,v
> diff -u -p -r1.88 envy.c
> --- sys/dev/pci/envy.c 24 May 2024 06:02:53 -0000 1.88
> +++ sys/dev/pci/envy.c 8 Jul 2025 17:00:55 -0000
> @@ -110,6 +110,7 @@ int envy_halt_input(void *);
> int envy_query_devinfo(void *, struct mixer_devinfo *);
> int envy_get_port(void *, struct mixer_ctrl *);
> int envy_set_port(void *, struct mixer_ctrl *);
> +size_t envy_display_name(void *, char *, size_t);
> #if NMIDI > 0
> int envy_midi_open(void *, int, void (*)(void *, int),
> void (*)(void *), void *);
> @@ -191,6 +192,7 @@ const struct audio_hw_if envy_hw_if = {
> .freem = envy_freem,
> .trigger_output = envy_trigger_output,
> .trigger_input = envy_trigger_input,
> + .display_name = envy_display_name,
> };
>
> #if NMIDI > 0
> @@ -2426,6 +2428,14 @@ envy_set_port(void *self, struct mixer_c
> if (idx < ndev)
> return sc->card->dac->set(sc, ctl, idx);
> return ENXIO;
> +}
> +
> +size_t
> +envy_display_name(void *self, char *buf, size_t size)
> +{
> + struct envy_softc *sc = (struct envy_softc *)self;
> +
> + return strlcpy(buf, sc->card->name, size);
> }
>
> #if NMIDI > 0
> Index: sys/dev/usb/uaudio.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/uaudio.c,v
> diff -u -p -r1.178 uaudio.c
> --- sys/dev/usb/uaudio.c 7 Jan 2025 12:49:40 -0000 1.178
> +++ sys/dev/usb/uaudio.c 8 Jul 2025 17:00:59 -0000
> @@ -212,6 +212,7 @@ struct uaudio_softc {
> struct device dev;
> struct usbd_device *udev;
> int version;
> + int instnum;
>
> /*
> * UAC exposes the device as a circuit of units. Input and
> @@ -442,6 +443,7 @@ int uaudio_halt_input(void *);
> int uaudio_query_devinfo(void *, struct mixer_devinfo *);
> int uaudio_get_port(void *, struct mixer_ctrl *);
> int uaudio_set_port(void *, struct mixer_ctrl *);
> +size_t uaudio_display_name(void *, char *, size_t);
>
> int uaudio_process_unit(struct uaudio_softc *,
> struct uaudio_unit *, int,
> @@ -493,6 +495,7 @@ const struct audio_hw_if uaudio_hw_if =
> .copy_output = uaudio_copy_output,
> .underrun = uaudio_underrun,
> .set_blksz = uaudio_set_blksz,
> + .display_name = uaudio_display_name,
> };
>
> /*
> @@ -2800,6 +2803,7 @@ uaudio_process_conf(struct uaudio_softc
> i = uaudio_iface_index(sc, ifnum);
> if (i != -1 && usbd_iface_claimed(sc->udev, i)) {
> DPRINTF("%s: %d: AC already claimed\n", __func__, ifnum);
> + sc->instnum++;
> break;
> }
> if (sc->unit_list != NULL) {
> @@ -4480,6 +4484,38 @@ uaudio_set_port(void *arg, struct mixer_
> rc = uaudio_set_port_do(sc, ctl);
> usbd_ref_decr(sc->udev);
> return rc;
> +}
> +
> +size_t
> +uaudio_display_name(void *arg, char *buf, size_t size)
> +{
> + struct uaudio_softc *sc = arg;
> + char *vendor = sc->udev->vendor;
> + char *product = sc->udev->product;
> + size_t i;
> +
> + if (product == NULL || vendor == NULL)
> + return strlcpy(buf, DEVNAME(sc), size);
> +
> + /*
> + * Certain devices prefix the product name with the vendor name,
> + * drop the prefix
> + */
> + for (i = 0; product[i] != 0; i++) {
> + if (vendor[i] == 0) {
> + while (product[i] == ' ')
> + i++;
> + product += i;
> + break;
> + }
> + if (vendor[i] != product[i])
> + break;
> + }
> +
> + if (sc->instnum > 0)
> + return snprintf(buf, size, "%s#%u", product, sc->instnum + 1);
> + else
> + return strlcpy(buf, product, size);
> }
>
> int
>
Expose better display names for audio(4) devices