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

« back to all changes in this revision

Viewing changes to os_cmd/FreeBSD/ossdetect/ossdetect.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: OSS device autodetection utility for FreeBSD
 
3
 *
 
4
 */
 
5
/*
 
6
 *
 
7
 * This file is part of Open Sound System.
 
8
 *
 
9
 * Copyright (C) 4Front Technologies 1996-2008.
 
10
 *
 
11
 * This this source file is released under GPL v2 license (no other versions).
 
12
 * See the COPYING file included in the main directory of this source
 
13
 * distribution for the license terms and conditions.
 
14
 *
 
15
 */
 
16
 
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <unistd.h>
 
20
#include <fcntl.h>
 
21
#include <string.h>
 
22
#include <sys/types.h>
 
23
#include <sys/stat.h>
 
24
#include <sys/param.h>
 
25
#include <sys/pciio.h>
 
26
#include <dev/pci/pcireg.h>
 
27
 
 
28
#define PCI_PASS        0
 
29
#define USB_PASS        1
 
30
#define PSEUDO_PASS     2
 
31
#define MAX_PASS        3
 
32
 
 
33
#define OSSLIBDIRLEN 512
 
34
static char *osslibdir = NULL;
 
35
 
 
36
static int verbose = 0;
 
37
 
 
38
typedef struct
 
39
{
 
40
  char *key, *driver, *name;
 
41
  int is_3rdparty;
 
42
  int detected;
 
43
  int pass;
 
44
} driver_def_t;
 
45
 
 
46
typedef struct drv_slist
 
47
{
 
48
  const char * drv_name;
 
49
  struct drv_slist * next;
 
50
} drvlist_t;
 
51
static drvlist_t * drvl = NULL;
 
52
 
 
53
#define MAX_DRIVERS     1000
 
54
static driver_def_t drivers[MAX_DRIVERS];
 
55
static int ndrivers = 0;
 
56
 
 
57
static int add_drv (const char *, int);
 
58
static void create_devlinks (mode_t);
 
59
#if 0
 
60
static int remove_devlinks (const char *);
 
61
#endif
 
62
static drvlist_t * prepend_drvlist (const char *);
 
63
static char * get_mapname (void);
 
64
static void load_license (const char *);
 
65
static void load_devlist (const char *, int);
 
66
static void pci_detect (void);
 
67
 
 
68
static char *
 
69
get_mapname (void)
 
70
{
 
71
  FILE *f;
 
72
  static char name[OSSLIBDIRLEN], tmp[OSSLIBDIRLEN+11];
 
73
  struct stat st;
 
74
 
 
75
  if ((f = fopen ("/etc/oss.conf", "r")) == NULL)
 
76
    {
 
77
      perror ("/etc/oss.conf");
 
78
      goto oexit2;
 
79
    }
 
80
 
 
81
  while (fgets (tmp, sizeof (tmp), f) != NULL)
 
82
    {
 
83
      int l = strlen (tmp);
 
84
      if (l > 0 && tmp[l - 1] == '\n')
 
85
        tmp[l - 1] = '\0';
 
86
 
 
87
      if (strncmp (tmp, "OSSLIBDIR=", 10) == 0)
 
88
        {
 
89
          l = snprintf (name, sizeof (name), "%s", &tmp[10]);
 
90
          if ((l >= OSSLIBDIRLEN) || (l < 0))
 
91
            {
 
92
              fprintf (stderr, "String in /etc/oss.conf is too long!\n");
 
93
              goto oexit;
 
94
            }
 
95
          if ((stat (name, &st) == -1) || !S_ISDIR(st.st_mode))
 
96
            {
 
97
              fprintf (stderr, "Directory %s from /etc/oss.conf cannot "
 
98
                               "be used!\n", name);
 
99
              goto oexit;
 
100
            }
 
101
          fclose (f);
 
102
          return name;
 
103
        }
 
104
    }
 
105
 
 
106
  fprintf (stderr, "OSSLIBDIR not set in /etc/oss.conf, using default "
 
107
                   "/usr/lib/oss\n");
 
108
oexit:
 
109
  fclose (f);
 
110
oexit2:
 
111
  snprintf (name, sizeof (name), "/usr/lib/oss");
 
112
  return name;
 
113
}
 
