1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Information interface for ALSA driver 4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 5 */ 6 7 #include <linux/slab.h> 8 #include <linux/time.h> 9 #include <linux/string.h> 10 #include <linux/export.h> 11 #include <sound/core.h> 12 #include <sound/minors.h> 13 #include <sound/info.h> 14 #include <linux/utsname.h> 15 #include <linux/mutex.h> 16 17 /* 18 * OSS compatible part 19 */ 20 21 static DEFINE_MUTEX(strings); 22 static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; 23 24 int snd_oss_info_register(int dev, int num, char *string) 25 { 26 char *x; 27 28 if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT)) 29 return -ENXIO; 30 if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS)) 31 return -ENXIO; 32 mutex_lock(&strings); 33 if (string == NULL) { 34 if ((x = snd_sndstat_strings[num][dev]) != NULL) { 35 kfree(x); 36 x = NULL; 37 } 38 } else { 39 x = kstrdup(string, GFP_KERNEL); 40 if (x == NULL) { 41 mutex_unlock(&strings); 42 return -ENOMEM; 43 } 44 } 45 snd_sndstat_strings[num][dev] = x; 46 mutex_unlock(&strings); 47 return 0; 48 } 49 EXPORT_SYMBOL(snd_oss_info_register); 50 51 static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) 52 { 53 int idx, ok = -1; 54 char *str; 55 56 snd_iprintf(buf, "\n%s:", id); 57 mutex_lock(&strings); 58 for (idx = 0; idx < SNDRV_CARDS; idx++) { 59 str = snd_sndstat_strings[idx][dev]; 60 if (str) { 61 if (ok < 0) { 62 snd_iprintf(buf, "\n"); 63 ok++; 64 } 65 snd_iprintf(buf, "%i: %s\n", idx, str); 66 } 67 } 68 mutex_unlock(&strings); 69 if (ok < 0) 70 snd_iprintf(buf, " NOT ENABLED IN CONFIG\n"); 71 return ok; 72 } 73 74 static void snd_sndstat_proc_read(struct snd_info_entry *entry, 75 struct snd_info_buffer *buffer) 76 { 77 snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA emulation code)\n"); 78 snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", 79 init_utsname()->sysname, 80 init_utsname()->nodename, 81 init_utsname()->release, 82 init_utsname()->version, 83 init_utsname()->machine); 84 snd_iprintf(buffer, "Config options: 0\n"); 85 snd_iprintf(buffer, "\nInstalled drivers: \n"); 86 snd_iprintf(buffer, "Type 10: ALSA emulation\n"); 87 snd_iprintf(buffer, "\nCard config: \n"); 88 snd_card_info_read_oss(buffer); 89 snd_sndstat_show_strings(buffer, "Audio devices", SNDRV_OSS_INFO_DEV_AUDIO); 90 snd_sndstat_show_strings(buffer, "Synth devices", SNDRV_OSS_INFO_DEV_SYNTH); 91 snd_sndstat_show_strings(buffer, "Midi devices", SNDRV_OSS_INFO_DEV_MIDI); 92 snd_sndstat_show_strings(buffer, "Timers", SNDRV_OSS_INFO_DEV_TIMERS); 93 snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); 94 } 95 96 int __init snd_info_minor_register(void) 97 { 98 struct snd_info_entry *entry; 99 100 memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); 101 entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", 102 snd_oss_root); 103 if (!entry) 104 return -ENOMEM; 105 entry->c.text.read = snd_sndstat_proc_read; 106 return snd_info_register(entry); /* freed in error path */ 107 } 108