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