The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pcm/sndstat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2001 Cameron Grant <gandalf@vilnya.demon.co.uk>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <dev/sound/pcm/sound.h>
   28 #include <dev/sound/pcm/vchan.h>
   29 
   30 SND_DECLARE_FILE("$FreeBSD: releng/5.0/sys/dev/sound/pcm/sndstat.c 107237 2002-11-25 17:17:43Z cg $");
   31 
   32 #define SS_TYPE_MODULE          0
   33 #define SS_TYPE_FIRST           1
   34 #define SS_TYPE_PCM             1
   35 #define SS_TYPE_MIDI            2
   36 #define SS_TYPE_SEQUENCER       3
   37 #define SS_TYPE_LAST            3
   38 
   39 static d_open_t sndstat_open;
   40 static d_close_t sndstat_close;
   41 static d_read_t sndstat_read;
   42 
   43 static struct cdevsw sndstat_cdevsw = {
   44         /* open */      sndstat_open,
   45         /* close */     sndstat_close,
   46         /* read */      sndstat_read,
   47         /* write */     nowrite,
   48         /* ioctl */     noioctl,
   49         /* poll */      nopoll,
   50         /* mmap */      nommap,
   51         /* strategy */  nostrategy,
   52         /* name */      "sndstat",
   53         /* maj */       SND_CDEV_MAJOR,
   54         /* dump */      nodump,
   55         /* psize */     nopsize,
   56         /* flags */     0,
   57 };
   58 
   59 struct sndstat_entry {
   60         SLIST_ENTRY(sndstat_entry) link;
   61         device_t dev;
   62         char *str;
   63         sndstat_handler handler;
   64         int type, unit;
   65 };
   66 
   67 #ifdef  USING_MUTEX
   68 static struct mtx sndstat_lock;
   69 #endif
   70 static struct sbuf sndstat_sbuf;
   71 static dev_t sndstat_dev = 0;
   72 static int sndstat_isopen = 0;
   73 static int sndstat_bufptr;
   74 static int sndstat_maxunit = -1;
   75 static int sndstat_files = 0;
   76 
   77 static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none);
   78 
   79 static int sndstat_verbose = 1;
   80 #ifdef  USING_MUTEX
   81 TUNABLE_INT("hw.snd.verbose", &sndstat_verbose);
   82 #else
   83 TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose);
   84 #endif
   85 
   86 static int sndstat_prepare(struct sbuf *s);
   87 
   88 static int
   89 sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
   90 {
   91         intrmask_t s;
   92         int error, verbose;
   93 
   94         verbose = sndstat_verbose;
   95         error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
   96         if (error == 0 && req->newptr != NULL) {
   97                 s = spltty();
   98                 mtx_lock(&sndstat_lock);
   99                 if (verbose < 0 || verbose > 3)
  100                         error = EINVAL;
  101                 else
  102                         sndstat_verbose = verbose;
  103                 mtx_unlock(&sndstat_lock);
  104                 splx(s);
  105         }
  106         return error;
  107 }
  108 SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW,
  109             0, sizeof(int), sysctl_hw_sndverbose, "I", "");
  110 
  111 static int
  112 sndstat_open(dev_t i_dev, int flags, int mode, struct thread *td)
  113 {
  114         intrmask_t s;
  115         int error;
  116 
  117         s = spltty();
  118         mtx_lock(&sndstat_lock);
  119         if (sndstat_isopen) {
  120                 mtx_unlock(&sndstat_lock);
  121                 splx(s);
  122                 return EBUSY;
  123         }
  124         sndstat_isopen = 1;
  125         mtx_unlock(&sndstat_lock);
  126         splx(s);
  127         if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
  128                 error = ENXIO;
  129                 goto out;
  130         }
  131         sndstat_bufptr = 0;
  132         error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
  133 out:
  134         if (error) {
  135                 s = spltty();
  136                 mtx_lock(&sndstat_lock);
  137                 sndstat_isopen = 0;
  138                 mtx_unlock(&sndstat_lock);
  139                 splx(s);
  140         }
  141         return (error);
  142 }
  143 
  144 static int
  145 sndstat_close(dev_t i_dev, int flags, int mode, struct thread *td)
  146 {
  147         intrmask_t s;
  148 
  149         s = spltty();
  150         mtx_lock(&sndstat_lock);
  151         if (!sndstat_isopen) {
  152                 mtx_unlock(&sndstat_lock);
  153                 splx(s);
  154                 return EBADF;
  155         }
  156         sbuf_delete(&sndstat_sbuf);
  157         sndstat_isopen = 0;
  158 
  159         mtx_unlock(&sndstat_lock);
  160         splx(s);
  161         return 0;
  162 }
  163 
  164 static int
  165 sndstat_read(dev_t i_dev, struct uio *buf, int flag)
  166 {
  167         intrmask_t s;
  168         int l, err;
  169 
  170         s = spltty();
  171         mtx_lock(&sndstat_lock);
  172         if (!sndstat_isopen) {
  173                 mtx_unlock(&sndstat_lock);
  174                 splx(s);
  175                 return EBADF;
  176         }
  177         l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
  178         err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
  179         sndstat_bufptr += l;
  180 
  181         mtx_unlock(&sndstat_lock);
  182         splx(s);
  183         return err;
  184 }
  185 
  186 /************************************************************************/
  187 
  188 static struct sndstat_entry *
  189 sndstat_find(int type, int unit)
  190 {
  191         struct sndstat_entry *ent;
  192 
  193         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  194                 if (ent->type == type && ent->unit == unit)
  195                         return ent;
  196         }
  197 
  198         return NULL;
  199 }
  200 
  201 int
  202 sndstat_register(device_t dev, char *str, sndstat_handler handler)
  203 {
  204         intrmask_t s;
  205         struct sndstat_entry *ent;
  206         const char *devtype;
  207         int type, unit;
  208 
  209         if (dev) {
  210                 unit = device_get_unit(dev);
  211                 devtype = device_get_name(dev);
  212                 if (!strcmp(devtype, "pcm"))
  213                         type = SS_TYPE_PCM;
  214                 else if (!strcmp(devtype, "midi"))
  215                         type = SS_TYPE_MIDI;
  216                 else if (!strcmp(devtype, "sequencer"))
  217                         type = SS_TYPE_SEQUENCER;
  218                 else
  219                         return EINVAL;
  220         } else {
  221                 type = SS_TYPE_MODULE;
  222                 unit = -1;
  223         }
  224 
  225         ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK);
  226         if (!ent)
  227                 return ENOSPC;
  228 
  229         ent->dev = dev;
  230         ent->str = str;
  231         ent->type = type;
  232         ent->unit = unit;
  233         ent->handler = handler;
  234 
  235         s = spltty();
  236         mtx_lock(&sndstat_lock);
  237         SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
  238         if (type == SS_TYPE_MODULE)
  239                 sndstat_files++;
  240         sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
  241         mtx_unlock(&sndstat_lock);
  242         splx(s);
  243 
  244         return 0;
  245 }
  246 
  247 int
  248 sndstat_registerfile(char *str)
  249 {
  250         return sndstat_register(NULL, str, NULL);
  251 }
  252 
  253 int
  254 sndstat_unregister(device_t dev)
  255 {
  256         intrmask_t s;
  257         struct sndstat_entry *ent;
  258 
  259         s = spltty();
  260         mtx_lock(&sndstat_lock);
  261         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  262                 if (ent->dev == dev) {
  263                         SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
  264                         mtx_unlock(&sndstat_lock);
  265                         splx(s);
  266                         free(ent, M_DEVBUF);
  267 
  268                         return 0;
  269                 }
  270         }
  271         mtx_unlock(&sndstat_lock);
  272         splx(s);
  273 
  274         return ENXIO;
  275 }
  276 
  277 int
  278 sndstat_unregisterfile(char *str)
  279 {
  280         intrmask_t s;
  281         struct sndstat_entry *ent;
  282 
  283         s = spltty();
  284         mtx_lock(&sndstat_lock);
  285         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  286                 if (ent->dev == NULL && ent->str == str) {
  287                         SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
  288                         sndstat_files--;
  289                         mtx_unlock(&sndstat_lock);
  290                         splx(s);
  291                         free(ent, M_DEVBUF);
  292 
  293                         return 0;
  294                 }
  295         }
  296         mtx_unlock(&sndstat_lock);
  297         splx(s);
  298 
  299         return ENXIO;
  300 }
  301 
  302 /************************************************************************/
  303 
  304 static int
  305 sndstat_prepare(struct sbuf *s)
  306 {
  307         struct sndstat_entry *ent;
  308         int i, j;
  309 
  310         sbuf_printf(s, "FreeBSD Audio Driver (newpcm)\n");
  311         if (SLIST_EMPTY(&sndstat_devlist)) {
  312                 sbuf_printf(s, "No devices installed.\n");
  313                 sbuf_finish(s);
  314                 return sbuf_len(s);
  315         }
  316 
  317         sbuf_printf(s, "Installed devices:\n");
  318 
  319         for (i = 0; i <= sndstat_maxunit; i++) {
  320                 for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
  321                         ent = sndstat_find(j, i);
  322                         if (!ent)
  323                                 continue;
  324                         sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
  325                         sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
  326                         sbuf_printf(s, " %s", ent->str);
  327                         if (ent->handler)
  328                                 ent->handler(s, ent->dev, sndstat_verbose);
  329                         else
  330                                 sbuf_printf(s, " [no handler]");
  331                         sbuf_printf(s, "\n");
  332                 }
  333         }
  334 
  335         if (sndstat_verbose >= 3 && sndstat_files > 0) {
  336                 sbuf_printf(s, "\nFile Versions:\n");
  337 
  338                 SLIST_FOREACH(ent, &sndstat_devlist, link) {
  339                         if (ent->dev == NULL && ent->str != NULL)
  340                                 sbuf_printf(s, "%s\n", ent->str);
  341                 }
  342         }
  343 
  344         sbuf_finish(s);
  345         return sbuf_len(s);
  346 }
  347 
  348 static int
  349 sndstat_init(void)
  350 {
  351         mtx_init(&sndstat_lock, "sndstat", NULL, 0);
  352         sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
  353 
  354         return (sndstat_dev != 0)? 0 : ENXIO;
  355 }
  356 
  357 static int
  358 sndstat_uninit(void)
  359 {
  360         intrmask_t s;
  361 
  362         s = spltty();
  363         mtx_lock(&sndstat_lock);
  364         if (sndstat_isopen) {
  365                 mtx_unlock(&sndstat_lock);
  366                 splx(s);
  367                 return EBUSY;
  368         }
  369 
  370         if (sndstat_dev)
  371                 destroy_dev(sndstat_dev);
  372         sndstat_dev = 0;
  373 
  374         splx(s);
  375         mtx_destroy(&sndstat_lock);
  376         return 0;
  377 }
  378 
  379 int
  380 sndstat_busy(void)
  381 {
  382         return (sndstat_isopen);
  383 }
  384 
  385 static void
  386 sndstat_sysinit(void *p)
  387 {
  388         sndstat_init();
  389 }
  390 
  391 static void
  392 sndstat_sysuninit(void *p)
  393 {
  394         sndstat_uninit();
  395 }
  396 
  397 SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
  398 SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
  399 
  400 

Cache object: d5030cf47baf660a9e5f08a34d887f23


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.