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