114
 
 
115
static void
 
116
load_license (const char *fname)
 
117
{
 
118
  struct stat st;
 
119
  char cmd[2*OSSLIBDIRLEN];
 
120
  int n;
 
121
 
 
122
  if (stat (fname, &st) == -1)
 
123
    return;                     /* Doesn't exist */
 
124
 
 
125
  if (stat ("/usr/sbin/osslic", &st) == -1)
 
126
    return;                     /* No osslic utility in the system. No need to install license. */
 
127
 
 
128
  n = snprintf (cmd, sizeof (cmd), "/usr/sbin/osslic -q %s/%s", osslibdir,
 
129
                fname);
 
130
  if (n >= sizeof (cmd) || n < 0) return;
 
131
  if (((n = system (cmd)) == -1))
 
132
    fprintf (stderr, "Cannot run osslic!\n");
 
133
}
 
134
 
 
135
static void
 
136
load_devlist (const char *fname, int is_3rdparty)
 
137
{
 
138
  FILE *f;
 
139
  char line[256], *p, rfname[2*OSSLIBDIRLEN];
 
140
  char *driver, *key, *name;
 
141
 
 
142
  snprintf (rfname, sizeof (rfname), "%s/%s", osslibdir, fname);
 
143
 
 
144
  if ((f = fopen (rfname, "r")) == NULL)
 
145
    {
 
146
      perror (rfname);
 
147
      exit (-1);
 
148
    }
 
149
 
 
150
  while (fgets (line, sizeof (line), f) != NULL)
 
151
    {
 
152
      p = line;
 
153
      while (*p)
 
154
        {
 
155
          if (*p == '#' || *p == '\n')
 
156
            *p = 0;
 
157
          p++;
 
158
        }
 
159
 
 
160
      /* Drivers with upper case names are unsupported ones */
 
161
      if ((*line >= 'A' && *line <= 'Z') || (*line == '\0'))
 
162
        continue;
 
163
 
 
164
      driver = line;
 
165
      p = line;
 
166
 
 
167
      while (*p && *p != '\t' && *p != ' ')
 
168
        p++;
 
169
      if (*p)
 
170
        *p++ = 0;
 
171
      key = p;
 
172
 
 
173
      while (*p && *p != '\t')
 
174
        p++;
 
175
      if (*p)
 
176
        *p++ = 0;
 
177
      name = p;
 
178
 
 
179
      if (verbose > 1)
 
180
        printf ("device=%s, name=%s, driver=%s\n", key, name, driver);
 
181
 
 
182
      if (ndrivers >= MAX_DRIVERS)
 
183
        {
 
184
          printf ("Too many drivers defined in drivers.list\n");
 
185
          exit (-1);
 
186
        }
 
187
 
 
188
      drivers[ndrivers].key = strdup (key);
 
189
      drivers[ndrivers].driver = strdup (driver);
 
190
      drivers[ndrivers].name = strdup (name);
 
191
      drivers[ndrivers].is_3rdparty = is_3rdparty;
 
192
      drivers[ndrivers].detected = 0;
 
193
 
 
194
      ndrivers++;
 
195
    }
 
196
 
 
197
  fclose (f);
 
198
}
 
199
 
 
200
static int
 
201
add_drv (const char * id, int pass)
 
202
{
 
203
  int i;
 
204
 
 
205
  for (i = 0; i < ndrivers; i++)
 
206
    {
 
207
      if (strcmp (id, drivers[i].key) == 0)
 
208
        {
 
209
          if (verbose > 0)
 
210
            printf ("Detected %s\n", drivers[i].name);
 
211
          drivers[i].detected = 1;
 
212
          drivers[i].pass = pass;
 
213
          return 1;
 
214
        }
 
215
    }
 
216
 
 
217
  return 0;
 
218
}
 
