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 x = snd_sndstat_strings[num][dev]; 35 if (x) { 36 kfree(x); 37 x = NULL; 38 } 39 } else { 40 x = kstrdup(string, GFP_KERNEL); 41 if (x == NULL) { 42 mutex_unlock(&strings); 43 return -ENOMEM; 44 } 45 } 46 snd_sndstat_strings[num][dev] = x; 47 mutex_unlock(&strings); 48 return 0; 49 } 50 EXPORT_SYMBOL(snd_oss_info_register); 51 52 static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) 53 { 54 int idx, ok = -1; 55 char *str; 56 57 snd_iprintf(buf, "\n%s:", id); 58 mutex_lock(&strings); 59 for (idx = 0; idx < SNDRV_CARDS; idx++) { 60 str = snd_sndstat_strings[idx][dev]; 61 if (str) { 62 if (ok < 0) { 63 snd_iprintf(buf, "\n"); 64 ok++; 65 } 66 snd_iprintf(buf, "%i: %s\n", idx, str); 67 } 68 } 69 mutex_unlock(&strings); 70 if (ok < 0) 71 snd_iprintf(buf, " NOT ENABLED IN CONFIG\n"); 72 return ok; 73 } 74 75 static void snd_sndstat_proc_read(struct snd_info_entry *entry, 76 struct snd_info_buffer *buffer) 77 { 78 snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA emulation code)\n"); 79 snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", 80 init_utsname()->sysname, 81 init_utsname()->nodename, 82 init_utsname()->release, 83 init_utsname()->version, 84 init_utsname()->machine); 85 snd_iprintf(buffer, "Config options: 0\n"); 86 snd_iprintf(buffer, "\nInstalled drivers: \n"); 87 snd_iprintf(buffer, "Type 10: ALSA emulation\n"); 88 snd_iprintf(buffer, "\nCard config: \n"); 89 snd_card_info_read_oss(buffer); 90 snd_sndstat_show_strings(buffer, "Audio devices", SNDRV_OSS_INFO_DEV_AUDIO); 91 snd_sndstat_show_strings(buffer, "Synth devices", SNDRV_OSS_INFO_DEV_SYNTH); 92 snd_sndstat_show_strings(buffer, "Midi devices", SNDRV_OSS_INFO_DEV_MIDI); 93 snd_sndstat_show_strings(buffer, "Timers", SNDRV_OSS_INFO_DEV_TIMERS); 94 snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); 95 } 96 97 int __init snd_info_minor_register(void) 98 { 99 struct snd_info_entry *entry; 100 101 memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); 102 entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", 103 snd_oss_root); 104 if (!entry) 105 return -ENOMEM; 106 entry->c.text.read = snd_sndstat_proc_read; 107 return snd_info_register(entry); /* freed in error path */ 108 } 109