Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: rawmidi: Skip UMP devices at SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE

Applications may look for rawmidi devices with the ioctl
SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE. Returning a UMP device from this
ioctl may confuse the existing applications that support only the
legacy rawmidi.

This patch changes the code to skip the UMP devices from the lookup
for avoiding the confusion, and introduces a new ioctl to look for the
UMP devices instead.

Along with this change, bump the CTL protocol version to 2.0.9.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230523075358.9672-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+38 -22
+2 -1
include/uapi/sound/asound.h
··· 1016 1016 * * 1017 1017 ****************************************************************************/ 1018 1018 1019 - #define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) 1019 + #define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) 1020 1020 1021 1021 struct snd_ctl_card_info { 1022 1022 int card; /* card number */ ··· 1177 1177 #define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) 1178 1178 #define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) 1179 1179 #define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) 1180 + #define SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE _IOWR('U', 0x43, int) 1180 1181 #define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) 1181 1182 #define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) 1182 1183
+36 -21
sound/core/rawmidi.c
··· 1012 1012 return -ENOTTY; 1013 1013 } 1014 1014 1015 + /* ioctl to find the next device; either legacy or UMP depending on @find_ump */ 1016 + static int snd_rawmidi_next_device(struct snd_card *card, int __user *argp, 1017 + bool find_ump) 1018 + 1019 + { 1020 + struct snd_rawmidi *rmidi; 1021 + int device; 1022 + bool is_ump; 1023 + 1024 + if (get_user(device, argp)) 1025 + return -EFAULT; 1026 + if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ 1027 + device = SNDRV_RAWMIDI_DEVICES - 1; 1028 + mutex_lock(&register_mutex); 1029 + device = device < 0 ? 0 : device + 1; 1030 + for (; device < SNDRV_RAWMIDI_DEVICES; device++) { 1031 + rmidi = snd_rawmidi_search(card, device); 1032 + if (!rmidi) 1033 + continue; 1034 + is_ump = rawmidi_is_ump(rmidi); 1035 + if (find_ump == is_ump) 1036 + break; 1037 + } 1038 + if (device == SNDRV_RAWMIDI_DEVICES) 1039 + device = -1; 1040 + mutex_unlock(&register_mutex); 1041 + if (put_user(device, argp)) 1042 + return -EFAULT; 1043 + return 0; 1044 + } 1045 + 1015 1046 static int snd_rawmidi_control_ioctl(struct snd_card *card, 1016 1047 struct snd_ctl_file *control, 1017 1048 unsigned int cmd, ··· 1052 1021 1053 1022 switch (cmd) { 1054 1023 case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: 1055 - { 1056 - int device; 1057 - 1058 - if (get_user(device, (int __user *)argp)) 1059 - return -EFAULT; 1060 - if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ 1061 - device = SNDRV_RAWMIDI_DEVICES - 1; 1062 - mutex_lock(&register_mutex); 1063 - device = device < 0 ? 0 : device + 1; 1064 - while (device < SNDRV_RAWMIDI_DEVICES) { 1065 - if (snd_rawmidi_search(card, device)) 1066 - break; 1067 - device++; 1068 - } 1069 - if (device == SNDRV_RAWMIDI_DEVICES) 1070 - device = -1; 1071 - mutex_unlock(&register_mutex); 1072 - if (put_user(device, (int __user *)argp)) 1073 - return -EFAULT; 1074 - return 0; 1075 - } 1024 + return snd_rawmidi_next_device(card, argp, false); 1025 + #if IS_ENABLED(CONFIG_SND_UMP) 1026 + case SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE: 1027 + return snd_rawmidi_next_device(card, argp, true); 1028 + #endif 1076 1029 case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE: 1077 1030 { 1078 1031 int val;