219
 
 
220
#if 0
 
221
static int
 
222
remove_devlinks (const char * dirname)
 
223
{
 
224
  char path[PATH_MAX];
 
225
  DIR * dr;
 
226
  struct dirent * de;
 
227
  struct stat st;
 
228
 
 
229
  if ((dr = opendir (dirname)) == NULL)
 
230
    {
 
231
      if (errno == ENONET) return 0;
 
232
      perror ("opendir");
 
233
      return -1;
 
234
    }
 
235
 
 
236
  while ((de = readdir (dr)) != NULL)
 
237
    {
 
238
      if ((!strcmp (de->d_name, ".")) || (!strcmp (de->d_name, ".."))) continue;
 
239
 
 
240
      snprintf (path, sizeof (path), "%s/%s", dirname, de->d_name);
 
241
 
 
242
      if ((stat (path, &st) != -1) && (S_ISDIR (st.st_mode))) remove_devlinks (path);
 
243
      else
 
244
        {
 
245
          if (verbose > 2) fprintf (stderr, "Removing %s\n", path);
 
246
          unlink (path);
 
247
        }
 
248
    }
 
249
 
 
250
  closedir (dr);
 
251
  if (verbose > 2) fprintf (stderr, "Removing %s\n", path);
 
252
  if (rmdir (dirname) == -1)
 
253
    {
 
254
      fprintf (stderr, "Couldn't remove %s\n", path);
 
255
      return -1;
 
256
    }
 
257
  return 0;
 
258
}
 
259
#endif
 
260
 
 
261
static void
 
262
create_devlinks (mode_t node_m)
 
263
{
 
264
/* Doesn't work, since /proc isn't mounted by default on FreeBSD */
 
265
  FILE *f;
 
266
  char line[256], tmp[300], *p, *s;
 
267
  mode_t perm;
 
268
  int minor, major;
 
269
 
 
270
  if ((f = fopen ("/proc/opensound/devfiles", "r")) == NULL)
 
271
    {
 
272
      perror ("/proc/opensound/devfiles");
 
273
      fprintf (stderr, "Cannot connect to the OSS kernel module.\n");
 
274
      fprintf (stderr, "Perhaps you need to execute 'soundon' to load OSS\n");
 
275
      exit (-1);
 
276
    }
 
277
 
 
278
/* remove_devlinks("/dev/oss"); */
 
279
  perm = umask (0);
 
280
  mkdir ("/dev/oss", 0755);
 
281
 
 
282
  while (fgets (line, sizeof (line), f) != NULL)
 
283
    {
 
284
      char dev[64] = "/dev/";
 
285
 
 
286
      s = strchr (line, '\n');
 
287
      if (s) *s = '\0';
 
288
 
 
289
      if (sscanf (line, "%s %d %d", dev + 5, &major, &minor) != 3)
 
290
        {
 
291
          fprintf (stderr, "Syntax error in /proc/opensound/devfiles\n");
 
292
          fprintf (stderr, "%s\n", line);
 
293
          exit (-1);
 
294
        }
 
295
 
 
296
/*
 
297
 * Check if the device is located in a subdirectory (say /dev/oss/sblive0/pcm0).
 
298
 */
 
299
      strcpy (tmp, dev);
 
300
 
 
301
      s = tmp + 5;
 
302
      p = s;
 
303
      while (*s)
 
304
        {
 
305
          if (*s == '/')
 
306
            p = s;
 
307
          s++;
 
308
        }
 
309
 
 
310
      if (*p == '/')
 
311
        {
 
312
          *p = 0;               /* Extract the directory name part */
 
313
          mkdir (tmp, 0755);
 
314
        }
 
315
 
 
316
      unlink (dev);
 
317
      if (verbose)
 
318
        printf ("mknod %s c %d %d -m %o\n", dev, major, minor, node_m);
 
319
      if (mknod (dev, node_m, makedev (major, minor)) == -1)
 
320
        perror (dev);
 
321
    }
 
322
 
 
323
  umask (perm);
 
324
  fclose (f);
 
325
}
 
