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