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