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