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