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