1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 5 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006 6 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> 7 * All rights reserved. 8 * Copyright (c) 2024-2025 The FreeBSD Foundation 9 * 10 * Portions of this software were developed by Christos Margiolis 11 * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifdef HAVE_KERNEL_OPTION_HEADERS 36 #include "opt_snd.h" 37 #endif 38 39 #include <dev/sound/pcm/sound.h> 40 #include <dev/sound/pcm/vchan.h> 41 #include <sys/ctype.h> 42 #include <sys/lock.h> 43 #include <sys/rwlock.h> 44 #include <sys/sysent.h> 45 46 #include <vm/vm.h> 47 #include <vm/vm_object.h> 48 #include <vm/vm_page.h> 49 #include <vm/vm_pager.h> 50 51 struct dsp_cdevpriv { 52 struct snddev_info *sc; 53 struct pcm_channel *rdch; 54 struct pcm_channel *wrch; 55 }; 56 57 static int dsp_mmap_allow_prot_exec = -1; 58 SYSCTL_INT(_hw_snd, OID_AUTO, compat_linux_mmap, CTLFLAG_RWTUN, 59 &dsp_mmap_allow_prot_exec, 0, 60 "linux mmap compatibility (-1=force-disable 0=auto)"); 61 62 static int dsp_basename_clone = 1; 63 SYSCTL_INT(_hw_snd, OID_AUTO, basename_clone, CTLFLAG_RWTUN, 64 &dsp_basename_clone, 0, 65 "DSP basename cloning (0: Disable; 1: Enabled)"); 66 67 #define DSP_REGISTERED(x) (PCM_REGISTERED(x) && (x)->dsp_dev != NULL) 68 69 #define DSP_F_VALID(x) ((x) & (FREAD | FWRITE)) 70 #define DSP_F_DUPLEX(x) (((x) & (FREAD | FWRITE)) == (FREAD | FWRITE)) 71 #define DSP_F_SIMPLEX(x) (!DSP_F_DUPLEX(x)) 72 #define DSP_F_READ(x) ((x) & FREAD) 73 #define DSP_F_WRITE(x) ((x) & FWRITE) 74 75 static d_open_t dsp_open; 76 static d_read_t dsp_read; 77 static d_write_t dsp_write; 78 static d_ioctl_t dsp_ioctl; 79 static d_poll_t dsp_poll; 80 static d_mmap_single_t dsp_mmap_single; 81 static d_kqfilter_t dsp_kqfilter; 82 83 struct cdevsw dsp_cdevsw = { 84 .d_version = D_VERSION, 85 .d_open = dsp_open, 86 .d_read = dsp_read, 87 .d_write = dsp_write, 88 .d_ioctl = dsp_ioctl, 89 .d_poll = dsp_poll, 90 .d_kqfilter = dsp_kqfilter, 91 .d_mmap_single = dsp_mmap_single, 92 .d_name = "dsp", 93 }; 94 95 static eventhandler_tag dsp_ehtag = NULL; 96 97 static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group); 98 static int dsp_oss_syncstart(int sg_id); 99 static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy); 100 static int dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled); 101 static int dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map); 102 static int dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map); 103 static int dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch, int *mask); 104 #ifdef OSSV4_EXPERIMENT 105 static int dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label); 106 static int dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label); 107 static int dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song); 108 static int dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song); 109 static int dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name); 110 #endif 111 112 int 113 dsp_make_dev(device_t dev) 114 { 115 struct make_dev_args devargs; 116 struct snddev_info *sc; 117 int err, unit; 118 119 sc = device_get_softc(dev); 120 unit = device_get_unit(dev); 121 122 make_dev_args_init(&devargs); 123 devargs.mda_devsw = &dsp_cdevsw; 124 devargs.mda_uid = UID_ROOT; 125 devargs.mda_gid = GID_AUDIO; 126 devargs.mda_mode = 0660; 127 devargs.mda_si_drv1 = sc; 128 err = make_dev_s(&devargs, &sc->dsp_dev, "dsp%d", unit); 129 if (err != 0) { 130 device_printf(dev, "failed to create dsp%d: error %d", 131 unit, err); 132 return (ENXIO); 133 } 134 135 return (0); 136 } 137 138 void 139 dsp_destroy_dev(device_t dev) 140 { 141 struct snddev_info *d; 142 143 d = device_get_softc(dev); 144 destroy_dev(d->dsp_dev); 145 } 146 147 static int 148 dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction, 149 int flags, struct thread *td) 150 { 151 struct pcm_channel *c; 152 char *comm; 153 pid_t pid; 154 int err; 155 bool vdir_enabled; 156 157 KASSERT(d != NULL && ch != NULL && 158 (direction == PCMDIR_PLAY || direction == PCMDIR_REC), 159 ("%s(): invalid d=%p ch=%p direction=%d", 160 __func__, d, ch, direction)); 161 PCM_BUSYASSERT(d); 162 163 pid = td->td_proc->p_pid; 164 comm = td->td_proc->p_comm; 165 166 vdir_enabled = (direction == PCMDIR_PLAY && d->flags & SD_F_PVCHANS) || 167 (direction == PCMDIR_REC && d->flags & SD_F_RVCHANS); 168 169 *ch = NULL; 170 CHN_FOREACH(c, d, channels.pcm.primary) { 171 CHN_LOCK(c); 172 if (c->direction != direction) { 173 CHN_UNLOCK(c); 174 continue; 175 } 176 /* Find an available primary channel to use. */ 177 if ((c->flags & CHN_F_BUSY) == 0 || 178 (vdir_enabled && (c->flags & CHN_F_HAS_VCHAN))) 179 break; 180 CHN_UNLOCK(c); 181 } 182 if (c == NULL) 183 return (EBUSY); 184 185 /* 186 * We can have the following cases: 187 * - vchans are enabled, add a new vchan to the primary channel. 188 * - vchans are disabled, use the primary channel directly. 189 */ 190 if (vdir_enabled && ((c->flags & CHN_F_BUSY) == 0 || 191 c->flags & CHN_F_HAS_VCHAN)) { 192 err = vchan_create(c, ch); 193 CHN_UNLOCK(c); 194 if (err != 0) 195 return (err); 196 CHN_LOCK(*ch); 197 } else if ((c->flags & CHN_F_BUSY) == 0) { 198 *ch = c; 199 } else { 200 CHN_UNLOCK(c); 201 return (ENODEV); 202 } 203 204 (*ch)->flags |= CHN_F_BUSY; 205 if (flags & O_NONBLOCK) 206 (*ch)->flags |= CHN_F_NBIO; 207 if (flags & O_EXCL) 208 (*ch)->flags |= CHN_F_EXCLUSIVE; 209 (*ch)->pid = pid; 210 strlcpy((*ch)->comm, (comm != NULL) ? comm : CHN_COMM_UNKNOWN, 211 sizeof((*ch)->comm)); 212 213 if ((err = chn_reset(*ch, (*ch)->format, (*ch)->speed)) != 0) 214 return (err); 215 chn_vpc_reset(*ch, SND_VOL_C_PCM, 0); 216 217 CHN_UNLOCK(*ch); 218 219 return (0); 220 } 221 222 static void 223 dsp_close(void *data) 224 { 225 struct dsp_cdevpriv *priv = data; 226 struct pcm_channel *rdch, *wrch, *parent; 227 struct snddev_info *d; 228 int sg_ids; 229 230 if (priv == NULL) 231 return; 232 233 d = priv->sc; 234 /* At this point pcm_unregister() will destroy all channels anyway. */ 235 if (!DSP_REGISTERED(d)) 236 goto skip; 237 238 PCM_GIANT_ENTER(d); 239 240 PCM_LOCK(d); 241 PCM_WAIT(d); 242 PCM_ACQUIRE(d); 243 244 rdch = priv->rdch; 245 wrch = priv->wrch; 246 247 if (rdch != NULL) 248 CHN_REMOVE(d, rdch, channels.pcm.opened); 249 if (wrch != NULL) 250 CHN_REMOVE(d, wrch, channels.pcm.opened); 251 252 if (rdch != NULL || wrch != NULL) { 253 PCM_UNLOCK(d); 254 if (rdch != NULL) { 255 /* 256 * The channel itself need not be locked because: 257 * a) Adding a channel to a syncgroup happens only 258 * in dsp_ioctl(), which cannot run concurrently 259 * to dsp_close(). 260 * b) The syncmember pointer (sm) is protected by 261 * the global syncgroup list lock. 262 * c) A channel can't just disappear, invalidating 263 * pointers, unless it's closed/dereferenced 264 * first. 265 */ 266 PCM_SG_LOCK(); 267 sg_ids = chn_syncdestroy(rdch); 268 PCM_SG_UNLOCK(); 269 if (sg_ids != 0) 270 free_unr(pcmsg_unrhdr, sg_ids); 271 272 /* 273 * Go through the channel abort/flush path for both 274 * primary and virtual channels to ensure that, in the 275 * case of vchans, the stream is always properly 276 * stopped, and the primary channels do not keep being 277 * interrupted even if all vchans are gone. 278 */ 279 CHN_LOCK(rdch); 280 chn_abort(rdch); /* won't sleep */ 281 rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | 282 CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO); 283 chn_reset(rdch, 0, 0); 284 chn_release(rdch); 285 if (rdch->flags & CHN_F_VIRTUAL) { 286 parent = rdch->parentchannel; 287 CHN_LOCK(parent); 288 CHN_LOCK(rdch); 289 vchan_destroy(rdch); 290 CHN_UNLOCK(parent); 291 } 292 } 293 if (wrch != NULL) { 294 /* 295 * Please see block above. 296 */ 297 PCM_SG_LOCK(); 298 sg_ids = chn_syncdestroy(wrch); 299 PCM_SG_UNLOCK(); 300 if (sg_ids != 0) 301 free_unr(pcmsg_unrhdr, sg_ids); 302 303 CHN_LOCK(wrch); 304 chn_flush(wrch); /* may sleep */ 305 wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | 306 CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO); 307 chn_reset(wrch, 0, 0); 308 chn_release(wrch); 309 if (wrch->flags & CHN_F_VIRTUAL) { 310 parent = wrch->parentchannel; 311 CHN_LOCK(parent); 312 CHN_LOCK(wrch); 313 vchan_destroy(wrch); 314 CHN_UNLOCK(parent); 315 } 316 } 317 PCM_LOCK(d); 318 } 319 320 PCM_RELEASE(d); 321 PCM_UNLOCK(d); 322 323 PCM_GIANT_LEAVE(d); 324 skip: 325 free(priv, M_DEVBUF); 326 priv = NULL; 327 } 328 329 static int 330 dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td) 331 { 332 struct dsp_cdevpriv *priv; 333 struct pcm_channel *ch; 334 struct snddev_info *d; 335 int error, dir; 336 337 /* Kind of impossible.. */ 338 if (i_dev == NULL || td == NULL) 339 return (ENODEV); 340 341 d = i_dev->si_drv1; 342 if (!DSP_REGISTERED(d)) 343 return (EBADF); 344 345 if (PCM_CHANCOUNT(d) >= PCM_MAXCHANS) 346 return (ENOMEM); 347 348 priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO); 349 priv->sc = d; 350 351 error = devfs_set_cdevpriv(priv, dsp_close); 352 if (error != 0) 353 return (error); 354 355 PCM_GIANT_ENTER(d); 356 357 /* Lock snddev so nobody else can monkey with it. */ 358 PCM_LOCK(d); 359 PCM_WAIT(d); 360 361 error = 0; 362 if (!DSP_F_VALID(flags)) 363 error = EINVAL; 364 else if (!DSP_F_DUPLEX(flags) && 365 ((DSP_F_READ(flags) && d->reccount == 0) || 366 (DSP_F_WRITE(flags) && d->playcount == 0))) 367 error = ENOTSUP; 368 if (pcm_getflags(d->dev) & SD_F_SIMPLEX) { 369 if (DSP_F_DUPLEX(flags)) { 370 /* 371 * If no channels are opened yet, and we request 372 * DUPLEX, limit to playback only, otherwise open one 373 * channel in a direction that already exists. 374 */ 375 if (CHN_EMPTY(d, channels.pcm.opened)) { 376 if (d->playcount > 0) 377 flags &= ~FREAD; 378 else if (d->reccount > 0) 379 flags &= ~FWRITE; 380 } else { 381 ch = CHN_FIRST(d, channels.pcm.opened); 382 if (ch->direction == PCMDIR_PLAY) 383 flags &= ~FREAD; 384 else if (ch->direction == PCMDIR_REC) 385 flags &= ~FWRITE; 386 } 387 } else if (!CHN_EMPTY(d, channels.pcm.opened)) { 388 /* 389 * If we requested SIMPLEX, make sure we do not open a 390 * channel in the opposite direction. 391 */ 392 ch = CHN_FIRST(d, channels.pcm.opened); 393 dir = DSP_F_READ(flags) ? PCMDIR_REC : PCMDIR_PLAY; 394 if (ch->direction != dir) 395 error = ENOTSUP; 396 } 397 } 398 if (error != 0) { 399 PCM_UNLOCK(d); 400 PCM_GIANT_EXIT(d); 401 return (error); 402 } 403 404 /* 405 * That is just enough. Acquire and unlock pcm lock so 406 * the other will just have to wait until we finish doing 407 * everything. 408 */ 409 PCM_ACQUIRE(d); 410 PCM_UNLOCK(d); 411 412 if (DSP_F_WRITE(flags)) { 413 error = dsp_chn_alloc(d, &priv->wrch, PCMDIR_PLAY, flags, td); 414 if (error != 0) { 415 PCM_RELEASE_QUICK(d); 416 PCM_GIANT_EXIT(d); 417 return (error); 418 } 419 PCM_LOCK(d); 420 CHN_INSERT_HEAD(d, priv->wrch, channels.pcm.opened); 421 PCM_UNLOCK(d); 422 } 423 if (DSP_F_READ(flags)) { 424 error = dsp_chn_alloc(d, &priv->rdch, PCMDIR_REC, flags, td); 425 if (error != 0) { 426 PCM_RELEASE_QUICK(d); 427 PCM_GIANT_EXIT(d); 428 return (error); 429 } 430 PCM_LOCK(d); 431 CHN_INSERT_HEAD(d, priv->rdch, channels.pcm.opened); 432 PCM_UNLOCK(d); 433 } 434 435 PCM_RELEASE_QUICK(d); 436 PCM_GIANT_LEAVE(d); 437 438 return (0); 439 } 440 441 static __inline int 442 dsp_io_ops(struct dsp_cdevpriv *priv, struct uio *buf) 443 { 444 struct snddev_info *d; 445 struct pcm_channel *ch; 446 int (*chn_io)(struct pcm_channel *, struct uio *); 447 int ret; 448 449 d = priv->sc; 450 if (!DSP_REGISTERED(d)) 451 return (EBADF); 452 453 PCM_GIANT_ENTER(d); 454 455 switch (buf->uio_rw) { 456 case UIO_READ: 457 ch = priv->rdch; 458 chn_io = chn_read; 459 break; 460 case UIO_WRITE: 461 ch = priv->wrch; 462 chn_io = chn_write; 463 break; 464 } 465 if (ch == NULL) { 466 PCM_GIANT_EXIT(d); 467 return (ENXIO); 468 } 469 CHN_LOCK(ch); 470 471 if (!(ch->flags & CHN_F_BUSY) || 472 (ch->flags & (CHN_F_MMAP | CHN_F_DEAD))) { 473 CHN_UNLOCK(ch); 474 PCM_GIANT_EXIT(d); 475 return (ENXIO); 476 } else if (!(ch->flags & CHN_F_RUNNING)) 477 ch->flags |= CHN_F_RUNNING; 478 479 /* 480 * chn_read/write must give up channel lock in order to copy bytes 481 * from/to userland, so up the "in progress" counter to make sure 482 * someone else doesn't come along and muss up the buffer. 483 */ 484 ch->inprog++; 485 ret = chn_io(ch, buf); 486 ch->inprog--; 487 488 CHN_BROADCAST(&ch->cv); 489 CHN_UNLOCK(ch); 490 491 PCM_GIANT_LEAVE(d); 492 493 return (ret); 494 } 495 496 static int 497 dsp_read(struct cdev *i_dev, struct uio *buf, int flag) 498 { 499 struct dsp_cdevpriv *priv; 500 int err; 501 502 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 503 return (err); 504 return (dsp_io_ops(priv, buf)); 505 } 506 507 static int 508 dsp_write(struct cdev *i_dev, struct uio *buf, int flag) 509 { 510 struct dsp_cdevpriv *priv; 511 int err; 512 513 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 514 return (err); 515 return (dsp_io_ops(priv, buf)); 516 } 517 518 static int 519 dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *ch, 520 u_long cmd, caddr_t arg) 521 { 522 struct snddev_info *d; 523 struct pcm_channel *rdch, *wrch; 524 int j, left, right, center, mute; 525 526 d = priv->sc; 527 if (!PCM_REGISTERED(d)) 528 return (-1); 529 530 PCM_UNLOCKASSERT(d); 531 532 j = cmd & 0xff; 533 534 rdch = priv->rdch; 535 wrch = priv->wrch; 536 537 if (ch == NULL) { 538 if (j == SOUND_MIXER_RECLEV && rdch != NULL) 539 ch = rdch; 540 else if (j == SOUND_MIXER_PCM && wrch != NULL) 541 ch = wrch; 542 } 543 544 if (ch == NULL) 545 return (EINVAL); 546 547 CHN_LOCK(ch); 548 if (!(ch->feederflags & (1 << FEEDER_VOLUME))) { 549 CHN_UNLOCK(ch); 550 return (EINVAL); 551 } 552 553 switch (cmd & ~0xff) { 554 case MIXER_WRITE(0): 555 switch (j) { 556 case SOUND_MIXER_MUTE: 557 if (ch->direction == PCMDIR_REC) { 558 chn_setmute_multi(ch, SND_VOL_C_PCM, (*(int *)arg & SOUND_MASK_RECLEV) != 0); 559 } else { 560 chn_setmute_multi(ch, SND_VOL_C_PCM, (*(int *)arg & SOUND_MASK_PCM) != 0); 561 } 562 break; 563 case SOUND_MIXER_PCM: 564 if (ch->direction != PCMDIR_PLAY) 565 break; 566 left = *(int *)arg & 0x7f; 567 right = ((*(int *)arg) >> 8) & 0x7f; 568 center = (left + right) >> 1; 569 chn_setvolume_multi(ch, SND_VOL_C_PCM, 570 left, right, center); 571 break; 572 case SOUND_MIXER_RECLEV: 573 if (ch->direction != PCMDIR_REC) 574 break; 575 left = *(int *)arg & 0x7f; 576 right = ((*(int *)arg) >> 8) & 0x7f; 577 center = (left + right) >> 1; 578 chn_setvolume_multi(ch, SND_VOL_C_PCM, 579 left, right, center); 580 break; 581 default: 582 /* ignore all other mixer writes */ 583 break; 584 } 585 break; 586 587 case MIXER_READ(0): 588 switch (j) { 589 case SOUND_MIXER_MUTE: 590 mute = chn_getmute_matrix(ch, 591 SND_VOL_C_PCM, SND_CHN_T_FL) || 592 chn_getmute_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FR); 593 if (ch->direction == PCMDIR_REC) { 594 *(int *)arg = mute << SOUND_MIXER_RECLEV; 595 } else { 596 *(int *)arg = mute << SOUND_MIXER_PCM; 597 } 598 break; 599 case SOUND_MIXER_PCM: 600 if (ch->direction != PCMDIR_PLAY) 601 break; 602 *(int *)arg = chn_getvolume_matrix(ch, 603 SND_VOL_C_PCM, SND_CHN_T_FL); 604 *(int *)arg |= chn_getvolume_matrix(ch, 605 SND_VOL_C_PCM, SND_CHN_T_FR) << 8; 606 break; 607 case SOUND_MIXER_RECLEV: 608 if (ch->direction != PCMDIR_REC) 609 break; 610 *(int *)arg = chn_getvolume_matrix(ch, 611 SND_VOL_C_PCM, SND_CHN_T_FL); 612 *(int *)arg |= chn_getvolume_matrix(ch, 613 SND_VOL_C_PCM, SND_CHN_T_FR) << 8; 614 break; 615 case SOUND_MIXER_DEVMASK: 616 case SOUND_MIXER_CAPS: 617 case SOUND_MIXER_STEREODEVS: 618 if (ch->direction == PCMDIR_REC) 619 *(int *)arg = SOUND_MASK_RECLEV; 620 else 621 *(int *)arg = SOUND_MASK_PCM; 622 break; 623 default: 624 *(int *)arg = 0; 625 break; 626 } 627 break; 628 629 default: 630 break; 631 } 632 CHN_UNLOCK(ch); 633 return (0); 634 } 635 636 #ifdef COMPAT_FREEBSD32 637 typedef struct _snd_chan_param32 { 638 uint32_t play_rate; 639 uint32_t rec_rate; 640 uint32_t play_format; 641 uint32_t rec_format; 642 } snd_chan_param32; 643 #define AIOGFMT32 _IOC_NEWTYPE(AIOGFMT, snd_chan_param32) 644 #define AIOSFMT32 _IOC_NEWTYPE(AIOSFMT, snd_chan_param32) 645 646 typedef struct _snd_capabilities32 { 647 uint32_t rate_min, rate_max; 648 uint32_t formats; 649 uint32_t bufsize; 650 uint32_t mixers; 651 uint32_t inputs; 652 uint16_t left, right; 653 } snd_capabilities32; 654 #define AIOGCAP32 _IOC_NEWTYPE(AIOGCAP, snd_capabilities32) 655 656 typedef struct audio_errinfo32 657 { 658 int32_t play_underruns; 659 int32_t rec_overruns; 660 uint32_t play_ptradjust; 661 uint32_t rec_ptradjust; 662 int32_t play_errorcount; 663 int32_t rec_errorcount; 664 int32_t play_lasterror; 665 int32_t rec_lasterror; 666 int32_t play_errorparm; 667 int32_t rec_errorparm; 668 int32_t filler[16]; 669 } audio_errinfo32; 670 #define SNDCTL_DSP_GETERROR32 _IOC_NEWTYPE(SNDCTL_DSP_GETERROR, audio_errinfo32) 671 #endif 672 673 static int 674 dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 675 struct thread *td) 676 { 677 struct dsp_cdevpriv *priv; 678 struct pcm_channel *chn, *rdch, *wrch; 679 struct snddev_info *d; 680 u_long xcmd; 681 int *arg_i, ret, tmp, err; 682 683 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 684 return (err); 685 686 d = priv->sc; 687 if (!DSP_REGISTERED(d)) 688 return (EBADF); 689 690 PCM_GIANT_ENTER(d); 691 692 arg_i = (int *)arg; 693 ret = 0; 694 xcmd = 0; 695 chn = NULL; 696 697 if (IOCGROUP(cmd) == 'M') { 698 if (cmd == OSS_GETVERSION) { 699 *arg_i = SOUND_VERSION; 700 PCM_GIANT_EXIT(d); 701 return (0); 702 } 703 ret = dsp_ioctl_channel(priv, NULL, cmd, arg); 704 if (ret != -1) { 705 PCM_GIANT_EXIT(d); 706 return (ret); 707 } 708 709 if (d->mixer_dev != NULL) { 710 PCM_ACQUIRE_QUICK(d); 711 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td); 712 PCM_RELEASE_QUICK(d); 713 } else 714 ret = EBADF; 715 716 PCM_GIANT_EXIT(d); 717 718 return (ret); 719 } 720 721 /* 722 * Certain ioctls may be made on any type of device (audio, mixer, 723 * and MIDI). Handle those special cases here. 724 */ 725 if (IOCGROUP(cmd) == 'X') { 726 PCM_ACQUIRE_QUICK(d); 727 switch(cmd) { 728 case SNDCTL_SYSINFO: 729 sound_oss_sysinfo((oss_sysinfo *)arg); 730 break; 731 case SNDCTL_CARDINFO: 732 ret = sound_oss_card_info((oss_card_info *)arg); 733 break; 734 case SNDCTL_AUDIOINFO: 735 ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg, 736 false); 737 break; 738 case SNDCTL_AUDIOINFO_EX: 739 ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg, 740 true); 741 break; 742 case SNDCTL_ENGINEINFO: 743 ret = dsp_oss_engineinfo(i_dev, (oss_audioinfo *)arg); 744 break; 745 case SNDCTL_MIXERINFO: 746 ret = mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg); 747 break; 748 default: 749 ret = EINVAL; 750 } 751 PCM_RELEASE_QUICK(d); 752 PCM_GIANT_EXIT(d); 753 return (ret); 754 } 755 756 rdch = priv->rdch; 757 wrch = priv->wrch; 758 759 if (wrch != NULL && (wrch->flags & CHN_F_DEAD)) 760 wrch = NULL; 761 if (rdch != NULL && (rdch->flags & CHN_F_DEAD)) 762 rdch = NULL; 763 764 if (wrch == NULL && rdch == NULL) { 765 PCM_GIANT_EXIT(d); 766 return (EINVAL); 767 } 768 769 switch(cmd) { 770 case AIONWRITE: /* how many bytes can write ? */ 771 if (wrch) { 772 CHN_LOCK(wrch); 773 /* 774 if (wrch && wrch->bufhard.dl) 775 while (chn_wrfeed(wrch) == 0); 776 */ 777 *arg_i = sndbuf_getfree(wrch->bufsoft); 778 CHN_UNLOCK(wrch); 779 } else { 780 *arg_i = 0; 781 ret = EINVAL; 782 } 783 break; 784 785 case AIOSSIZE: /* set the current blocksize */ 786 { 787 struct snd_size *p = (struct snd_size *)arg; 788 789 p->play_size = 0; 790 p->rec_size = 0; 791 PCM_ACQUIRE_QUICK(d); 792 if (wrch) { 793 CHN_LOCK(wrch); 794 chn_setblocksize(wrch, 2, p->play_size); 795 p->play_size = wrch->bufsoft->blksz; 796 CHN_UNLOCK(wrch); 797 } 798 if (rdch) { 799 CHN_LOCK(rdch); 800 chn_setblocksize(rdch, 2, p->rec_size); 801 p->rec_size = rdch->bufsoft->blksz; 802 CHN_UNLOCK(rdch); 803 } 804 PCM_RELEASE_QUICK(d); 805 } 806 break; 807 case AIOGSIZE: /* get the current blocksize */ 808 { 809 struct snd_size *p = (struct snd_size *)arg; 810 811 if (wrch) { 812 CHN_LOCK(wrch); 813 p->play_size = wrch->bufsoft->blksz; 814 CHN_UNLOCK(wrch); 815 } 816 if (rdch) { 817 CHN_LOCK(rdch); 818 p->rec_size = rdch->bufsoft->blksz; 819 CHN_UNLOCK(rdch); 820 } 821 } 822 break; 823 824 case AIOSFMT: 825 case AIOGFMT: 826 #ifdef COMPAT_FREEBSD32 827 case AIOSFMT32: 828 case AIOGFMT32: 829 #endif 830 { 831 snd_chan_param *p = (snd_chan_param *)arg; 832 833 #ifdef COMPAT_FREEBSD32 834 snd_chan_param32 *p32 = (snd_chan_param32 *)arg; 835 snd_chan_param param; 836 837 if (cmd == AIOSFMT32) { 838 p = ¶m; 839 p->play_rate = p32->play_rate; 840 p->rec_rate = p32->rec_rate; 841 p->play_format = p32->play_format; 842 p->rec_format = p32->rec_format; 843 } 844 #endif 845 if (cmd == AIOSFMT && 846 ((p->play_format != 0 && p->play_rate == 0) || 847 (p->rec_format != 0 && p->rec_rate == 0))) { 848 ret = EINVAL; 849 break; 850 } 851 PCM_ACQUIRE_QUICK(d); 852 if (wrch) { 853 CHN_LOCK(wrch); 854 if (cmd == AIOSFMT && p->play_format != 0) { 855 chn_setformat(wrch, 856 SND_FORMAT(p->play_format, 857 AFMT_CHANNEL(wrch->format), 858 AFMT_EXTCHANNEL(wrch->format))); 859 chn_setspeed(wrch, p->play_rate); 860 } 861 p->play_rate = wrch->speed; 862 p->play_format = AFMT_ENCODING(wrch->format); 863 CHN_UNLOCK(wrch); 864 } else { 865 p->play_rate = 0; 866 p->play_format = 0; 867 } 868 if (rdch) { 869 CHN_LOCK(rdch); 870 if (cmd == AIOSFMT && p->rec_format != 0) { 871 chn_setformat(rdch, 872 SND_FORMAT(p->rec_format, 873 AFMT_CHANNEL(rdch->format), 874 AFMT_EXTCHANNEL(rdch->format))); 875 chn_setspeed(rdch, p->rec_rate); 876 } 877 p->rec_rate = rdch->speed; 878 p->rec_format = AFMT_ENCODING(rdch->format); 879 CHN_UNLOCK(rdch); 880 } else { 881 p->rec_rate = 0; 882 p->rec_format = 0; 883 } 884 PCM_RELEASE_QUICK(d); 885 #ifdef COMPAT_FREEBSD32 886 if (cmd == AIOSFMT32 || cmd == AIOGFMT32) { 887 p32->play_rate = p->play_rate; 888 p32->rec_rate = p->rec_rate; 889 p32->play_format = p->play_format; 890 p32->rec_format = p->rec_format; 891 } 892 #endif 893 } 894 break; 895 896 case AIOGCAP: /* get capabilities */ 897 #ifdef COMPAT_FREEBSD32 898 case AIOGCAP32: 899 #endif 900 { 901 snd_capabilities *p = (snd_capabilities *)arg; 902 struct pcmchan_caps *pcaps = NULL, *rcaps = NULL; 903 struct cdev *pdev; 904 #ifdef COMPAT_FREEBSD32 905 snd_capabilities32 *p32 = (snd_capabilities32 *)arg; 906 snd_capabilities capabilities; 907 908 if (cmd == AIOGCAP32) { 909 p = &capabilities; 910 p->rate_min = p32->rate_min; 911 p->rate_max = p32->rate_max; 912 p->formats = p32->formats; 913 p->bufsize = p32->bufsize; 914 p->mixers = p32->mixers; 915 p->inputs = p32->inputs; 916 p->left = p32->left; 917 p->right = p32->right; 918 } 919 #endif 920 PCM_LOCK(d); 921 if (rdch) { 922 CHN_LOCK(rdch); 923 rcaps = chn_getcaps(rdch); 924 } 925 if (wrch) { 926 CHN_LOCK(wrch); 927 pcaps = chn_getcaps(wrch); 928 } 929 p->rate_min = max(rcaps? rcaps->minspeed : 0, 930 pcaps? pcaps->minspeed : 0); 931 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, 932 pcaps? pcaps->maxspeed : 1000000); 933 p->bufsize = min(rdch? rdch->bufsoft->bufsize : 1000000, 934 wrch? wrch->bufsoft->bufsize : 1000000); 935 /* XXX bad on sb16 */ 936 p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & 937 (wrch? chn_getformats(wrch) : 0xffffffff); 938 if (rdch && wrch) { 939 p->formats |= 940 (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 0 : 941 AFMT_FULLDUPLEX; 942 } 943 pdev = d->mixer_dev; 944 p->mixers = 1; /* default: one mixer */ 945 p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; 946 p->left = p->right = 100; 947 if (wrch) 948 CHN_UNLOCK(wrch); 949 if (rdch) 950 CHN_UNLOCK(rdch); 951 PCM_UNLOCK(d); 952 #ifdef COMPAT_FREEBSD32 953 if (cmd == AIOGCAP32) { 954 p32->rate_min = p->rate_min; 955 p32->rate_max = p->rate_max; 956 p32->formats = p->formats; 957 p32->bufsize = p->bufsize; 958 p32->mixers = p->mixers; 959 p32->inputs = p->inputs; 960 p32->left = p->left; 961 p32->right = p->right; 962 } 963 #endif 964 } 965 break; 966 967 case AIOSTOP: 968 if (*arg_i == AIOSYNC_PLAY && wrch) { 969 CHN_LOCK(wrch); 970 *arg_i = chn_abort(wrch); 971 CHN_UNLOCK(wrch); 972 } else if (*arg_i == AIOSYNC_CAPTURE && rdch) { 973 CHN_LOCK(rdch); 974 *arg_i = chn_abort(rdch); 975 CHN_UNLOCK(rdch); 976 } else { 977 printf("AIOSTOP: bad channel 0x%x\n", *arg_i); 978 *arg_i = 0; 979 } 980 break; 981 982 case AIOSYNC: 983 printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n", 984 ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); 985 break; 986 case FIONREAD: /* get # bytes to read */ 987 if (rdch) { 988 CHN_LOCK(rdch); 989 /* if (rdch && rdch->bufhard.dl) 990 while (chn_rdfeed(rdch) == 0); 991 */ 992 *arg_i = sndbuf_getready(rdch->bufsoft); 993 CHN_UNLOCK(rdch); 994 } else { 995 *arg_i = 0; 996 ret = EINVAL; 997 } 998 break; 999 1000 case FIOASYNC: /*set/clear async i/o */ 1001 DEB( printf("FIOASYNC\n") ; ) 1002 break; 1003 1004 case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */ 1005 case FIONBIO: /* set/clear non-blocking i/o */ 1006 if (rdch) { 1007 CHN_LOCK(rdch); 1008 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i) 1009 rdch->flags |= CHN_F_NBIO; 1010 else 1011 rdch->flags &= ~CHN_F_NBIO; 1012 CHN_UNLOCK(rdch); 1013 } 1014 if (wrch) { 1015 CHN_LOCK(wrch); 1016 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i) 1017 wrch->flags |= CHN_F_NBIO; 1018 else 1019 wrch->flags &= ~CHN_F_NBIO; 1020 CHN_UNLOCK(wrch); 1021 } 1022 break; 1023 1024 case SNDCTL_DSP_GETBLKSIZE: 1025 chn = wrch ? wrch : rdch; 1026 if (chn) { 1027 CHN_LOCK(chn); 1028 *arg_i = chn->bufsoft->blksz; 1029 CHN_UNLOCK(chn); 1030 } else { 1031 *arg_i = 0; 1032 ret = EINVAL; 1033 } 1034 break; 1035 1036 case SNDCTL_DSP_SETBLKSIZE: 1037 RANGE(*arg_i, 16, 65536); 1038 PCM_ACQUIRE_QUICK(d); 1039 if (wrch) { 1040 CHN_LOCK(wrch); 1041 chn_setblocksize(wrch, 2, *arg_i); 1042 CHN_UNLOCK(wrch); 1043 } 1044 if (rdch) { 1045 CHN_LOCK(rdch); 1046 chn_setblocksize(rdch, 2, *arg_i); 1047 CHN_UNLOCK(rdch); 1048 } 1049 PCM_RELEASE_QUICK(d); 1050 break; 1051 1052 case SNDCTL_DSP_RESET: 1053 DEB(printf("dsp reset\n")); 1054 if (wrch) { 1055 CHN_LOCK(wrch); 1056 chn_abort(wrch); 1057 chn_resetbuf(wrch); 1058 CHN_UNLOCK(wrch); 1059 } 1060 if (rdch) { 1061 CHN_LOCK(rdch); 1062 chn_abort(rdch); 1063 chn_resetbuf(rdch); 1064 CHN_UNLOCK(rdch); 1065 } 1066 break; 1067 1068 case SNDCTL_DSP_SYNC: 1069 DEB(printf("dsp sync\n")); 1070 /* chn_sync may sleep */ 1071 if (wrch) { 1072 CHN_LOCK(wrch); 1073 chn_sync(wrch, 0); 1074 CHN_UNLOCK(wrch); 1075 } 1076 break; 1077 1078 case SNDCTL_DSP_SPEED: 1079 /* chn_setspeed may sleep */ 1080 tmp = 0; 1081 PCM_ACQUIRE_QUICK(d); 1082 if (wrch) { 1083 CHN_LOCK(wrch); 1084 ret = chn_setspeed(wrch, *arg_i); 1085 tmp = wrch->speed; 1086 CHN_UNLOCK(wrch); 1087 } 1088 if (rdch && ret == 0) { 1089 CHN_LOCK(rdch); 1090 ret = chn_setspeed(rdch, *arg_i); 1091 if (tmp == 0) 1092 tmp = rdch->speed; 1093 CHN_UNLOCK(rdch); 1094 } 1095 PCM_RELEASE_QUICK(d); 1096 *arg_i = tmp; 1097 break; 1098 1099 case SOUND_PCM_READ_RATE: 1100 chn = wrch ? wrch : rdch; 1101 if (chn) { 1102 CHN_LOCK(chn); 1103 *arg_i = chn->speed; 1104 CHN_UNLOCK(chn); 1105 } else { 1106 *arg_i = 0; 1107 ret = EINVAL; 1108 } 1109 break; 1110 1111 case SNDCTL_DSP_STEREO: 1112 tmp = -1; 1113 *arg_i = (*arg_i)? 2 : 1; 1114 PCM_ACQUIRE_QUICK(d); 1115 if (wrch) { 1116 CHN_LOCK(wrch); 1117 ret = chn_setformat(wrch, 1118 SND_FORMAT(wrch->format, *arg_i, 0)); 1119 tmp = (AFMT_CHANNEL(wrch->format) > 1)? 1 : 0; 1120 CHN_UNLOCK(wrch); 1121 } 1122 if (rdch && ret == 0) { 1123 CHN_LOCK(rdch); 1124 ret = chn_setformat(rdch, 1125 SND_FORMAT(rdch->format, *arg_i, 0)); 1126 if (tmp == -1) 1127 tmp = (AFMT_CHANNEL(rdch->format) > 1)? 1 : 0; 1128 CHN_UNLOCK(rdch); 1129 } 1130 PCM_RELEASE_QUICK(d); 1131 *arg_i = tmp; 1132 break; 1133 1134 case SOUND_PCM_WRITE_CHANNELS: 1135 /* case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */ 1136 if (*arg_i < 0 || *arg_i > AFMT_CHANNEL_MAX) { 1137 *arg_i = 0; 1138 ret = EINVAL; 1139 break; 1140 } 1141 if (*arg_i != 0) { 1142 uint32_t ext = 0; 1143 1144 tmp = 0; 1145 /* 1146 * Map channel number to surround sound formats. 1147 * Devices that need bitperfect mode to operate 1148 * (e.g. more than SND_CHN_MAX channels) are not 1149 * subject to any mapping. 1150 */ 1151 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 1152 struct pcmchan_matrix *m; 1153 1154 if (*arg_i > SND_CHN_MAX) 1155 *arg_i = SND_CHN_MAX; 1156 1157 m = feeder_matrix_default_channel_map(*arg_i); 1158 if (m != NULL) 1159 ext = m->ext; 1160 } 1161 1162 PCM_ACQUIRE_QUICK(d); 1163 if (wrch) { 1164 CHN_LOCK(wrch); 1165 ret = chn_setformat(wrch, 1166 SND_FORMAT(wrch->format, *arg_i, ext)); 1167 tmp = AFMT_CHANNEL(wrch->format); 1168 CHN_UNLOCK(wrch); 1169 } 1170 if (rdch && ret == 0) { 1171 CHN_LOCK(rdch); 1172 ret = chn_setformat(rdch, 1173 SND_FORMAT(rdch->format, *arg_i, ext)); 1174 if (tmp == 0) 1175 tmp = AFMT_CHANNEL(rdch->format); 1176 CHN_UNLOCK(rdch); 1177 } 1178 PCM_RELEASE_QUICK(d); 1179 *arg_i = tmp; 1180 } else { 1181 chn = wrch ? wrch : rdch; 1182 CHN_LOCK(chn); 1183 *arg_i = AFMT_CHANNEL(chn->format); 1184 CHN_UNLOCK(chn); 1185 } 1186 break; 1187 1188 case SOUND_PCM_READ_CHANNELS: 1189 chn = wrch ? wrch : rdch; 1190 if (chn) { 1191 CHN_LOCK(chn); 1192 *arg_i = AFMT_CHANNEL(chn->format); 1193 CHN_UNLOCK(chn); 1194 } else { 1195 *arg_i = 0; 1196 ret = EINVAL; 1197 } 1198 break; 1199 1200 case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */ 1201 chn = wrch ? wrch : rdch; 1202 if (chn) { 1203 CHN_LOCK(chn); 1204 *arg_i = chn_getformats(chn); 1205 CHN_UNLOCK(chn); 1206 } else { 1207 *arg_i = 0; 1208 ret = EINVAL; 1209 } 1210 break; 1211 1212 case SNDCTL_DSP_SETFMT: /* sets _one_ format */ 1213 if (*arg_i != AFMT_QUERY) { 1214 tmp = 0; 1215 PCM_ACQUIRE_QUICK(d); 1216 if (wrch) { 1217 CHN_LOCK(wrch); 1218 ret = chn_setformat(wrch, SND_FORMAT(*arg_i, 1219 AFMT_CHANNEL(wrch->format), 1220 AFMT_EXTCHANNEL(wrch->format))); 1221 tmp = wrch->format; 1222 CHN_UNLOCK(wrch); 1223 } 1224 if (rdch && ret == 0) { 1225 CHN_LOCK(rdch); 1226 ret = chn_setformat(rdch, SND_FORMAT(*arg_i, 1227 AFMT_CHANNEL(rdch->format), 1228 AFMT_EXTCHANNEL(rdch->format))); 1229 if (tmp == 0) 1230 tmp = rdch->format; 1231 CHN_UNLOCK(rdch); 1232 } 1233 PCM_RELEASE_QUICK(d); 1234 *arg_i = AFMT_ENCODING(tmp); 1235 } else { 1236 chn = wrch ? wrch : rdch; 1237 CHN_LOCK(chn); 1238 *arg_i = AFMT_ENCODING(chn->format); 1239 CHN_UNLOCK(chn); 1240 } 1241 break; 1242 1243 case SNDCTL_DSP_SETFRAGMENT: 1244 DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg)); 1245 { 1246 uint32_t fragln = (*arg_i) & 0x0000ffff; 1247 uint32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16; 1248 uint32_t fragsz; 1249 uint32_t r_maxfrags, r_fragsz; 1250 1251 RANGE(fragln, 4, 16); 1252 fragsz = 1 << fragln; 1253 1254 if (maxfrags == 0) 1255 maxfrags = CHN_2NDBUFMAXSIZE / fragsz; 1256 if (maxfrags < 2) 1257 maxfrags = 2; 1258 if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE) 1259 maxfrags = CHN_2NDBUFMAXSIZE / fragsz; 1260 1261 DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz)); 1262 PCM_ACQUIRE_QUICK(d); 1263 if (rdch) { 1264 CHN_LOCK(rdch); 1265 ret = chn_setblocksize(rdch, maxfrags, fragsz); 1266 r_maxfrags = rdch->bufsoft->blkcnt; 1267 r_fragsz = rdch->bufsoft->blksz; 1268 CHN_UNLOCK(rdch); 1269 } else { 1270 r_maxfrags = maxfrags; 1271 r_fragsz = fragsz; 1272 } 1273 if (wrch && ret == 0) { 1274 CHN_LOCK(wrch); 1275 ret = chn_setblocksize(wrch, maxfrags, fragsz); 1276 maxfrags = wrch->bufsoft->blkcnt; 1277 fragsz = wrch->bufsoft->blksz; 1278 CHN_UNLOCK(wrch); 1279 } else { /* use whatever came from the read channel */ 1280 maxfrags = r_maxfrags; 1281 fragsz = r_fragsz; 1282 } 1283 PCM_RELEASE_QUICK(d); 1284 1285 fragln = 0; 1286 while (fragsz > 1) { 1287 fragln++; 1288 fragsz >>= 1; 1289 } 1290 *arg_i = (maxfrags << 16) | fragln; 1291 } 1292 break; 1293 1294 case SNDCTL_DSP_GETISPACE: 1295 /* return the size of data available in the input queue */ 1296 { 1297 audio_buf_info *a = (audio_buf_info *)arg; 1298 if (rdch) { 1299 struct snd_dbuf *bs = rdch->bufsoft; 1300 1301 CHN_LOCK(rdch); 1302 a->bytes = sndbuf_getready(bs); 1303 a->fragments = a->bytes / bs->blksz; 1304 a->fragstotal = bs->blkcnt; 1305 a->fragsize = bs->blksz; 1306 CHN_UNLOCK(rdch); 1307 } else 1308 ret = EINVAL; 1309 } 1310 break; 1311 1312 case SNDCTL_DSP_GETOSPACE: 1313 /* return space available in the output queue */ 1314 { 1315 audio_buf_info *a = (audio_buf_info *)arg; 1316 if (wrch) { 1317 struct snd_dbuf *bs = wrch->bufsoft; 1318 1319 CHN_LOCK(wrch); 1320 a->bytes = sndbuf_getfree(bs); 1321 a->fragments = a->bytes / bs->blksz; 1322 a->fragstotal = bs->blkcnt; 1323 a->fragsize = bs->blksz; 1324 CHN_UNLOCK(wrch); 1325 } else 1326 ret = EINVAL; 1327 } 1328 break; 1329 1330 case SNDCTL_DSP_GETIPTR: 1331 { 1332 count_info *a = (count_info *)arg; 1333 if (rdch) { 1334 struct snd_dbuf *bs = rdch->bufsoft; 1335 1336 CHN_LOCK(rdch); 1337 a->bytes = bs->total; 1338 a->blocks = sndbuf_getblocks(bs) - rdch->blocks; 1339 a->ptr = sndbuf_getfreeptr(bs); 1340 rdch->blocks = sndbuf_getblocks(bs); 1341 CHN_UNLOCK(rdch); 1342 } else 1343 ret = EINVAL; 1344 } 1345 break; 1346 1347 case SNDCTL_DSP_GETOPTR: 1348 { 1349 count_info *a = (count_info *)arg; 1350 if (wrch) { 1351 struct snd_dbuf *bs = wrch->bufsoft; 1352 1353 CHN_LOCK(wrch); 1354 a->bytes = bs->total; 1355 a->blocks = sndbuf_getblocks(bs) - wrch->blocks; 1356 a->ptr = sndbuf_getreadyptr(bs); 1357 wrch->blocks = sndbuf_getblocks(bs); 1358 CHN_UNLOCK(wrch); 1359 } else 1360 ret = EINVAL; 1361 } 1362 break; 1363 1364 case SNDCTL_DSP_GETCAPS: 1365 PCM_LOCK(d); 1366 *arg_i = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; 1367 if (rdch && wrch && !(pcm_getflags(d->dev) & SD_F_SIMPLEX)) 1368 *arg_i |= PCM_CAP_DUPLEX; 1369 if (rdch && (rdch->flags & CHN_F_VIRTUAL) != 0) 1370 *arg_i |= PCM_CAP_VIRTUAL; 1371 if (wrch && (wrch->flags & CHN_F_VIRTUAL) != 0) 1372 *arg_i |= PCM_CAP_VIRTUAL; 1373 PCM_UNLOCK(d); 1374 break; 1375 1376 case SOUND_PCM_READ_BITS: 1377 chn = wrch ? wrch : rdch; 1378 if (chn) { 1379 CHN_LOCK(chn); 1380 if (chn->format & AFMT_8BIT) 1381 *arg_i = 8; 1382 else if (chn->format & AFMT_16BIT) 1383 *arg_i = 16; 1384 else if (chn->format & AFMT_24BIT) 1385 *arg_i = 24; 1386 else if (chn->format & AFMT_32BIT) 1387 *arg_i = 32; 1388 else 1389 ret = EINVAL; 1390 CHN_UNLOCK(chn); 1391 } else { 1392 *arg_i = 0; 1393 ret = EINVAL; 1394 } 1395 break; 1396 1397 case SNDCTL_DSP_SETTRIGGER: 1398 if (rdch) { 1399 CHN_LOCK(rdch); 1400 rdch->flags &= ~CHN_F_NOTRIGGER; 1401 if (*arg_i & PCM_ENABLE_INPUT) 1402 chn_start(rdch, 1); 1403 else { 1404 chn_abort(rdch); 1405 chn_resetbuf(rdch); 1406 rdch->flags |= CHN_F_NOTRIGGER; 1407 } 1408 CHN_UNLOCK(rdch); 1409 } 1410 if (wrch) { 1411 CHN_LOCK(wrch); 1412 wrch->flags &= ~CHN_F_NOTRIGGER; 1413 if (*arg_i & PCM_ENABLE_OUTPUT) 1414 chn_start(wrch, 1); 1415 else { 1416 chn_abort(wrch); 1417 chn_resetbuf(wrch); 1418 wrch->flags |= CHN_F_NOTRIGGER; 1419 } 1420 CHN_UNLOCK(wrch); 1421 } 1422 break; 1423 1424 case SNDCTL_DSP_GETTRIGGER: 1425 *arg_i = 0; 1426 if (wrch) { 1427 CHN_LOCK(wrch); 1428 if (wrch->flags & CHN_F_TRIGGERED) 1429 *arg_i |= PCM_ENABLE_OUTPUT; 1430 CHN_UNLOCK(wrch); 1431 } 1432 if (rdch) { 1433 CHN_LOCK(rdch); 1434 if (rdch->flags & CHN_F_TRIGGERED) 1435 *arg_i |= PCM_ENABLE_INPUT; 1436 CHN_UNLOCK(rdch); 1437 } 1438 break; 1439 1440 case SNDCTL_DSP_GETODELAY: 1441 if (wrch) { 1442 struct snd_dbuf *bs = wrch->bufsoft; 1443 1444 CHN_LOCK(wrch); 1445 *arg_i = sndbuf_getready(bs); 1446 CHN_UNLOCK(wrch); 1447 } else 1448 ret = EINVAL; 1449 break; 1450 1451 case SNDCTL_DSP_POST: 1452 if (wrch) { 1453 CHN_LOCK(wrch); 1454 wrch->flags &= ~CHN_F_NOTRIGGER; 1455 chn_start(wrch, 1); 1456 CHN_UNLOCK(wrch); 1457 } 1458 break; 1459 1460 case SNDCTL_DSP_SETDUPLEX: 1461 /* 1462 * switch to full-duplex mode if card is in half-duplex 1463 * mode and is able to work in full-duplex mode 1464 */ 1465 PCM_LOCK(d); 1466 if (rdch && wrch && (pcm_getflags(d->dev) & SD_F_SIMPLEX)) 1467 pcm_setflags(d->dev, pcm_getflags(d->dev)^SD_F_SIMPLEX); 1468 PCM_UNLOCK(d); 1469 break; 1470 1471 /* 1472 * The following four ioctls are simple wrappers around mixer_ioctl 1473 * with no further processing. xcmd is short for "translated 1474 * command". 1475 */ 1476 case SNDCTL_DSP_GETRECVOL: 1477 if (xcmd == 0) { 1478 xcmd = SOUND_MIXER_READ_RECLEV; 1479 chn = rdch; 1480 } 1481 /* FALLTHROUGH */ 1482 case SNDCTL_DSP_SETRECVOL: 1483 if (xcmd == 0) { 1484 xcmd = SOUND_MIXER_WRITE_RECLEV; 1485 chn = rdch; 1486 } 1487 /* FALLTHROUGH */ 1488 case SNDCTL_DSP_GETPLAYVOL: 1489 if (xcmd == 0) { 1490 xcmd = SOUND_MIXER_READ_PCM; 1491 chn = wrch; 1492 } 1493 /* FALLTHROUGH */ 1494 case SNDCTL_DSP_SETPLAYVOL: 1495 if (xcmd == 0) { 1496 xcmd = SOUND_MIXER_WRITE_PCM; 1497 chn = wrch; 1498 } 1499 1500 ret = dsp_ioctl_channel(priv, chn, xcmd, arg); 1501 if (ret != -1) { 1502 PCM_GIANT_EXIT(d); 1503 return (ret); 1504 } 1505 1506 if (d->mixer_dev != NULL) { 1507 PCM_ACQUIRE_QUICK(d); 1508 ret = mixer_ioctl_cmd(d->mixer_dev, xcmd, arg, -1, td); 1509 PCM_RELEASE_QUICK(d); 1510 } else 1511 ret = ENOTSUP; 1512 1513 break; 1514 1515 case SNDCTL_DSP_GET_RECSRC_NAMES: 1516 case SNDCTL_DSP_GET_RECSRC: 1517 case SNDCTL_DSP_SET_RECSRC: 1518 if (d->mixer_dev != NULL) { 1519 PCM_ACQUIRE_QUICK(d); 1520 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td); 1521 PCM_RELEASE_QUICK(d); 1522 } else 1523 ret = ENOTSUP; 1524 break; 1525 1526 /* 1527 * The following 3 ioctls aren't very useful at the moment. For 1528 * now, only a single channel is associated with a cdev (/dev/dspN 1529 * instance), so there's only a single output routing to use (i.e., 1530 * the wrch bound to this cdev). 1531 */ 1532 case SNDCTL_DSP_GET_PLAYTGT_NAMES: 1533 { 1534 oss_mixer_enuminfo *ei; 1535 ei = (oss_mixer_enuminfo *)arg; 1536 ei->dev = 0; 1537 ei->ctrl = 0; 1538 ei->version = 0; /* static for now */ 1539 ei->strindex[0] = 0; 1540 1541 if (wrch != NULL) { 1542 ei->nvalues = 1; 1543 strlcpy(ei->strings, wrch->name, 1544 sizeof(ei->strings)); 1545 } else { 1546 ei->nvalues = 0; 1547 ei->strings[0] = '\0'; 1548 } 1549 } 1550 break; 1551 case SNDCTL_DSP_GET_PLAYTGT: 1552 case SNDCTL_DSP_SET_PLAYTGT: /* yes, they are the same for now */ 1553 /* 1554 * Re: SET_PLAYTGT 1555 * OSSv4: "The value that was accepted by the device will 1556 * be returned back in the variable pointed by the 1557 * argument." 1558 */ 1559 if (wrch != NULL) 1560 *arg_i = 0; 1561 else 1562 ret = EINVAL; 1563 break; 1564 1565 case SNDCTL_DSP_SILENCE: 1566 /* 1567 * Flush the software (pre-feed) buffer, but try to minimize playback 1568 * interruption. (I.e., record unplayed samples with intent to 1569 * restore by SNDCTL_DSP_SKIP.) Intended for application "pause" 1570 * functionality. 1571 */ 1572 if (wrch == NULL) 1573 ret = EINVAL; 1574 else { 1575 struct snd_dbuf *bs; 1576 CHN_LOCK(wrch); 1577 while (wrch->inprog != 0) 1578 cv_wait(&wrch->cv, &wrch->lock); 1579 bs = wrch->bufsoft; 1580 if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) { 1581 bs->sl = sndbuf_getready(bs); 1582 sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs)); 1583 sndbuf_fillsilence(bs); 1584 chn_start(wrch, 0); 1585 } 1586 CHN_UNLOCK(wrch); 1587 } 1588 break; 1589 1590 case SNDCTL_DSP_SKIP: 1591 /* 1592 * OSSv4 docs: "This ioctl call discards all unplayed samples in the 1593 * playback buffer by moving the current write position immediately 1594 * before the point where the device is currently reading the samples." 1595 */ 1596 if (wrch == NULL) 1597 ret = EINVAL; 1598 else { 1599 struct snd_dbuf *bs; 1600 CHN_LOCK(wrch); 1601 while (wrch->inprog != 0) 1602 cv_wait(&wrch->cv, &wrch->lock); 1603 bs = wrch->bufsoft; 1604 if ((bs->shadbuf != NULL) && (bs->sl > 0)) { 1605 sndbuf_softreset(bs); 1606 sndbuf_acquire(bs, bs->shadbuf, bs->sl); 1607 bs->sl = 0; 1608 chn_start(wrch, 0); 1609 } 1610 CHN_UNLOCK(wrch); 1611 } 1612 break; 1613 1614 case SNDCTL_DSP_CURRENT_OPTR: 1615 case SNDCTL_DSP_CURRENT_IPTR: 1616 /** 1617 * @note Changing formats resets the buffer counters, which differs 1618 * from the 4Front drivers. However, I don't expect this to be 1619 * much of a problem. 1620 * 1621 * @note In a test where @c CURRENT_OPTR is called immediately after write 1622 * returns, this driver is about 32K samples behind whereas 1623 * 4Front's is about 8K samples behind. Should determine source 1624 * of discrepancy, even if only out of curiosity. 1625 * 1626 * @todo Actually test SNDCTL_DSP_CURRENT_IPTR. 1627 */ 1628 chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch; 1629 if (chn == NULL) 1630 ret = EINVAL; 1631 else { 1632 struct snd_dbuf *bs; 1633 /* int tmp; */ 1634 1635 oss_count_t *oc = (oss_count_t *)arg; 1636 1637 CHN_LOCK(chn); 1638 bs = chn->bufsoft; 1639 oc->samples = bs->total / bs->align; 1640 oc->fifo_samples = sndbuf_getready(bs) / bs->align; 1641 CHN_UNLOCK(chn); 1642 } 1643 break; 1644 1645 case SNDCTL_DSP_HALT_OUTPUT: 1646 case SNDCTL_DSP_HALT_INPUT: 1647 chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch; 1648 if (chn == NULL) 1649 ret = EINVAL; 1650 else { 1651 CHN_LOCK(chn); 1652 chn_abort(chn); 1653 CHN_UNLOCK(chn); 1654 } 1655 break; 1656 1657 case SNDCTL_DSP_LOW_WATER: 1658 /* 1659 * Set the number of bytes required to attract attention by 1660 * select/poll. 1661 */ 1662 if (wrch != NULL) { 1663 CHN_LOCK(wrch); 1664 wrch->lw = (*arg_i > 1) ? *arg_i : 1; 1665 CHN_UNLOCK(wrch); 1666 } 1667 if (rdch != NULL) { 1668 CHN_LOCK(rdch); 1669 rdch->lw = (*arg_i > 1) ? *arg_i : 1; 1670 CHN_UNLOCK(rdch); 1671 } 1672 break; 1673 1674 case SNDCTL_DSP_GETERROR: 1675 #ifdef COMPAT_FREEBSD32 1676 case SNDCTL_DSP_GETERROR32: 1677 #endif 1678 /* 1679 * OSSv4 docs: "All errors and counters will automatically be 1680 * cleared to zeroes after the call so each call will return only 1681 * the errors that occurred after the previous invocation. ... The 1682 * play_underruns and rec_overrun fields are the only useful fields 1683 * returned by OSS 4.0." 1684 */ 1685 { 1686 audio_errinfo *ei = (audio_errinfo *)arg; 1687 #ifdef COMPAT_FREEBSD32 1688 audio_errinfo errinfo; 1689 audio_errinfo32 *ei32 = (audio_errinfo32 *)arg; 1690 1691 if (cmd == SNDCTL_DSP_GETERROR32) { 1692 ei = &errinfo; 1693 } 1694 #endif 1695 1696 bzero((void *)ei, sizeof(*ei)); 1697 1698 if (wrch != NULL) { 1699 CHN_LOCK(wrch); 1700 ei->play_underruns = wrch->xruns; 1701 wrch->xruns = 0; 1702 CHN_UNLOCK(wrch); 1703 } 1704 if (rdch != NULL) { 1705 CHN_LOCK(rdch); 1706 ei->rec_overruns = rdch->xruns; 1707 rdch->xruns = 0; 1708 CHN_UNLOCK(rdch); 1709 } 1710 #ifdef COMPAT_FREEBSD32 1711 if (cmd == SNDCTL_DSP_GETERROR32) { 1712 bzero((void *)ei32, sizeof(*ei32)); 1713 ei32->play_underruns = ei->play_underruns; 1714 ei32->rec_overruns = ei->rec_overruns; 1715 ei32->play_ptradjust = ei->play_ptradjust; 1716 ei32->rec_ptradjust = ei->rec_ptradjust; 1717 ei32->play_errorcount = ei->play_errorcount; 1718 ei32->rec_errorcount = ei->rec_errorcount; 1719 ei32->play_lasterror = ei->play_lasterror; 1720 ei32->rec_lasterror = ei->rec_lasterror; 1721 ei32->play_errorparm = ei->play_errorparm; 1722 ei32->rec_errorparm = ei->rec_errorparm; 1723 } 1724 #endif 1725 } 1726 break; 1727 1728 case SNDCTL_DSP_SYNCGROUP: 1729 PCM_ACQUIRE_QUICK(d); 1730 ret = dsp_oss_syncgroup(wrch, rdch, (oss_syncgroup *)arg); 1731 PCM_RELEASE_QUICK(d); 1732 break; 1733 1734 case SNDCTL_DSP_SYNCSTART: 1735 PCM_ACQUIRE_QUICK(d); 1736 ret = dsp_oss_syncstart(*arg_i); 1737 PCM_RELEASE_QUICK(d); 1738 break; 1739 1740 case SNDCTL_DSP_POLICY: 1741 PCM_ACQUIRE_QUICK(d); 1742 ret = dsp_oss_policy(wrch, rdch, *arg_i); 1743 PCM_RELEASE_QUICK(d); 1744 break; 1745 1746 case SNDCTL_DSP_COOKEDMODE: 1747 PCM_ACQUIRE_QUICK(d); 1748 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) 1749 ret = dsp_oss_cookedmode(wrch, rdch, *arg_i); 1750 PCM_RELEASE_QUICK(d); 1751 break; 1752 case SNDCTL_DSP_GET_CHNORDER: 1753 PCM_ACQUIRE_QUICK(d); 1754 ret = dsp_oss_getchnorder(wrch, rdch, (unsigned long long *)arg); 1755 PCM_RELEASE_QUICK(d); 1756 break; 1757 case SNDCTL_DSP_SET_CHNORDER: 1758 PCM_ACQUIRE_QUICK(d); 1759 ret = dsp_oss_setchnorder(wrch, rdch, (unsigned long long *)arg); 1760 PCM_RELEASE_QUICK(d); 1761 break; 1762 case SNDCTL_DSP_GETCHANNELMASK: /* XXX vlc */ 1763 PCM_ACQUIRE_QUICK(d); 1764 ret = dsp_oss_getchannelmask(wrch, rdch, (int *)arg); 1765 PCM_RELEASE_QUICK(d); 1766 break; 1767 case SNDCTL_DSP_BIND_CHANNEL: /* XXX what?!? */ 1768 ret = EINVAL; 1769 break; 1770 #ifdef OSSV4_EXPERIMENT 1771 /* 1772 * XXX The following ioctls are not yet supported and just return 1773 * EINVAL. 1774 */ 1775 case SNDCTL_DSP_GETOPEAKS: 1776 case SNDCTL_DSP_GETIPEAKS: 1777 chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch; 1778 if (chn == NULL) 1779 ret = EINVAL; 1780 else { 1781 oss_peaks_t *op = (oss_peaks_t *)arg; 1782 int lpeak, rpeak; 1783 1784 CHN_LOCK(chn); 1785 ret = chn_getpeaks(chn, &lpeak, &rpeak); 1786 if (ret == -1) 1787 ret = EINVAL; 1788 else { 1789 (*op)[0] = lpeak; 1790 (*op)[1] = rpeak; 1791 } 1792 CHN_UNLOCK(chn); 1793 } 1794 break; 1795 1796 /* 1797 * XXX Once implemented, revisit this for proper cv protection 1798 * (if necessary). 1799 */ 1800 case SNDCTL_GETLABEL: 1801 ret = dsp_oss_getlabel(wrch, rdch, (oss_label_t *)arg); 1802 break; 1803 case SNDCTL_SETLABEL: 1804 ret = dsp_oss_setlabel(wrch, rdch, (oss_label_t *)arg); 1805 break; 1806 case SNDCTL_GETSONG: 1807 ret = dsp_oss_getsong(wrch, rdch, (oss_longname_t *)arg); 1808 break; 1809 case SNDCTL_SETSONG: 1810 ret = dsp_oss_setsong(wrch, rdch, (oss_longname_t *)arg); 1811 break; 1812 case SNDCTL_SETNAME: 1813 ret = dsp_oss_setname(wrch, rdch, (oss_longname_t *)arg); 1814 break; 1815 #endif /* !OSSV4_EXPERIMENT */ 1816 case SNDCTL_DSP_MAPINBUF: 1817 case SNDCTL_DSP_MAPOUTBUF: 1818 case SNDCTL_DSP_SETSYNCRO: 1819 /* undocumented */ 1820 1821 case SNDCTL_DSP_SUBDIVIDE: 1822 case SOUND_PCM_WRITE_FILTER: 1823 case SOUND_PCM_READ_FILTER: 1824 /* dunno what these do, don't sound important */ 1825 1826 default: 1827 DEB(printf("default ioctl fn 0x%08lx fail\n", cmd)); 1828 ret = EINVAL; 1829 break; 1830 } 1831 1832 PCM_GIANT_LEAVE(d); 1833 1834 return (ret); 1835 } 1836 1837 static int 1838 dsp_poll(struct cdev *i_dev, int events, struct thread *td) 1839 { 1840 struct dsp_cdevpriv *priv; 1841 struct snddev_info *d; 1842 struct pcm_channel *wrch, *rdch; 1843 int ret, e, err; 1844 1845 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 1846 return (err); 1847 d = priv->sc; 1848 if (!DSP_REGISTERED(d)) { 1849 /* XXX many clients don't understand POLLNVAL */ 1850 return (events & (POLLHUP | POLLPRI | POLLIN | 1851 POLLRDNORM | POLLOUT | POLLWRNORM)); 1852 } 1853 PCM_GIANT_ENTER(d); 1854 1855 ret = 0; 1856 1857 wrch = priv->wrch; 1858 rdch = priv->rdch; 1859 1860 if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) { 1861 CHN_LOCK(wrch); 1862 e = (events & (POLLOUT | POLLWRNORM)); 1863 if (e) 1864 ret |= chn_poll(wrch, e, td); 1865 CHN_UNLOCK(wrch); 1866 } 1867 1868 if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) { 1869 CHN_LOCK(rdch); 1870 e = (events & (POLLIN | POLLRDNORM)); 1871 if (e) 1872 ret |= chn_poll(rdch, e, td); 1873 CHN_UNLOCK(rdch); 1874 } 1875 1876 PCM_GIANT_LEAVE(d); 1877 1878 return (ret); 1879 } 1880 1881 struct dsp_mmap_handle { 1882 struct cdev *cdev; 1883 struct snd_dbuf *buf; 1884 }; 1885 1886 static int 1887 dsp_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, 1888 vm_ooffset_t foff, struct ucred *cred, u_short *color) 1889 { 1890 struct dsp_mmap_handle *h = handle; 1891 1892 dev_ref(h->cdev); 1893 sndbuf_ref(h->buf); 1894 return (0); 1895 } 1896 1897 static void 1898 dsp_dev_pager_dtor(void *handle) 1899 { 1900 struct dsp_mmap_handle *h = handle; 1901 1902 sndbuf_rele(h->buf); 1903 dev_rel(h->cdev); 1904 free(h, M_DEVBUF); 1905 } 1906 1907 static int 1908 dsp_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, 1909 vm_page_t *mres) 1910 { 1911 struct dsp_mmap_handle *h = object->handle; 1912 vm_page_t m; 1913 uintptr_t addr; 1914 vm_paddr_t paddr; 1915 1916 addr = (uintptr_t)offset; 1917 if (addr < (uintptr_t)h->buf->buf || 1918 addr >= (uintptr_t)h->buf->buf + h->buf->allocsize) 1919 return (VM_PAGER_ERROR); 1920 paddr = vtophys((void *)addr); 1921 1922 if (((*mres)->flags & PG_FICTITIOUS) != 0) { 1923 m = *mres; 1924 vm_page_updatefake(m, paddr, object->memattr); 1925 } else { 1926 VM_OBJECT_WUNLOCK(object); 1927 m = vm_page_getfake(paddr, object->memattr); 1928 VM_OBJECT_WLOCK(object); 1929 vm_page_replace(m, object, (*mres)->pindex, *mres); 1930 *mres = m; 1931 } 1932 m->valid = VM_PAGE_BITS_ALL; 1933 return (VM_PAGER_OK); 1934 } 1935 1936 static void 1937 dsp_dev_pager_path(void *handle, char *path, size_t len) 1938 { 1939 struct dsp_mmap_handle *h = handle; 1940 1941 dev_copyname(h->cdev, path, len); 1942 } 1943 1944 static const struct cdev_pager_ops dsp_dev_pager_ops = { 1945 .cdev_pg_ctor = dsp_dev_pager_ctor, 1946 .cdev_pg_dtor = dsp_dev_pager_dtor, 1947 .cdev_pg_fault = dsp_dev_pager_fault, 1948 .cdev_pg_path = dsp_dev_pager_path, 1949 }; 1950 1951 static int 1952 dsp_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, 1953 vm_size_t size, struct vm_object **object, int nprot) 1954 { 1955 struct dsp_mmap_handle *handle; 1956 struct dsp_cdevpriv *priv; 1957 struct snddev_info *d; 1958 struct pcm_channel *c; 1959 int err; 1960 bool dealloc; 1961 1962 if (*offset >= *offset + size) 1963 return (EINVAL); 1964 1965 /* 1966 * https://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html 1967 */ 1968 if ((nprot & PROT_EXEC) && (dsp_mmap_allow_prot_exec < 0 || 1969 (dsp_mmap_allow_prot_exec == 0 && 1970 SV_CURPROC_ABI() != SV_ABI_LINUX))) 1971 return (EINVAL); 1972 1973 if ((nprot & (PROT_READ | PROT_WRITE)) == 0) 1974 return (EINVAL); 1975 1976 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 1977 return (err); 1978 d = priv->sc; 1979 if (!DSP_REGISTERED(d)) 1980 return (EINVAL); 1981 1982 PCM_GIANT_ENTER(d); 1983 1984 /* 1985 * PROT_READ (alone) selects the input buffer. 1986 * PROT_WRITE (alone) selects the output buffer. 1987 * PROT_WRITE|PROT_READ together select the output buffer. 1988 */ 1989 c = ((nprot & PROT_WRITE) != 0) ? priv->wrch : priv->rdch; 1990 if (c == NULL) { 1991 PCM_GIANT_EXIT(d); 1992 return (EINVAL); 1993 } 1994 1995 CHN_LOCK(c); 1996 if ((c->flags & CHN_F_MMAP_INVALID) || 1997 c->bufsoft->allocsize < *offset + size) { 1998 CHN_UNLOCK(c); 1999 PCM_GIANT_EXIT(d); 2000 return (EINVAL); 2001 } 2002 c->flags |= CHN_F_MMAP; 2003 *offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset); 2004 CHN_UNLOCK(c); 2005 2006 handle = malloc(sizeof(*handle), M_DEVBUF, M_WAITOK); 2007 handle->cdev = cdev; 2008 handle->buf = c->bufsoft; 2009 *object = cdev_pager_allocate(handle, OBJT_DEVICE, &dsp_dev_pager_ops, 2010 size, nprot, *offset, curthread->td_ucred); 2011 PCM_GIANT_LEAVE(d); 2012 if (*object != NULL) { 2013 err = 0; 2014 dealloc = false; 2015 CHN_LOCK(c); 2016 if (c->flags & CHN_F_MMAP_INVALID) { 2017 c->flags &= ~CHN_F_MMAP; 2018 err = EINVAL; 2019 dealloc = true; 2020 } 2021 CHN_UNLOCK(c); 2022 /* We use a helper bool to keep the channel locking simpler. */ 2023 if (dealloc) 2024 vm_object_deallocate(*object); 2025 } else { 2026 free(handle, M_DEVBUF); 2027 err = ENOMEM; 2028 } 2029 2030 return (err); 2031 } 2032 2033 static const char *dsp_aliases[] = { 2034 "dsp_ac3", 2035 "dsp_mmap", 2036 "dsp_multich", 2037 "dsp_spdifout", 2038 "dsp_spdifin", 2039 }; 2040 2041 static void 2042 dsp_clone(void *arg, struct ucred *cred, char *name, int namelen, 2043 struct cdev **dev) 2044 { 2045 struct snddev_info *d; 2046 size_t i; 2047 2048 if (*dev != NULL) 2049 return; 2050 if (strcmp(name, "dsp") == 0 && dsp_basename_clone) 2051 goto found; 2052 for (i = 0; i < nitems(dsp_aliases); i++) { 2053 if (strcmp(name, dsp_aliases[i]) == 0) 2054 goto found; 2055 } 2056 return; 2057 found: 2058 bus_topo_lock(); 2059 d = devclass_get_softc(pcm_devclass, snd_unit); 2060 /* 2061 * If we only have a single soundcard attached and we detach it right 2062 * before entering dsp_clone(), there is a chance pcm_unregister() will 2063 * have returned already, meaning it will have set snd_unit to -1, and 2064 * thus devclass_get_softc() will return NULL here. 2065 */ 2066 if (DSP_REGISTERED(d)) { 2067 *dev = d->dsp_dev; 2068 dev_ref(*dev); 2069 } 2070 bus_topo_unlock(); 2071 } 2072 2073 static void 2074 dsp_sysinit(void *p) 2075 { 2076 if (dsp_ehtag != NULL) 2077 return; 2078 dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000); 2079 } 2080 2081 static void 2082 dsp_sysuninit(void *p) 2083 { 2084 if (dsp_ehtag == NULL) 2085 return; 2086 EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag); 2087 dsp_ehtag = NULL; 2088 } 2089 2090 SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL); 2091 SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL); 2092 2093 static void 2094 dsp_oss_audioinfo_unavail(oss_audioinfo *ai, int unit) 2095 { 2096 bzero(ai, sizeof(*ai)); 2097 ai->dev = unit; 2098 snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit); 2099 ai->pid = -1; 2100 strlcpy(ai->cmd, CHN_COMM_UNUSED, sizeof(ai->cmd)); 2101 ai->card_number = unit; 2102 ai->port_number = unit; 2103 ai->mixer_dev = -1; 2104 ai->legacy_device = unit; 2105 } 2106 2107 /** 2108 * @brief Handler for SNDCTL_AUDIOINFO. 2109 * 2110 * Gathers information about the audio device specified in ai->dev. If 2111 * ai->dev == -1, then this function gathers information about the current 2112 * device. If the call comes in on a non-audio device and ai->dev == -1, 2113 * return EINVAL. 2114 * 2115 * This routine is supposed to go practically straight to the hardware, 2116 * getting capabilities directly from the sound card driver, side-stepping 2117 * the intermediate channel interface. 2118 * 2119 * @note 2120 * Calling threads must not hold any snddev_info or pcm_channel locks. 2121 * 2122 * @param dev device on which the ioctl was issued 2123 * @param ai ioctl request data container 2124 * @param ex flag to distinguish between SNDCTL_AUDIOINFO from 2125 * SNDCTL_AUDIOINFO_EX 2126 * 2127 * @retval 0 success 2128 * @retval EINVAL ai->dev specifies an invalid device 2129 */ 2130 int 2131 dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai, bool ex) 2132 { 2133 struct pcmchan_caps *caps; 2134 struct pcm_channel *ch; 2135 struct snddev_info *d; 2136 uint32_t fmts; 2137 int i, minch, maxch, unit; 2138 2139 /* 2140 * If probing the device that received the ioctl, make sure it's a 2141 * DSP device. (Users may use this ioctl with /dev/mixer and 2142 * /dev/midi.) 2143 */ 2144 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) 2145 return (EINVAL); 2146 2147 bus_topo_lock(); 2148 for (unit = 0; pcm_devclass != NULL && 2149 unit < devclass_get_maxunit(pcm_devclass); unit++) { 2150 d = devclass_get_softc(pcm_devclass, unit); 2151 if (!PCM_REGISTERED(d)) { 2152 if ((ai->dev == -1 && unit == snd_unit) || 2153 ai->dev == unit) { 2154 dsp_oss_audioinfo_unavail(ai, unit); 2155 bus_topo_unlock(); 2156 return (0); 2157 } else { 2158 d = NULL; 2159 continue; 2160 } 2161 } 2162 2163 PCM_UNLOCKASSERT(d); 2164 PCM_LOCK(d); 2165 if ((ai->dev == -1 && d->dsp_dev == i_dev) || 2166 (ai->dev == unit)) { 2167 PCM_UNLOCK(d); 2168 break; 2169 } else { 2170 PCM_UNLOCK(d); 2171 d = NULL; 2172 } 2173 } 2174 bus_topo_unlock(); 2175 2176 /* Exhausted the search -- nothing is locked, so return. */ 2177 if (d == NULL) 2178 return (EINVAL); 2179 2180 /* XXX Need Giant magic entry ??? */ 2181 2182 PCM_UNLOCKASSERT(d); 2183 PCM_LOCK(d); 2184 2185 bzero((void *)ai, sizeof(oss_audioinfo)); 2186 ai->dev = unit; 2187 strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name)); 2188 ai->pid = -1; 2189 strlcpy(ai->cmd, CHN_COMM_UNKNOWN, sizeof(ai->cmd)); 2190 ai->card_number = unit; 2191 ai->port_number = unit; 2192 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; 2193 ai->legacy_device = unit; 2194 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); 2195 ai->enabled = device_is_attached(d->dev) ? 1 : 0; 2196 ai->next_play_engine = 0; 2197 ai->next_rec_engine = 0; 2198 ai->busy = 0; 2199 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; 2200 ai->iformats = 0; 2201 ai->oformats = 0; 2202 ai->min_rate = INT_MAX; 2203 ai->max_rate = 0; 2204 ai->min_channels = INT_MAX; 2205 ai->max_channels = 0; 2206 2207 /* Gather global information about the device. */ 2208 CHN_FOREACH(ch, d, channels.pcm) { 2209 CHN_UNLOCKASSERT(ch); 2210 CHN_LOCK(ch); 2211 2212 /* 2213 * Skip physical channels if we are servicing SNDCTL_AUDIOINFO, 2214 * or VCHANs if we are servicing SNDCTL_AUDIOINFO_EX. 2215 * 2216 * For SNDCTL_AUDIOINFO do not skip the physical channels if 2217 * there are no VCHANs. 2218 */ 2219 if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) || 2220 ((!ex && (ch->flags & CHN_F_VIRTUAL) == 0) && 2221 (d->pvchancount > 0 || d->rvchancount > 0))) { 2222 CHN_UNLOCK(ch); 2223 continue; 2224 } 2225 2226 if ((ch->flags & CHN_F_BUSY) == 0) { 2227 ai->busy |= (ch->direction == PCMDIR_PLAY) ? 2228 OPEN_WRITE : OPEN_READ; 2229 } 2230 2231 ai->caps |= 2232 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | 2233 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : 2234 PCM_CAP_INPUT); 2235 2236 caps = chn_getcaps(ch); 2237 2238 minch = INT_MAX; 2239 maxch = 0; 2240 fmts = 0; 2241 for (i = 0; caps->fmtlist[i]; i++) { 2242 fmts |= AFMT_ENCODING(caps->fmtlist[i]); 2243 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); 2244 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); 2245 } 2246 2247 if (ch->direction == PCMDIR_PLAY) 2248 ai->oformats |= fmts; 2249 else 2250 ai->iformats |= fmts; 2251 2252 if (ex || (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 2253 ai->min_rate = min(ai->min_rate, caps->minspeed); 2254 ai->max_rate = max(ai->max_rate, caps->maxspeed); 2255 } else { 2256 ai->min_rate = min(ai->min_rate, feeder_rate_min); 2257 ai->max_rate = max(ai->max_rate, feeder_rate_max); 2258 } 2259 ai->min_channels = min(ai->min_channels, minch); 2260 ai->max_channels = max(ai->max_channels, maxch); 2261 2262 CHN_UNLOCK(ch); 2263 } 2264 if (ai->min_rate == INT_MAX) 2265 ai->min_rate = 0; 2266 if (ai->min_channels == INT_MAX) 2267 ai->min_channels = 0; 2268 2269 PCM_UNLOCK(d); 2270 2271 return (0); 2272 } 2273 2274 static int 2275 dsp_oss_engineinfo_cb(void *data, void *arg) 2276 { 2277 struct dsp_cdevpriv *priv = data; 2278 struct pcm_channel *ch = arg; 2279 2280 if (DSP_REGISTERED(priv->sc) && (ch == priv->rdch || ch == priv->wrch)) 2281 return (1); 2282 2283 return (0); 2284 } 2285 2286 /** 2287 * @brief Handler for SNDCTL_ENGINEINFO 2288 * 2289 * Gathers information about the audio device's engine specified in ai->dev. 2290 * If ai->dev == -1, then this function gathers information about the current 2291 * device. If the call comes in on a non-audio device and ai->dev == -1, 2292 * return EINVAL. 2293 * 2294 * This routine is supposed to go practically straight to the hardware, 2295 * getting capabilities directly from the sound card driver, side-stepping 2296 * the intermediate channel interface. 2297 * 2298 * @note 2299 * Calling threads must not hold any snddev_info or pcm_channel locks. 2300 * 2301 * @param dev device on which the ioctl was issued 2302 * @param ai ioctl request data container 2303 * 2304 * @retval 0 success 2305 * @retval EINVAL ai->dev specifies an invalid device 2306 */ 2307 int 2308 dsp_oss_engineinfo(struct cdev *i_dev, oss_audioinfo *ai) 2309 { 2310 struct pcmchan_caps *caps; 2311 struct pcm_channel *ch; 2312 struct snddev_info *d; 2313 uint32_t fmts; 2314 int i, nchan, *rates, minch, maxch, unit; 2315 2316 /* 2317 * If probing the device that received the ioctl, make sure it's a 2318 * DSP device. (Users may use this ioctl with /dev/mixer and 2319 * /dev/midi.) 2320 */ 2321 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) 2322 return (EINVAL); 2323 2324 ch = NULL; 2325 nchan = 0; 2326 2327 /* 2328 * Search for the requested audio device (channel). Start by 2329 * iterating over pcm devices. 2330 */ 2331 bus_topo_lock(); 2332 for (unit = 0; pcm_devclass != NULL && 2333 unit < devclass_get_maxunit(pcm_devclass); unit++) { 2334 d = devclass_get_softc(pcm_devclass, unit); 2335 if (!PCM_REGISTERED(d)) 2336 continue; 2337 2338 /* XXX Need Giant magic entry ??? */ 2339 2340 /* See the note in function docblock */ 2341 PCM_UNLOCKASSERT(d); 2342 PCM_LOCK(d); 2343 2344 CHN_FOREACH(ch, d, channels.pcm) { 2345 CHN_UNLOCKASSERT(ch); 2346 CHN_LOCK(ch); 2347 if ((ai->dev == -1 && devfs_foreach_cdevpriv( 2348 i_dev, dsp_oss_engineinfo_cb, ch) != 0) || 2349 ai->dev == nchan) 2350 break; 2351 CHN_UNLOCK(ch); 2352 ++nchan; 2353 } 2354 2355 if (ch == NULL) { 2356 PCM_UNLOCK(d); 2357 continue; 2358 } 2359 2360 /* 2361 * At this point, the following synchronization stuff 2362 * has happened: 2363 * - a specific PCM device is locked. 2364 * - a specific audio channel has been locked, so be 2365 * sure to unlock when exiting; 2366 */ 2367 2368 caps = chn_getcaps(ch); 2369 2370 /* 2371 * With all handles collected, zero out the user's 2372 * container and begin filling in its fields. 2373 */ 2374 bzero((void *)ai, sizeof(oss_audioinfo)); 2375 2376 ai->dev = nchan; 2377 strlcpy(ai->name, ch->name, sizeof(ai->name)); 2378 2379 if ((ch->flags & CHN_F_BUSY) == 0) 2380 ai->busy = 0; 2381 else 2382 ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; 2383 2384 ai->pid = ch->pid; 2385 strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); 2386 2387 /* 2388 * These flags stolen from SNDCTL_DSP_GETCAPS handler. 2389 * Note, however, that a single channel operates in 2390 * only one direction, so PCM_CAP_DUPLEX is out. 2391 */ 2392 /** 2393 * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep 2394 * these in pcmchan::caps? 2395 */ 2396 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | 2397 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | 2398 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); 2399 2400 /* 2401 * Collect formats supported @b natively by the 2402 * device. Also determine min/max channels. 2403 */ 2404 minch = INT_MAX; 2405 maxch = 0; 2406 fmts = 0; 2407 for (i = 0; caps->fmtlist[i]; i++) { 2408 fmts |= AFMT_ENCODING(caps->fmtlist[i]); 2409 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); 2410 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); 2411 } 2412 2413 if (ch->direction == PCMDIR_PLAY) 2414 ai->oformats = fmts; 2415 else 2416 ai->iformats = fmts; 2417 2418 /** 2419 * @note 2420 * @c magic - OSSv4 docs: "Reserved for internal use 2421 * by OSS." 2422 * 2423 * @par 2424 * @c card_number - OSSv4 docs: "Number of the sound 2425 * card where this device belongs or -1 if this 2426 * information is not available. Applications 2427 * should normally not use this field for any 2428 * purpose." 2429 */ 2430 ai->card_number = unit; 2431 /** 2432 * @todo @c song_name - depends first on 2433 * SNDCTL_[GS]ETSONG @todo @c label - depends 2434 * on SNDCTL_[GS]ETLABEL 2435 * @todo @c port_number - routing information? 2436 */ 2437 ai->port_number = unit; 2438 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; 2439 /** 2440 * @note 2441 * @c legacy_device - OSSv4 docs: "Obsolete." 2442 */ 2443 ai->legacy_device = unit; 2444 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); 2445 ai->enabled = device_is_attached(d->dev) ? 1 : 0; 2446 /** 2447 * @note 2448 * @c flags - OSSv4 docs: "Reserved for future use." 2449 * 2450 * @note 2451 * @c binding - OSSv4 docs: "Reserved for future use." 2452 * 2453 * @todo @c handle - haven't decided how to generate 2454 * this yet; bus, vendor, device IDs? 2455 */ 2456 2457 if ((ch->flags & CHN_F_EXCLUSIVE) || 2458 (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 2459 ai->min_rate = caps->minspeed; 2460 ai->max_rate = caps->maxspeed; 2461 } else { 2462 ai->min_rate = feeder_rate_min; 2463 ai->max_rate = feeder_rate_max; 2464 } 2465 2466 ai->min_channels = minch; 2467 ai->max_channels = maxch; 2468 2469 ai->nrates = chn_getrates(ch, &rates); 2470 if (ai->nrates > OSS_MAX_SAMPLE_RATES) 2471 ai->nrates = OSS_MAX_SAMPLE_RATES; 2472 2473 for (i = 0; i < ai->nrates; i++) 2474 ai->rates[i] = rates[i]; 2475 2476 ai->next_play_engine = 0; 2477 ai->next_rec_engine = 0; 2478 2479 CHN_UNLOCK(ch); 2480 PCM_UNLOCK(d); 2481 bus_topo_unlock(); 2482 2483 return (0); 2484 } 2485 bus_topo_unlock(); 2486 2487 /* Exhausted the search -- nothing is locked, so return. */ 2488 return (EINVAL); 2489 } 2490 2491 /** 2492 * @brief Assigns a PCM channel to a sync group. 2493 * 2494 * Sync groups are used to enable audio operations on multiple devices 2495 * simultaneously. They may be used with any number of devices and may 2496 * span across applications. Devices are added to groups with 2497 * the SNDCTL_DSP_SYNCGROUP ioctl, and operations are triggered with the 2498 * SNDCTL_DSP_SYNCSTART ioctl. 2499 * 2500 * If the @c id field of the @c group parameter is set to zero, then a new 2501 * sync group is created. Otherwise, wrch and rdch (if set) are added to 2502 * the group specified. 2503 * 2504 * @todo As far as memory allocation, should we assume that things are 2505 * okay and allocate with M_WAITOK before acquiring channel locks, 2506 * freeing later if not? 2507 * 2508 * @param wrch output channel associated w/ device (if any) 2509 * @param rdch input channel associated w/ device (if any) 2510 * @param group Sync group parameters 2511 * 2512 * @retval 0 success 2513 * @retval non-zero error to be propagated upstream 2514 */ 2515 static int 2516 dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group) 2517 { 2518 struct pcmchan_syncmember *smrd, *smwr; 2519 struct pcmchan_syncgroup *sg; 2520 int ret, sg_ids[3]; 2521 2522 smrd = NULL; 2523 smwr = NULL; 2524 sg = NULL; 2525 ret = 0; 2526 2527 /* 2528 * Free_unr() may sleep, so store released syncgroup IDs until after 2529 * all locks are released. 2530 */ 2531 sg_ids[0] = sg_ids[1] = sg_ids[2] = 0; 2532 2533 PCM_SG_LOCK(); 2534 2535 /* 2536 * - Insert channel(s) into group's member list. 2537 * - Set CHN_F_NOTRIGGER on channel(s). 2538 * - Stop channel(s). 2539 */ 2540 2541 /* 2542 * If device's channels are already mapped to a group, unmap them. 2543 */ 2544 if (wrch) { 2545 CHN_LOCK(wrch); 2546 sg_ids[0] = chn_syncdestroy(wrch); 2547 } 2548 2549 if (rdch) { 2550 CHN_LOCK(rdch); 2551 sg_ids[1] = chn_syncdestroy(rdch); 2552 } 2553 2554 /* 2555 * Verify that mode matches character device properites. 2556 * - Bail if PCM_ENABLE_OUTPUT && wrch == NULL. 2557 * - Bail if PCM_ENABLE_INPUT && rdch == NULL. 2558 */ 2559 if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) || 2560 ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) { 2561 ret = EINVAL; 2562 goto out; 2563 } 2564 2565 /* 2566 * An id of zero indicates the user wants to create a new 2567 * syncgroup. 2568 */ 2569 if (group->id == 0) { 2570 sg = malloc(sizeof(*sg), M_DEVBUF, M_NOWAIT); 2571 if (sg != NULL) { 2572 SLIST_INIT(&sg->members); 2573 sg->id = alloc_unr(pcmsg_unrhdr); 2574 2575 group->id = sg->id; 2576 SLIST_INSERT_HEAD(&snd_pcm_syncgroups, sg, link); 2577 } else 2578 ret = ENOMEM; 2579 } else { 2580 SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) { 2581 if (sg->id == group->id) 2582 break; 2583 } 2584 if (sg == NULL) 2585 ret = EINVAL; 2586 } 2587 2588 /* Couldn't create or find a syncgroup. Fail. */ 2589 if (sg == NULL) 2590 goto out; 2591 2592 /* 2593 * Allocate a syncmember, assign it and a channel together, and 2594 * insert into syncgroup. 2595 */ 2596 if (group->mode & PCM_ENABLE_INPUT) { 2597 smrd = malloc(sizeof(*smrd), M_DEVBUF, M_NOWAIT); 2598 if (smrd == NULL) { 2599 ret = ENOMEM; 2600 goto out; 2601 } 2602 2603 SLIST_INSERT_HEAD(&sg->members, smrd, link); 2604 smrd->parent = sg; 2605 smrd->ch = rdch; 2606 2607 chn_abort(rdch); 2608 rdch->flags |= CHN_F_NOTRIGGER; 2609 rdch->sm = smrd; 2610 } 2611 2612 if (group->mode & PCM_ENABLE_OUTPUT) { 2613 smwr = malloc(sizeof(*smwr), M_DEVBUF, M_NOWAIT); 2614 if (smwr == NULL) { 2615 ret = ENOMEM; 2616 goto out; 2617 } 2618 2619 SLIST_INSERT_HEAD(&sg->members, smwr, link); 2620 smwr->parent = sg; 2621 smwr->ch = wrch; 2622 2623 chn_abort(wrch); 2624 wrch->flags |= CHN_F_NOTRIGGER; 2625 wrch->sm = smwr; 2626 } 2627 2628 out: 2629 if (ret != 0) { 2630 free(smrd, M_DEVBUF); 2631 if ((sg != NULL) && SLIST_EMPTY(&sg->members)) { 2632 sg_ids[2] = sg->id; 2633 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2634 free(sg, M_DEVBUF); 2635 } 2636 2637 if (wrch) 2638 wrch->sm = NULL; 2639 if (rdch) 2640 rdch->sm = NULL; 2641 } 2642 2643 if (wrch) 2644 CHN_UNLOCK(wrch); 2645 if (rdch) 2646 CHN_UNLOCK(rdch); 2647 2648 PCM_SG_UNLOCK(); 2649 2650 if (sg_ids[0]) 2651 free_unr(pcmsg_unrhdr, sg_ids[0]); 2652 if (sg_ids[1]) 2653 free_unr(pcmsg_unrhdr, sg_ids[1]); 2654 if (sg_ids[2]) 2655 free_unr(pcmsg_unrhdr, sg_ids[2]); 2656 2657 return (ret); 2658 } 2659 2660 /** 2661 * @brief Launch a sync group into action 2662 * 2663 * Sync groups are established via SNDCTL_DSP_SYNCGROUP. This function 2664 * iterates over all members, triggering them along the way. 2665 * 2666 * @note Caller must not hold any channel locks. 2667 * 2668 * @param sg_id sync group identifier 2669 * 2670 * @retval 0 success 2671 * @retval non-zero error worthy of propagating upstream to user 2672 */ 2673 static int 2674 dsp_oss_syncstart(int sg_id) 2675 { 2676 struct pcmchan_syncmember *sm, *sm_tmp; 2677 struct pcmchan_syncgroup *sg; 2678 struct pcm_channel *c; 2679 int ret, needlocks; 2680 2681 /* Get the synclists lock */ 2682 PCM_SG_LOCK(); 2683 2684 do { 2685 ret = 0; 2686 needlocks = 0; 2687 2688 /* Search for syncgroup by ID */ 2689 SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) { 2690 if (sg->id == sg_id) 2691 break; 2692 } 2693 2694 /* Return EINVAL if not found */ 2695 if (sg == NULL) { 2696 ret = EINVAL; 2697 break; 2698 } 2699 2700 /* Any removals resulting in an empty group should've handled this */ 2701 KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup")); 2702 2703 /* 2704 * Attempt to lock all member channels - if any are already 2705 * locked, unlock those acquired, sleep for a bit, and try 2706 * again. 2707 */ 2708 SLIST_FOREACH(sm, &sg->members, link) { 2709 if (CHN_TRYLOCK(sm->ch) == 0) { 2710 int timo = hz * 5/1000; 2711 if (timo < 1) 2712 timo = 1; 2713 2714 /* Release all locked channels so far, retry */ 2715 SLIST_FOREACH(sm_tmp, &sg->members, link) { 2716 /* sm is the member already locked */ 2717 if (sm == sm_tmp) 2718 break; 2719 CHN_UNLOCK(sm_tmp->ch); 2720 } 2721 2722 /** @todo Is PRIBIO correct/ */ 2723 ret = msleep(sm, &snd_pcm_syncgroups_mtx, 2724 PRIBIO | PCATCH, "pcmsg", timo); 2725 if (ret == EINTR || ret == ERESTART) 2726 break; 2727 2728 needlocks = 1; 2729 ret = 0; /* Assumes ret == EAGAIN... */ 2730 } 2731 } 2732 } while (needlocks && ret == 0); 2733 2734 /* Proceed only if no errors encountered. */ 2735 if (ret == 0) { 2736 /* 2737 * Unlock all members before starting any of them. 2738 * Holding multiple channel locks while calling chn_start() 2739 * on a virtual channel can trigger the parent, which 2740 * acquires PCM_LOCK() while other virtual channels are 2741 * still locked -- a lock order reversal. 2742 */ 2743 SLIST_FOREACH(sm, &sg->members, link) { 2744 sm->ch->sm = NULL; 2745 sm->ch->flags &= ~CHN_F_NOTRIGGER; 2746 CHN_UNLOCK(sm->ch); 2747 } 2748 2749 /* 2750 * Start each channel individually, then remove it from 2751 * the sync group and free its member structure. 2752 */ 2753 while ((sm = SLIST_FIRST(&sg->members)) != NULL) { 2754 c = sm->ch; 2755 CHN_LOCK(c); 2756 chn_start(c, 1); 2757 CHN_UNLOCK(c); 2758 SLIST_REMOVE_HEAD(&sg->members, link); 2759 free(sm, M_DEVBUF); 2760 } 2761 2762 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2763 free(sg, M_DEVBUF); 2764 } 2765 2766 PCM_SG_UNLOCK(); 2767 2768 /* 2769 * Free_unr() may sleep, so be sure to give up the syncgroup lock 2770 * first. 2771 */ 2772 if (ret == 0) 2773 free_unr(pcmsg_unrhdr, sg_id); 2774 2775 return (ret); 2776 } 2777 2778 /** 2779 * @brief Handler for SNDCTL_DSP_POLICY 2780 * 2781 * The SNDCTL_DSP_POLICY ioctl is a simpler interface to control fragment 2782 * size and count like with SNDCTL_DSP_SETFRAGMENT. Instead of the user 2783 * specifying those two parameters, s/he simply selects a number from 0..10 2784 * which corresponds to a buffer size. Smaller numbers request smaller 2785 * buffers with lower latencies (at greater overhead from more frequent 2786 * interrupts), while greater numbers behave in the opposite manner. 2787 * 2788 * The 4Front spec states that a value of 5 should be the default. However, 2789 * this implementation deviates slightly by using a linear scale without 2790 * consulting drivers. I.e., even though drivers may have different default 2791 * buffer sizes, a policy argument of 5 will have the same result across 2792 * all drivers. 2793 * 2794 * See http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html for 2795 * more information. 2796 * 2797 * @todo When SNDCTL_DSP_COOKEDMODE is supported, it'll be necessary to 2798 * work with hardware drivers directly. 2799 * 2800 * @note PCM channel arguments must not be locked by caller. 2801 * 2802 * @param wrch Pointer to opened playback channel (optional; may be NULL) 2803 * @param rdch " recording channel (optional; may be NULL) 2804 * @param policy Integer from [0:10] 2805 * 2806 * @retval 0 constant (for now) 2807 */ 2808 static int 2809 dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy) 2810 { 2811 int ret; 2812 2813 if (policy < CHN_POLICY_MIN || policy > CHN_POLICY_MAX) 2814 return (EIO); 2815 2816 /* Default: success */ 2817 ret = 0; 2818 2819 if (rdch) { 2820 CHN_LOCK(rdch); 2821 ret = chn_setlatency(rdch, policy); 2822 CHN_UNLOCK(rdch); 2823 } 2824 2825 if (wrch && ret == 0) { 2826 CHN_LOCK(wrch); 2827 ret = chn_setlatency(wrch, policy); 2828 CHN_UNLOCK(wrch); 2829 } 2830 2831 if (ret) 2832 ret = EIO; 2833 2834 return (ret); 2835 } 2836 2837 /** 2838 * @brief Enable or disable "cooked" mode 2839 * 2840 * This is a handler for @c SNDCTL_DSP_COOKEDMODE. When in cooked mode, which 2841 * is the default, the sound system handles rate and format conversions 2842 * automatically (ex: user writing 11025Hz/8 bit/unsigned but card only 2843 * operates with 44100Hz/16bit/signed samples). 2844 * 2845 * Disabling cooked mode is intended for applications wanting to mmap() 2846 * a sound card's buffer space directly, bypassing the FreeBSD 2-stage 2847 * feeder architecture, presumably to gain as much control over audio 2848 * hardware as possible. 2849 * 2850 * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_COOKEDMODE.html 2851 * for more details. 2852 * 2853 * @param wrch playback channel (optional; may be NULL) 2854 * @param rdch recording channel (optional; may be NULL) 2855 * @param enabled 0 = raw mode, 1 = cooked mode 2856 * 2857 * @retval EINVAL Operation not yet supported. 2858 */ 2859 static int 2860 dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled) 2861 { 2862 2863 /* 2864 * XXX I just don't get it. Why don't they call it 2865 * "BITPERFECT" ~ SNDCTL_DSP_BITPERFECT !?!?. 2866 * This is just plain so confusing, incoherent, 2867 * <insert any non-printable characters here>. 2868 */ 2869 if (!(enabled == 1 || enabled == 0)) 2870 return (EINVAL); 2871 2872 /* 2873 * I won't give in. I'm inverting its logic here and now. 2874 * Brag all you want, but "BITPERFECT" should be the better 2875 * term here. 2876 */ 2877 enabled ^= 0x00000001; 2878 2879 if (wrch != NULL) { 2880 CHN_LOCK(wrch); 2881 wrch->flags &= ~CHN_F_BITPERFECT; 2882 wrch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; 2883 CHN_UNLOCK(wrch); 2884 } 2885 2886 if (rdch != NULL) { 2887 CHN_LOCK(rdch); 2888 rdch->flags &= ~CHN_F_BITPERFECT; 2889 rdch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; 2890 CHN_UNLOCK(rdch); 2891 } 2892 2893 return (0); 2894 } 2895 2896 /** 2897 * @brief Retrieve channel interleaving order 2898 * 2899 * This is the handler for @c SNDCTL_DSP_GET_CHNORDER. 2900 * 2901 * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_GET_CHNORDER.html 2902 * for more details. 2903 * 2904 * @note As the ioctl definition is still under construction, FreeBSD 2905 * does not currently support SNDCTL_DSP_GET_CHNORDER. 2906 * 2907 * @param wrch playback channel (optional; may be NULL) 2908 * @param rdch recording channel (optional; may be NULL) 2909 * @param map channel map (result will be stored there) 2910 * 2911 * @retval EINVAL Operation not yet supported. 2912 */ 2913 static int 2914 dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map) 2915 { 2916 struct pcm_channel *ch; 2917 int ret; 2918 2919 ch = (wrch != NULL) ? wrch : rdch; 2920 if (ch != NULL) { 2921 CHN_LOCK(ch); 2922 ret = chn_oss_getorder(ch, map); 2923 CHN_UNLOCK(ch); 2924 } else 2925 ret = EINVAL; 2926 2927 return (ret); 2928 } 2929 2930 /** 2931 * @brief Specify channel interleaving order 2932 * 2933 * This is the handler for @c SNDCTL_DSP_SET_CHNORDER. 2934 * 2935 * @note As the ioctl definition is still under construction, FreeBSD 2936 * does not currently support @c SNDCTL_DSP_SET_CHNORDER. 2937 * 2938 * @param wrch playback channel (optional; may be NULL) 2939 * @param rdch recording channel (optional; may be NULL) 2940 * @param map channel map 2941 * 2942 * @retval EINVAL Operation not yet supported. 2943 */ 2944 static int 2945 dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map) 2946 { 2947 int ret; 2948 2949 ret = 0; 2950 2951 if (wrch != NULL) { 2952 CHN_LOCK(wrch); 2953 ret = chn_oss_setorder(wrch, map); 2954 CHN_UNLOCK(wrch); 2955 } 2956 2957 if (ret == 0 && rdch != NULL) { 2958 CHN_LOCK(rdch); 2959 ret = chn_oss_setorder(rdch, map); 2960 CHN_UNLOCK(rdch); 2961 } 2962 2963 return (ret); 2964 } 2965 2966 static int 2967 dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch, 2968 int *mask) 2969 { 2970 struct pcm_channel *ch; 2971 uint32_t chnmask; 2972 int ret; 2973 2974 chnmask = 0; 2975 ch = (wrch != NULL) ? wrch : rdch; 2976 2977 if (ch != NULL) { 2978 CHN_LOCK(ch); 2979 ret = chn_oss_getmask(ch, &chnmask); 2980 CHN_UNLOCK(ch); 2981 } else 2982 ret = EINVAL; 2983 2984 if (ret == 0) 2985 *mask = chnmask; 2986 2987 return (ret); 2988 } 2989 2990 static void 2991 dsp_kqdetach(struct knote *kn) 2992 { 2993 struct pcm_channel *ch = kn->kn_hook; 2994 2995 if (ch == NULL) 2996 return; 2997 CHN_LOCK(ch); 2998 knlist_remove(&ch->bufsoft->sel.si_note, kn, 1); 2999 CHN_UNLOCK(ch); 3000 } 3001 3002 static int 3003 dsp_kqevent(struct knote *kn, long hint) 3004 { 3005 struct pcm_channel *ch = kn->kn_hook; 3006 3007 CHN_LOCKASSERT(ch); 3008 if (ch->flags & CHN_F_DEAD) { 3009 kn->kn_flags |= EV_EOF; 3010 return (1); 3011 } 3012 kn->kn_data = 0; 3013 if (chn_polltrigger(ch)) { 3014 if (kn->kn_filter == EVFILT_READ) { 3015 kn->kn_data = sndbuf_getready(ch->bufsoft); 3016 if (ch->flags & CHN_F_MMAP) 3017 kn->kn_kevent.ext[0] = sndbuf_getfreeptr(ch->bufsoft); 3018 else 3019 kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align; 3020 } else { 3021 kn->kn_data = sndbuf_getfree(ch->bufsoft); 3022 if (ch->flags & CHN_F_MMAP) 3023 kn->kn_kevent.ext[0] = sndbuf_getreadyptr(ch->bufsoft); 3024 else 3025 kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align; 3026 } 3027 kn->kn_kevent.ext[1] = ch->xruns; 3028 } 3029 3030 return (kn->kn_data > 0); 3031 } 3032 3033 static const struct filterops dsp_filtops = { 3034 .f_isfd = 1, 3035 .f_detach = dsp_kqdetach, 3036 .f_event = dsp_kqevent, 3037 }; 3038 3039 static int 3040 dsp_kqfilter(struct cdev *dev, struct knote *kn) 3041 { 3042 struct dsp_cdevpriv *priv; 3043 struct snddev_info *d; 3044 struct pcm_channel *ch; 3045 int err = 0; 3046 3047 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 3048 return (err); 3049 3050 d = priv->sc; 3051 if (!DSP_REGISTERED(d)) 3052 return (EBADF); 3053 PCM_GIANT_ENTER(d); 3054 switch (kn->kn_filter) { 3055 case EVFILT_READ: 3056 ch = priv->rdch; 3057 break; 3058 case EVFILT_WRITE: 3059 ch = priv->wrch; 3060 break; 3061 default: 3062 kn->kn_hook = NULL; 3063 err = EINVAL; 3064 ch = NULL; 3065 break; 3066 } 3067 if (ch != NULL) { 3068 kn->kn_fop = &dsp_filtops; 3069 CHN_LOCK(ch); 3070 knlist_add(&ch->bufsoft->sel.si_note, kn, 1); 3071 CHN_UNLOCK(ch); 3072 kn->kn_hook = ch; 3073 } else 3074 err = EINVAL; 3075 PCM_GIANT_LEAVE(d); 3076 3077 return (err); 3078 } 3079 3080 #ifdef OSSV4_EXPERIMENT 3081 /** 3082 * @brief Retrieve an audio device's label 3083 * 3084 * This is a handler for the @c SNDCTL_GETLABEL ioctl. 3085 * 3086 * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html 3087 * for more details. 3088 * 3089 * From Hannu@4Front: "For example ossxmix (just like some HW mixer 3090 * consoles) can show variable "labels" for certain controls. By default 3091 * the application name (say quake) is shown as the label but 3092 * applications may change the labels themselves." 3093 * 3094 * @note As the ioctl definition is still under construction, FreeBSD 3095 * does not currently support @c SNDCTL_GETLABEL. 3096 * 3097 * @param wrch playback channel (optional; may be NULL) 3098 * @param rdch recording channel (optional; may be NULL) 3099 * @param label label gets copied here 3100 * 3101 * @retval EINVAL Operation not yet supported. 3102 */ 3103 static int 3104 dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label) 3105 { 3106 return (EINVAL); 3107 } 3108 3109 /** 3110 * @brief Specify an audio device's label 3111 * 3112 * This is a handler for the @c SNDCTL_SETLABEL ioctl. Please see the 3113 * comments for @c dsp_oss_getlabel immediately above. 3114 * 3115 * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html 3116 * for more details. 3117 * 3118 * @note As the ioctl definition is still under construction, FreeBSD 3119 * does not currently support SNDCTL_SETLABEL. 3120 * 3121 * @param wrch playback channel (optional; may be NULL) 3122 * @param rdch recording channel (optional; may be NULL) 3123 * @param label label gets copied from here 3124 * 3125 * @retval EINVAL Operation not yet supported. 3126 */ 3127 static int 3128 dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label) 3129 { 3130 return (EINVAL); 3131 } 3132 3133 /** 3134 * @brief Retrieve name of currently played song 3135 * 3136 * This is a handler for the @c SNDCTL_GETSONG ioctl. Audio players could 3137 * tell the system the name of the currently playing song, which would be 3138 * visible in @c /dev/sndstat. 3139 * 3140 * See @c http://manuals.opensound.com/developer/SNDCTL_GETSONG.html 3141 * for more details. 3142 * 3143 * @note As the ioctl definition is still under construction, FreeBSD 3144 * does not currently support SNDCTL_GETSONG. 3145 * 3146 * @param wrch playback channel (optional; may be NULL) 3147 * @param rdch recording channel (optional; may be NULL) 3148 * @param song song name gets copied here 3149 * 3150 * @retval EINVAL Operation not yet supported. 3151 */ 3152 static int 3153 dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song) 3154 { 3155 return (EINVAL); 3156 } 3157 3158 /** 3159 * @brief Retrieve name of currently played song 3160 * 3161 * This is a handler for the @c SNDCTL_SETSONG ioctl. Audio players could 3162 * tell the system the name of the currently playing song, which would be 3163 * visible in @c /dev/sndstat. 3164 * 3165 * See @c http://manuals.opensound.com/developer/SNDCTL_SETSONG.html 3166 * for more details. 3167 * 3168 * @note As the ioctl definition is still under construction, FreeBSD 3169 * does not currently support SNDCTL_SETSONG. 3170 * 3171 * @param wrch playback channel (optional; may be NULL) 3172 * @param rdch recording channel (optional; may be NULL) 3173 * @param song song name gets copied from here 3174 * 3175 * @retval EINVAL Operation not yet supported. 3176 */ 3177 static int 3178 dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song) 3179 { 3180 return (EINVAL); 3181 } 3182 3183 /** 3184 * @brief Rename a device 3185 * 3186 * This is a handler for the @c SNDCTL_SETNAME ioctl. 3187 * 3188 * See @c http://manuals.opensound.com/developer/SNDCTL_SETNAME.html for 3189 * more details. 3190 * 3191 * From Hannu@4Front: "This call is used to change the device name 3192 * reported in /dev/sndstat and ossinfo. So instead of using some generic 3193 * 'OSS loopback audio (MIDI) driver' the device may be given a meaningfull 3194 * name depending on the current context (for example 'OSS virtual wave table 3195 * synth' or 'VoIP link to London')." 3196 * 3197 * @note As the ioctl definition is still under construction, FreeBSD 3198 * does not currently support SNDCTL_SETNAME. 3199 * 3200 * @param wrch playback channel (optional; may be NULL) 3201 * @param rdch recording channel (optional; may be NULL) 3202 * @param name new device name gets copied from here 3203 * 3204 * @retval EINVAL Operation not yet supported. 3205 */ 3206 static int 3207 dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name) 3208 { 3209 return (EINVAL); 3210 } 3211 #endif /* !OSSV4_EXPERIMENT */ 3212