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