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 <cg@freebsd.org>
    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.2/sys/dev/sound/pcm/sndstat.c 119853 2003-09-07 16:28:03Z 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         .d_open =       sndstat_open,
   45         .d_close =      sndstat_close,
   46         .d_read =       sndstat_read,
   47         .d_name =       "sndstat",
   48         .d_maj =        SND_CDEV_MAJOR,
   49 };
   50 
   51 struct sndstat_entry {
   52         SLIST_ENTRY(sndstat_entry) link;
   53         device_t dev;
   54         char *str;
   55         sndstat_handler handler;
   56         int type, unit;
   57 };
   58 
   59 #ifdef  USING_MUTEX
   60 static struct mtx sndstat_lock;
   61 #endif
   62 static struct sbuf sndstat_sbuf;
   63 static dev_t sndstat_dev = 0;
   64 static int sndstat_isopen = 0;
   65 static int sndstat_bufptr;
   66 static int sndstat_maxunit = -1;
   67 static int sndstat_files = 0;
   68 
   69 static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none);
   70 
   71 static int sndstat_verbose = 1;
   72 #ifdef  USING_MUTEX
   73 TUNABLE_INT("hw.snd.verbose", &sndstat_verbose);
   74 #else
   75 TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose);
   76 #endif
   77 
   78 static int sndstat_prepare(struct sbuf *s);
   79 
   80 static int
   81 sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
   82 {
   83         intrmask_t s;
   84         int error, verbose;
   85 
   86         verbose = sndstat_verbose;
   87         error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
   88         if (error == 0 && req->newptr != NULL) {
   89                 s = spltty();
   90                 mtx_lock(&sndstat_lock);
   91                 if (verbose < 0 || verbose > 3)
   92                         error = EINVAL;
   93                 else
   94                         sndstat_verbose = verbose;
   95                 mtx_unlock(&sndstat_lock);
   96                 splx(s);
   97         }
   98         return error;
   99 }
  100 SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW,
  101             0, sizeof(int), sysctl_hw_sndverbose, "I", "");
  102 
  103 static int
  104 sndstat_open(dev_t i_dev, int flags, int mode, struct thread *td)
  105 {
  106         intrmask_t s;
  107         int error;
  108 
  109         s = spltty();
  110         mtx_lock(&sndstat_lock);
  111         if (sndstat_isopen) {
  112                 mtx_unlock(&sndstat_lock);
  113                 splx(s);
  114                 return EBUSY;
  115         }
  116         sndstat_isopen = 1;
  117         mtx_unlock(&sndstat_lock);
  118         splx(s);
  119         if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
  120                 error = ENXIO;
  121                 goto out;
  122         }
  123         sndstat_bufptr = 0;
  124         error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
  125 out:
  126         if (error) {
  127                 s = spltty();
  128                 mtx_lock(&sndstat_lock);
  129                 sndstat_isopen = 0;
  130                 mtx_unlock(&sndstat_lock);
  131                 splx(s);
  132         }
  133         return (error);
  134 }
  135 
  136 static int
  137 sndstat_close(dev_t i_dev, int flags, int mode, struct thread *td)
  138 {
  139         intrmask_t s;
  140 
  141         s = spltty();
  142         mtx_lock(&sndstat_lock);
  143         if (!sndstat_isopen) {
  144                 mtx_unlock(&sndstat_lock);
  145                 splx(s);
  146                 return EBADF;
  147         }
  148         sbuf_delete(&sndstat_sbuf);
  149         sndstat_isopen = 0;
  150 
  151         mtx_unlock(&sndstat_lock);
  152         splx(s);
  153         return 0;
  154 }
  155 
  156 static int
  157 sndstat_read(dev_t i_dev, struct uio *buf, int flag)
  158 {
  159         intrmask_t s;
  160         int l, err;
  161 
  162         s = spltty();
  163         mtx_lock(&sndstat_lock);
  164         if (!sndstat_isopen) {
  165                 mtx_unlock(&sndstat_lock);
  166                 splx(s);
  167                 return EBADF;
  168         }
  169         l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
  170         err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
  171         sndstat_bufptr += l;
  172 
  173         mtx_unlock(&sndstat_lock);
  174         splx(s);
  175         return err;
  176 }
  177 
  178 /************************************************************************/
  179 
  180 static struct sndstat_entry *
  181 sndstat_find(int type, int unit)
  182 {
  183         struct sndstat_entry *ent;
  184 
  185         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  186                 if (ent->type == type && ent->unit == unit)
  187                         return ent;
  188         }
  189 
  190         return NULL;
  191 }
  192 
  193 int
  194 sndstat_register(device_t dev, char *str, sndstat_handler handler)
  195 {
  196         intrmask_t s;
  197         struct sndstat_entry *ent;
  198         const char *devtype;
  199         int type, unit;
  200 
  201         if (dev) {
  202                 unit = device_get_unit(dev);
  203                 devtype = device_get_name(dev);
  204                 if (!strcmp(devtype, "pcm"))
  205                         type = SS_TYPE_PCM;
  206                 else if (!strcmp(devtype, "midi"))
  207                         type = SS_TYPE_MIDI;
  208                 else if (!strcmp(devtype, "sequencer"))
  209                         type = SS_TYPE_SEQUENCER;
  210                 else
  211                         return EINVAL;
  212         } else {
  213                 type = SS_TYPE_MODULE;
  214                 unit = -1;
  215         }
  216 
  217         ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK);
  218         if (!ent)
  219                 return ENOSPC;
  220 
  221         ent->dev = dev;
  222         ent->str = str;
  223         ent->type = type;
  224         ent->unit = unit;
  225         ent->handler = handler;
  226 
  227         s = spltty();
  228         mtx_lock(&sndstat_lock);
  229         SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
  230         if (type == SS_TYPE_MODULE)
  231                 sndstat_files++;
  232         sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
  233         mtx_unlock(&sndstat_lock);
  234         splx(s);
  235 
  236         return 0;
  237 }
  238 
  239 int
  240 sndstat_registerfile(char *str)
  241 {
  242         return sndstat_register(NULL, str, NULL);
  243 }
  244 
  245 int
  246 sndstat_unregister(device_t dev)
  247 {
  248         intrmask_t s;
  249         struct sndstat_entry *ent;
  250 
  251         s = spltty();
  252         mtx_lock(&sndstat_lock);
  253         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  254                 if (ent->dev == dev) {
  255                         SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
  256                         mtx_unlock(&sndstat_lock);
  257                         splx(s);
  258                         free(ent, M_DEVBUF);
  259 
  260                         return 0;
  261                 }
  262         }
  263         mtx_unlock(&sndstat_lock);
  264         splx(s);
  265 
  266         return ENXIO;
  267 }
  268 
  269 int
  270 sndstat_unregisterfile(char *str)
  271 {
  272         intrmask_t s;
  273         struct sndstat_entry *ent;
  274 
  275         s = spltty();
  276         mtx_lock(&sndstat_lock);
  277         SLIST_FOREACH(ent, &sndstat_devlist, link) {
  278                 if (ent->dev == NULL && ent->str == str) {
  279                         SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
  280                         sndstat_files--;
  281                         mtx_unlock(&sndstat_lock);
  282                         splx(s);
  283                         free(ent, M_DEVBUF);
  284 
  285                         return 0;
  286                 }
  287         }
  288         mtx_unlock(&sndstat_lock);
  289         splx(s);
  290 
  291         return ENXIO;
  292 }
  293 
  294 /************************************************************************/
  295 
  296 static int
  297 sndstat_prepare(struct sbuf *s)
  298 {
  299         struct sndstat_entry *ent;
  300         int i, j;
  301 
  302         sbuf_printf(s, "FreeBSD Audio Driver (newpcm)\n");
  303         if (SLIST_EMPTY(&sndstat_devlist)) {
  304                 sbuf_printf(s, "No devices installed.\n");
  305                 sbuf_finish(s);
  306                 return sbuf_len(s);
  307         }
  308 
  309         sbuf_printf(s, "Installed devices:\n");
  310 
  311         for (i = 0; i <= sndstat_maxunit; i++) {
  312                 for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
  313                         ent = sndstat_find(j, i);
  314                         if (!ent)
  315                                 continue;
  316                         sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
  317                         sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
  318                         sbuf_printf(s, " %s", ent->str);
  319                         if (ent->handler)
  320                                 ent->handler(s, ent->dev, sndstat_verbose);
  321                         else
  322                                 sbuf_printf(s, " [no handler]");
  323                         sbuf_printf(s, "\n");
  324                 }
  325         }
  326 
  327         if (sndstat_verbose >= 3 && sndstat_files > 0) {
  328                 sbuf_printf(s, "\nFile Versions:\n");
  329 
  330                 SLIST_FOREACH(ent, &sndstat_devlist, link) {
  331                         if (ent->dev == NULL && ent->str != NULL)
  332                                 sbuf_printf(s, "%s\n", ent->str);
  333                 }
  334         }
  335 
  336         sbuf_finish(s);
  337         return sbuf_len(s);
  338 }
  339 
  340 static int
  341 sndstat_init(void)
  342 {
  343         mtx_init(&sndstat_lock, "sndstat", NULL, 0);
  344         sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
  345 
  346         return (sndstat_dev != 0)? 0 : ENXIO;
  347 }
  348 
  349 static int
  350 sndstat_uninit(void)
  351 {
  352         intrmask_t s;
  353 
  354         s = spltty();
  355         mtx_lock(&sndstat_lock);
  356         if (sndstat_isopen) {
  357                 mtx_unlock(&sndstat_lock);
  358                 splx(s);
  359                 return EBUSY;
  360         }
  361 
  362         if (sndstat_dev)
  363                 destroy_dev(sndstat_dev);
  364         sndstat_dev = 0;
  365 
  366         splx(s);
  367         mtx_destroy(&sndstat_lock);
  368         return 0;
  369 }
  370 
  371 int
  372 sndstat_busy(void)
  373 {
  374         return (sndstat_isopen);
  375 }
  376 
  377 static void
  378 sndstat_sysinit(void *p)
  379 {
  380         sndstat_init();
  381 }
  382 
  383 static void
  384 sndstat_sysuninit(void *p)
  385 {
  386         sndstat_uninit();
  387 }
  388 
  389 SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
  390 SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
  391 
  392 

Cache object: 61ccfd8ea013c25eaaeb6026be4f07ef


[ 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.