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