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