~ubuntu-branches/ubuntu/vivid/oss4/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/cmd.patch/cmd/ossdevlinks/ossdevlinks.c

  • Committer: Package Import Robot
  • Author(s): Sebastien NOEL
  • Date: 2012-11-19 11:47:24 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20121119114724-svu8mq7x3pk64nez
Tags: 4.2-build2007-1
* New upstream release.
* Acknowledge NMU, thanks Michael Gilbert.
* Add debian/patches/110_ld-as-needed.patch: Rearrange order of linker
  arguments to fix building with "ld --as-needed" (closes: #630737).
* Add missing dependency on dpkg-dev to oss4-dkms and oss4-source
  (closes: #687086).
* Fix typo in the changelog (closes: #628876, #675933)
* Add debian/patches/002_fix-linux-oss_native_word.patch (closes: #693657).
  Thanks to Ben Hutchings.
* Add debian/patches/003_linux-error-logging-fixes.patch (closes: #693657).
  Thanks to Ben Hutchings.
* check for /lib/modules/${kernelver}/build in addition of
  /lib/modules/${kernelver}/source (closes: #587191).
* oss4-dkms.dkms.in: fix 'CLEAN' rules (closes: #653374).

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 "/usr/lib/oss"
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, "OSSLIBDIR=", 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, "etc/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
 
}