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