~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to cmd/ossdevlinks/ossdevlinks.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: Legacy sound device management utility
 
3
 *
 
4
 * Description:
 
5
 * Device file naming scheme was changed in OSS 4.0. This utility is used
 
6
 * to create old style "legacy" device files such as /dev/dsp0 to the
 
7
 * corresponding new type name (such as /dev/oss/oss_sblive0/pcm0).
 
8
 *
 
9
 * By default the currently existing device links will be preserved. Legacy
 
10
 * devices for newly installed devices will be allocated after the
 
11
 * previously available devices.
 
12
 *
 
13
 * Commad line options:
 
14
 * -f      Write legacydev file to <argument>.
 
15
 * -v      Produce verbose output.
 
16
 * -r      Remove all pre-existing legacy devices and reset the device
 
17
 *         numbering (not recommended).
 
18
 * -N      Don't modify links
 
19
 */
 
20
/*
 
21
 *
 
22
 * This file is part of Open Sound System.
 
23
 *
 
24
 * Copyright (C) 4Front Technologies 1996-2008.
 
25
 *
 
26
 * This this source file is released under GPL v2 license (no other versions).
 
27
 * See the COPYING file included in the main directory of this source
 
28
 * distribution for the license terms and conditions.
 
29
 *
 
30
 */
 
31
 
 
32
#include <stdio.h>
 
33
#include <unistd.h>
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
#include <fcntl.h>
 
37
#include <dirent.h>
 
38
#include <fnmatch.h>
 
39
#include <errno.h>
 
40
#include <sys/types.h>
 
41
#include <sys/stat.h>
 
42
#include <sys/ioctl.h>
 
43
#include "oss_config.h"
 
44
 
 
45
#define MAXDEV  HARD_MAX_AUDIO_DEVFILES
 
46
 
 
47
static oss_sysinfo si;
 
48
#ifdef sun
 
49
  static char * legacydev_file = "/etc/oss/legacy_devices";
 
50
#else
 
51
  static char * legacydev_file = NULL;
 
52
#endif
 
53
static int err = 0, mixerfd = -1, recreate_all = 0, verbose = 0,
 
54
           no_links = 0;
 
55
 
 
56
static void create_dsplinks (void);
 
57
static void create_mixerlinks (void);
 
58
static int find_dsplink (oss_audioinfo *);
 
59
static int find_mixerlink (oss_mixerinfo *);
 
60
static void save_link (FILE *, char *);
 
61
static void save_links (void);
 
62
static int remove_nodes (const char *, const char *);
 
63
#ifdef CONFIG_OSS_MIDI
 
64
static void create_midilinks (void);
 
65
static int find_midilink (oss_midi_info *);
 
66
#endif
 
67
 
 
68
#if PATH_MAX == -1
 
69
#undef PATH_MAX
 
70
#endif 
 
71
#ifndef PATH_MAX
 
72
#define PATH_MAX 1024 
 
73
#endif
 
74
 
 
75
#if defined(sun)
 
76
#define DEFAULT_OSSLIBDIR "/etc/oss"
 
77
#else
 
78
#define DEFAULT_OSSLIBDIR "/var/lib/oss4"
 
79
#endif
 
80
 
 
81
static char *
 
82
get_mapname (void)
 
83
{
 
84
  FILE *f;
 
85
#define OSSLIBDIRLEN PATH_MAX
 
86
  char tmp[OSSLIBDIRLEN+11];
 
87
  static char name[OSSLIBDIRLEN];
 
88
  struct stat st;
 
89
 
 
90
  if ((f = fopen ("/etc/oss.conf", "r")) == NULL)
 
91
    {
 
92
      // perror ("/etc/oss.conf");
 
93
      goto oexit;
 
94
    }
 
95
 
 
96
  while (fgets (tmp, sizeof (tmp), f) != NULL)
 
97
    {
 
98
      int l = strlen (tmp);
 
99
      if (l > 0 && tmp[l - 1] == '\n')
 
100
        tmp[l - 1] = '\0';
 
101
 
 
102
      if (strncmp (tmp, "OSSVARDIR=", 10) == 0)
 
103
        {
 
104
          l = snprintf (name, sizeof (name), "%s", &tmp[10]);
 
105
          if ((l >= OSSLIBDIRLEN) || (l < 0))
 
106
            {
 
107
              fprintf (stderr, "String in /etc/oss.conf is too long!\n");
 
108
              goto oexit;
 
109
            }
 
110
          if ((stat (name, &st) == -1) || !S_ISDIR(st.st_mode))
 
111
            {
 
112
              fprintf (stderr, "Directory %s from /etc/oss.conf cannot "
 
113
                               "be used!\n", name);
 
114
              goto oexit;
 
115
            }
 
116
          fclose (f);
 
117
          return name;
 
118
        }
 
119
    }
 
120
 
 
121
oexit:
 
122
  fclose (f);
 
123
  snprintf (name, sizeof (name), DEFAULT_OSSLIBDIR);
 
124
  return name;
 
125
}
 
126
 
 
127
static int
 
128
remove_nodes (const char * dirname, const char * pattern)
 
129
{
 
130
  char path[PATH_MAX];
 
131
  DIR * dr;
 
132
  struct dirent * de;
 
133
  struct stat st;
 
134
 
 
135
  if ((dr = opendir (dirname)) == NULL)
 
136
    {
 
137
      if (errno == ENOENT) return 0;
 
138
      fprintf (stderr, "Cannot open %s\n", dirname);
 
139
      perror ("opendir");
 
140
      return -1;
 
141
    }
 
142
 
 
143
  while ((de = readdir (dr)) != NULL)
 
144
    {
 
145
      if (fnmatch (pattern, de->d_name, FNM_PATHNAME | FNM_PERIOD)) continue;
 
146
 
 
147
      snprintf (path, sizeof (path), "%s/%s", dirname, de->d_name);
 
148
 
 
149
      /* We want to remove dangling symlinks too, so no error check here */
 
150
      if ((stat (path, &st) != -1) &&
 
151
      /* No nodes that ossdevlinks may need to remove are directories */
 
152
          (S_ISDIR (st.st_mode))) continue;
 
153
      if (verbose > 2) fprintf (stderr, "Removing %s\n", path);
 
154
      if ((unlink (path) == -1) && (errno != ENOENT))
 
155
        fprintf (stderr, "unlink %s: %s\n", path, strerror(errno));
 
156
    }
 
157
 
 
158
  closedir (dr);
 
159
  return 0;
 
160
}
 
161
 
 
162
/*
 
163
 *****************************
 
164
 * /dev/dsp handling
 
165
 */
 
166
 
 
167
static int
 
168
find_dsplink (oss_audioinfo * ai)
 
