mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-03-29 07:57:59 -04:00
control: ucm: add ioctl to retrieve full card components
The fixed-size components field in SNDRV_CTL_IOCTL_CARD_INFO can be too small on systems with many audio devices. The kernel [1] will provide a new ioctl to read the full string while truncating the original in card_info if it grows too big. Make sure alsa-lib can read the full string if the original is truncated. [1] https://lore.kernel.org/all/20260303145815.9930-1-mstrozek@opensource.cirrus.com/ Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
This commit is contained in:
parent
75ed5f05ba
commit
22c3701630
4 changed files with 61 additions and 6 deletions
|
|
@ -101,7 +101,6 @@
|
||||||
#define _snd_pcm_sw_params snd_pcm_sw_params
|
#define _snd_pcm_sw_params snd_pcm_sw_params
|
||||||
#define _snd_pcm_status snd_pcm_status
|
#define _snd_pcm_status snd_pcm_status
|
||||||
|
|
||||||
#define _snd_ctl_card_info snd_ctl_card_info
|
|
||||||
#define _snd_ctl_elem_id snd_ctl_elem_id
|
#define _snd_ctl_elem_id snd_ctl_elem_id
|
||||||
#define _snd_ctl_elem_list snd_ctl_elem_list
|
#define _snd_ctl_elem_list snd_ctl_elem_list
|
||||||
#define _snd_ctl_elem_info snd_ctl_elem_info
|
#define _snd_ctl_elem_info snd_ctl_elem_info
|
||||||
|
|
@ -226,6 +225,20 @@
|
||||||
#include "seq_midi_event.h"
|
#include "seq_midi_event.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
|
/* V2 structure - increased components string from 128 bytes to 512 bytes */
|
||||||
|
struct _snd_ctl_card_info {
|
||||||
|
int card; /* card number */
|
||||||
|
int pad; /* reserved for future (was type) */
|
||||||
|
unsigned char id[16]; /* ID of card (user selectable) */
|
||||||
|
unsigned char driver[16]; /* Driver name */
|
||||||
|
unsigned char name[32]; /* Short name of soundcard */
|
||||||
|
unsigned char longname[80]; /* name + info text about soundcard */
|
||||||
|
unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
|
||||||
|
unsigned char mixername[80]; /* visual mixer identification */
|
||||||
|
char components[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct _snd_async_handler {
|
struct _snd_async_handler {
|
||||||
enum {
|
enum {
|
||||||
SND_ASYNC_HANDLER_GENERIC,
|
SND_ASYNC_HANDLER_GENERIC,
|
||||||
|
|
|
||||||
|
|
@ -1044,7 +1044,7 @@ struct snd_timer_tread {
|
||||||
* *
|
* *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9)
|
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
|
||||||
|
|
||||||
struct snd_ctl_card_info {
|
struct snd_ctl_card_info {
|
||||||
int card; /* card number */
|
int card; /* card number */
|
||||||
|
|
@ -1058,6 +1058,17 @@ struct snd_ctl_card_info {
|
||||||
unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
|
unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Card components can exceed the fixed 128 bytes in snd_ctl_card_info.
|
||||||
|
* Use SNDRV_CTL_IOCTL_CARD_COMPONENTS to retrieve the full string.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct snd_ctl_card_components {
|
||||||
|
int card; /* card number */
|
||||||
|
unsigned int length; /* returned length of components string for ioctl query */
|
||||||
|
unsigned char *components; /* user buffer for components string */
|
||||||
|
};
|
||||||
|
|
||||||
typedef int __bitwise snd_ctl_elem_type_t;
|
typedef int __bitwise snd_ctl_elem_type_t;
|
||||||
#define SNDRV_CTL_ELEM_TYPE_NONE ((snd_ctl_elem_type_t) 0) /* invalid */
|
#define SNDRV_CTL_ELEM_TYPE_NONE ((snd_ctl_elem_type_t) 0) /* invalid */
|
||||||
#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((snd_ctl_elem_type_t) 1) /* boolean type */
|
#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((snd_ctl_elem_type_t) 1) /* boolean type */
|
||||||
|
|
@ -1184,6 +1195,7 @@ struct snd_ctl_tlv {
|
||||||
|
|
||||||
#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
|
#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
|
||||||
#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
|
#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
|
||||||
|
#define SNDRV_CTL_IOCTL_CARD_COMPONENTS _IOWR('U', 0x02, struct snd_ctl_card_components)
|
||||||
#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
|
#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
|
||||||
#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
|
#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
|
||||||
#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
|
#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,17 @@
|
||||||
static int snd_card_load2(const char *control)
|
static int snd_card_load2(const char *control)
|
||||||
{
|
{
|
||||||
int open_dev;
|
int open_dev;
|
||||||
snd_ctl_card_info_t info;
|
struct snd_ctl_card_info kinfo;
|
||||||
|
|
||||||
open_dev = snd_open_device(control, O_RDONLY);
|
open_dev = snd_open_device(control, O_RDONLY);
|
||||||
if (open_dev >= 0) {
|
if (open_dev >= 0) {
|
||||||
if (ioctl(open_dev, SNDRV_CTL_IOCTL_CARD_INFO, &info) < 0) {
|
if (ioctl(open_dev, SNDRV_CTL_IOCTL_CARD_INFO, &kinfo) < 0) {
|
||||||
int err = -errno;
|
int err = -errno;
|
||||||
close(open_dev);
|
close(open_dev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
close(open_dev);
|
close(open_dev);
|
||||||
return info.card;
|
return kinfo.card;
|
||||||
} else {
|
} else {
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,10 +129,40 @@ static int snd_ctl_hw_subscribe_events(snd_ctl_t *handle, int subscribe)
|
||||||
static int snd_ctl_hw_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
|
static int snd_ctl_hw_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
|
||||||
{
|
{
|
||||||
snd_ctl_hw_t *hw = handle->private_data;
|
snd_ctl_hw_t *hw = handle->private_data;
|
||||||
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0) {
|
struct snd_ctl_card_info kinfo;
|
||||||
|
struct snd_ctl_card_components comp;
|
||||||
|
|
||||||
|
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, &kinfo) < 0) {
|
||||||
snd_errornum(CONTROL, "SNDRV_CTL_IOCTL_CARD_INFO failed");
|
snd_errornum(CONTROL, "SNDRV_CTL_IOCTL_CARD_INFO failed");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snd_ctl_card_info_clear(info);
|
||||||
|
info->card = kinfo.card;
|
||||||
|
info->pad = kinfo.pad;
|
||||||
|
snd_strlcpy((char *)info->id, (char *)kinfo.id, sizeof(info->id));
|
||||||
|
snd_strlcpy((char *)info->driver, (char *)kinfo.driver, sizeof(info->driver));
|
||||||
|
snd_strlcpy((char *)info->name, (char *)kinfo.name, sizeof(info->name));
|
||||||
|
snd_strlcpy((char *)info->longname, (char *)kinfo.longname, sizeof(info->longname));
|
||||||
|
snd_strlcpy((char *)info->reserved_, (char *)kinfo.reserved_, sizeof(info->reserved_));
|
||||||
|
snd_strlcpy((char *)info->mixername, (char *)kinfo.mixername, sizeof(info->mixername));
|
||||||
|
if (strnlen((char *)kinfo.components, sizeof(kinfo.components)) == sizeof(kinfo.components) - 1 &&
|
||||||
|
kinfo.components[sizeof(kinfo.components) - 2] == '>') {
|
||||||
|
comp.components = (unsigned char *)info->components;
|
||||||
|
comp.length = sizeof(info->components);
|
||||||
|
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_COMPONENTS, &comp) < 0) {
|
||||||
|
snd_errornum(CONTROL, "SNDRV_CTL_IOCTL_CARD_COMPONENTS failed");
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
if (comp.length != strnlen((char *)comp.components, sizeof(info->components)) + 1 ) {
|
||||||
|
snd_error(CONTROL, "SNDRV_CTL_IOCTL_CARD_COMPONENTS unexpected length %u, should be %u",
|
||||||
|
comp.length, strnlen((char *)comp.components, sizeof(info->components)) + 1);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snd_strlcpy(info->components, (char *)kinfo.components, sizeof(info->components));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue