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;
26
* All kind of status messages
28
#define MAX_MESSAGE 50
29
static char *messages[MAX_MESSAGE];
30
static int nmessages; /* # of display messages (/dev/sndstat) */
33
put_status (const char *s)
37
if (sndstat_len + l >= 4000)
40
memcpy (&sndstat_buf[sndstat_len], s, l);
47
put_status_int (unsigned int val, int radix)
49
char buf[11], *rx = "%d";
52
return put_status ("0");
56
sprintf (buf, rx, val);
58
return put_status (buf);
65
* Write the status information to the sndstat_buf and update sndstat_len.
66
* There is a limit of 4000 bytes for the data.
69
int i, p, missing_devs = 0;
71
extern char *oss_license_string;
75
put_status ("OSS " OSS_VERSION_STRING);
76
put_status (oss_license_string);
77
put_status (" (C) 4Front Technologies 1996-2012\n");
79
#ifdef LICENSED_VERSION
80
oss_print_license (put_status, put_status_int);
83
#ifdef OSS_CONFIG_OPTIONS
84
put_status ("\nSource configration options: ");
85
put_status (OSS_CONFIG_OPTIONS);
90
put_status ("\nHg revision: ");
91
put_status (OSS_HG_INFO);
99
for (i = 0; i < nmessages; i++)
101
if (!put_status (messages[i]))
108
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
110
#if defined(__FreeBSD__)
111
extern char version[];
114
put_status ("Kernel: ");
115
put_status (version);
122
* This code is obsolete and not functional at this moment.
124
if (!put_status ("\nDevice objects:\n"))
127
for (i = 0; i < oss_num_cards; i++)
131
oss_get_cardinfo (i, tmp, sizeof (tmp) - 1);
132
if (!put_status (tmp))
134
if (!put_status ("\n"))
140
if (!put_status ("\nAudio devices:\n"))
145
if (audio_devfiles != NULL)
146
for (i = 0; i < MAX_AUDIO_DEVFILES +100 && missing_devs < 40; i++)
150
if (i < num_audio_devfiles)
151
if (audio_devfiles[i]->card_number != cardno)
154
cardno = audio_devfiles[i]->card_number;
158
* New device numbering scheme may have /dev/dsp# devices in different
159
* order than the order of devices in audio_devices[]. Find the right device
160
* based on the adev->real_dev number. Note that device numbering may have
161
* holes if devices have been removed after running ossdevlinks -f last time.
164
for (j = 0; j < num_audio_devfiles; j++)
166
if (audio_devfiles[j]->real_dev == i)
170
d = audio_devfiles[j]->audio_devfile;
181
if (missing_devs > 0) /* There is a hole in numbering */
182
for (j = i - missing_devs; j < i; j++)
185
if (!put_status_int (j, 10))
187
if (!put_status (": (Undefined or removed device)\n"))
192
if (!put_status_int (i, 10))
194
if (!put_status (": "))
196
if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
199
if (!put_status (audio_devfiles[d]->name))
201
if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
204
if ((audio_devfiles[d]->flags & ADEV_DUPLEX)
205
|| (audio_devfiles[d]->flags & ADEV_NOINPUT)
206
|| (audio_devfiles[d]->flags & ADEV_NOOUTPUT))
210
if (!put_status (" ("))
213
if (audio_devfiles[d]->flags & ADEV_NOINPUT)
217
if (!put_status ("OUTPUT"))
221
if (audio_devfiles[d]->flags & ADEV_NOOUTPUT)
225
if (!put_status ("INPUT"))
229
if (audio_devfiles[d]->flags & ADEV_DUPLEX)
233
if (!put_status ("DUPLEX"))
236
if (!put_status (")"))
240
if (!put_status ("\n"))
244
adev_t *adev = audio_devfiles[d];
245
int n = 0, single = 0;
246
if (adev->next_out == NULL)
251
if (adev->open_mode != 0)
255
if (!put_status (" "))
260
if (!put_status (" "))
266
put_status ("Opened ");
267
if (adev->open_mode & OPEN_READ)
269
if (adev->open_mode & OPEN_WRITE)
275
put_status ("Engine ");
276
put_status_int (n + 1, 10);
277
put_status (" opened ");
278
if (adev->open_mode & OPEN_READ)
280
if (adev->open_mode & OPEN_WRITE)
285
if (adev->pid != -1 || *adev->label != 0)
287
if (*adev->label != 0)
289
if (!put_status (adev->label))
291
if (!put_status ("/"))
295
put_status_int (adev->pid, 10);
299
if (!put_status ("unknown application"))
303
if (!put_status (" @ "))
305
if (!put_status_int (adev->user_parms.rate, 10))
307
if (!put_status ("/"))
309
if (!put_status_int (adev->hw_parms.rate, 10))
311
if (!put_status (" Hz"))
315
if (!put_status (" Fragment: "))
318
if (!put_status (audio_show_latency (adev->engine_num)))
322
if (!put_status ("\n"))
325
if (*adev->song_name != 0)
329
if (!put_status (" "))
334
if (!put_status (" "))
338
if (!put_status ("Song name: "))
340
if (!put_status (adev->song_name))
342
if (!put_status ("\n"))
347
adev = adev->next_out;
353
#ifdef CONFIG_OSS_MIDI
354
if (!put_status ("\nMIDI devices:\n"))
358
for (i = 0; i < MAX_MIDI_DEV * 2 && missing_devs < 16; i++)
362
for (j = 0; j < num_mididevs; j++)
363
if (midi_devs[j]->real_dev == i)
376
for (j = i - missing_devs; j < i; j++)
379
if (!put_status_int (j, 10))
381
if (!put_status (": (Unknown or removed device)\n"))
386
if (!put_status_int (i, 10))
388
if (!put_status (": "))
390
if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
392
if (!put_status (midi_devs[d]->name))
394
if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
396
if (!put_status ("\n"))
399
if (midi_devs[d]->pid != -1)
403
if (!put_status (" "))
408
if (!put_status (" "))
411
if (!put_status ("Open by "))
413
if (!put_status_int (midi_devs[d]->pid, 10))
415
if (*midi_devs[d]->cmd != 0)
417
if (!put_status ("/"))
419
if (!put_status (midi_devs[d]->cmd))
422
if (!put_status ("\n"))
424
if (midi_devs[d]->d->ioctl)
426
oss_longname_t song_name;
428
if (midi_devs[d]->d->ioctl (d, SNDCTL_GETSONG,
429
(ioctl_arg) song_name) >= 0
432
if (!put_status (" Song name: "))
434
if (!put_status (song_name))
436
if (!put_status ("\n"))
445
/* TODO: No timer available at this moment */
446
if (!put_status ("\nTimers:\n"))
449
for (i = 0; i < oss_num_timers; i++)
451
if (!put_status_int (i, 10))
453
if (!put_status (": "))
455
if (!put_status (oss_timer_devs[i]->info.name))
457
if (!put_status ("\n"))
462
if (!put_status ("\nMixers:\n"))
467
for (i = 0; i < MAX_MIXER_DEV * 2 && missing_devs < 10; i++)
471
for (j = 0; j < num_mixers; j++)
472
if (mixer_devs[j]->real_dev == i)
485
for (j = i - missing_devs; j < i; j++)
488
if (!put_status_int (j, 10))
490
if (!put_status (": (Uninstalled or removed device\n"))
495
if (!put_status_int (i, 10))
497
if (!put_status (": "))
500
if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
501
if (!put_status ("("))
504
if (!put_status (mixer_devs[d]->name))
507
if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
508
if (!put_status (")"))
511
if (!put_status ("\n"))
517
for (i = 0; i < OSS_HISTORY_SIZE; i++)
518
if (*oss_history[i] != 0)
522
#ifdef GET_PROCESS_UID
523
if (GET_PROCESS_UID () == 0)
526
if (!put_status ("\nHistory:\n"))
531
for (i = 0; i < OSS_HISTORY_SIZE; i++)
533
int ix = (p + i) % OSS_HISTORY_SIZE;
535
if (*oss_history[ix] == 0)
538
if (!put_status (oss_history[ix]))
540
if (!put_status ("\n"))
547
("\n\nNOTICE! This /dev/sndstat file is obsolete - use the ossinfo command instead\n"))
553
("\n\nWARNING! Legacy device numbering in /dev/sndstat is different from actual device numbering\n"))
557
put_status ("\n\nNOTICE! Device numbers shown above may be wrong.\n");
558
put_status (" Use the ossinfo command to find out the correct device names.\n");
560
sndstat_buf[sndstat_len] = 0;
564
store_msg (char *msg)
568
if (strlen (msg) > 100 || nmessages >= MAX_MESSAGE)
571
s = PMALLOC (NULL, strlen (msg) + 1);
577
messages[nmessages++] = s;
581
read_status (uio_t * buf, int count)
584
* Return at most 'count' bytes from the sndstat_buf.
589
c = sndstat_len - sndstat_ptr;
596
if (uiomove (&sndstat_buf[sndstat_ptr], l, UIO_READ, buf) != 0)
605
sndstat_open (int dev, int dev_class, struct fileinfo *file,
606
int recursive, int open_flags, int *redirect)
608
/* TODO: Concurrency control */
613
if ((sndstat_buf = KERNEL_MALLOC (4096)) == NULL)
628
sndstat_close (int dev, struct fileinfo *file)
630
KERNEL_FREE (sndstat_buf);
637
sndstat_read (int dev, struct fileinfo *file, uio_t * buf, int count)
640
l = read_status (buf, count);
646
sndstat_write (int dev, struct fileinfo *file, uio_t * buf, int count)
649
* This dummy write routine will be used for some internal management purposes
650
* in the future. At this moment it just tells the osscore module that it
651
* should permit detaching itself.
654
extern int oss_detach_enabled;
655
oss_detach_enabled = 1;
664
sndstat_ioctl (int dev, struct fileinfo *bogus,
665
unsigned int cmd, ioctl_arg arg)
667
if (cmd == OSS_GETVERSION)
668
return *arg = OSS_VERSION;
673
static oss_cdev_drv_t sndstat_cdev_drv = {
682
install_sndstat (oss_device_t * osdev)
684
//static int already_installed=0;
686
// if (!already_installed++) // TODO: Is it necessaary to prevent loading sndstat multiple times?
687
oss_install_chrdev (osdev, "sndstat", OSS_DEV_STATUS, 0, &sndstat_cdev_drv,