2
* Purpose: /dev/sndstat driver
8
* This file is part of Open Sound System.
10
* Copyright (C) 4Front Technologies 1996-2008.
12
* This this source file is released under GPL v2 license (no other versions).
13
* See the COPYING file included in the main directory of this source
14
* distribution for the license terms and conditions.
18
#include <oss_config.h>
19
#include <midi_core.h>
21
static char *sndstat_buf = NULL;
22
static int sndstat_len, sndstat_ptr;
23
static volatile int sndstat_busy = 0;
24
int riptide_notice = 0; /* The Riptide driver will set this to 1 */
27
* All kind of status messages
29
#define MAX_MESSAGE 50
30
static char *messages[MAX_MESSAGE];
31
static int nmessages; /* # of display messages (/dev/sndstat) */
34
put_status (const char *s)
38
if (sndstat_len + l >= 4000)
41
memcpy (&sndstat_buf[sndstat_len], s, l);
48
put_status_int (unsigned int val, int radix)
50
char buf[11], *rx = "%d";
53
return put_status ("0");
57
sprintf (buf, rx, val);
59
return put_status (buf);
66
* Write the status information to the sndstat_buf and update sndstat_len.
67
* There is a limit of 4000 bytes for the data.
70
int i, p, missing_devs = 0;
72
extern char *oss_license_string;
76
put_status ("OSS " OSS_VERSION_STRING);
77
put_status (oss_license_string);
78
put_status (" (C) 4Front Technologies 1996-2011\n");
81
put_status ("RipTide Driver (C) 2000, Conexant Systems, Inc.\n");
83
#ifdef LICENSED_VERSION
84
oss_print_license (put_status, put_status_int);
87
#ifdef OSS_CONFIG_OPTIONS
88
put_status ("\nSource configration options: ");
89
put_status (OSS_CONFIG_OPTIONS);
94
put_status ("\nHg revision: ");
95
put_status (OSS_HG_INFO);
103
for (i = 0; i < nmessages; i++)
105
if (!put_status (messages[i]))
112
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
114
#if defined(__FreeBSD__)
115
extern char version[];
118
put_status ("Kernel: ");
119
put_status (version);
126
* This code is obsolete and not functional at this moment.
128
if (!put_status ("\nDevice objects:\n"))
131
for (i = 0; i < oss_num_cards; i++)
135
oss_get_cardinfo (i, tmp, sizeof (tmp) - 1);
136
if (!put_status (tmp))
138
if (!put_status ("\n"))
144
if (!put_status ("\nAudio devices:\n"))
149
if (audio_devfiles != NULL)
150
for (i = 0; i < MAX_AUDIO_DEVFILES +100 && missing_devs < 40; i++)
154
if (i < num_audio_devfiles)
155
if (audio_devfiles[i]->card_number != cardno)
158
cardno = audio_devfiles[i]->card_number;
162
* New device numbering scheme may have /dev/dsp# devices in different
163
* order than the order of devices in audio_devices[]. Find the right device
164
* based on the adev->real_dev number. Note that device numbering may have
165
* holes if devices have been removed after running ossdevlinks -f last time.
168
for (j = 0; j < num_audio_devfiles; j++)
170
if (audio_devfiles[j]->real_dev == i)
174
d = audio_devfiles[j]->audio_devfile;
185
if (missing_devs > 0) /* There is a hole in numbering */
186
for (j = i - missing_devs; j < i; j++)
189
if (!put_status_int (j, 10))
191
if (!put_status (": (Undefined or removed device)\n"))
196
if (!put_status_int (i, 10))
198
if (!put_status (": "))
200
if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
203
if (!put_status (audio_devfiles[d]->name))
205
if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
208
if ((audio_devfiles[d]->flags & ADEV_DUPLEX)
209
|| (audio_devfiles[d]->flags & ADEV_NOINPUT)
210
|| (audio_devfiles[d]->flags & ADEV_NOOUTPUT))
214
if (!put_status (" ("))
217
if (audio_devfiles[d]->flags & ADEV_NOINPUT)
221
if (!put_status ("OUTPUT"))
225
if (audio_devfiles[d]->flags & ADEV_NOOUTPUT)
229
if (!put_status ("INPUT"))
233
if (audio_devfiles[d]->flags & ADEV_DUPLEX)
237
if (!put_status ("DUPLEX"))
240
if (!put_status (")"))
244
if (!put_status ("\n"))
248
adev_t *adev = audio_devfiles[d];
249
int n = 0, single = 0;
250
if (adev->next_out == NULL)
255
if (adev->open_mode != 0)
259
if (!put_status (" "))
264
if (!put_status (" "))
270
put_status ("Opened ");
271
if (adev->open_mode & OPEN_READ)
273
if (adev->open_mode & OPEN_WRITE)
279
put_status ("Engine ");
280
put_status_int (n + 1, 10);
281
put_status (" opened ");
282
if (adev->open_mode & OPEN_READ)
284
if (adev->open_mode & OPEN_WRITE)
289
if (adev->pid != -1 || *adev->label != 0)
291
if (*adev->label != 0)
293
if (!put_status (adev->label))
295
if (!put_status ("/"))
299
put_status_int (adev->pid, 10);
303
if (!put_status ("unknown application"))
307
if (!put_status (" @ "))
309
if (!put_status_int (adev->user_parms.rate, 10))
311
if (!put_status ("/"))
313
if (!put_status_int (adev->hw_parms.rate, 10))
315
if (!put_status (" Hz"))
319
if (!put_status (" Fragment: "))
322
if (!put_status (audio_show_latency (adev->engine_num)))
326
if (!put_status ("\n"))
329
if (*adev->song_name != 0)
333
if (!put_status (" "))
338
if (!put_status (" "))
342
if (!put_status ("Song name: "))
344
if (!put_status (adev->song_name))
346
if (!put_status ("\n"))
351
adev = adev->next_out;
357
#ifdef CONFIG_OSS_MIDI
358
if (!put_status ("\nMIDI devices:\n"))
362
for (i = 0; i < MAX_MIDI_DEV * 2 && missing_devs < 16; i++)
366
for (j = 0; j < num_mididevs; j++)
367
if (midi_devs[j]->real_dev == i)
380
for (j = i - missing_devs; j < i; j++)
383
if (!put_status_int (j, 10))
385
if (!put_status (": (Unknown or removed device)\n"))
390
if (!put_status_int (i, 10))
392
if (!put_status (": "))
394
if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
396
if (!put_status (midi_devs[d]->name))
398
if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
400
if (!put_status ("\n"))
403
if (midi_devs[d]->pid != -1)
407
if (!put_status (" "))
412
if (!put_status (" "))
415
if (!put_status ("Open by "))
417
if (!put_status_int (midi_devs[d]->pid, 10))
419
if (*midi_devs[d]->cmd != 0)
421
if (!put_status ("/"))
423
if (!put_status (midi_devs[d]->cmd))
426
if (!put_status ("\n"))
428
if (midi_devs[d]->d->ioctl)
430
oss_longname_t song_name;
432
if (midi_devs[d]->d->ioctl (d, SNDCTL_GETSONG,
433
(ioctl_arg) song_name) >= 0
436
if (!put_status (" Song name: "))
438
if (!put_status (song_name))
440
if (!put_status ("\n"))
449
/* TODO: No timer available at this moment */
450
if (!put_status ("\nTimers:\n"))
453
for (i = 0; i < oss_num_timers; i++)
455
if (!put_status_int (i, 10))
457
if (!put_status (": "))
459
if (!put_status (oss_timer_devs[i]->info.name))
461
if (!put_status ("\n"))
466
if (!put_status ("\nMixers:\n"))
471
for (i = 0; i < MAX_MIXER_DEV * 2 && missing_devs < 10; i++)
475
for (j = 0; j < num_mixers; j++)
476
if (mixer_devs[j]->real_dev == i)
489
for (j = i - missing_devs; j < i; j++)
492
if (!put_status_int (j, 10))
494
if (!put_status (": (Uninstalled or removed device\n"))
499
if (!put_status_int (i, 10))
501
if (!put_status (": "))
504
if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
505
if (!put_status ("("))
508
if (!put_status (mixer_devs[d]->name))
511
if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
512
if (!put_status (")"))
515
if (!put_status ("\n"))
521
for (i = 0; i < OSS_HISTORY_SIZE; i++)
522
if (*oss_history[i] != 0)
526
#ifdef GET_PROCESS_UID
527
if (GET_PROCESS_UID () == 0)
530
if (!put_status ("\nHistory:\n"))
535
for (i = 0; i < OSS_HISTORY_SIZE; i++)
537
int ix = (p + i) % OSS_HISTORY_SIZE;
539
if (*oss_history[ix] == 0)
542
if (!put_status (oss_history[ix]))
544
if (!put_status ("\n"))
551
("\n\nNOTICE! This /dev/sndstat file is obsolete - use the ossinfo command instead\n"))
557
("\n\nWARNING! Legacy device numbering in /dev/sndstat is different from actual device numbering\n"))
561
put_status ("\n\nNOTICE! Device numbers shown above may be wrong.\n");
562
put_status (" Use the ossinfo command to find out the correct device names.\n");
564
sndstat_buf[sndstat_len] = 0;
568
store_msg (char *msg)
572
if (strlen (msg) > 100 || nmessages >= MAX_MESSAGE)
575
s = PMALLOC (NULL, strlen (msg) + 1);
581
messages[nmessages++] = s;
585
read_status (uio_t * buf, int count)
588
* Return at most 'count' bytes from the sndstat_buf.
593
c = sndstat_len - sndstat_ptr;
600
if (uiomove (&sndstat_buf[sndstat_ptr], l, UIO_READ, buf) != 0)
609
sndstat_open (int dev, int dev_class, struct fileinfo *file,
610
int recursive, int open_flags, int *redirect)
612
/* TODO: Concurrency control */
617
if ((sndstat_buf = KERNEL_MALLOC (4096)) == NULL)
632
sndstat_close (int dev, struct fileinfo *file)
634
KERNEL_FREE (sndstat_buf);
641
sndstat_read (int dev, struct fileinfo *file, uio_t * buf, int count)
644
l = read_status (buf, count);
650
sndstat_write (int dev, struct fileinfo *file, uio_t * buf, int count)
653
* This dummy write routine will be used for some internal management purposes
654
* in the future. At this moment it just tells the osscore module that it
655
* should permit detaching itself.
658
extern int oss_detach_enabled;
659
oss_detach_enabled = 1;
668
sndstat_ioctl (int dev, struct fileinfo *bogus,
669
unsigned int cmd, ioctl_arg arg)
671
if (cmd == OSS_GETVERSION)
672
return *arg = OSS_VERSION;
677
static oss_cdev_drv_t sndstat_cdev_drv = {
686
install_sndstat (oss_device_t * osdev)
688
//static int already_installed=0;
690
// if (!already_installed++) // TODO: Is it necessaary to prevent loading sndstat multiple times?
691
oss_install_chrdev (osdev, "sndstat", OSS_DEV_STATUS, 0, &sndstat_cdev_drv,