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