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

Cache object: 61f3a25f4ed53f7d788b2d858aa30fca


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