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