~ubuntu-branches/ubuntu/trusty/oss4/trusty-proposed

« back to all changes in this revision

Viewing changes to kernel/framework/sndstat/oss_sndstat.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis, Samuel Thibault, Romain Beauxis, Sebastien NOEL
  • Date: 2011-06-14 10:06:56 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110614100656-cx4oc7u426zn812z
Tags: 4.2-build2004-1
[ Samuel Thibault ]
* debian/control: Add liboss4-salsa2, liboss4-salsa-dev and
  liboss4-salsa-asound2 packages, equivalent to (and will replace) those from
  the oss-libsalsa package (Closes: #589127).
* debian/patches/liboss4-salsa.patch: New patch to rename libsalsa into
  liboss4-salsa to avoid conflicts in the archive for no good reason.
* debian/rules: Make in libOSSlib and libsalsa.
* debian/liboss4-salsa-dev.install, debian/liboss4-salsa2.install,
  debian/liboss4-salsa-asound2.links, debian/liboss4-salsa-dev.links:
  Install liboss4-salsa libraries like was done in the oss-libsalsa package.
* include-alsa: Add a copy of ALSA 1.0.5 headers: Cf ALSA_1.0.* symbols in
  libsalsa, this is the roughly supported version.
* debian/copyright: Update for new include-alsa files.
* alsa.pc: New file for compatibility with libasound-dev.
* debian/control:
  - Add Vcs-Browser and Vcs-Svn fields.
  - Use linux-any instead of the list of Linux archs (Closes: #604679).
  - Make dkms dependency linux-any only.
* debian/patches/hurd_iot.patch: New patch to fix soundcard.h usage in
  libsalsa on hurd-i386.
* debian/patches/libsalsa_fixes.patch: New patch to fix some printf usages
  and ioctl declaration in libsalsa.
* debian/patches/no_EBADE.patch: New patch to cope with hurd-i386 not having
  EBADE.
* debian/patches/CFLAGS.patch: New patch to make oss4 take debian/rules
  CFLAGS into account.
* debian/patches/snd_asoundlib_version.patch: New patch to add
  snd_asoundlib_version().
* debian/patches/generic_srccconf.patch: New patch to fix source
  configuration on unknown archs.

[ Romain Beauxis ]
* Fixed README.Debian to only mention dkms' modules.
* Switch to dpkg-source 3.0 (quilt) format
* Added DM-Upload-Allowed: yes

[ Sebastien NOEL ]
* New upstream release (Closes: #595298, #619272).
* Fix typo in initscript (Closes: #627149).
* debian/control: adjust linux-headers dependencies (Closes: #628879).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: /dev/sndstat driver
 
3
 *
 
4
 * Description:
 
5
 */
 
6
/*
 
7
 *
 
8
 * This file is part of Open Sound System.
 
9
 *
 
10
 * Copyright (C) 4Front Technologies 1996-2008.
 
11
 *
 
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.
 
15
 *
 
16
 */
 
17
 
 
18
#include <oss_config.h>
 
19
#include <midi_core.h>
 
20
 
 
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 */
 
25
 
 
26
/*
 
27
 * All kind of status messages
 
28
 */
 
29
#define MAX_MESSAGE 50
 
30
static char *messages[MAX_MESSAGE];
 
31
static int nmessages;           /* # of display messages (/dev/sndstat) */
 
32
 
 
33
static int
 
34
put_status (const char *s)
 
35
{
 
36
  int l = strlen (s);
 
37
 
 
38
  if (sndstat_len + l >= 4000)
 
39
    return 0;
 
40
 
 
41
  memcpy (&sndstat_buf[sndstat_len], s, l);
 
42
  sndstat_len += l;
 
43
 
 
44
  return 1;
 
45
}
 
46
 
 
47
static int
 
48
put_status_int (unsigned int val, int radix)
 
49
{
 
50
  char buf[11], *rx = "%d";
 
51
 
 
52
  if (!val)
 
53
    return put_status ("0");
 
54
 
 
55
  if (radix == 16)
 
56
    rx = "%x";
 
57
  sprintf (buf, rx, val);
 
58
 
 
59
  return put_status (buf);
 
60
}
 
61
 
 
62
static void
 
63
init_status (void)
 
64
{
 
65
  /*
 
66
   * Write the status information to the sndstat_buf and update sndstat_len.
 
67
   * There is a limit of 4000 bytes for the data.
 
68
   */
 
69
 
 
70
  int i, p, missing_devs = 0;
 
71
  int notify = 0;
 
72
  extern char *oss_license_string;
 
73
 
 
74
  sndstat_ptr = 0;
 
75
 
 
76
  put_status ("OSS " OSS_VERSION_STRING);
 
77
  put_status (oss_license_string);
 
78
  put_status (" (C) 4Front Technologies 1996-2009\n");
 
79
 
 
80
  if (riptide_notice)
 
81
    put_status ("RipTide Driver (C) 2000, Conexant Systems, Inc.\n");
 
82
 
 
83
#ifdef LICENSED_VERSION
 
84
  oss_print_license (put_status, put_status_int);
 
85
#endif
 
86
 
 
87
#ifdef OSS_CONFIG_OPTIONS
 
88
  put_status ("\nSource configration options: ");
 
89
  put_status (OSS_CONFIG_OPTIONS);
 
90
  put_status ("\n");
 
91
#endif
 
92
 
 
93
#ifdef OSS_HG_INFO
 
94
  put_status ("\nHg revision: ");
 
95
  put_status (OSS_HG_INFO);
 
96
  put_status ("\n");
 
97
#endif
 
98
 
 
99
  if (nmessages > 0)
 
100
    {
 
101
      put_status ("\n");
 
102
 
 
103
      for (i = 0; i < nmessages; i++)
 
104
        {
 
105
          if (!put_status (messages[i]))
 
106
            return;
 
107
        }
 
108
 
 
109
      put_status ("\n");
 
110
    }
 
111
 
 
112
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 
113
  {
 
114
#if defined(__FreeBSD__)
 
115
    extern char version[];
 
116
#endif
 
117
 
 
118
    put_status ("Kernel: ");
 
119
    put_status (version);
 
120
    put_status ("\n");
 
121
  }
 
122
#endif
 
123
 
 
124
#if 0
 
125
/*
 
126
 * This code is obsolete and not functional at this moment.
 
127
 */
 
128
  if (!put_status ("\nDevice objects:\n"))
 
129
    return;
 
130
 
 
131
  for (i = 0; i < oss_num_cards; i++)
 
132
    {
 
133
      char tmp[256];
 
134
 
 
135
      oss_get_cardinfo (i, tmp, sizeof (tmp) - 1);
 
136
      if (!put_status (tmp))
 
137
        return;
 
138
      if (!put_status ("\n"))
 
139
        return;
 
140
    }
 
141
 
 
142
#endif
 
143
 
 
144
  if (!put_status ("\nAudio devices:\n"))
 
145
    return;
 
146
 
 
147
  missing_devs = 0;
 
148
 
 
149
  if (audio_devfiles != NULL)
 
150
    for (i = 0; i < MAX_AUDIO_DEVFILES +100 && missing_devs < 40; i++)
 
151
      {
 
152
        int j, d;
 
153
#if 0
 
154
        if (i < num_audio_devfiles)
 
155
        if (audio_devfiles[i]->card_number != cardno)
 
156
          {
 
157
            put_status (" \n");
 
158
            cardno = audio_devfiles[i]->card_number;
 
159
          }
 
160
#endif
 
161
/*
 
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.
 
166
 */
 
167
        d = -1;
 
168
        for (j = 0; j < num_audio_devfiles; j++)
 
169
          {
 
170
            if (audio_devfiles[j]->real_dev == i)
 
171
              {
 
172
                if (j != i)
 
173
                  notify = 1;
 
174
                d = audio_devfiles[j]->audio_devfile;
 
175
                break;
 
176
              }
 
177
          }
 
178
 
 
179
        if (d == -1)
 
180
          {
 
181
            missing_devs++;
 
182
            continue;
 
183
          }
 
184
 
 
185
        if (missing_devs > 0)   /* There is a hole in numbering */
 
186
          for (j = i - missing_devs; j < i; j++)
 
187
            {
 
188
              notify = 1;
 
189
              if (!put_status_int (j, 10))
 
190
                return;
 
191
              if (!put_status (": (Undefined or removed device)\n"))
 
192
                return;
 
193
            }
 
194
        missing_devs = 0;
 
195
 
 
196
        if (!put_status_int (i, 10))
 
197
          return;
 
198
        if (!put_status (": "))
 
199
          return;
 
200
        if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
 
201
          put_status ("(");
 
202
 
 
203
        if (!put_status (audio_devfiles[d]->name))
 
204
          return;
 
205
        if (!audio_devfiles[d]->enabled || audio_devfiles[d]->unloaded)
 
206
          put_status (")");
 
207
 
 
208
        if ((audio_devfiles[d]->flags & ADEV_DUPLEX)
 
209
            || (audio_devfiles[d]->flags & ADEV_NOINPUT)
 
210
            || (audio_devfiles[d]->flags & ADEV_NOOUTPUT))
 
211
          {
 
212
            int nn = 0;
 
213
 
 
214
            if (!put_status (" ("))
 
215
              return;
 
216
 
 
217
            if (audio_devfiles[d]->flags & ADEV_NOINPUT)
 
218
              {
 
219
                if (nn++)
 
220
                  put_status (",");
 
221
                if (!put_status ("OUTPUT"))
 
222
                  return;
 
223
              }
 
224
 
 
225
            if (audio_devfiles[d]->flags & ADEV_NOOUTPUT)
 
226
              {
 
227
                if (nn++)
 
228
                  put_status (",");
 
229
                if (!put_status ("INPUT"))
 
230
                  return;
 
231
              }
 
232
 
 
233
            if (audio_devfiles[d]->flags & ADEV_DUPLEX)
 
234
              {
 
235
                if (nn++)
 
236
                  put_status (",");
 
237
                if (!put_status ("DUPLEX"))
 
238
                  return;
 
239
              }
 
240
            if (!put_status (")"))
 
241
              return;
 
242
          }
 
243
 
 
244
        if (!put_status ("\n"))
 
245
          return;
 
246
 
 
247
        {
 
248
          adev_t *adev = audio_devfiles[d];
 
249
          int n = 0, single = 0;
 
250
          if (adev->next_out == NULL)
 
251
            single = 1;
 
252
 
 
253
          while (adev != NULL)
 
254
            {
 
255
              if (adev->open_mode != 0)
 
256
                {
 
257
                  if (i < 10)
 
258
                    {
 
259
                      if (!put_status ("   "))
 
260
                        return;
 
261
                    }
 
262
                  else
 
263
                    {
 
264
                      if (!put_status ("    "))
 
265
                        return;
 
266
                    }
 
267
 
 
268
                  if (single)
 
269
                    {
 
270
                      put_status ("Opened ");
 
271
                      if (adev->open_mode & OPEN_READ)
 
272
                        put_status ("IN");
 
273
                      if (adev->open_mode & OPEN_WRITE)
 
274
                        put_status ("OUT");
 
275
                      put_status (" by ");
 
276
                    }
 
277
                  else
 
278
                    {
 
279
                      put_status ("Engine ");
 
280
                      put_status_int (n + 1, 10);
 
281
                      put_status (" opened ");
 
282
                      if (adev->open_mode & OPEN_READ)
 
283
                        put_status ("IN");
 
284
                      if (adev->open_mode & OPEN_WRITE)
 
285
                        put_status ("OUT");
 
286
                      put_status (" by ");
 
287
                    }
 
288
 
 
289
                  if (adev->pid != -1 || *adev->label != 0)
 
290
                    {
 
291
                      if (*adev->label != 0)
 
292
                        {
 
293
                          if (!put_status (adev->label))
 
294
                            return;
 
295
                          if (!put_status ("/"))
 
296
                            return;
 
297
                        }
 
298
 
 
299
                      put_status_int (adev->pid, 10);
 
300
                    }
 
301
                  else
 
302
                    {
 
303
                      if (!put_status ("unknown application"))
 
304
                        return;
 
305
                    }
 
306
 
 
307
                  if (!put_status (" @ "))
 
308
                    return;
 
309
                  if (!put_status_int (adev->user_parms.rate, 10))
 
310
                    return;
 
311
                  if (!put_status ("/"))
 
312
                    return;
 
313
                  if (!put_status_int (adev->hw_parms.rate, 10))
 
314
                    return;
 
315
                  if (!put_status (" Hz"))
 
316
                    return;
 
317
 
 
318
#if 1
 
319
                  if (!put_status (" Fragment: "))
 
320
                    return;
 
321
 
 
322
                  if (!put_status (audio_show_latency (adev->engine_num)))
 
323
                    return;
 
324
#endif
 
325
 
 
326
                  if (!put_status ("\n"))
 
327
                    return;
 
328
 
 
329
                  if (*adev->song_name != 0)
 
330
                    {
 
331
                      if (i < 10)
 
332
                        {
 
333
                          if (!put_status ("   "))
 
334
                            return;
 
335
                        }
 
336
                      else
 
337
                        {
 
338
                          if (!put_status ("    "))
 
339
                            return;
 
340
                        }
 
341
 
 
342
                      if (!put_status ("Song name: "))
 
343
                        return;
 
344
                      if (!put_status (adev->song_name))
 
345
                        return;
 
346
                      if (!put_status ("\n"))
 
347
                        return;
 
348
                    }
 
349
                }
 
350
 
 
351
              adev = adev->next_out;
 
352
              n++;
 
353
            }
 
354
        }
 
355
      }
 
356
 
 
357
#ifdef CONFIG_OSS_MIDI
 
358
  if (!put_status ("\nMIDI devices:\n"))
 
359
    return;
 
360
 
 
361
  missing_devs = 0;
 
362
  for (i = 0; i < MAX_MIDI_DEV * 2 && missing_devs < 16; i++)
 
363
    {
 
364
      int j, d = -1;
 
365
 
 
366
      for (j = 0; j < num_mididevs; j++)
 
367
        if (midi_devs[j]->real_dev == i)
 
368
          {
 
369
            d = j;
 
370
            if (j != i)
 
371
              notify = 1;
 
372
          }
 
373
 
 
374
      if (d == -1)
 
375
        {
 
376
          missing_devs++;
 
377
          continue;
 
378
        }
 
379
 
 
380
      for (j = i - missing_devs; j < i; j++)
 
381
        {
 
382
          notify = 1;
 
383
          if (!put_status_int (j, 10))
 
384
            return;
 
385
          if (!put_status (": (Unknown or removed device)\n"))
 
386
            return;
 
387
        }
 
388
      missing_devs = 0;
 
389
 
 
390
      if (!put_status_int (i, 10))
 
391
        return;
 
392
      if (!put_status (": "))
 
393
        return;
 
394
      if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
 
395
        put_status ("(");
 
396
      if (!put_status (midi_devs[d]->name))
 
397
        return;
 
398
      if (!midi_devs[d]->enabled || midi_devs[d]->unloaded)
 
399
        put_status (")");
 
400
      if (!put_status ("\n"))
 
401
        return;
 
402
 
 
403
      if (midi_devs[d]->pid != -1)
 
404
        {
 
405
          if (i < 10)
 
406
            {
 
407
              if (!put_status ("   "))
 
408
                return;
 
409
            }
 
410
          else
 
411
            {
 
412
              if (!put_status ("    "))
 
413
                return;
 
414
            }
 
415
          if (!put_status ("Open by "))
 
416
            return;
 
417
          if (!put_status_int (midi_devs[d]->pid, 10))
 
418
            return;
 
419
          if (*midi_devs[d]->cmd != 0)
 
420
            {
 
421
              if (!put_status ("/"))
 
422
                return;
 
423
              if (!put_status (midi_devs[d]->cmd))
 
424
                return;
 
425
            }
 
426
          if (!put_status ("\n"))
 
427
            return;
 
428
          if (midi_devs[d]->d->ioctl)
 
429
            {
 
430
              oss_longname_t song_name;
 
431
 
 
432
              if (midi_devs[d]->d->ioctl (d, SNDCTL_GETSONG,
 
433
                                          (ioctl_arg) song_name) >= 0
 
434
                  && *song_name != 0)
 
435
                {
 
436
                  if (!put_status ("   Song name: "))
 
437
                    return;
 
438
                  if (!put_status (song_name))
 
439
                    return;
 
440
                  if (!put_status ("\n"))
 
441
                    return;
 
442
                }
 
443
            }
 
444
        }
 
445
    }
 
446
#endif
 
447
 
 
448
#if 0
 
449
  /* TODO: No timer available at this moment */
 
450
  if (!put_status ("\nTimers:\n"))
 
451
    return;
 
452
 
 
453
  for (i = 0; i < oss_num_timers; i++)
 
454
    {
 
455
      if (!put_status_int (i, 10))
 
456
        return;
 
457
      if (!put_status (": "))
 
458
        return;
 
459
      if (!put_status (oss_timer_devs[i]->info.name))
 
460
        return;
 
461
      if (!put_status ("\n"))
 
462
        return;
 
463
    }
 
464
#endif
 
465
 
 
466
  if (!put_status ("\nMixers:\n"))
 
467
    return;
 
468
 
 
469
  missing_devs = 0;
 
470
 
 
471
  for (i = 0; i < MAX_MIXER_DEV * 2 && missing_devs < 10; i++)
 
472
    {
 
473
      int j, d = -1;
 
474
 
 
475
      for (j = 0; j < num_mixers; j++)
 
476
        if (mixer_devs[j]->real_dev == i)
 
477
          {
 
478
            if (j != i)
 
479
              notify = 1;
 
480
            d = j;
 
481
          }
 
482
 
 
483
      if (d == -1)
 
484
        {
 
485
          missing_devs++;
 
486
          continue;
 
487
        }
 
488
 
 
489
      for (j = i - missing_devs; j < i; j++)
 
490
        {
 
491
          notify = 1;
 
492
          if (!put_status_int (j, 10))
 
493
            return;
 
494
          if (!put_status (": (Uninstalled or removed device\n"))
 
495
            return;
 
496
        }
 
497
      missing_devs = 0;
 
498
 
 
499
      if (!put_status_int (i, 10))
 
500
        return;
 
501
      if (!put_status (": "))
 
502
        return;
 
503
 
 
504
      if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
 
505
        if (!put_status ("("))
 
506
          return;
 
507
 
 
508
      if (!put_status (mixer_devs[d]->name))
 
509
        return;
 
510
 
 
511
      if (!mixer_devs[d]->enabled || mixer_devs[d]->unloaded)
 
512
        if (!put_status (")"))
 
513
          return;
 
514
 
 
515
      if (!put_status ("\n"))
 
516
        return;
 
517
    }
 
518
 
 
519
#if 1
 
520
  p = 0;
 
521
  for (i = 0; i < OSS_HISTORY_SIZE; i++)
 
522
    if (*oss_history[i] != 0)
 
523
      p++;
 
524
 
 
525
  if (p > 0)
 
526
#ifdef GET_PROCESS_UID
 
527
    if (GET_PROCESS_UID () == 0)
 
528
#endif
 
529
      {
 
530
        if (!put_status ("\nHistory:\n"))
 
531
          return;
 
532
 
 
533
        p = oss_history_p;
 
534
 
 
535
        for (i = 0; i < OSS_HISTORY_SIZE; i++)
 
536
          {
 
537
            int ix = (p + i) % OSS_HISTORY_SIZE;
 
538
 
 
539
            if (*oss_history[ix] == 0)
 
540
              continue;
 
541
 
 
542
            if (!put_status (oss_history[ix]))
 
543
              return;
 
544
            if (!put_status ("\n"))
 
545
              return;
 
546
          }
 
547
      }
 
548
#endif
 
549
#if 0
 
550
  if (!put_status
 
551
      ("\n\nNOTICE! This /dev/sndstat file is obsolete - use the ossinfo command instead\n"))
 
552
    return;
 
553
#endif
 
554
  if (notify)
 
555
    {
 
556
      if (!put_status
 
557
          ("\n\nWARNING! Legacy device numbering in /dev/sndstat is different from actual device numbering\n"))
 
558
        return;
 
559
    }
 
560
 
 
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");
 
563
 
 
564
  sndstat_buf[sndstat_len] = 0;
 
565
}
 
566
 
 
567
void
 
568
store_msg (char *msg)
 
569
{
 
570
  char *s;
 
571
 
 
572
  if (strlen (msg) > 100 || nmessages >= MAX_MESSAGE)
 
573
    return;
 
574
 
 
575
  s = PMALLOC (NULL, strlen (msg) + 1);
 
576
  if (s == NULL)
 
577
    {
 
578
      return;
 
579
    }
 
580
  strcpy (s, msg);
 
581
  messages[nmessages++] = s;
 
582
}
 
583
 
 
584
static int
 
585
read_status (uio_t * buf, int count)
 
586
{
 
587
  /*
 
588
   * Return at most 'count' bytes from the sndstat_buf.
 
589
   */
 
590
  int l, c;
 
591
 
 
592
  l = count;
 
593
  c = sndstat_len - sndstat_ptr;
 
594
 
 
595
  if (l > c)
 
596
    l = c;
 
597
  if (l <= 0)
 
598
    return 0;
 
599
 
 
600
  if (uiomove (&sndstat_buf[sndstat_ptr], l, UIO_READ, buf) != 0)
 
601
    return OSS_EFAULT;
 
602
  sndstat_ptr += l;
 
603
 
 
604
  return l;
 
605
}
 
606
 
 
607
/*ARGSUSED*/
 
608
static int
 
609
sndstat_open (int dev, int dev_class, struct fileinfo *file,
 
610
              int recursive, int open_flags, int *redirect)
 
611
{
 
612
  /* TODO: Concurrency control */
 
613
  if (sndstat_busy)
 
614
    return OSS_EBUSY;
 
615
  sndstat_busy = 1;
 
616
 
 
617
  if ((sndstat_buf = KERNEL_MALLOC (4096)) == NULL)
 
618
    {
 
619
      sndstat_busy = 0;
 
620
      return OSS_ENOMEM;
 
621
    }
 
622
 
 
623
  sndstat_len = 0;
 
624
  init_status ();
 
625
  sndstat_ptr = 0;
 
626
 
 
627
  return 0;
 
628
}
 
629
 
 
630
/*ARGSUSED*/
 
631
static void
 
632
sndstat_close (int dev, struct fileinfo *file)
 
633
{
 
634
  KERNEL_FREE (sndstat_buf);
 
635
  sndstat_buf = NULL;
 
636
  sndstat_busy = 0;
 
637
}
 
638
 
 
639
/*ARGSUSED*/
 
640
static int
 
641
sndstat_read (int dev, struct fileinfo *file, uio_t * buf, int count)
 
642
{
 
643
  int l;
 
644
  l = read_status (buf, count);
 
645
  return l;
 
646
}
 
647
 
 
648
/*ARGSUSED*/
 
649
static int
 
650
sndstat_write (int dev, struct fileinfo *file, uio_t * buf, int count)
 
651
{
 
652
/*
 
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.
 
656
 */
 
657
#ifdef sun
 
658
  extern int oss_detach_enabled;
 
659
  oss_detach_enabled = 1;
 
660
  return count;
 
661
#else
 
662
  return OSS_EIO;
 
663
#endif
 
664
}
 
665
 
 
666
/*ARGSUSED*/
 
667
static int
 
668
sndstat_ioctl (int dev, struct fileinfo *bogus,
 
669
               unsigned int cmd, ioctl_arg arg)
 
670
{
 
671
  if (cmd == OSS_GETVERSION)
 
672
    return *arg = OSS_VERSION;
 
673
 
 
674
  return OSS_EINVAL;
 
675
}
 
676
 
 
677
static oss_cdev_drv_t sndstat_cdev_drv = {
 
678
  sndstat_open,
 
679
  sndstat_close,
 
680
  sndstat_read,
 
681
  sndstat_write,
 
682
  sndstat_ioctl
 
683
};
 
684
 
 
685
void
 
686
install_sndstat (oss_device_t * osdev)
 
687
{
 
688
  //static int already_installed=0;
 
689
 
 
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,
 
692
                      0);
 
693
}