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