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