326
 
 
327
static void
 
328
pci_detect (void)
 
329
{
 
330
  int fd;
 
331
  struct pci_conf_io pc;
 
332
  struct pci_conf conf[255], *p;
 
333
 
 
334
  if ((fd = open ("/dev/pci", O_RDONLY, 0)) == -1)
 
335
    {
 
336
      perror ("/dev/pci");
 
337
      exit (-1);
 
338
    }
 
339
 
 
340
  bzero (&pc, sizeof (struct pci_conf_io));
 
341
  pc.match_buf_len = sizeof (conf);
 
342
  pc.matches = conf;
 
343
 
 
344
  do
 
345
    {
 
346
      if (ioctl (fd, PCIOCGETCONF, &pc) == -1)
 
347
        {
 
348
          perror ("ioctl(PCIOCGETCONF)");
 
349
          exit (1);
 
350
        }
 
351
 
 
352
      /*
 
353
       * 255 entries should be more than enough for most people,
 
354
       * but if someone has more devices, and then changes things
 
355
       * around between ioctls, we'll do the cheezy thing and
 
356
       * just bail.  The alternative would be to go back to the
 
357
       * beginning of the list, and print things twice, which may
 
358
       * not be desireable.
 
359
       */
 
360
      if (pc.status == PCI_GETCONF_LIST_CHANGED)
 
361
        {
 
362
          fprintf (stderr, "PCI device list changed, please try again");
 
363
          exit (1);
 
364
          close (fd);
 
365
          return;
 
366
        }
 
367
      else if (pc.status == PCI_GETCONF_ERROR)
 
368
        {
 
369
          fprintf (stderr, "error returned from PCIOCGETCONF ioctl");
 
370
          exit (1);
 
371
          close (fd);
 
372
          return;
 
373
        }
 
374
      for (p = conf; p < &conf[pc.num_matches]; p++)
 
375
        {
 
376
 
 
377
          char name[32];
 
378
 
 
379
          if (verbose > 2)
 
380
            printf ("%s%d@pci%d:%d:%d:\tclass=0x%06x card=0x%08x "
 
381
                    "chip=0x%08x rev=0x%02x hdr=0x%02x\n",
 
382
                    (p->pd_name && *p->pd_name) ? p->pd_name :
 
383
                    "none",
 
384
                    (p->pd_name && *p->pd_name) ? (int) p->pd_unit :
 
385
                    p->pc_sel.pc_bus, p->pc_sel.pc_dev,
 
386
                    p->pc_sel.pc_func, (p->pc_class << 16) |
 
387
                    (p->pc_subclass << 8) | p->pc_progif,
 
388
                    (p->pc_subdevice << 16) | p->pc_subvendor,
 
389
                    (p->pc_device << 16) | p->pc_vendor,
 
390
                    p->pc_revid, p->pc_hdr);
 
391
 
 
392
          sprintf (name, "pcs%x,%x", p->pc_subvendor, p->pc_subdevice);
 
393
          if (add_drv (name, PCI_PASS))
 
394
            continue;
 
395
 
 
396
          sprintf (name, "pci%x,%x", p->pc_vendor, p->pc_device);
 
397
          if (add_drv (name, PCI_PASS))
 
398
            continue;
 
399
        }
 
400
    }
 
401
  while (pc.status == PCI_GETCONF_MORE_DEVS);
 
402
 
 
403
  close (fd);
 
404
}
 
405
 
 
406
static drvlist_t *
 
407
prepend_drvlist (const char * name)
 
408
{
 
409
  drvlist_t * dp;
 
410
 
 
411
  dp = malloc (sizeof (drvlist_t));
 
412
  if (dp == NULL)
 
413
    {
 
414
      fprintf (stderr, "Can't allocate memory!\n");
 
415
      exit (-1);
 
416
    }
 
417
 
 
418
  dp->drv_name = name;
 
419
  dp->next = drvl;
 
420
  return dp;
 
421
}
 