169
{
 
170
  int dev;
 
171
/*
 
172
 * Look for a legacy (/dev/dsp#) devife file that is a symlink to
 
173
 * ai->devnode. Return the device number if a
 
174
 * matching link is found. Return -1 if nothing is found.
 
175
 */
 
176
 
 
177
  struct stat st;
 
178
  char devname[64], linkdev[256];
 
179
 
 
180
  for (dev = 0; dev < MAXDEV; dev++)
 
181
    {
 
182
      sprintf (devname, "/dev/dsp%d", dev);
 
183
      if (lstat (devname, &st) != -1)
 
184
        if (S_ISLNK (st.st_mode))
 
185
          {
 
186
            int l;
 
187
 
 
188
            if ((l = readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
189
              {
 
190
                continue;
 
191
              }
 
192
            else
 
193
              {
 
194
                linkdev[l] = 0;
 
195
                if (strcmp (linkdev, ai->devnode) == 0) /* Match */
 
196
                  {
 
197
                    ai->legacy_device = dev;
 
198
                    return dev;
 
199
                  }
 
200
              }
 
201
          }
 
202
    }
 
203
 
 
204
  return -1;                    /* Nothing found */
 
205
}
 
206
 
 
207
static void
 
208
create_dsplinks (void)
 
209
{
 
210
  int dev, newdev, numfiles = 0, legacy_number = 0;
 
211
  struct stat st;
 
212
  char devname[64];
 
213
 
 
214
  oss_audioinfo *ai, *audiodevs[MAXDEV];
 
215
 
 
216
  oss_renumber_t renum = { 0 };
 
217
 
 
218
  if (recreate_all)
 
219
    {
 
220
      if ((unlink ("/dev/dsp") == -1) && (errno != ENOENT))
 
221
        fprintf (stderr, "Couldn't remove /dev/dsp link!\n");
 
222
      remove_nodes ("/dev", "dsp[0-9]*");
 
223
      remove_nodes ("/dev", "dsp_*");
 
224
    }
 
225
 
 
226
  if (verbose) printf ("%d audio devices\n", si.numaudios);
 
227
 
 
228
  if (si.numaudios < 1)
 
229
    return;
 
230
 
 
231
  for (dev = 0; dev < si.numaudios; dev++)
 
232
    {
 
233
      ai = malloc (sizeof (*ai));
 
234
 
 
235
      ai->dev = dev;
 
236
 
 
237
      if (ioctl (mixerfd, SNDCTL_AUDIOINFO, ai) == -1)
 
238
        {
 
239
          perror ("SNDCTL_AUDIOINFO");
 
240
          exit (-1);
 
241
        }
 
242
 
 
243
      audiodevs[dev] = ai;
 
244
 
 
245
      /* if (verbose) printf ("Adev %d = %s\n", dev, ai->devnode); */
 
246
    }
 
247
 
 
248
  for (dev = 0; dev < MAXDEV; dev++)
 
249
    {
 
250
 
 
251
      sprintf (devname, "/dev/dsp%d", dev);
 
252
      newdev = dev;
 
253
 
 
254
      if (lstat (devname, &st) != -1)
 
255
        {
 
256
          if (S_ISLNK (st.st_mode))
 
257
            numfiles = dev + 1;
 
258
        }
 
259
    }
 
260
 
 
261
  if (verbose) printf ("/dev/dsp%d is the next free legacy device\n", numfiles);
 
262
 
 
263
  for (dev = 0; dev < si.numaudios; dev++)
 
264
    {
 
265
      int recreate = 0;
 
266
#ifdef VDEV_SUPPORT
 
267
      if (audiodevs[dev]->caps & PCM_CAP_HIDDEN)        /* Ignore hidden devices */
 
268
        {
 
269
          audiodevs[dev]->legacy_device = -1;
 
270
          continue;
 
271
        }
 
272
#endif
 
273
 
 
274
      newdev = legacy_number++;
 
275
      sprintf (devname, "/dev/dsp%d", newdev);
 
276
 
 
277
      if (lstat (devname, &st) == -1)
 
278
        {
 
279
          if (verbose) printf ("%s: %s\n", devname, strerror (errno));
 
280
          recreate = 1;
 
281
        }
 
282
      else
 
283
        {
 
284
          if (S_ISCHR (st.st_mode))
 
285
            {
 
286
              if (verbose) printf ("%s: character device\n", devname);
 
287
              recreate = 1;
 
288
            }
 
289
          else if (S_ISLNK (st.st_mode))
 
290
            {
 
291
              int l;
 
292
 
 
293
              char linkdev[256];
 
294
              if ((l =
 
295
                   readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
296
                {
 
297
                  perror ("readlink");
 
298
                  strcpy (linkdev, "Invalid");
 
299
                }
 
300
              else
 
301
                {
 
302
                  linkdev[l] = 0;
 
303
                }
 
304
 
 
305
              if (verbose) printf ("%s: symlink -> %s ", devname, linkdev);
 
306
 
 
307
              if (strcmp (linkdev, audiodevs[dev]->devnode) != 0)
 
308
                {
 
309
                  if (verbose) printf ("(should be %s)\n",
 
310
                                       audiodevs[dev]->devnode);
 
311
                  if ((newdev = find_dsplink (audiodevs[dev])) == -1)
 
312
                    {
 
313
                      recreate = 1;
 
314
                      newdev = numfiles++;
 
315
                    }
 
316
                  else
 
317
                    if (verbose) printf ("\tAlready linked to /dev/dsp%d\n",
 
318
                                         newdev);
 
319
                }
 
320
              else
 
321
                if (verbose) printf ("OK\n");
 
322
            }
 
323
          else
 
324
            {
 
325
              if (verbose) printf ("%s: unknown file type\n", devname);
 
326
              recreate = 1;
 
327
            }
 
328
 
 
329
        }
 
330
 
 
331
      if (recreate)
 
332
        {
 
333
          audiodevs[dev]->legacy_device = newdev;
 
334
          sprintf (devname, "/dev/dsp%d", newdev);
 
335
 
 
336
          if (strcmp (audiodevs[dev]->devnode, devname) != 0)   /* Not the same */
 
337
            {
 
338
              unlink (devname);
 
339
              if (symlink (audiodevs[dev]->devnode, devname) == -1)
 
340
                {
 
341
                  perror ("symlink");
 
342
                  fprintf (stderr, "Cannot create link %s->%s\n", devname,
 
343
                           audiodevs[dev]->devnode);
 
344
                  exit (-1);
 
345
                }
 
346
 
 
347
              if (verbose) printf ("Created new legacy device %s -> %s\n",
 
348
                                   devname, audiodevs[dev]->devnode);
 
349
              audiodevs[dev]->legacy_device = newdev;
 
350
            }
 
351
        }
 
352
    }
 
353
 
 
354
  if (verbose) printf ("%d legacy dsp device files\n", numfiles);
 
355
 
 
356
  renum.n = si.numaudios;
 
357
 
 
358
  for (dev = 0; dev < si.numaudios; dev++)
 
359
    {
 
360
      if (audiodevs[dev]->legacy_device != dev)
 
361
        if (audiodevs[dev]->legacy_device >= 0)
 
362
          if (verbose) printf ("Adev %d (%s) is legacy device file "
 
363
                               "/dev/dsp%d\n", dev, audiodevs[dev]->devnode,
 
364
                               audiodevs[dev]->legacy_device);
 
365
 
 
366
      renum.map[dev] = audiodevs[dev]->legacy_device;
 
367
    }
 
368
 
 
369
  if (ioctl (mixerfd, OSSCTL_RENUM_AUDIODEVS, &renum) == -1)
 
370
    {
 
371
      perror ("audio_renum");
 
372
    }
 
373
 
 
374
 
 
375
/*
 
376
 * Find out a suitable /dev/dsp device (input and output capable).
 
377
 * Remove old /dev/dsp if it appears to be a character device node.
 
378
 */
 
379
  if (lstat ("/dev/dsp", &st) != -1)
 
380
    if (S_ISCHR (st.st_mode))
 
381
      unlink ("/dev/dsp");
 
382
 
 
383
/*
 
384
 * Remove /dev/dsp link that points to some bogus device. This may
 
385
 * happen if some hot-pluggable (USB) device has been
 
386
 * removed from the system.
 
387
 */
 
388
  if (lstat ("/dev/dsp", &st) != -1)    /* /dev/dsp exists (and is symlink) */
 
389
    if (stat ("/dev/dsp", &st) == -1)   /* But points to nowhere */
 
390
      unlink ("/dev/dsp");
 
391
 
 
392
/*
 
393
 * Next find a duplex capable audio device.
 
394
 */
 
395
 
 
396
  for (dev = 0; dev < si.numaudios; dev++)
 
397
    {
 
398
      ai = audiodevs[dev];
 
399
 
 
400
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
401
        continue;
 
402
 
 
403
      if (!(ai->caps & PCM_CAP_INPUT))
 
404
        continue;
 
405
 
 
406
      if (ai->min_channels > 2 || ai->max_channels < 2) /* No stereo */
 
407
         continue;
 
408
 
 
409
      if (verbose) printf ("%s is the default /dev/dsp device\n", ai->devnode);
 
410
      err = symlink (ai->devnode, "/dev/dsp");  /* Ignore errors */
 
411
      break;
 
412
    }
 
413
 
 
414
/*
 
415
 * Find out a suitable /dev/dsp_out device.
 
416
 */
 
417
 
 
418
  for (dev = 0; dev < si.numaudios; dev++)
 
419
    {
 
420
      ai = audiodevs[dev];
 
421
 
 
422
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
423
        continue;
 
424
 
 
425
      if (verbose) printf ("%s is the default dsp_out device\n", ai->devnode);
 
426
      err = symlink (ai->devnode, "/dev/dsp_out");      /* Ignore errors */
 
427
 
 
428
      /*
 
429
       * Also link /dev/dsp just in case the link doesn't
 
430
       * exist yet.
 
431
       */
 
432
      err = symlink (ai->devnode, "/dev/dsp");  /* Ignore errors */
 
433
      break;
 
434
    }
 
435
 
 
436
/*
 
437
 * Find out a suitable /dev/dsp_in device.
 
438
 */
 
439
 
 
440
  for (dev = 0; dev < si.numaudios; dev++)
 
441
    {
 
442
      ai = audiodevs[dev];
 
443
 
 
444
      if (!(ai->caps & PCM_CAP_INPUT))
 
445
        continue;
 
446
 
 
447
      if (verbose) printf ("%s is the default dsp_in device\n", ai->devnode);
 
448
      err = symlink (ai->devnode, "/dev/dsp_in");       /* Ignore errors */
 
449
 
 
450
      /*
 
451
       * Also link /dev/dsp just in case the link doesn't
 
452
       * exist yet.
 
453
       */
 
454
      err = symlink (ai->devnode, "/dev/dsp");  /* Ignore errors */
 
455
      break;
 
456
    }
 
457
 
 
458
/*
 
459
 * Find out a suitable /dev/dsp_ac3 output device.
 
460
 */
 
461
 
 
462
  for (dev = 0; dev < si.numaudios; dev++)
 
463
    {
 
464
      ai = audiodevs[dev];
 
465
 
 
466
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
467
        continue;
 
468
 
 
469
      if (!(ai->oformats & AFMT_AC3))
 
470
        continue;
 
471
 
 
472
      if (verbose) printf ("%s is the default AC3 output device\n",
 
473
                           ai->devnode);
 
474
      err = symlink (ai->devnode, "/dev/dsp_ac3");      /* Ignore errors */
 
475
      break;
 
476
    }
 
477
 
 
478
/*
 
479
 * Find out a suitable /dev/dsp_mmap output device.
 
480
 */
 
481
 
 
482
  for (dev = 0; dev < si.numaudios; dev++)
 
483
    {
 
484
      ai = audiodevs[dev];
 
485
 
 
486
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
487
        continue;
 
488
 
 
489
      if (!(ai->caps & PCM_CAP_MMAP))
 
490
        continue;
 
491
 
 
492
      if (!(ai->caps & PCM_CAP_TRIGGER))
 
493
        continue;
 
494
 
 
495
      if (ai->max_channels < 2)
 
496
        continue;
 
497
 
 
498
      if (ai->min_channels > 2)
 
499
        continue;
 
500
 
 
501
      if (verbose) printf ("%s is the default mmap output device\n",
 
502
                           ai->devnode);
 
503
      err = symlink (ai->devnode, "/dev/dsp_mmap");     /* Ignore errors */
 
504
      break;
 
505
    }
 
506
 
 
507
/*
 
508
 * Find out a suitable /dev/dsp_multich output device.
 
509
 */
 
510
 
 
511
  for (dev = 0; dev < si.numaudios; dev++)
 
512
    {
 
513
      ai = audiodevs[dev];
 
514
 
 
515
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
516
        continue;
 
517
 
 
518
      if (ai->max_channels < 4)
 
519
        continue;
 
520
 
 
521
      if (verbose) printf ("%s is the default multichan output device\n",
 
522
                           ai->devnode);
 
523
      err = symlink (ai->devnode, "/dev/dsp_multich");  /* Ignore errors */
 
524
      break;
 
525
    }
 
526
 
 
527
/*
 
528
 * Find out a suitable /dev/dsp_spdifout output device.
 
529
 */
 
530
 
 
531
  for (dev = 0; dev < si.numaudios; dev++)
 
532
    {
 
533
      ai = audiodevs[dev];
 
534
 
 
535
      if (!(ai->caps & PCM_CAP_OUTPUT))
 
536
        continue;
 
537
 
 
538
      if (!(ai->caps & PCM_CAP_DIGITALOUT))
 
539
        continue;
 
540
 
 
541
      if (verbose) printf ("%s is the default S/PDIF digital output device\n",
 
542
                           ai->devnode);
 
543
      err = symlink (ai->devnode, "/dev/dsp_spdifout"); /* Ignore errors */
 
544
      break;
 
545
    }
 
546
 
 
547
/*
 
548
 * Find out a suitable /dev/dsp_spdifin input device.
 
549
 */
 
550
 
 
551
  for (dev = 0; dev < si.numaudios; dev++)
 
552
    {
 
553
      ai = audiodevs[dev];
 
554
 
 
555
      if (!(ai->caps & PCM_CAP_INPUT))
 
556
        continue;
 
557
 
 
558
      if (!(ai->caps & PCM_CAP_DIGITALIN))
 
559
        continue;
 
560
 
 
561
      if (verbose) printf ("%s is the default S/PDIF digital input device\n",
 
562
                           ai->devnode);
 
563
      err = symlink (ai->devnode, "/dev/dsp_spdifin");  /* Ignore errors */
 
564
      break;
 
565
    }
 
566
}
 
567
 
 
568
/*
 
569
 *****************************
 
570
 * /dev/mixer handling
 
571
 */
 
572
 
 
573
static int
 
574
find_mixerlink (oss_mixerinfo * xi)
 
575
{
 
576
  int dev;
 
577
/*
 
578
 * Look for a legacy (/dev/mixer#) devife file that is a symlink to
 
579
 * xi->devnode. Return the device number if a
 
580
 * matching link is found. Return -1 if nothing is found.
 
581
 */
 
582
 
 
583
  struct stat st;
 
584
  char devname[64], linkdev[256];
 
585
 
 
586
  for (dev = 0; dev < MAXDEV; dev++)
 
587
    {
 
588
      sprintf (devname, "/dev/mixer%d", dev);
 
589
      if (lstat (devname, &st) != -1)
 
590
        if (S_ISLNK (st.st_mode))
 
591
          {
 
592
            int l;
 
593
 
 
594
            if ((l = readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
595
              {
 
596
                continue;
 
597
              }
 
598
            else
 
599
              {
 
600
                linkdev[l] = 0;
 
601
                if (strcmp (linkdev, xi->devnode) == 0) /* Match */
 
602
                  {
 
603
                    xi->legacy_device = dev;
 
604
                    return dev;
 
605
                  }
 
606
              }
 
607
          }
 
608
    }
 
609
 
 
610
  return -1;                    /* Nothing found */
 
611
}
 
612
 
 
613
static void
 
614
create_mixerlinks (void)
 
615
{
 
616
  int dev, newdev, numfiles = 0;
 
617
  struct stat st;
 
618
  char devname[64];
 
619
 
 
620
  oss_mixerinfo *xi, *mixerdevs[MAXDEV];
 
621
 
 
622
  oss_renumber_t renum = { 0 };
 
623
 
 
624
  if (recreate_all)
 
625
    remove_nodes ("/dev", "mixer[0-9]*");
 
626
 
 
627
  if (verbose) printf ("%d mixer devices\n", si.nummixers);
 
628
 
 
629
  if (si.nummixers < 1)
 
630
    return;
 
631
 
 
632
  for (dev = 0; dev < si.nummixers; dev++)
 
633
    {
 
634
      xi = malloc (sizeof (*xi));
 
635
 
 
636
      xi->dev = dev;
 
637
 
 
638
      if (ioctl (mixerfd, SNDCTL_MIXERINFO, xi) == -1)
 
639
        {
 
640
          perror ("SNDCTL_MIXERINFO");
 
641
          exit (-1);
 
642
        }
 
643
 
 
644
      mixerdevs[dev] = xi;
 
645
 
 
646
      /* if (verbose) printf ("Mixdev %d = %s\n", dev, xi->devnode); */
 
647
    }
 
648
 
 
649
  for (dev = 0; dev < MAXDEV; dev++)
 
650
    {
 
651
 
 
652
      sprintf (devname, "/dev/mixer%d", dev);
 
653
      newdev = dev;
 
654
 
 
655
      if (lstat (devname, &st) != -1)
 
656
        {
 
657
          if (S_ISLNK (st.st_mode))
 
658
            numfiles = dev + 1;
 
659
        }
 
660
    }
 
661
 
 
662
  if (numfiles < si.nummixers)
 
663
    numfiles = si.nummixers;
 
664
 
 
665
  if (verbose) printf ("/dev/mixer%d is the next free legacy device\n",
 
666
                       numfiles);
 
667
 
 
668
  for (dev = 0; dev < si.nummixers; dev++)
 
669
    {
 
670
      int recreate = 0;
 
671
 
 
672
      sprintf (devname, "/dev/mixer%d", dev);
 
673
      newdev = dev;
 
674
 
 
675
      if (lstat (devname, &st) == -1)
 
676
        {
 
677
          if (verbose) printf ("%s: %s\n", devname, strerror (errno));
 
678
          recreate = 1;
 
679
        }
 
680
      else
 
681
        {
 
682
          if (S_ISCHR (st.st_mode))
 
683
            {
 
684
              if (verbose) printf ("%s: character device\n", devname);
 
685
              recreate = 1;
 
686
            }
 
687
          else if (S_ISLNK (st.st_mode))
 
688
            {
 
689
              int l;
 
690
 
 
691
              char linkdev[256];
 
692
              if ((l =
 
693
                   readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
694
                {
 
695
                  perror ("readlink");
 
696
                  strcpy (linkdev, "Invalid");
 
697
                }
 
698
              else
 
699
                {
 
700
                  linkdev[l] = 0;
 
701
                }
 
702
 
 
703
              if (verbose) printf ("%s: symlink -> %s ", devname, linkdev);
 
704
 
 
705
              if (strcmp (linkdev, mixerdevs[dev]->devnode) != 0)
 
706
                {
 
707
                  if (verbose) printf ("(should be %s)\n",
 
708
                                       mixerdevs[dev]->devnode);
 
709
                  if ((newdev = find_mixerlink (mixerdevs[dev])) == -1)
 
710
                    {
 
711
                      recreate = 1;
 
712
                      newdev = numfiles++;
 
713
                    }
 
714
                  else
 
715
                    if (verbose) printf ("\tAlready linked to /dev/mixer%d\n",
 
716
                                         newdev);
 
717
                }
 
718
              else
 
719
                if (verbose) printf ("OK\n");
 
720
            }
 
721
          else
 
722
            {
 
723
              if (verbose) printf ("%s: unknown file type\n", devname);
 
724
              recreate = 1;
 
725
            }
 
726
 
 
727
        }
 
728
 
 
729
      if (recreate)
 
730
        {
 
731
          mixerdevs[dev]->legacy_device = newdev;
 
732
          sprintf (devname, "/dev/mixer%d", newdev);
 
733
 
 
734
          if (strcmp (mixerdevs[dev]->devnode, devname) != 0)   /* Not the same */
 
735
            {
 
736
              unlink (devname);
 
737
              if (symlink (mixerdevs[dev]->devnode, devname) == -1)
 
738
                {
 
739
                  perror ("symlink");
 
740
                  fprintf (stderr, "Cannot create link %s->%s\n", devname,
 
741
                           mixerdevs[dev]->devnode);
 
742
                  exit (-1);
 
743
                }
 
744
 
 
745
              if (verbose) printf ("Created new legacy device %s -> %s\n",
 
746
                                   devname, mixerdevs[dev]->devnode);
 
747
            }
 
748
        }
 
749
    }
 
750
 
 
751
  if (verbose) printf ("%d legacy mixer device files\n", numfiles);
 
752
 
 
753
  renum.n = si.nummixers;
 
754
 
 
755
  for (dev = 0; dev < si.nummixers; dev++)
 
756
    {
 
757
      if (mixerdevs[dev]->legacy_device != dev)
 
758
        if (verbose) printf ("Mixdev %d is legacy device file /dev/mixer%d\n",
 
759
                             dev, mixerdevs[dev]->legacy_device);
 
760
      renum.map[dev] = mixerdevs[dev]->legacy_device;
 
761
    }
 
762
 
 
763
  if (ioctl (mixerfd, OSSCTL_RENUM_MIXERDEVS, &renum) == -1)
 
764
    {
 
765
      perror ("mixer_renum");
 
766
    }
 
767
}
 
768
 
 
769
#ifdef CONFIG_OSS_MIDI
 
770
/*
 
771
 * MIDI devices (/dev/midiNN)
 
772
 */
 
773
 
 
774
static int
 
775
find_midilink (oss_midi_info * xi)
 
776
{
 
777
  int dev;
 
778
/*
 
779
 * Look for a legacy (/dev/midi#) devife file that is a symlink to
 
780
 * xi->devnode. Return the device number if a
 
781
 * matching link is found. Return -1 if nothing is found.
 
782
 */
 
783
 
 
784
  struct stat st;
 
785
  char devname[64], linkdev[256];
 
786
 
 
787
  for (dev = 0; dev < MAXDEV; dev++)
 
788
    {
 
789
      sprintf (devname, "/dev/midi%02d", dev);
 
790
      if (lstat (devname, &st) != -1)
 
791
        if (S_ISLNK (st.st_mode))
 
792
          {
 
793
            int l;
 
794
 
 
795
            if ((l = readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
796
              {
 
797
                continue;
 
798
              }
 
799
            else
 
800
              {
 
801
                linkdev[l] = 0;
 
802
                if (strcmp (linkdev, xi->devnode) == 0) /* Match */
 
803
                  {
 
804
                    xi->legacy_device = dev;
 
805
                    return dev;
 
806
                  }
 
807
              }
 
808
          }
 
809
    }
 
810
 
 
811
  return -1;                    /* Nothing found */
 
812
}
 
813
 
 
814
static void
 
815
create_midilinks (void)
 
816
{
 
817
  int dev, newdev, numfiles = 0;
 
818
  struct stat st;
 
819
  char devname[64];
 
820
 
 
821
  oss_midi_info *xi, *mididevs[MAXDEV];
 
822
 
 
823
  oss_renumber_t renum = { 0 };
 
824
 
 
825
  if (recreate_all)
 
826
    remove_nodes ("/dev", "midi[0-9]*");
 
827
 
 
828
  if (si.nummidis < 1)          /* No MIDI devices in the system */
 
829
    return;
 
830
 
 
831
  if (verbose) printf ("%d midi devices\n", si.nummidis);
 
832
  for (dev = 0; dev < si.nummidis; dev++)
 
833
    {
 
834
      xi = malloc (sizeof (*xi));
 
835
 
 
836
      xi->dev = dev;
 
837
 
 
838
      if (ioctl (mixerfd, SNDCTL_MIDIINFO, xi) == -1)
 
839
        {
 
840
          perror ("SNDCTL_MIDIINFO");
 
841
          exit (-1);
 
842
        }
 
843
 
 
844
      mididevs[dev] = xi;
 
845
 
 
846
      /* if (verbose) printf ("Mididev %d = %s\n", dev, xi->devnode); */
 
847
    }
 
848
 
 
849
  for (dev = 0; dev < MAXDEV; dev++)
 
850
    {
 
851
 
 
852
      sprintf (devname, "/dev/midi%02d", dev);
 
853
      newdev = dev;
 
854
 
 
855
      if (lstat (devname, &st) != -1)
 
856
        {
 
857
          if (S_ISLNK (st.st_mode))
 
858
            numfiles = dev + 1;
 
859
        }
 
860
    }
 
861
 
 
862
  if (numfiles < si.nummidis)
 
863
    numfiles = si.nummidis;
 
864
 
 
865
  if (verbose) printf ("/dev/midi%02d is the next free legacy device\n",numfiles);
 
866
 
 
867
  for (dev = 0; dev < si.nummidis; dev++)
 
868
    {
 
869
      int recreate = 0;
 
870
 
 
871
      sprintf (devname, "/dev/midi%02d", dev);
 
872
      newdev = dev;
 
873
 
 
874
      if (lstat (devname, &st) == -1)
 
875
        {
 
876
          if (verbose) printf ("%s: %s\n", devname, strerror (errno));
 
877
          recreate = 1;
 
878
        }
 
879
      else
 
880
        {
 
881
          if (S_ISCHR (st.st_mode))
 
882
            {
 
883
              if (verbose) printf ("%s: character device\n", devname);
 
884
              recreate = 1;
 
885
            }
 
886
          else if (S_ISLNK (st.st_mode))
 
887
            {
 
888
              int l;
 
889
 
 
890
              char linkdev[256];
 
891
              if ((l =
 
892
                   readlink (devname, linkdev, sizeof (linkdev) - 1)) == -1)
 
893
                {
 
894
                  perror ("readlink");
 
895
                  strcpy (linkdev, "Invalid");
 
896
                }
 
897
              else
 
898
                {
 
899
                  linkdev[l] = 0;
 
900
                }
 
901
 
 
902
              if (verbose) printf ("%s: symlink -> %s ", devname, linkdev);
 
903
 
 
904
              if (strcmp (linkdev, mididevs[dev]->devnode) != 0)
 
905
                {
 
906
                  if (verbose) printf ("(should be %s)\n",
 
907
                                       mididevs[dev]->devnode);
 
908
                  if ((newdev = find_midilink (mididevs[dev])) == -1)
 
909
                    {
 
910
                      recreate = 1;
 
911
                      newdev = numfiles++;
 
912
                    }
 
913
                  else
 
914
                    if (verbose) printf ("\tAlready linked to /dev/midi%02d\n",
 
915
                                         newdev);
 
916
                }
 
917
              else
 
918
                if (verbose) printf ("OK\n");
 
919
            }
 
920
          else
 
921
            {
 
922
              if (verbose) printf ("%s: unknown file type\n", devname);
 
923
              recreate = 1;
 
924
            }
 
925
 
 
926
        }
 
927
 
 
928
      if (recreate)
 
929
        {
 
930
          mididevs[dev]->legacy_device = newdev;
 
931
          sprintf (devname, "/dev/midi%02d", newdev);
 
932
 
 
933
          if (strcmp (mididevs[dev]->devnode, devname) != 0)    /* Not the same */
 
934
            {
 
935
              unlink (devname);
 
936
              if (symlink (mididevs[dev]->devnode, devname) == -1)
 
937
                {
 
938
                  perror ("symlink");
 
939
                  fprintf (stderr, "Cannot create link %s->%s\n", devname,
 
940
                           mididevs[dev]->devnode);
 
941
                  exit (-1);
 
942
                }
 
943
 
 
944
              if (verbose) printf ("Created new legacy device %s -> %s\n",
 
945
                                   devname, mididevs[dev]->devnode);
 
946
            }
 
947
        }
 
948
    }
 
949
 
 
950
  if (verbose) printf ("%d legacy MIDI device files\n", numfiles);
 
951
 
 
952
  renum.n = si.nummidis;
 
953
 
 
954
  for (dev = 0; dev < si.nummidis; dev++)
 
955
    {
 
956
      if (mididevs[dev]->legacy_device != dev)
 
957
        if (verbose) printf ("Mididev %d is legacy device file /dev/midi%02d\n",
 
958
                             dev, mididevs[dev]->legacy_device);
 
959
      renum.map[dev] = mididevs[dev]->legacy_device;
 
960
    }
 
961
 
 
962
  if (ioctl (mixerfd, OSSCTL_RENUM_MIDIDEVS, &renum) == -1)
 
963
    {
 
964
      perror ("midi_renum");
 
965
    }
 
966
}
 
967
#endif
 
968
 
 
969
static void
 
970
save_link (FILE * f, char *devname)
 
971
{
 
972
  char linkname[256];
 
973
  int l;
 
974
 
 
975
  if ((l = readlink (devname, linkname, sizeof (linkname) - 1)) == -1)
 
976
    return;
 
977
  linkname[l] = 0;
 
978
 
 
979
  fprintf (f, "rm -f %s;ln -sf %s %s\n", devname, linkname, devname);
 
980
}
 
981
 
 
982
static void
 
983
save_links (void)
 
984
{
 
985
  FILE *f;
 
986
  int i;
 
987
  char devfile[32];
 
988
 
 
989
  if (legacydev_file == NULL)
 
990
    {
 
991
      char lfile[PATH_MAX+20], * osslibdir;
 
992
 
 
993
      osslibdir = get_mapname ();
 
994
      snprintf (lfile, sizeof (lfile), "%s/%s", osslibdir, "legacy_devices");
 
995
      if ((f = fopen (lfile, "w")) == NULL)
 
996
        {
 
997
          perror (lfile);
 
998
          return;
 
999
        }
 
1000
    }
 
1001
  else if ((f = fopen (legacydev_file, "w")) == NULL)
 
1002
    {
 
1003
      perror (legacydev_file);
 
1004
      return;
 
1005
    }
 
1006
 
 
1007
/*
 
1008
 * /dev/dsp#
 
1009
 */
 
1010
 
 
1011
  for (i = 0; i < MAXDEV; i++)
 
1012
    {
 
1013
      sprintf (devfile, "/dev/dsp%d", i);
 
1014
      save_link (f, devfile);
 
1015
    }
 
1016
 
 
1017
  save_link (f, "/dev/dsp");
 
1018
  save_link (f, "/dev/dsp_ac3");
 
1019
  save_link (f, "/dev/dsp_in");
 
1020
  save_link (f, "/dev/dsp_mmap");
 
1021
  save_link (f, "/dev/dsp_multich");
 
1022
  save_link (f, "/dev/dsp_out");
 
1023
  save_link (f, "/dev/dsp_spdifout");
 
1024
  save_link (f, "/dev/dsp_spdifin");
 
1025
 
 
1026
/*
 
1027
 * /dev/mixer#
 
1028
 */
 
1029
 
 
1030
  for (i = 0; i < MAXDEV; i++)
 
1031
    {
 
1032
      sprintf (devfile, "/dev/mixer%d", i);
 
1033
      save_link (f, devfile);
 
1034
    }
 
1035
 
 
1036
#ifdef CONFIG_OSS_MIDI
 
1037
/*
 
1038
 * /dev/midi##
 
1039
 */
 
1040
 
 
1041
  for (i = 0; i < MAXDEV; i++)
 
1042
    {
 
1043
      sprintf (devfile, "/dev/midi%02d", i);
 
1044
      save_link (f, devfile);
 
1045
    }
 
1046
#endif
 
1047
 
 
1048
  fclose (f);
 
1049
}
 
1050
 
 
1051
int
 
1052
main (int argc, char *argv[])
 
1053
{
 
1054
  int c;
 
1055
 
 
1056
  if ((mixerfd = open ("/dev/mixer", O_RDWR, 0)) == -1)
 
1057
    {
 
1058
      perror ("/dev/mixer");
 
1059
      exit (-1);
 
1060
    }
 
1061
 
 
1062
  if (ioctl (mixerfd, SNDCTL_SYSINFO, &si) == -1)
 
1063
    {
 
1064
      if (errno == ENXIO)
 
1065
        {
 
1066
          fprintf (stderr,
 
1067
                   "OSS has not detected any supported sound hardware ");
 
1068
          fprintf (stderr, "in your system.\n");
 
1069
          exit (-1);
 
1070
        }
 
1071
      else
 
1072
        {
 
1073
          perror ("SNDCTL_SYSINFO");
 
1074
          if (errno == EINVAL)
 
1075
            fprintf (stderr, "Error: OSS version 4.0 or later is required\n");
 
1076
          exit (-1);
 
1077
        }
 
1078
    }
 
1079
 
 
1080
  while ((c = getopt (argc, argv, "Nf:rv")) != EOF)
 
1081
  switch (c)
 
1082
    {
 
1083
    case 'f':
 
1084
      legacydev_file = optarg;
 
1085
      break;
 
1086
 
 
1087
    case 'r':
 
1088
      recreate_all = 1;
 
1089
      break;
 
1090
 
 
1091
    case 'v':
 
1092
      verbose++;
 
1093
      break;
 
1094
 
 
1095
    case 'N':
 
1096
      no_links = 1;
 
1097
      break;
 
1098
    }
 
1099
 
 
1100
  if (!no_links) {
 
1101
    create_dsplinks ();
 
1102
    create_mixerlinks ();
 
1103
#ifdef CONFIG_OSS_MIDI
 
1104
    create_midilinks ();
 
1105
#endif
 
1106
  }
 
1107
 
 
1108
  close (mixerfd);
 
1109
 
 
1110
  save_links ();
 
1111
 
 
1112
  return 0;
 
1113
}