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


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