422
 
 
423
int
 
424
main (int argc, char *argv[])
 
425
{
 
426
  char instfname[2*OSSLIBDIRLEN], *p;
 
427
  int i, do_license = 0, make_devs = 0, pass;
 
428
  mode_t node_m = S_IFCHR | 0666;
 
429
  struct stat st;
 
430
  FILE *f;
 
431
 
 
432
  while ((i = getopt(argc, argv, "L:a:dilm:uv")) != EOF)
 
433
    switch (i)
 
434
      {
 
435
        case 'v':
 
436
          verbose++;
 
437
          break;
 
438
 
 
439
        case 'd':
 
440
          make_devs = 1;
 
441
          break;
 
442
 
 
443
        case 'i':
 
444
          drvl = prepend_drvlist ("oss_imux");
 
445
          break;
 
446
 
 
447
        case 'u':
 
448
          drvl = prepend_drvlist ("oss_userdev");
 
449
          break;
 
450
 
 
451
        case 'a':
 
452
          drvl = prepend_drvlist (optarg);
 
453
          break;
 
454
 
 
455
        case 'l':
 
456
          do_license = 1;
 
457
          break;
 
458
 
 
459
        case 'L':
 
460
          osslibdir = optarg;
 
461
          break;
 
462
 
 
463
        case 'm':
 
464
          p = optarg;
 
465
          node_m = 0;
 
466
          while ((*p >= '0') && (*p <= '7')) node_m = node_m * 8 + *p++ - '0';
 
467
          if ((*p) || (node_m & ~(S_IRWXU|S_IRWXG|S_IRWXO)))
 
468
            {
 
469
              fprintf (stderr, "Invalid permissions: %s\n", optarg);
 
470
              exit(1);
 
471
            }
 
472
          node_m |= S_IFCHR;
 
473
          break;
 
474
 
 
475
        default:
 
476
          fprintf (stderr, "%s: bad usage\n", argv[0]);
 
477
          exit (-1);
 
478
      }
 
479
 
 
480
  if (osslibdir == NULL) osslibdir = get_mapname ();
 
481
 
 
482
  if (make_devs == 1)
 
483
    {
 
484
      create_devlinks (node_m);
 
485
      exit (0);
 
486
    }
 
487
 
 
488
  if (do_license == 1)
 
489
    {
 
490
      load_license ("etc/license.asc");
 
491
      exit (0);
 
492
    }
 
493
 
 
494
  load_devlist ("etc/devices.list", 0);
 
495
 
 
496
  if (stat ("/etc/oss_3rdparty", &st) != -1)
 
497
    load_devlist ("/etc/oss_3rdparty", 1);
 
498
 
 
499
  pci_detect ();
 
500
 
 
501
  while (drvl != NULL)
 
502
    {
 
503
      drvlist_t * d = drvl;
 
504
      add_drv (drvl->drv_name, PSEUDO_PASS);
 
505
      drvl = drvl->next;
 
506
      free (d);
 
507
    }
 
508
 
 
509
  snprintf (instfname, sizeof (instfname), "%s/%s", osslibdir,
 
510
            "etc/installed_drivers");
 
511
 
 
512
  if ((f = fopen (instfname, "w")) == NULL)
 
513
    {
 
514
      perror (instfname);
 
515
      exit (-1);
 
516
    }
 
517
 
 
518
  for (pass = 0; pass < MAX_PASS; pass++)
 
519
    for (i = 0; i < ndrivers; i++)
 
520
      if (drivers[i].pass == pass && drivers[i].detected)
 
521
        {
 
522
          fprintf (f, "%s #%s\n", drivers[i].driver, drivers[i].name);
 
523
        }
 
524
 
 
525
  fclose (f);
 
526
 
 
527
  exit (0);
 
528
}