summaryrefslogtreecommitdiff
path: root/os_cmd/FreeBSD
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /os_cmd/FreeBSD
downloadoss4-upstream/4.2-build2006.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'os_cmd/FreeBSD')
-rw-r--r--os_cmd/FreeBSD/.config3
-rw-r--r--os_cmd/FreeBSD/ossdetect/ossdetect.c528
-rw-r--r--os_cmd/FreeBSD/ossdetect/ossdetect.man32
3 files changed, 563 insertions, 0 deletions
diff --git a/os_cmd/FreeBSD/.config b/os_cmd/FreeBSD/.config
new file mode 100644
index 0000000..99cac14
--- /dev/null
+++ b/os_cmd/FreeBSD/.config
@@ -0,0 +1,3 @@
+targetos=FreeBSD
+mode=sbin
+cflags=-I/sys
diff --git a/os_cmd/FreeBSD/ossdetect/ossdetect.c b/os_cmd/FreeBSD/ossdetect/ossdetect.c
new file mode 100644
index 0000000..678244b
--- /dev/null
+++ b/os_cmd/FreeBSD/ossdetect/ossdetect.c
@@ -0,0 +1,528 @@
+/*
+ * Purpose: OSS device autodetection utility for FreeBSD
+ *
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/pciio.h>
+#include <dev/pci/pcireg.h>
+
+#define PCI_PASS 0
+#define USB_PASS 1
+#define PSEUDO_PASS 2
+#define MAX_PASS 3
+
+#define OSSLIBDIRLEN 512
+static char *osslibdir = NULL;
+
+static int verbose = 0;
+
+typedef struct
+{
+ char *key, *driver, *name;
+ int is_3rdparty;
+ int detected;
+ int pass;
+} driver_def_t;
+
+typedef struct drv_slist
+{
+ const char * drv_name;
+ struct drv_slist * next;
+} drvlist_t;
+static drvlist_t * drvl = NULL;
+
+#define MAX_DRIVERS 1000
+static driver_def_t drivers[MAX_DRIVERS];
+static int ndrivers = 0;
+
+static int add_drv (const char *, int);
+static void create_devlinks (mode_t);
+#if 0
+static int remove_devlinks (const char *);
+#endif
+static drvlist_t * prepend_drvlist (const char *);
+static char * get_mapname (void);
+static void load_license (const char *);
+static void load_devlist (const char *, int);
+static void pci_detect (void);
+
+static char *
+get_mapname (void)
+{
+ FILE *f;
+ static char name[OSSLIBDIRLEN], tmp[OSSLIBDIRLEN+11];
+ struct stat st;
+
+ if ((f = fopen ("/etc/oss.conf", "r")) == NULL)
+ {
+ perror ("/etc/oss.conf");
+ goto oexit2;
+ }
+
+ while (fgets (tmp, sizeof (tmp), f) != NULL)
+ {
+ int l = strlen (tmp);
+ if (l > 0 && tmp[l - 1] == '\n')
+ tmp[l - 1] = '\0';
+
+ if (strncmp (tmp, "OSSLIBDIR=", 10) == 0)
+ {
+ l = snprintf (name, sizeof (name), "%s", &tmp[10]);
+ if ((l >= OSSLIBDIRLEN) || (l < 0))
+ {
+ fprintf (stderr, "String in /etc/oss.conf is too long!\n");
+ goto oexit;
+ }
+ if ((stat (name, &st) == -1) || !S_ISDIR(st.st_mode))
+ {
+ fprintf (stderr, "Directory %s from /etc/oss.conf cannot "
+ "be used!\n", name);
+ goto oexit;
+ }
+ fclose (f);
+ return name;
+ }
+ }
+
+ fprintf (stderr, "OSSLIBDIR not set in /etc/oss.conf, using default "
+ "/usr/lib/oss\n");
+oexit:
+ fclose (f);
+oexit2:
+ snprintf (name, sizeof (name), "/usr/lib/oss");
+ return name;
+}
+
+static void
+load_license (const char *fname)
+{
+ struct stat st;
+ char cmd[2*OSSLIBDIRLEN];
+ int n;
+
+ if (stat (fname, &st) == -1)
+ return; /* Doesn't exist */
+
+ if (stat ("/usr/sbin/osslic", &st) == -1)
+ return; /* No osslic utility in the system. No need to install license. */
+
+ n = snprintf (cmd, sizeof (cmd), "/usr/sbin/osslic -q %s/%s", osslibdir,
+ fname);
+ if (n >= sizeof (cmd) || n < 0) return;
+ if (((n = system (cmd)) == -1))
+ fprintf (stderr, "Cannot run osslic!\n");
+}
+
+static void
+load_devlist (const char *fname, int is_3rdparty)
+{
+ FILE *f;
+ char line[256], *p, rfname[2*OSSLIBDIRLEN];
+ char *driver, *key, *name;
+
+ snprintf (rfname, sizeof (rfname), "%s/%s", osslibdir, fname);
+
+ if ((f = fopen (rfname, "r")) == NULL)
+ {
+ perror (rfname);
+ exit (-1);
+ }
+
+ while (fgets (line, sizeof (line), f) != NULL)
+ {
+ p = line;
+ while (*p)
+ {
+ if (*p == '#' || *p == '\n')
+ *p = 0;
+ p++;
+ }
+
+ /* Drivers with upper case names are unsupported ones */
+ if ((*line >= 'A' && *line <= 'Z') || (*line == '\0'))
+ continue;
+
+ driver = line;
+ p = line;
+
+ while (*p && *p != '\t' && *p != ' ')
+ p++;
+ if (*p)
+ *p++ = 0;
+ key = p;
+
+ while (*p && *p != '\t')
+ p++;
+ if (*p)
+ *p++ = 0;
+ name = p;
+
+ if (verbose > 1)
+ printf ("device=%s, name=%s, driver=%s\n", key, name, driver);
+
+ if (ndrivers >= MAX_DRIVERS)
+ {
+ printf ("Too many drivers defined in drivers.list\n");
+ exit (-1);
+ }
+
+ drivers[ndrivers].key = strdup (key);
+ drivers[ndrivers].driver = strdup (driver);
+ drivers[ndrivers].name = strdup (name);
+ drivers[ndrivers].is_3rdparty = is_3rdparty;
+ drivers[ndrivers].detected = 0;
+
+ ndrivers++;
+ }
+
+ fclose (f);
+}
+
+static int
+add_drv (const char * id, int pass)
+{
+ int i;
+
+ for (i = 0; i < ndrivers; i++)
+ {
+ if (strcmp (id, drivers[i].key) == 0)
+ {
+ if (verbose > 0)
+ printf ("Detected %s\n", drivers[i].name);
+ drivers[i].detected = 1;
+ drivers[i].pass = pass;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+static int
+remove_devlinks (const char * dirname)
+{
+ char path[PATH_MAX];
+ DIR * dr;
+ struct dirent * de;
+ struct stat st;
+
+ if ((dr = opendir (dirname)) == NULL)
+ {
+ if (errno == ENONET) return 0;
+ perror ("opendir");
+ return -1;
+ }
+
+ while ((de = readdir (dr)) != NULL)
+ {
+ if ((!strcmp (de->d_name, ".")) || (!strcmp (de->d_name, ".."))) continue;
+
+ snprintf (path, sizeof (path), "%s/%s", dirname, de->d_name);
+
+ if ((stat (path, &st) != -1) && (S_ISDIR (st.st_mode))) remove_devlinks (path);
+ else
+ {
+ if (verbose > 2) fprintf (stderr, "Removing %s\n", path);
+ unlink (path);
+ }
+ }
+
+ closedir (dr);
+ if (verbose > 2) fprintf (stderr, "Removing %s\n", path);
+ if (rmdir (dirname) == -1)
+ {
+ fprintf (stderr, "Couldn't remove %s\n", path);
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+static void
+create_devlinks (mode_t node_m)
+{
+/* Doesn't work, since /proc isn't mounted by default on FreeBSD */
+ FILE *f;
+ char line[256], tmp[300], *p, *s;
+ mode_t perm;
+ int minor, major;
+
+ if ((f = fopen ("/proc/opensound/devfiles", "r")) == NULL)
+ {
+ perror ("/proc/opensound/devfiles");
+ fprintf (stderr, "Cannot connect to the OSS kernel module.\n");
+ fprintf (stderr, "Perhaps you need to execute 'soundon' to load OSS\n");
+ exit (-1);
+ }
+
+/* remove_devlinks("/dev/oss"); */
+ perm = umask (0);
+ mkdir ("/dev/oss", 0755);
+
+ while (fgets (line, sizeof (line), f) != NULL)
+ {
+ char dev[64] = "/dev/";
+
+ s = strchr (line, '\n');
+ if (s) *s = '\0';
+
+ if (sscanf (line, "%s %d %d", dev + 5, &major, &minor) != 3)
+ {
+ fprintf (stderr, "Syntax error in /proc/opensound/devfiles\n");
+ fprintf (stderr, "%s\n", line);
+ exit (-1);
+ }
+
+/*
+ * Check if the device is located in a subdirectory (say /dev/oss/sblive0/pcm0).
+ */
+ strcpy (tmp, dev);
+
+ s = tmp + 5;
+ p = s;
+ while (*s)
+ {
+ if (*s == '/')
+ p = s;
+ s++;
+ }
+
+ if (*p == '/')
+ {
+ *p = 0; /* Extract the directory name part */
+ mkdir (tmp, 0755);
+ }
+
+ unlink (dev);
+ if (verbose)
+ printf ("mknod %s c %d %d -m %o\n", dev, major, minor, node_m);
+ if (mknod (dev, node_m, makedev (major, minor)) == -1)
+ perror (dev);
+ }
+
+ umask (perm);
+ fclose (f);
+}
+
+static void
+pci_detect (void)
+{
+ int fd;
+ struct pci_conf_io pc;
+ struct pci_conf conf[255], *p;
+
+ if ((fd = open ("/dev/pci", O_RDONLY, 0)) == -1)
+ {
+ perror ("/dev/pci");
+ exit (-1);
+ }
+
+ bzero (&pc, sizeof (struct pci_conf_io));
+ pc.match_buf_len = sizeof (conf);
+ pc.matches = conf;
+
+ do
+ {
+ if (ioctl (fd, PCIOCGETCONF, &pc) == -1)
+ {
+ perror ("ioctl(PCIOCGETCONF)");
+ exit (1);
+ }
+
+ /*
+ * 255 entries should be more than enough for most people,
+ * but if someone has more devices, and then changes things
+ * around between ioctls, we'll do the cheezy thing and
+ * just bail. The alternative would be to go back to the
+ * beginning of the list, and print things twice, which may
+ * not be desireable.
+ */
+ if (pc.status == PCI_GETCONF_LIST_CHANGED)
+ {
+ fprintf (stderr, "PCI device list changed, please try again");
+ exit (1);
+ close (fd);
+ return;
+ }
+ else if (pc.status == PCI_GETCONF_ERROR)
+ {
+ fprintf (stderr, "error returned from PCIOCGETCONF ioctl");
+ exit (1);
+ close (fd);
+ return;
+ }
+ for (p = conf; p < &conf[pc.num_matches]; p++)
+ {
+
+ char name[32];
+
+ if (verbose > 2)
+ printf ("%s%d@pci%d:%d:%d:\tclass=0x%06x card=0x%08x "
+ "chip=0x%08x rev=0x%02x hdr=0x%02x\n",
+ (p->pd_name && *p->pd_name) ? p->pd_name :
+ "none",
+ (p->pd_name && *p->pd_name) ? (int) p->pd_unit :
+ p->pc_sel.pc_bus, p->pc_sel.pc_dev,
+ p->pc_sel.pc_func, (p->pc_class << 16) |
+ (p->pc_subclass << 8) | p->pc_progif,
+ (p->pc_subdevice << 16) | p->pc_subvendor,
+ (p->pc_device << 16) | p->pc_vendor,
+ p->pc_revid, p->pc_hdr);
+
+ sprintf (name, "pcs%x,%x", p->pc_subvendor, p->pc_subdevice);
+ if (add_drv (name, PCI_PASS))
+ continue;
+
+ sprintf (name, "pci%x,%x", p->pc_vendor, p->pc_device);
+ if (add_drv (name, PCI_PASS))
+ continue;
+ }
+ }
+ while (pc.status == PCI_GETCONF_MORE_DEVS);
+
+ close (fd);
+}
+
+static drvlist_t *
+prepend_drvlist (const char * name)
+{
+ drvlist_t * dp;
+
+ dp = malloc (sizeof (drvlist_t));
+ if (dp == NULL)
+ {
+ fprintf (stderr, "Can't allocate memory!\n");
+ exit (-1);
+ }
+
+ dp->drv_name = name;
+ dp->next = drvl;
+ return dp;
+}
+
+int
+main (int argc, char *argv[])
+{
+ char instfname[2*OSSLIBDIRLEN], *p;
+ int i, do_license = 0, make_devs = 0, pass;
+ mode_t node_m = S_IFCHR | 0666;
+ struct stat st;
+ FILE *f;
+
+ while ((i = getopt(argc, argv, "L:a:dilm:uv")) != EOF)
+ switch (i)
+ {
+ case 'v':
+ verbose++;
+ break;
+
+ case 'd':
+ make_devs = 1;
+ break;
+
+ case 'i':
+ drvl = prepend_drvlist ("oss_imux");
+ break;
+
+ case 'u':
+ drvl = prepend_drvlist ("oss_userdev");
+ break;
+
+ case 'a':
+ drvl = prepend_drvlist (optarg);
+ break;
+
+ case 'l':
+ do_license = 1;
+ break;
+
+ case 'L':
+ osslibdir = optarg;
+ break;
+
+ case 'm':
+ p = optarg;
+ node_m = 0;
+ while ((*p >= '0') && (*p <= '7')) node_m = node_m * 8 + *p++ - '0';
+ if ((*p) || (node_m & ~(S_IRWXU|S_IRWXG|S_IRWXO)))
+ {
+ fprintf (stderr, "Invalid permissions: %s\n", optarg);
+ exit(1);
+ }
+ node_m |= S_IFCHR;
+ break;
+
+ default:
+ fprintf (stderr, "%s: bad usage\n", argv[0]);
+ exit (-1);
+ }
+
+ if (osslibdir == NULL) osslibdir = get_mapname ();
+
+ if (make_devs == 1)
+ {
+ create_devlinks (node_m);
+ exit (0);
+ }
+
+ if (do_license == 1)
+ {
+ load_license ("etc/license.asc");
+ exit (0);
+ }
+
+ load_devlist ("etc/devices.list", 0);
+
+ if (stat ("/etc/oss_3rdparty", &st) != -1)
+ load_devlist ("/etc/oss_3rdparty", 1);
+
+ pci_detect ();
+
+ while (drvl != NULL)
+ {
+ drvlist_t * d = drvl;
+ add_drv (drvl->drv_name, PSEUDO_PASS);
+ drvl = drvl->next;
+ free (d);
+ }
+
+ snprintf (instfname, sizeof (instfname), "%s/%s", osslibdir,
+ "etc/installed_drivers");
+
+ if ((f = fopen (instfname, "w")) == NULL)
+ {
+ perror (instfname);
+ exit (-1);
+ }
+
+ for (pass = 0; pass < MAX_PASS; pass++)
+ for (i = 0; i < ndrivers; i++)
+ if (drivers[i].pass == pass && drivers[i].detected)
+ {
+ fprintf (f, "%s #%s\n", drivers[i].driver, drivers[i].name);
+ }
+
+ fclose (f);
+
+ exit (0);
+}
diff --git a/os_cmd/FreeBSD/ossdetect/ossdetect.man b/os_cmd/FreeBSD/ossdetect/ossdetect.man
new file mode 100644
index 0000000..a05cca5
--- /dev/null
+++ b/os_cmd/FreeBSD/ossdetect/ossdetect.man
@@ -0,0 +1,32 @@
+NAME
+ossdetect - Open Sound System audio device detection program.
+
+SYNOPSIS
+ossdetect [-diuv] [-m<mode>] [-L<path>]
+
+DESCRIPTION
+The ossdetect application performs automatic detection of soundcards.
+The application looks at the /usr/lib/oss/etc/device.list and performs
+automatic detection. It will create a file with the list of the configured
+drivers in /usr/lib/oss/etc/installed_drivers.
+
+The Input Multiplexer driver (IMUX) is not configured by default and
+can be added to the OSS configuration using the -i option.
+
+OPTIONS
+-d Create device file links.
+-i Adds the oss_imux driver.
+-m<mode> Create nodes with permissions set to octal <mode>.
+-u Adds the oss_userdev driver.
+-v Verbose output.
+-L<path> Use <path> as root directory for OSS files.
+ Default: Path from /etc/oss.conf, followed by /usr/lib/oss.
+
+SEE ALSO
+ossdevlinks(1), ossinfo(1)
+
+FILES
+/usr/sbin/ossdetect
+
+AUTHOR
+4Front Technologies