Lines Matching +full:dsp +full:- +full:ctrl

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
5 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
8 * Copyright (c) 2024-2025 The FreeBSD Foundation
60 "linux mmap compatibility (-1=force disable 0=auto 1=force enable)");
65 "DSP basename cloning (0: Disable; 1: Enabled)");
67 #define DSP_REGISTERED(x) (PCM_REGISTERED(x) && (x)->dsp_dev != NULL)
94 .d_name = "dsp",
130 err = make_dev_s(&devargs, &sc->dsp_dev, "dsp%d", unit); in dsp_make_dev()
132 device_printf(dev, "failed to create dsp%d: error %d", in dsp_make_dev()
146 destroy_dev(d->dsp_dev); in dsp_destroy_dev()
152 if (priv->rdch != NULL && DSP_F_READ(prio)) in dsp_lock_chans()
153 CHN_LOCK(priv->rdch); in dsp_lock_chans()
154 if (priv->wrch != NULL && DSP_F_WRITE(prio)) in dsp_lock_chans()
155 CHN_LOCK(priv->wrch); in dsp_lock_chans()
161 if (priv->rdch != NULL && DSP_F_READ(prio)) in dsp_unlock_chans()
162 CHN_UNLOCK(priv->rdch); in dsp_unlock_chans()
163 if (priv->wrch != NULL && DSP_F_WRITE(prio)) in dsp_unlock_chans()
164 CHN_UNLOCK(priv->wrch); in dsp_unlock_chans()
183 pid = td->td_proc->p_pid; in dsp_chn_alloc()
184 comm = td->td_proc->p_comm; in dsp_chn_alloc()
186 vdir_enabled = (direction == PCMDIR_PLAY && d->flags & SD_F_PVCHANS) || in dsp_chn_alloc()
187 (direction == PCMDIR_REC && d->flags & SD_F_RVCHANS); in dsp_chn_alloc()
192 if (c->direction != direction) { in dsp_chn_alloc()
197 if ((c->flags & CHN_F_BUSY) == 0 || in dsp_chn_alloc()
198 (vdir_enabled && (c->flags & CHN_F_HAS_VCHAN))) in dsp_chn_alloc()
207 * - vchans are enabled, add a new vchan to the primary channel. in dsp_chn_alloc()
208 * - vchans are disabled, use the primary channel directly. in dsp_chn_alloc()
210 if (vdir_enabled && ((c->flags & CHN_F_BUSY) == 0 || in dsp_chn_alloc()
211 c->flags & CHN_F_HAS_VCHAN)) { in dsp_chn_alloc()
217 } else if ((c->flags & CHN_F_BUSY) == 0) { in dsp_chn_alloc()
224 (*ch)->flags |= CHN_F_BUSY; in dsp_chn_alloc()
226 (*ch)->flags |= CHN_F_NBIO; in dsp_chn_alloc()
228 (*ch)->flags |= CHN_F_EXCLUSIVE; in dsp_chn_alloc()
229 (*ch)->pid = pid; in dsp_chn_alloc()
230 strlcpy((*ch)->comm, (comm != NULL) ? comm : CHN_COMM_UNKNOWN, in dsp_chn_alloc()
231 sizeof((*ch)->comm)); in dsp_chn_alloc()
233 if ((err = chn_reset(*ch, (*ch)->format, (*ch)->speed)) != 0) in dsp_chn_alloc()
253 d = priv->sc; in dsp_close()
264 rdch = priv->rdch; in dsp_close()
265 wrch = priv->wrch; in dsp_close()
292 if (rdch->flags & CHN_F_VIRTUAL) { in dsp_close()
293 parent = rdch->parentchannel; in dsp_close()
301 rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | in dsp_close()
317 if (wrch->flags & CHN_F_VIRTUAL) { in dsp_close()
318 parent = wrch->parentchannel; in dsp_close()
326 wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | in dsp_close()
356 d = i_dev->si_drv1; in dsp_open()
364 priv->sc = d; in dsp_open()
380 ((DSP_F_READ(flags) && d->reccount == 0) || in dsp_open()
381 (DSP_F_WRITE(flags) && d->playcount == 0))) in dsp_open()
383 if (pcm_getflags(d->dev) & SD_F_SIMPLEX) { in dsp_open()
391 if (d->playcount > 0) in dsp_open()
393 else if (d->reccount > 0) in dsp_open()
397 if (ch->direction == PCMDIR_PLAY) in dsp_open()
399 else if (ch->direction == PCMDIR_REC) in dsp_open()
409 if (ch->direction != dir) in dsp_open()
428 error = dsp_chn_alloc(d, &priv->wrch, PCMDIR_PLAY, flags, td); in dsp_open()
435 CHN_INSERT_HEAD(d, priv->wrch, channels.pcm.opened); in dsp_open()
439 error = dsp_chn_alloc(d, &priv->rdch, PCMDIR_REC, flags, td); in dsp_open()
446 CHN_INSERT_HEAD(d, priv->rdch, channels.pcm.opened); in dsp_open()
466 (buf->uio_rw == UIO_READ || buf->uio_rw == UIO_WRITE), in dsp_io_ops()
469 d = priv->sc; in dsp_io_ops()
475 switch (buf->uio_rw) { in dsp_io_ops()
478 ch = &priv->rdch; in dsp_io_ops()
483 ch = &priv->wrch; in dsp_io_ops()
487 panic("invalid/corrupted uio direction: %d", buf->uio_rw); in dsp_io_ops()
491 runpid = buf->uio_td->td_proc->p_pid; in dsp_io_ops()
495 if (*ch == NULL || !((*ch)->flags & CHN_F_BUSY)) { in dsp_io_ops()
496 if (priv->rdch != NULL || priv->wrch != NULL) in dsp_io_ops()
502 if (((*ch)->flags & (CHN_F_MMAP | CHN_F_DEAD)) || in dsp_io_ops()
503 (((*ch)->flags & CHN_F_RUNNING) && (*ch)->pid != runpid)) { in dsp_io_ops()
507 } else if (!((*ch)->flags & CHN_F_RUNNING)) { in dsp_io_ops()
508 (*ch)->flags |= CHN_F_RUNNING; in dsp_io_ops()
509 (*ch)->pid = runpid; in dsp_io_ops()
517 ++(*ch)->inprog; in dsp_io_ops()
519 --(*ch)->inprog; in dsp_io_ops()
521 CHN_BROADCAST(&(*ch)->cv); in dsp_io_ops()
560 d = priv->sc; in dsp_ioctl_channel()
561 if (!PCM_REGISTERED(d) || !(pcm_getflags(d->dev) & SD_F_VPC)) in dsp_ioctl_channel()
562 return (-1); in dsp_ioctl_channel()
568 rdch = priv->rdch; in dsp_ioctl_channel()
569 wrch = priv->wrch; in dsp_ioctl_channel()
582 if (!(ch->feederflags & (1 << FEEDER_VOLUME))) { in dsp_ioctl_channel()
591 if (ch->direction == PCMDIR_REC) { in dsp_ioctl_channel()
598 if (ch->direction != PCMDIR_PLAY) in dsp_ioctl_channel()
607 if (ch->direction != PCMDIR_REC) in dsp_ioctl_channel()
626 if (ch->direction == PCMDIR_REC) { in dsp_ioctl_channel()
633 if (ch->direction != PCMDIR_PLAY) in dsp_ioctl_channel()
641 if (ch->direction != PCMDIR_REC) in dsp_ioctl_channel()
651 if (ch->direction == PCMDIR_REC) in dsp_ioctl_channel()
682 d = priv->sc; in dsp_ioctl()
700 if (ret != -1) { in dsp_ioctl()
705 if (d->mixer_dev != NULL) { in dsp_ioctl()
707 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td, in dsp_ioctl()
753 rdch = priv->rdch; in dsp_ioctl()
754 wrch = priv->wrch; in dsp_ioctl()
756 if (wrch != NULL && (wrch->flags & CHN_F_DEAD)) in dsp_ioctl()
758 if (rdch != NULL && (rdch->flags & CHN_F_DEAD)) in dsp_ioctl()
775 if (wrch && wrch->bufhard.dl) in dsp_ioctl()
778 *arg_i = sndbuf_getfree(wrch->bufsoft); in dsp_ioctl()
790 p->play_size = 0; in dsp_ioctl()
791 p->rec_size = 0; in dsp_ioctl()
795 chn_setblocksize(wrch, 2, p->play_size); in dsp_ioctl()
796 p->play_size = sndbuf_getblksz(wrch->bufsoft); in dsp_ioctl()
801 chn_setblocksize(rdch, 2, p->rec_size); in dsp_ioctl()
802 p->rec_size = sndbuf_getblksz(rdch->bufsoft); in dsp_ioctl()
814 p->play_size = sndbuf_getblksz(wrch->bufsoft); in dsp_ioctl()
819 p->rec_size = sndbuf_getblksz(rdch->bufsoft); in dsp_ioctl()
831 ((p->play_format != 0 && p->play_rate == 0) || in dsp_ioctl()
832 (p->rec_format != 0 && p->rec_rate == 0))) { in dsp_ioctl()
839 if (cmd == AIOSFMT && p->play_format != 0) { in dsp_ioctl()
841 SND_FORMAT(p->play_format, in dsp_ioctl()
842 AFMT_CHANNEL(wrch->format), in dsp_ioctl()
843 AFMT_EXTCHANNEL(wrch->format))); in dsp_ioctl()
844 chn_setspeed(wrch, p->play_rate); in dsp_ioctl()
846 p->play_rate = wrch->speed; in dsp_ioctl()
847 p->play_format = AFMT_ENCODING(wrch->format); in dsp_ioctl()
850 p->play_rate = 0; in dsp_ioctl()
851 p->play_format = 0; in dsp_ioctl()
855 if (cmd == AIOSFMT && p->rec_format != 0) { in dsp_ioctl()
857 SND_FORMAT(p->rec_format, in dsp_ioctl()
858 AFMT_CHANNEL(rdch->format), in dsp_ioctl()
859 AFMT_EXTCHANNEL(rdch->format))); in dsp_ioctl()
860 chn_setspeed(rdch, p->rec_rate); in dsp_ioctl()
862 p->rec_rate = rdch->speed; in dsp_ioctl()
863 p->rec_format = AFMT_ENCODING(rdch->format); in dsp_ioctl()
866 p->rec_rate = 0; in dsp_ioctl()
867 p->rec_format = 0; in dsp_ioctl()
888 p->rate_min = max(rcaps? rcaps->minspeed : 0, in dsp_ioctl()
889 pcaps? pcaps->minspeed : 0); in dsp_ioctl()
890 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, in dsp_ioctl()
891 pcaps? pcaps->maxspeed : 1000000); in dsp_ioctl()
892 p->bufsize = min(rdch? sndbuf_getsize(rdch->bufsoft) : 1000000, in dsp_ioctl()
893 wrch? sndbuf_getsize(wrch->bufsoft) : 1000000); in dsp_ioctl()
895 p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & in dsp_ioctl()
898 p->formats |= in dsp_ioctl()
899 (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 0 : in dsp_ioctl()
902 pdev = d->mixer_dev; in dsp_ioctl()
903 p->mixers = 1; /* default: one mixer */ in dsp_ioctl()
904 p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; in dsp_ioctl()
905 p->left = p->right = 100; in dsp_ioctl()
931 ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); in dsp_ioctl()
940 /* if (rdch && rdch->bufhard.dl) in dsp_ioctl()
943 *arg_i = sndbuf_getready(rdch->bufsoft); in dsp_ioctl()
955 case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */ in dsp_ioctl()
956 case FIONBIO: /* set/clear non-blocking i/o */ in dsp_ioctl()
960 rdch->flags |= CHN_F_NBIO; in dsp_ioctl()
962 rdch->flags &= ~CHN_F_NBIO; in dsp_ioctl()
968 wrch->flags |= CHN_F_NBIO; in dsp_ioctl()
970 wrch->flags &= ~CHN_F_NBIO; in dsp_ioctl()
976 * Finally, here is the linux-compatible ioctl interface in dsp_ioctl()
984 *arg_i = sndbuf_getblksz(chn->bufsoft); in dsp_ioctl()
1009 DEB(printf("dsp reset\n")); in dsp_ioctl()
1025 DEB(printf("dsp sync\n")); in dsp_ioctl()
1041 tmp = wrch->speed; in dsp_ioctl()
1048 tmp = rdch->speed; in dsp_ioctl()
1059 *arg_i = chn->speed; in dsp_ioctl()
1068 tmp = -1; in dsp_ioctl()
1074 SND_FORMAT(wrch->format, *arg_i, 0)); in dsp_ioctl()
1075 tmp = (AFMT_CHANNEL(wrch->format) > 1)? 1 : 0; in dsp_ioctl()
1081 SND_FORMAT(rdch->format, *arg_i, 0)); in dsp_ioctl()
1082 if (tmp == -1) in dsp_ioctl()
1083 tmp = (AFMT_CHANNEL(rdch->format) > 1)? 1 : 0; in dsp_ioctl()
1107 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_ioctl()
1115 ext = m->ext; in dsp_ioctl()
1122 SND_FORMAT(wrch->format, *arg_i, ext)); in dsp_ioctl()
1123 tmp = AFMT_CHANNEL(wrch->format); in dsp_ioctl()
1129 SND_FORMAT(rdch->format, *arg_i, ext)); in dsp_ioctl()
1131 tmp = AFMT_CHANNEL(rdch->format); in dsp_ioctl()
1139 *arg_i = AFMT_CHANNEL(chn->format); in dsp_ioctl()
1148 *arg_i = AFMT_CHANNEL(chn->format); in dsp_ioctl()
1175 AFMT_CHANNEL(wrch->format), in dsp_ioctl()
1176 AFMT_EXTCHANNEL(wrch->format))); in dsp_ioctl()
1177 tmp = wrch->format; in dsp_ioctl()
1183 AFMT_CHANNEL(rdch->format), in dsp_ioctl()
1184 AFMT_EXTCHANNEL(rdch->format))); in dsp_ioctl()
1186 tmp = rdch->format; in dsp_ioctl()
1194 *arg_i = AFMT_ENCODING(chn->format); in dsp_ioctl()
1222 r_maxfrags = sndbuf_getblkcnt(rdch->bufsoft); in dsp_ioctl()
1223 r_fragsz = sndbuf_getblksz(rdch->bufsoft); in dsp_ioctl()
1232 maxfrags = sndbuf_getblkcnt(wrch->bufsoft); in dsp_ioctl()
1233 fragsz = sndbuf_getblksz(wrch->bufsoft); in dsp_ioctl()
1255 struct snd_dbuf *bs = rdch->bufsoft; in dsp_ioctl()
1258 a->bytes = sndbuf_getready(bs); in dsp_ioctl()
1259 a->fragments = a->bytes / sndbuf_getblksz(bs); in dsp_ioctl()
1260 a->fragstotal = sndbuf_getblkcnt(bs); in dsp_ioctl()
1261 a->fragsize = sndbuf_getblksz(bs); in dsp_ioctl()
1273 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1276 a->bytes = sndbuf_getfree(bs); in dsp_ioctl()
1277 a->fragments = a->bytes / sndbuf_getblksz(bs); in dsp_ioctl()
1278 a->fragstotal = sndbuf_getblkcnt(bs); in dsp_ioctl()
1279 a->fragsize = sndbuf_getblksz(bs); in dsp_ioctl()
1290 struct snd_dbuf *bs = rdch->bufsoft; in dsp_ioctl()
1293 a->bytes = sndbuf_gettotal(bs); in dsp_ioctl()
1294 a->blocks = sndbuf_getblocks(bs) - rdch->blocks; in dsp_ioctl()
1295 a->ptr = sndbuf_getfreeptr(bs); in dsp_ioctl()
1296 rdch->blocks = sndbuf_getblocks(bs); in dsp_ioctl()
1307 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1310 a->bytes = sndbuf_gettotal(bs); in dsp_ioctl()
1311 a->blocks = sndbuf_getblocks(bs) - wrch->blocks; in dsp_ioctl()
1312 a->ptr = sndbuf_getreadyptr(bs); in dsp_ioctl()
1313 wrch->blocks = sndbuf_getblocks(bs); in dsp_ioctl()
1323 if (rdch && wrch && !(pcm_getflags(d->dev) & SD_F_SIMPLEX)) in dsp_ioctl()
1325 if (rdch && (rdch->flags & CHN_F_VIRTUAL) != 0) in dsp_ioctl()
1327 if (wrch && (wrch->flags & CHN_F_VIRTUAL) != 0) in dsp_ioctl()
1336 if (chn->format & AFMT_8BIT) in dsp_ioctl()
1338 else if (chn->format & AFMT_16BIT) in dsp_ioctl()
1340 else if (chn->format & AFMT_24BIT) in dsp_ioctl()
1342 else if (chn->format & AFMT_32BIT) in dsp_ioctl()
1356 rdch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1362 rdch->flags |= CHN_F_NOTRIGGER; in dsp_ioctl()
1368 wrch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1374 wrch->flags |= CHN_F_NOTRIGGER; in dsp_ioctl()
1384 if (wrch->flags & CHN_F_TRIGGERED) in dsp_ioctl()
1390 if (rdch->flags & CHN_F_TRIGGERED) in dsp_ioctl()
1398 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1410 wrch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1418 * switch to full-duplex mode if card is in half-duplex in dsp_ioctl()
1419 * mode and is able to work in full-duplex mode in dsp_ioctl()
1422 if (rdch && wrch && (pcm_getflags(d->dev) & SD_F_SIMPLEX)) in dsp_ioctl()
1423 pcm_setflags(d->dev, pcm_getflags(d->dev)^SD_F_SIMPLEX); in dsp_ioctl()
1457 if (ret != -1) { in dsp_ioctl()
1462 if (d->mixer_dev != NULL) { in dsp_ioctl()
1464 ret = mixer_ioctl_cmd(d->mixer_dev, xcmd, arg, -1, td, in dsp_ioctl()
1475 if (d->mixer_dev != NULL) { in dsp_ioctl()
1477 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td, in dsp_ioctl()
1494 ei->dev = 0; in dsp_ioctl()
1495 ei->ctrl = 0; in dsp_ioctl()
1496 ei->version = 0; /* static for now */ in dsp_ioctl()
1497 ei->strindex[0] = 0; in dsp_ioctl()
1500 ei->nvalues = 1; in dsp_ioctl()
1501 strlcpy(ei->strings, wrch->name, in dsp_ioctl()
1502 sizeof(ei->strings)); in dsp_ioctl()
1504 ei->nvalues = 0; in dsp_ioctl()
1505 ei->strings[0] = '\0'; in dsp_ioctl()
1525 * Flush the software (pre-feed) buffer, but try to minimize playback in dsp_ioctl()
1535 while (wrch->inprog != 0) in dsp_ioctl()
1536 cv_wait(&wrch->cv, wrch->lock); in dsp_ioctl()
1537 bs = wrch->bufsoft; in dsp_ioctl()
1538 if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) { in dsp_ioctl()
1539 bs->sl = sndbuf_getready(bs); in dsp_ioctl()
1540 sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs)); in dsp_ioctl()
1559 while (wrch->inprog != 0) in dsp_ioctl()
1560 cv_wait(&wrch->cv, wrch->lock); in dsp_ioctl()
1561 bs = wrch->bufsoft; in dsp_ioctl()
1562 if ((bs->shadbuf != NULL) && (bs->sl > 0)) { in dsp_ioctl()
1564 sndbuf_acquire(bs, bs->shadbuf, bs->sl); in dsp_ioctl()
1565 bs->sl = 0; in dsp_ioctl()
1596 bs = chn->bufsoft; in dsp_ioctl()
1597 oc->samples = sndbuf_gettotal(bs) / sndbuf_getalign(bs); in dsp_ioctl()
1598 oc->fifo_samples = sndbuf_getready(bs) / sndbuf_getalign(bs); in dsp_ioctl()
1622 wrch->lw = (*arg_i > 1) ? *arg_i : 1; in dsp_ioctl()
1627 rdch->lw = (*arg_i > 1) ? *arg_i : 1; in dsp_ioctl()
1647 ei->play_underruns = wrch->xruns; in dsp_ioctl()
1648 wrch->xruns = 0; in dsp_ioctl()
1653 ei->rec_overruns = rdch->xruns; in dsp_ioctl()
1654 rdch->xruns = 0; in dsp_ioctl()
1680 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) in dsp_ioctl()
1718 if (ret == -1) in dsp_ioctl()
1779 d = priv->sc; in dsp_poll()
1790 wrch = priv->wrch; in dsp_poll()
1791 rdch = priv->rdch; in dsp_poll()
1793 if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) { in dsp_poll()
1799 if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) { in dsp_poll()
1839 * https://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html in dsp_mmap_single()
1861 d = priv->sc; in dsp_mmap_single()
1868 wrch = priv->wrch; in dsp_mmap_single()
1869 rdch = priv->rdch; in dsp_mmap_single()
1872 if (c == NULL || (c->flags & CHN_F_MMAP_INVALID) || in dsp_mmap_single()
1873 (*offset + size) > sndbuf_getallocsize(c->bufsoft) || in dsp_mmap_single()
1874 (wrch != NULL && (wrch->flags & CHN_F_MMAP_INVALID)) || in dsp_mmap_single()
1875 (rdch != NULL && (rdch->flags & CHN_F_MMAP_INVALID))) { in dsp_mmap_single()
1882 wrch->flags |= CHN_F_MMAP; in dsp_mmap_single()
1884 rdch->flags |= CHN_F_MMAP; in dsp_mmap_single()
1886 *offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset); in dsp_mmap_single()
1889 size, nprot, *offset, curthread->td_ucred); in dsp_mmap_single()
1915 if (strcmp(name, "dsp") == 0 && dsp_basename_clone) in dsp_clone()
1928 * have returned already, meaning it will have set snd_unit to -1, and in dsp_clone()
1932 *dev = d->dsp_dev; in dsp_clone()
1962 ai->dev = unit; in dsp_oss_audioinfo_unavail()
1963 snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit); in dsp_oss_audioinfo_unavail()
1964 ai->pid = -1; in dsp_oss_audioinfo_unavail()
1965 strlcpy(ai->cmd, CHN_COMM_UNUSED, sizeof(ai->cmd)); in dsp_oss_audioinfo_unavail()
1966 ai->card_number = unit; in dsp_oss_audioinfo_unavail()
1967 ai->port_number = unit; in dsp_oss_audioinfo_unavail()
1968 ai->mixer_dev = -1; in dsp_oss_audioinfo_unavail()
1969 ai->legacy_device = unit; in dsp_oss_audioinfo_unavail()
1975 * Gathers information about the audio device specified in ai->dev. If
1976 * ai->dev == -1, then this function gathers information about the current
1977 * device. If the call comes in on a non-audio device and ai->dev == -1,
1981 * getting capabilities directly from the sound card driver, side-stepping
1993 * @retval EINVAL ai->dev specifies an invalid device
2006 * DSP device. (Users may use this ioctl with /dev/mixer and in dsp_oss_audioinfo()
2009 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) in dsp_oss_audioinfo()
2017 if ((ai->dev == -1 && unit == snd_unit) || in dsp_oss_audioinfo()
2018 ai->dev == unit) { in dsp_oss_audioinfo()
2030 if ((ai->dev == -1 && d->dsp_dev == i_dev) || in dsp_oss_audioinfo()
2031 (ai->dev == unit)) { in dsp_oss_audioinfo()
2041 /* Exhausted the search -- nothing is locked, so return. */ in dsp_oss_audioinfo()
2051 ai->dev = unit; in dsp_oss_audioinfo()
2052 strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name)); in dsp_oss_audioinfo()
2053 ai->pid = -1; in dsp_oss_audioinfo()
2054 strlcpy(ai->cmd, CHN_COMM_UNKNOWN, sizeof(ai->cmd)); in dsp_oss_audioinfo()
2055 ai->card_number = unit; in dsp_oss_audioinfo()
2056 ai->port_number = unit; in dsp_oss_audioinfo()
2057 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; in dsp_oss_audioinfo()
2058 ai->legacy_device = unit; in dsp_oss_audioinfo()
2059 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); in dsp_oss_audioinfo()
2060 ai->enabled = device_is_attached(d->dev) ? 1 : 0; in dsp_oss_audioinfo()
2061 ai->next_play_engine = 0; in dsp_oss_audioinfo()
2062 ai->next_rec_engine = 0; in dsp_oss_audioinfo()
2063 ai->busy = 0; in dsp_oss_audioinfo()
2064 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; in dsp_oss_audioinfo()
2065 ai->iformats = 0; in dsp_oss_audioinfo()
2066 ai->oformats = 0; in dsp_oss_audioinfo()
2067 ai->min_rate = INT_MAX; in dsp_oss_audioinfo()
2068 ai->max_rate = 0; in dsp_oss_audioinfo()
2069 ai->min_channels = INT_MAX; in dsp_oss_audioinfo()
2070 ai->max_channels = 0; in dsp_oss_audioinfo()
2084 if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) || in dsp_oss_audioinfo()
2085 ((!ex && (ch->flags & CHN_F_VIRTUAL) == 0) && in dsp_oss_audioinfo()
2086 (d->pvchancount > 0 || d->rvchancount > 0))) { in dsp_oss_audioinfo()
2091 if ((ch->flags & CHN_F_BUSY) == 0) { in dsp_oss_audioinfo()
2092 ai->busy |= (ch->direction == PCMDIR_PLAY) ? in dsp_oss_audioinfo()
2096 ai->caps |= in dsp_oss_audioinfo()
2097 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | in dsp_oss_audioinfo()
2098 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : in dsp_oss_audioinfo()
2106 for (i = 0; caps->fmtlist[i]; i++) { in dsp_oss_audioinfo()
2107 fmts |= AFMT_ENCODING(caps->fmtlist[i]); in dsp_oss_audioinfo()
2108 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); in dsp_oss_audioinfo()
2109 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); in dsp_oss_audioinfo()
2112 if (ch->direction == PCMDIR_PLAY) in dsp_oss_audioinfo()
2113 ai->oformats |= fmts; in dsp_oss_audioinfo()
2115 ai->iformats |= fmts; in dsp_oss_audioinfo()
2117 if (ex || (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_oss_audioinfo()
2118 ai->min_rate = min(ai->min_rate, caps->minspeed); in dsp_oss_audioinfo()
2119 ai->max_rate = max(ai->max_rate, caps->maxspeed); in dsp_oss_audioinfo()
2121 ai->min_rate = min(ai->min_rate, feeder_rate_min); in dsp_oss_audioinfo()
2122 ai->max_rate = max(ai->max_rate, feeder_rate_max); in dsp_oss_audioinfo()
2124 ai->min_channels = min(ai->min_channels, minch); in dsp_oss_audioinfo()
2125 ai->max_channels = max(ai->max_channels, maxch); in dsp_oss_audioinfo()
2129 if (ai->min_rate == INT_MAX) in dsp_oss_audioinfo()
2130 ai->min_rate = 0; in dsp_oss_audioinfo()
2131 if (ai->min_channels == INT_MAX) in dsp_oss_audioinfo()
2132 ai->min_channels = 0; in dsp_oss_audioinfo()
2145 if (DSP_REGISTERED(priv->sc) && (ch == priv->rdch || ch == priv->wrch)) in dsp_oss_engineinfo_cb()
2154 * Gathers information about the audio device's engine specified in ai->dev.
2155 * If ai->dev == -1, then this function gathers information about the current
2156 * device. If the call comes in on a non-audio device and ai->dev == -1,
2160 * getting capabilities directly from the sound card driver, side-stepping
2170 * @retval EINVAL ai->dev specifies an invalid device
2183 * DSP device. (Users may use this ioctl with /dev/mixer and in dsp_oss_engineinfo()
2186 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) in dsp_oss_engineinfo()
2212 if ((ai->dev == -1 && devfs_foreach_cdevpriv( in dsp_oss_engineinfo()
2214 ai->dev == nchan) in dsp_oss_engineinfo()
2228 * - a specific PCM device is locked. in dsp_oss_engineinfo()
2229 * - a specific audio channel has been locked, so be in dsp_oss_engineinfo()
2241 ai->dev = nchan; in dsp_oss_engineinfo()
2242 strlcpy(ai->name, ch->name, sizeof(ai->name)); in dsp_oss_engineinfo()
2244 if ((ch->flags & CHN_F_BUSY) == 0) in dsp_oss_engineinfo()
2245 ai->busy = 0; in dsp_oss_engineinfo()
2247 ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; in dsp_oss_engineinfo()
2249 ai->pid = ch->pid; in dsp_oss_engineinfo()
2250 strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); in dsp_oss_engineinfo()
2258 * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep in dsp_oss_engineinfo()
2261 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | in dsp_oss_engineinfo()
2262 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | in dsp_oss_engineinfo()
2263 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); in dsp_oss_engineinfo()
2272 for (i = 0; caps->fmtlist[i]; i++) { in dsp_oss_engineinfo()
2273 fmts |= AFMT_ENCODING(caps->fmtlist[i]); in dsp_oss_engineinfo()
2274 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); in dsp_oss_engineinfo()
2275 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); in dsp_oss_engineinfo()
2278 if (ch->direction == PCMDIR_PLAY) in dsp_oss_engineinfo()
2279 ai->oformats = fmts; in dsp_oss_engineinfo()
2281 ai->iformats = fmts; in dsp_oss_engineinfo()
2285 * @c magic - OSSv4 docs: "Reserved for internal use in dsp_oss_engineinfo()
2289 * @c card_number - OSSv4 docs: "Number of the sound in dsp_oss_engineinfo()
2290 * card where this device belongs or -1 if this in dsp_oss_engineinfo()
2295 ai->card_number = unit; in dsp_oss_engineinfo()
2297 * @todo @c song_name - depends first on in dsp_oss_engineinfo()
2298 * SNDCTL_[GS]ETSONG @todo @c label - depends in dsp_oss_engineinfo()
2300 * @todo @c port_number - routing information? in dsp_oss_engineinfo()
2302 ai->port_number = unit; in dsp_oss_engineinfo()
2303 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; in dsp_oss_engineinfo()
2306 * @c legacy_device - OSSv4 docs: "Obsolete." in dsp_oss_engineinfo()
2308 ai->legacy_device = unit; in dsp_oss_engineinfo()
2309 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); in dsp_oss_engineinfo()
2310 ai->enabled = device_is_attached(d->dev) ? 1 : 0; in dsp_oss_engineinfo()
2313 * @c flags - OSSv4 docs: "Reserved for future use." in dsp_oss_engineinfo()
2316 * @c binding - OSSv4 docs: "Reserved for future use." in dsp_oss_engineinfo()
2318 * @todo @c handle - haven't decided how to generate in dsp_oss_engineinfo()
2322 if ((ch->flags & CHN_F_EXCLUSIVE) || in dsp_oss_engineinfo()
2323 (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_oss_engineinfo()
2324 ai->min_rate = caps->minspeed; in dsp_oss_engineinfo()
2325 ai->max_rate = caps->maxspeed; in dsp_oss_engineinfo()
2327 ai->min_rate = feeder_rate_min; in dsp_oss_engineinfo()
2328 ai->max_rate = feeder_rate_max; in dsp_oss_engineinfo()
2331 ai->min_channels = minch; in dsp_oss_engineinfo()
2332 ai->max_channels = maxch; in dsp_oss_engineinfo()
2334 ai->nrates = chn_getrates(ch, &rates); in dsp_oss_engineinfo()
2335 if (ai->nrates > OSS_MAX_SAMPLE_RATES) in dsp_oss_engineinfo()
2336 ai->nrates = OSS_MAX_SAMPLE_RATES; in dsp_oss_engineinfo()
2338 for (i = 0; i < ai->nrates; i++) in dsp_oss_engineinfo()
2339 ai->rates[i] = rates[i]; in dsp_oss_engineinfo()
2341 ai->next_play_engine = 0; in dsp_oss_engineinfo()
2342 ai->next_rec_engine = 0; in dsp_oss_engineinfo()
2352 /* Exhausted the search -- nothing is locked, so return. */ in dsp_oss_engineinfo()
2378 * @retval non-zero error to be propagated upstream
2401 * - Insert channel(s) into group's member list. in dsp_oss_syncgroup()
2402 * - Set CHN_F_NOTRIGGER on channel(s). in dsp_oss_syncgroup()
2403 * - Stop channel(s). in dsp_oss_syncgroup()
2421 * - Bail if PCM_ENABLE_OUTPUT && wrch == NULL. in dsp_oss_syncgroup()
2422 * - Bail if PCM_ENABLE_INPUT && rdch == NULL. in dsp_oss_syncgroup()
2424 if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) || in dsp_oss_syncgroup()
2425 ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) { in dsp_oss_syncgroup()
2434 if (group->id == 0) { in dsp_oss_syncgroup()
2437 SLIST_INIT(&sg->members); in dsp_oss_syncgroup()
2438 sg->id = alloc_unr(pcmsg_unrhdr); in dsp_oss_syncgroup()
2440 group->id = sg->id; in dsp_oss_syncgroup()
2446 if (sg->id == group->id) in dsp_oss_syncgroup()
2461 if (group->mode & PCM_ENABLE_INPUT) { in dsp_oss_syncgroup()
2468 SLIST_INSERT_HEAD(&sg->members, smrd, link); in dsp_oss_syncgroup()
2469 smrd->parent = sg; in dsp_oss_syncgroup()
2470 smrd->ch = rdch; in dsp_oss_syncgroup()
2473 rdch->flags |= CHN_F_NOTRIGGER; in dsp_oss_syncgroup()
2474 rdch->sm = smrd; in dsp_oss_syncgroup()
2477 if (group->mode & PCM_ENABLE_OUTPUT) { in dsp_oss_syncgroup()
2484 SLIST_INSERT_HEAD(&sg->members, smwr, link); in dsp_oss_syncgroup()
2485 smwr->parent = sg; in dsp_oss_syncgroup()
2486 smwr->ch = wrch; in dsp_oss_syncgroup()
2489 wrch->flags |= CHN_F_NOTRIGGER; in dsp_oss_syncgroup()
2490 wrch->sm = smwr; in dsp_oss_syncgroup()
2497 if ((sg != NULL) && SLIST_EMPTY(&sg->members)) { in dsp_oss_syncgroup()
2498 sg_ids[2] = sg->id; in dsp_oss_syncgroup()
2504 wrch->sm = NULL; in dsp_oss_syncgroup()
2506 rdch->sm = NULL; in dsp_oss_syncgroup()
2537 * @retval non-zero error worthy of propagating upstream to user
2556 if (sg->id == sg_id) in dsp_oss_syncstart()
2567 KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup")); in dsp_oss_syncstart()
2570 * Attempt to lock all member channels - if any are already in dsp_oss_syncstart()
2574 SLIST_FOREACH(sm, &sg->members, link) { in dsp_oss_syncstart()
2575 if (CHN_TRYLOCK(sm->ch) == 0) { in dsp_oss_syncstart()
2581 SLIST_FOREACH(sm_tmp, &sg->members, link) { in dsp_oss_syncstart()
2585 CHN_UNLOCK(sm_tmp->ch); in dsp_oss_syncstart()
2603 while ((sm = SLIST_FIRST(&sg->members)) != NULL) { in dsp_oss_syncstart()
2604 SLIST_REMOVE_HEAD(&sg->members, link); in dsp_oss_syncstart()
2606 c = sm->ch; in dsp_oss_syncstart()
2607 c->sm = NULL; in dsp_oss_syncstart()
2609 c->flags &= ~CHN_F_NOTRIGGER; in dsp_oss_syncstart()
2699 * a sound card's buffer space directly, bypassing the FreeBSD 2-stage
2720 * <insert any non-printable characters here>. in dsp_oss_cookedmode()
2734 wrch->flags &= ~CHN_F_BITPERFECT; in dsp_oss_cookedmode()
2735 wrch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; in dsp_oss_cookedmode()
2741 rdch->flags &= ~CHN_F_BITPERFECT; in dsp_oss_cookedmode()
2742 rdch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; in dsp_oss_cookedmode()