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

Cache object: 1f8690aa85cadb181e767d48bad63617


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