162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Information interface for ALSA driver 462306a36Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci#include <linux/time.h> 962306a36Sopenharmony_ci#include <linux/string.h> 1062306a36Sopenharmony_ci#include <linux/export.h> 1162306a36Sopenharmony_ci#include <sound/core.h> 1262306a36Sopenharmony_ci#include <sound/minors.h> 1362306a36Sopenharmony_ci#include <sound/info.h> 1462306a36Sopenharmony_ci#include <linux/utsname.h> 1562306a36Sopenharmony_ci#include <linux/mutex.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci * OSS compatible part 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic DEFINE_MUTEX(strings); 2262306a36Sopenharmony_cistatic char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciint snd_oss_info_register(int dev, int num, char *string) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci char *x; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT)) 2962306a36Sopenharmony_ci return -ENXIO; 3062306a36Sopenharmony_ci if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS)) 3162306a36Sopenharmony_ci return -ENXIO; 3262306a36Sopenharmony_ci mutex_lock(&strings); 3362306a36Sopenharmony_ci if (string == NULL) { 3462306a36Sopenharmony_ci x = snd_sndstat_strings[num][dev]; 3562306a36Sopenharmony_ci kfree(x); 3662306a36Sopenharmony_ci x = NULL; 3762306a36Sopenharmony_ci } else { 3862306a36Sopenharmony_ci x = kstrdup(string, GFP_KERNEL); 3962306a36Sopenharmony_ci if (x == NULL) { 4062306a36Sopenharmony_ci mutex_unlock(&strings); 4162306a36Sopenharmony_ci return -ENOMEM; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci snd_sndstat_strings[num][dev] = x; 4562306a36Sopenharmony_ci mutex_unlock(&strings); 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ciEXPORT_SYMBOL(snd_oss_info_register); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci int idx, ok = -1; 5362306a36Sopenharmony_ci char *str; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci snd_iprintf(buf, "\n%s:", id); 5662306a36Sopenharmony_ci mutex_lock(&strings); 5762306a36Sopenharmony_ci for (idx = 0; idx < SNDRV_CARDS; idx++) { 5862306a36Sopenharmony_ci str = snd_sndstat_strings[idx][dev]; 5962306a36Sopenharmony_ci if (str) { 6062306a36Sopenharmony_ci if (ok < 0) { 6162306a36Sopenharmony_ci snd_iprintf(buf, "\n"); 6262306a36Sopenharmony_ci ok++; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci snd_iprintf(buf, "%i: %s\n", idx, str); 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci mutex_unlock(&strings); 6862306a36Sopenharmony_ci if (ok < 0) 6962306a36Sopenharmony_ci snd_iprintf(buf, " NOT ENABLED IN CONFIG\n"); 7062306a36Sopenharmony_ci return ok; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic void snd_sndstat_proc_read(struct snd_info_entry *entry, 7462306a36Sopenharmony_ci struct snd_info_buffer *buffer) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA emulation code)\n"); 7762306a36Sopenharmony_ci snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", 7862306a36Sopenharmony_ci init_utsname()->sysname, 7962306a36Sopenharmony_ci init_utsname()->nodename, 8062306a36Sopenharmony_ci init_utsname()->release, 8162306a36Sopenharmony_ci init_utsname()->version, 8262306a36Sopenharmony_ci init_utsname()->machine); 8362306a36Sopenharmony_ci snd_iprintf(buffer, "Config options: 0\n"); 8462306a36Sopenharmony_ci snd_iprintf(buffer, "\nInstalled drivers: \n"); 8562306a36Sopenharmony_ci snd_iprintf(buffer, "Type 10: ALSA emulation\n"); 8662306a36Sopenharmony_ci snd_iprintf(buffer, "\nCard config: \n"); 8762306a36Sopenharmony_ci snd_card_info_read_oss(buffer); 8862306a36Sopenharmony_ci snd_sndstat_show_strings(buffer, "Audio devices", SNDRV_OSS_INFO_DEV_AUDIO); 8962306a36Sopenharmony_ci snd_sndstat_show_strings(buffer, "Synth devices", SNDRV_OSS_INFO_DEV_SYNTH); 9062306a36Sopenharmony_ci snd_sndstat_show_strings(buffer, "Midi devices", SNDRV_OSS_INFO_DEV_MIDI); 9162306a36Sopenharmony_ci snd_sndstat_show_strings(buffer, "Timers", SNDRV_OSS_INFO_DEV_TIMERS); 9262306a36Sopenharmony_ci snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciint __init snd_info_minor_register(void) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct snd_info_entry *entry; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); 10062306a36Sopenharmony_ci entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", 10162306a36Sopenharmony_ci snd_oss_root); 10262306a36Sopenharmony_ci if (!entry) 10362306a36Sopenharmony_ci return -ENOMEM; 10462306a36Sopenharmony_ci entry->c.text.read = snd_sndstat_proc_read; 10562306a36Sopenharmony_ci return snd_info_register(entry); /* freed in error path */ 10662306a36Sopenharmony_ci} 107