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 (MIXER_REGISTERED(d->mixer)) { 739 PCM_ACQUIRE_QUICK(d); 740 ret = mixer_ioctl_cmd(d->mixer->cdev, 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 #ifdef COMPAT_FREEBSD32 929 snd_capabilities32 *p32 = (snd_capabilities32 *)arg; 930 snd_capabilities capabilities; 931 932 if (cmd == AIOGCAP32) { 933 p = &capabilities; 934 p->rate_min = p32->rate_min; 935 p->rate_max = p32->rate_max; 936 p->formats = p32->formats; 937 p->bufsize = p32->bufsize; 938 p->mixers = p32->mixers; 939 p->inputs = p32->inputs; 940 p->left = p32->left; 941 p->right = p32->right; 942 } 943 #endif 944 PCM_LOCK(d); 945 if (rdch) { 946 CHN_LOCK(rdch); 947 rcaps = chn_getcaps(rdch); 948 } 949 if (wrch) { 950 CHN_LOCK(wrch); 951 pcaps = chn_getcaps(wrch); 952 } 953 p->rate_min = max(rcaps? rcaps->minspeed : 0, 954 pcaps? pcaps->minspeed : 0); 955 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, 956 pcaps? pcaps->maxspeed : 1000000); 957 p->bufsize = min(rdch? rdch->bufsoft->bufsize : 1000000, 958 wrch? wrch->bufsoft->bufsize : 1000000); 959 /* XXX bad on sb16 */ 960 p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & 961 (wrch? chn_getformats(wrch) : 0xffffffff); 962 if (rdch && wrch) { 963 p->formats |= 964 (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 0 : 965 AFMT_FULLDUPLEX; 966 } 967 p->mixers = 1; /* default: one mixer */ 968 p->inputs = d->mixer ? mix_getdevs(d->mixer) : 0; 969 p->left = p->right = 100; 970 if (wrch) 971 CHN_UNLOCK(wrch); 972 if (rdch) 973 CHN_UNLOCK(rdch); 974 PCM_UNLOCK(d); 975 #ifdef COMPAT_FREEBSD32 976 if (cmd == AIOGCAP32) { 977 p32->rate_min = p->rate_min; 978 p32->rate_max = p->rate_max; 979 p32->formats = p->formats; 980 p32->bufsize = p->bufsize; 981 p32->mixers = p->mixers; 982 p32->inputs = p->inputs; 983 p32->left = p->left; 984 p32->right = p->right; 985 } 986 #endif 987 } 988 break; 989 990 case AIOSTOP: 991 if (*arg_i == AIOSYNC_PLAY && wrch) { 992 CHN_LOCK(wrch); 993 *arg_i = chn_abort(wrch); 994 CHN_UNLOCK(wrch); 995 } else if (*arg_i == AIOSYNC_CAPTURE && rdch) { 996 CHN_LOCK(rdch); 997 *arg_i = chn_abort(rdch); 998 CHN_UNLOCK(rdch); 999 } else { 1000 printf("AIOSTOP: bad channel 0x%x\n", *arg_i); 1001 *arg_i = 0; 1002 } 1003 break; 1004 1005 case AIOSYNC: 1006 printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n", 1007 ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); 1008 break; 1009 case FIONREAD: /* get # bytes to read */ 1010 if (rdch) { 1011 CHN_LOCK(rdch); 1012 *arg_i = sndbuf_getready(rdch->bufsoft); 1013 CHN_UNLOCK(rdch); 1014 } else { 1015 *arg_i = 0; 1016 ret = EINVAL; 1017 } 1018 break; 1019 1020 case FIOASYNC: /*set/clear async i/o */ 1021 DEB( printf("FIOASYNC\n") ; ) 1022 break; 1023 1024 case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */ 1025 case FIONBIO: /* set/clear non-blocking i/o */ 1026 if (rdch) { 1027 CHN_LOCK(rdch); 1028 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i) 1029 rdch->flags |= CHN_F_NBIO; 1030 else 1031 rdch->flags &= ~CHN_F_NBIO; 1032 CHN_UNLOCK(rdch); 1033 } 1034 if (wrch) { 1035 CHN_LOCK(wrch); 1036 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i) 1037 wrch->flags |= CHN_F_NBIO; 1038 else 1039 wrch->flags &= ~CHN_F_NBIO; 1040 CHN_UNLOCK(wrch); 1041 } 1042 break; 1043 1044 case SNDCTL_DSP_GETBLKSIZE: 1045 chn = wrch ? wrch : rdch; 1046 if (chn) { 1047 CHN_LOCK(chn); 1048 *arg_i = chn->bufsoft->blksz; 1049 CHN_UNLOCK(chn); 1050 } else { 1051 *arg_i = 0; 1052 ret = EINVAL; 1053 } 1054 break; 1055 1056 case SNDCTL_DSP_SETBLKSIZE: 1057 RANGE(*arg_i, 16, 65536); 1058 PCM_ACQUIRE_QUICK(d); 1059 if (wrch) { 1060 CHN_LOCK(wrch); 1061 chn_setblocksize(wrch, 2, *arg_i); 1062 CHN_UNLOCK(wrch); 1063 } 1064 if (rdch) { 1065 CHN_LOCK(rdch); 1066 chn_setblocksize(rdch, 2, *arg_i); 1067 CHN_UNLOCK(rdch); 1068 } 1069 PCM_RELEASE_QUICK(d); 1070 break; 1071 1072 case SNDCTL_DSP_RESET: 1073 DEB(printf("dsp reset\n")); 1074 if (wrch) { 1075 CHN_LOCK(wrch); 1076 chn_abort(wrch); 1077 chn_resetbuf(wrch); 1078 CHN_UNLOCK(wrch); 1079 } 1080 if (rdch) { 1081 CHN_LOCK(rdch); 1082 chn_abort(rdch); 1083 chn_resetbuf(rdch); 1084 CHN_UNLOCK(rdch); 1085 } 1086 break; 1087 1088 case SNDCTL_DSP_SYNC: 1089 DEB(printf("dsp sync\n")); 1090 /* chn_sync may sleep */ 1091 if (wrch) { 1092 CHN_LOCK(wrch); 1093 chn_sync(wrch, 0); 1094 CHN_UNLOCK(wrch); 1095 } 1096 break; 1097 1098 case SNDCTL_DSP_SPEED: 1099 /* chn_setspeed may sleep */ 1100 tmp = 0; 1101 PCM_ACQUIRE_QUICK(d); 1102 if (wrch) { 1103 CHN_LOCK(wrch); 1104 ret = chn_setspeed(wrch, *arg_i); 1105 tmp = wrch->speed; 1106 CHN_UNLOCK(wrch); 1107 } 1108 if (rdch && ret == 0) { 1109 CHN_LOCK(rdch); 1110 ret = chn_setspeed(rdch, *arg_i); 1111 if (tmp == 0) 1112 tmp = rdch->speed; 1113 CHN_UNLOCK(rdch); 1114 } 1115 PCM_RELEASE_QUICK(d); 1116 *arg_i = tmp; 1117 break; 1118 1119 case SOUND_PCM_READ_RATE: 1120 chn = wrch ? wrch : rdch; 1121 if (chn) { 1122 CHN_LOCK(chn); 1123 *arg_i = chn->speed; 1124 CHN_UNLOCK(chn); 1125 } else { 1126 *arg_i = 0; 1127 ret = EINVAL; 1128 } 1129 break; 1130 1131 case SNDCTL_DSP_STEREO: 1132 tmp = -1; 1133 *arg_i = (*arg_i)? 2 : 1; 1134 PCM_ACQUIRE_QUICK(d); 1135 if (wrch) { 1136 CHN_LOCK(wrch); 1137 ret = chn_setformat(wrch, 1138 SND_FORMAT(wrch->format, *arg_i, 0)); 1139 tmp = (AFMT_CHANNEL(wrch->format) > 1)? 1 : 0; 1140 CHN_UNLOCK(wrch); 1141 } 1142 if (rdch && ret == 0) { 1143 CHN_LOCK(rdch); 1144 ret = chn_setformat(rdch, 1145 SND_FORMAT(rdch->format, *arg_i, 0)); 1146 if (tmp == -1) 1147 tmp = (AFMT_CHANNEL(rdch->format) > 1)? 1 : 0; 1148 CHN_UNLOCK(rdch); 1149 } 1150 PCM_RELEASE_QUICK(d); 1151 *arg_i = tmp; 1152 break; 1153 1154 case SOUND_PCM_WRITE_CHANNELS: 1155 /* case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */ 1156 if (*arg_i < 0 || *arg_i > AFMT_CHANNEL_MAX) { 1157 *arg_i = 0; 1158 ret = EINVAL; 1159 break; 1160 } 1161 if (*arg_i != 0) { 1162 uint32_t ext = 0; 1163 1164 tmp = 0; 1165 /* 1166 * Map channel number to surround sound formats. 1167 * Devices that need bitperfect mode to operate 1168 * (e.g. more than SND_CHN_MAX channels) are not 1169 * subject to any mapping. 1170 */ 1171 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 1172 struct pcmchan_matrix *m; 1173 1174 if (*arg_i > SND_CHN_MAX) 1175 *arg_i = SND_CHN_MAX; 1176 1177 m = feeder_matrix_default_channel_map(*arg_i); 1178 if (m != NULL) 1179 ext = m->ext; 1180 } 1181 1182 PCM_ACQUIRE_QUICK(d); 1183 if (wrch) { 1184 CHN_LOCK(wrch); 1185 ret = chn_setformat(wrch, 1186 SND_FORMAT(wrch->format, *arg_i, ext)); 1187 tmp = AFMT_CHANNEL(wrch->format); 1188 CHN_UNLOCK(wrch); 1189 } 1190 if (rdch && ret == 0) { 1191 CHN_LOCK(rdch); 1192 ret = chn_setformat(rdch, 1193 SND_FORMAT(rdch->format, *arg_i, ext)); 1194 if (tmp == 0) 1195 tmp = AFMT_CHANNEL(rdch->format); 1196 CHN_UNLOCK(rdch); 1197 } 1198 PCM_RELEASE_QUICK(d); 1199 *arg_i = tmp; 1200 } else { 1201 chn = wrch ? wrch : rdch; 1202 CHN_LOCK(chn); 1203 *arg_i = AFMT_CHANNEL(chn->format); 1204 CHN_UNLOCK(chn); 1205 } 1206 break; 1207 1208 case SOUND_PCM_READ_CHANNELS: 1209 chn = wrch ? wrch : rdch; 1210 if (chn) { 1211 CHN_LOCK(chn); 1212 *arg_i = AFMT_CHANNEL(chn->format); 1213 CHN_UNLOCK(chn); 1214 } else { 1215 *arg_i = 0; 1216 ret = EINVAL; 1217 } 1218 break; 1219 1220 case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */ 1221 chn = wrch ? wrch : rdch; 1222 if (chn) { 1223 CHN_LOCK(chn); 1224 *arg_i = chn_getformats(chn); 1225 CHN_UNLOCK(chn); 1226 } else { 1227 *arg_i = 0; 1228 ret = EINVAL; 1229 } 1230 break; 1231 1232 case SNDCTL_DSP_SETFMT: /* sets _one_ format */ 1233 if (*arg_i != AFMT_QUERY) { 1234 tmp = 0; 1235 PCM_ACQUIRE_QUICK(d); 1236 if (wrch) { 1237 CHN_LOCK(wrch); 1238 ret = chn_setformat(wrch, SND_FORMAT(*arg_i, 1239 AFMT_CHANNEL(wrch->format), 1240 AFMT_EXTCHANNEL(wrch->format))); 1241 tmp = wrch->format; 1242 CHN_UNLOCK(wrch); 1243 } 1244 if (rdch && ret == 0) { 1245 CHN_LOCK(rdch); 1246 ret = chn_setformat(rdch, SND_FORMAT(*arg_i, 1247 AFMT_CHANNEL(rdch->format), 1248 AFMT_EXTCHANNEL(rdch->format))); 1249 if (tmp == 0) 1250 tmp = rdch->format; 1251 CHN_UNLOCK(rdch); 1252 } 1253 PCM_RELEASE_QUICK(d); 1254 *arg_i = AFMT_ENCODING(tmp); 1255 } else { 1256 chn = wrch ? wrch : rdch; 1257 CHN_LOCK(chn); 1258 *arg_i = AFMT_ENCODING(chn->format); 1259 CHN_UNLOCK(chn); 1260 } 1261 break; 1262 1263 case SNDCTL_DSP_SETFRAGMENT: 1264 DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg)); 1265 { 1266 uint32_t fragln = (*arg_i) & 0x0000ffff; 1267 uint32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16; 1268 uint32_t fragsz; 1269 uint32_t r_maxfrags, r_fragsz; 1270 1271 RANGE(fragln, 4, 16); 1272 fragsz = 1 << fragln; 1273 1274 DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz)); 1275 PCM_ACQUIRE_QUICK(d); 1276 if (rdch) { 1277 CHN_LOCK(rdch); 1278 ret = chn_setblocksize(rdch, 1279 dsp_clamp_fragments(maxfrags, fragsz, 1280 chn_2ndbufmaxsize(rdch)), fragsz); 1281 r_maxfrags = rdch->bufsoft->blkcnt; 1282 r_fragsz = rdch->bufsoft->blksz; 1283 CHN_UNLOCK(rdch); 1284 } else { 1285 r_maxfrags = maxfrags; 1286 r_fragsz = fragsz; 1287 } 1288 if (wrch && ret == 0) { 1289 CHN_LOCK(wrch); 1290 ret = chn_setblocksize(wrch, 1291 dsp_clamp_fragments(maxfrags, fragsz, 1292 chn_2ndbufmaxsize(wrch)), fragsz); 1293 maxfrags = wrch->bufsoft->blkcnt; 1294 fragsz = wrch->bufsoft->blksz; 1295 CHN_UNLOCK(wrch); 1296 } else { /* use whatever came from the read channel */ 1297 maxfrags = r_maxfrags; 1298 fragsz = r_fragsz; 1299 } 1300 PCM_RELEASE_QUICK(d); 1301 1302 fragln = 0; 1303 while (fragsz > 1) { 1304 fragln++; 1305 fragsz >>= 1; 1306 } 1307 *arg_i = (maxfrags << 16) | fragln; 1308 } 1309 break; 1310 1311 case SNDCTL_DSP_GETISPACE: 1312 /* return the size of data available in the input queue */ 1313 { 1314 audio_buf_info *a = (audio_buf_info *)arg; 1315 if (rdch) { 1316 struct snd_dbuf *bs = rdch->bufsoft; 1317 1318 CHN_LOCK(rdch); 1319 a->bytes = sndbuf_getready(bs); 1320 a->fragments = a->bytes / bs->blksz; 1321 a->fragstotal = bs->blkcnt; 1322 a->fragsize = bs->blksz; 1323 CHN_UNLOCK(rdch); 1324 } else 1325 ret = EINVAL; 1326 } 1327 break; 1328 1329 case SNDCTL_DSP_GETOSPACE: 1330 /* return space available in the output queue */ 1331 { 1332 audio_buf_info *a = (audio_buf_info *)arg; 1333 if (wrch) { 1334 struct snd_dbuf *bs = wrch->bufsoft; 1335 1336 CHN_LOCK(wrch); 1337 a->bytes = sndbuf_getfree(bs); 1338 a->fragments = a->bytes / bs->blksz; 1339 a->fragstotal = bs->blkcnt; 1340 a->fragsize = bs->blksz; 1341 CHN_UNLOCK(wrch); 1342 } else 1343 ret = EINVAL; 1344 } 1345 break; 1346 1347 case SNDCTL_DSP_GETIPTR: 1348 { 1349 count_info *a = (count_info *)arg; 1350 if (rdch) { 1351 struct snd_dbuf *bs = rdch->bufsoft; 1352 1353 CHN_LOCK(rdch); 1354 a->bytes = bs->total; 1355 a->blocks = sndbuf_getblocks(bs) - rdch->blocks; 1356 a->ptr = sndbuf_getfreeptr(bs); 1357 rdch->blocks = sndbuf_getblocks(bs); 1358 CHN_UNLOCK(rdch); 1359 } else 1360 ret = EINVAL; 1361 } 1362 break; 1363 1364 case SNDCTL_DSP_GETOPTR: 1365 { 1366 count_info *a = (count_info *)arg; 1367 if (wrch) { 1368 struct snd_dbuf *bs = wrch->bufsoft; 1369 1370 CHN_LOCK(wrch); 1371 a->bytes = bs->total; 1372 a->blocks = sndbuf_getblocks(bs) - wrch->blocks; 1373 a->ptr = sndbuf_getreadyptr(bs); 1374 wrch->blocks = sndbuf_getblocks(bs); 1375 CHN_UNLOCK(wrch); 1376 } else 1377 ret = EINVAL; 1378 } 1379 break; 1380 1381 case SNDCTL_DSP_GETCAPS: 1382 PCM_LOCK(d); 1383 *arg_i = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; 1384 if (rdch && wrch && !(pcm_getflags(d->dev) & SD_F_SIMPLEX)) 1385 *arg_i |= PCM_CAP_DUPLEX; 1386 if (rdch && (rdch->flags & CHN_F_VIRTUAL) != 0) 1387 *arg_i |= PCM_CAP_VIRTUAL; 1388 if (wrch && (wrch->flags & CHN_F_VIRTUAL) != 0) 1389 *arg_i |= PCM_CAP_VIRTUAL; 1390 PCM_UNLOCK(d); 1391 break; 1392 1393 case SOUND_PCM_READ_BITS: 1394 chn = wrch ? wrch : rdch; 1395 if (chn) { 1396 CHN_LOCK(chn); 1397 if (chn->format & AFMT_8BIT) 1398 *arg_i = 8; 1399 else if (chn->format & AFMT_16BIT) 1400 *arg_i = 16; 1401 else if (chn->format & AFMT_24BIT) 1402 *arg_i = 24; 1403 else if (chn->format & AFMT_32BIT) 1404 *arg_i = 32; 1405 else 1406 ret = EINVAL; 1407 CHN_UNLOCK(chn); 1408 } else { 1409 *arg_i = 0; 1410 ret = EINVAL; 1411 } 1412 break; 1413 1414 case SNDCTL_DSP_SETTRIGGER: 1415 if (rdch) { 1416 CHN_LOCK(rdch); 1417 rdch->flags &= ~CHN_F_NOTRIGGER; 1418 if (*arg_i & PCM_ENABLE_INPUT) 1419 chn_start(rdch, 1); 1420 else { 1421 chn_abort(rdch); 1422 chn_resetbuf(rdch); 1423 rdch->flags |= CHN_F_NOTRIGGER; 1424 } 1425 CHN_UNLOCK(rdch); 1426 } 1427 if (wrch) { 1428 CHN_LOCK(wrch); 1429 wrch->flags &= ~CHN_F_NOTRIGGER; 1430 if (*arg_i & PCM_ENABLE_OUTPUT) 1431 chn_start(wrch, 1); 1432 else { 1433 chn_abort(wrch); 1434 chn_resetbuf(wrch); 1435 wrch->flags |= CHN_F_NOTRIGGER; 1436 } 1437 CHN_UNLOCK(wrch); 1438 } 1439 break; 1440 1441 case SNDCTL_DSP_GETTRIGGER: 1442 *arg_i = 0; 1443 if (wrch) { 1444 CHN_LOCK(wrch); 1445 if (wrch->flags & CHN_F_TRIGGERED) 1446 *arg_i |= PCM_ENABLE_OUTPUT; 1447 CHN_UNLOCK(wrch); 1448 } 1449 if (rdch) { 1450 CHN_LOCK(rdch); 1451 if (rdch->flags & CHN_F_TRIGGERED) 1452 *arg_i |= PCM_ENABLE_INPUT; 1453 CHN_UNLOCK(rdch); 1454 } 1455 break; 1456 1457 case SNDCTL_DSP_GETODELAY: 1458 if (wrch) { 1459 struct snd_dbuf *bs = wrch->bufsoft; 1460 1461 CHN_LOCK(wrch); 1462 *arg_i = sndbuf_getready(bs); 1463 CHN_UNLOCK(wrch); 1464 } else 1465 ret = EINVAL; 1466 break; 1467 1468 case SNDCTL_DSP_POST: 1469 if (wrch) { 1470 CHN_LOCK(wrch); 1471 wrch->flags &= ~CHN_F_NOTRIGGER; 1472 chn_start(wrch, 1); 1473 CHN_UNLOCK(wrch); 1474 } 1475 break; 1476 1477 case SNDCTL_DSP_SETDUPLEX: 1478 /* 1479 * switch to full-duplex mode if card is in half-duplex 1480 * mode and is able to work in full-duplex mode 1481 */ 1482 PCM_LOCK(d); 1483 if (rdch && wrch && (pcm_getflags(d->dev) & SD_F_SIMPLEX)) 1484 pcm_setflags(d->dev, pcm_getflags(d->dev)^SD_F_SIMPLEX); 1485 PCM_UNLOCK(d); 1486 break; 1487 1488 /* 1489 * The following four ioctls are simple wrappers around mixer_ioctl 1490 * with no further processing. xcmd is short for "translated 1491 * command". 1492 */ 1493 case SNDCTL_DSP_GETRECVOL: 1494 if (xcmd == 0) { 1495 xcmd = SOUND_MIXER_READ_RECLEV; 1496 chn = rdch; 1497 } 1498 /* FALLTHROUGH */ 1499 case SNDCTL_DSP_SETRECVOL: 1500 if (xcmd == 0) { 1501 xcmd = SOUND_MIXER_WRITE_RECLEV; 1502 chn = rdch; 1503 } 1504 /* FALLTHROUGH */ 1505 case SNDCTL_DSP_GETPLAYVOL: 1506 if (xcmd == 0) { 1507 xcmd = SOUND_MIXER_READ_PCM; 1508 chn = wrch; 1509 } 1510 /* FALLTHROUGH */ 1511 case SNDCTL_DSP_SETPLAYVOL: 1512 if (xcmd == 0) { 1513 xcmd = SOUND_MIXER_WRITE_PCM; 1514 chn = wrch; 1515 } 1516 1517 ret = dsp_ioctl_channel(priv, chn, xcmd, arg); 1518 if (ret != -1) { 1519 PCM_GIANT_EXIT(d); 1520 return (ret); 1521 } 1522 1523 if (MIXER_REGISTERED(d->mixer)) { 1524 PCM_ACQUIRE_QUICK(d); 1525 ret = mixer_ioctl_cmd(d->mixer->cdev, xcmd, arg, -1, td); 1526 PCM_RELEASE_QUICK(d); 1527 } else 1528 ret = ENOTSUP; 1529 1530 break; 1531 1532 case SNDCTL_DSP_GET_RECSRC_NAMES: 1533 case SNDCTL_DSP_GET_RECSRC: 1534 case SNDCTL_DSP_SET_RECSRC: 1535 if (MIXER_REGISTERED(d->mixer)) { 1536 PCM_ACQUIRE_QUICK(d); 1537 ret = mixer_ioctl_cmd(d->mixer->cdev, cmd, arg, -1, td); 1538 PCM_RELEASE_QUICK(d); 1539 } else 1540 ret = ENOTSUP; 1541 break; 1542 1543 /* 1544 * The following 3 ioctls aren't very useful at the moment. For 1545 * now, only a single channel is associated with a cdev (/dev/dspN 1546 * instance), so there's only a single output routing to use (i.e., 1547 * the wrch bound to this cdev). 1548 */ 1549 case SNDCTL_DSP_GET_PLAYTGT_NAMES: 1550 { 1551 oss_mixer_enuminfo *ei; 1552 ei = (oss_mixer_enuminfo *)arg; 1553 ei->dev = 0; 1554 ei->ctrl = 0; 1555 ei->version = 0; /* static for now */ 1556 ei->strindex[0] = 0; 1557 1558 if (wrch != NULL) { 1559 ei->nvalues = 1; 1560 strlcpy(ei->strings, wrch->name, 1561 sizeof(ei->strings)); 1562 } else { 1563 ei->nvalues = 0; 1564 ei->strings[0] = '\0'; 1565 } 1566 } 1567 break; 1568 case SNDCTL_DSP_GET_PLAYTGT: 1569 case SNDCTL_DSP_SET_PLAYTGT: /* yes, they are the same for now */ 1570 /* 1571 * Re: SET_PLAYTGT 1572 * OSSv4: "The value that was accepted by the device will 1573 * be returned back in the variable pointed by the 1574 * argument." 1575 */ 1576 if (wrch != NULL) 1577 *arg_i = 0; 1578 else 1579 ret = EINVAL; 1580 break; 1581 1582 case SNDCTL_DSP_SILENCE: 1583 /* 1584 * Flush the software (pre-feed) buffer, but try to minimize playback 1585 * interruption. (I.e., record unplayed samples with intent to 1586 * restore by SNDCTL_DSP_SKIP.) Intended for application "pause" 1587 * functionality. 1588 */ 1589 if (wrch == NULL) 1590 ret = EINVAL; 1591 else { 1592 struct snd_dbuf *bs; 1593 CHN_LOCK(wrch); 1594 while (wrch->inprog != 0) 1595 cv_wait(&wrch->cv, &wrch->lock); 1596 bs = wrch->bufsoft; 1597 if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) { 1598 bs->sl = sndbuf_getready(bs); 1599 sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs)); 1600 sndbuf_fillsilence(bs); 1601 chn_start(wrch, 0); 1602 } 1603 CHN_UNLOCK(wrch); 1604 } 1605 break; 1606 1607 case SNDCTL_DSP_SKIP: 1608 /* 1609 * OSSv4 docs: "This ioctl call discards all unplayed samples in the 1610 * playback buffer by moving the current write position immediately 1611 * before the point where the device is currently reading the samples." 1612 */ 1613 if (wrch == NULL) 1614 ret = EINVAL; 1615 else { 1616 struct snd_dbuf *bs; 1617 CHN_LOCK(wrch); 1618 while (wrch->inprog != 0) 1619 cv_wait(&wrch->cv, &wrch->lock); 1620 bs = wrch->bufsoft; 1621 if ((bs->shadbuf != NULL) && (bs->sl > 0)) { 1622 sndbuf_softreset(bs); 1623 sndbuf_acquire(bs, bs->shadbuf, bs->sl); 1624 bs->sl = 0; 1625 chn_start(wrch, 0); 1626 } 1627 CHN_UNLOCK(wrch); 1628 } 1629 break; 1630 1631 case SNDCTL_DSP_CURRENT_OPTR: 1632 case SNDCTL_DSP_CURRENT_IPTR: 1633 /** 1634 * @note Changing formats resets the buffer counters, which differs 1635 * from the 4Front drivers. However, I don't expect this to be 1636 * much of a problem. 1637 * 1638 * @note In a test where @c CURRENT_OPTR is called immediately after write 1639 * returns, this driver is about 32K samples behind whereas 1640 * 4Front's is about 8K samples behind. Should determine source 1641 * of discrepancy, even if only out of curiosity. 1642 * 1643 * @todo Actually test SNDCTL_DSP_CURRENT_IPTR. 1644 */ 1645 chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch; 1646 if (chn == NULL) 1647 ret = EINVAL; 1648 else { 1649 struct snd_dbuf *bs; 1650 1651 oss_count_t *oc = (oss_count_t *)arg; 1652 1653 CHN_LOCK(chn); 1654 bs = chn->bufsoft; 1655 oc->samples = bs->total / bs->align; 1656 oc->fifo_samples = sndbuf_getready(bs) / bs->align; 1657 CHN_UNLOCK(chn); 1658 } 1659 break; 1660 1661 case SNDCTL_DSP_HALT_OUTPUT: 1662 case SNDCTL_DSP_HALT_INPUT: 1663 chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch; 1664 if (chn == NULL) 1665 ret = EINVAL; 1666 else { 1667 CHN_LOCK(chn); 1668 chn_abort(chn); 1669 CHN_UNLOCK(chn); 1670 } 1671 break; 1672 1673 case SNDCTL_DSP_LOW_WATER: 1674 /* 1675 * Set the number of bytes required to attract attention by 1676 * select/poll. 1677 */ 1678 if (wrch != NULL) { 1679 CHN_LOCK(wrch); 1680 wrch->lw = dsp_low_water(wrch, *arg_i); 1681 CHN_UNLOCK(wrch); 1682 } 1683 if (rdch != NULL) { 1684 CHN_LOCK(rdch); 1685 rdch->lw = dsp_low_water(rdch, *arg_i); 1686 CHN_UNLOCK(rdch); 1687 } 1688 break; 1689 1690 case SNDCTL_DSP_GETERROR: 1691 #ifdef COMPAT_FREEBSD32 1692 case SNDCTL_DSP_GETERROR32: 1693 #endif 1694 /* 1695 * OSSv4 docs: "All errors and counters will automatically be 1696 * cleared to zeroes after the call so each call will return only 1697 * the errors that occurred after the previous invocation. ... The 1698 * play_underruns and rec_overrun fields are the only useful fields 1699 * returned by OSS 4.0." 1700 */ 1701 { 1702 audio_errinfo *ei = (audio_errinfo *)arg; 1703 #ifdef COMPAT_FREEBSD32 1704 audio_errinfo errinfo; 1705 audio_errinfo32 *ei32 = (audio_errinfo32 *)arg; 1706 1707 if (cmd == SNDCTL_DSP_GETERROR32) { 1708 ei = &errinfo; 1709 } 1710 #endif 1711 1712 bzero((void *)ei, sizeof(*ei)); 1713 1714 if (wrch != NULL) { 1715 CHN_LOCK(wrch); 1716 ei->play_underruns = wrch->xruns; 1717 wrch->xruns = 0; 1718 CHN_UNLOCK(wrch); 1719 } 1720 if (rdch != NULL) { 1721 CHN_LOCK(rdch); 1722 ei->rec_overruns = rdch->xruns; 1723 rdch->xruns = 0; 1724 CHN_UNLOCK(rdch); 1725 } 1726 #ifdef COMPAT_FREEBSD32 1727 if (cmd == SNDCTL_DSP_GETERROR32) { 1728 bzero((void *)ei32, sizeof(*ei32)); 1729 ei32->play_underruns = ei->play_underruns; 1730 ei32->rec_overruns = ei->rec_overruns; 1731 ei32->play_ptradjust = ei->play_ptradjust; 1732 ei32->rec_ptradjust = ei->rec_ptradjust; 1733 ei32->play_errorcount = ei->play_errorcount; 1734 ei32->rec_errorcount = ei->rec_errorcount; 1735 ei32->play_lasterror = ei->play_lasterror; 1736 ei32->rec_lasterror = ei->rec_lasterror; 1737 ei32->play_errorparm = ei->play_errorparm; 1738 ei32->rec_errorparm = ei->rec_errorparm; 1739 } 1740 #endif 1741 } 1742 break; 1743 1744 case SNDCTL_DSP_SYNCGROUP: 1745 PCM_ACQUIRE_QUICK(d); 1746 ret = dsp_oss_syncgroup(wrch, rdch, (oss_syncgroup *)arg); 1747 PCM_RELEASE_QUICK(d); 1748 break; 1749 1750 case SNDCTL_DSP_SYNCSTART: 1751 PCM_ACQUIRE_QUICK(d); 1752 ret = dsp_oss_syncstart(*arg_i); 1753 PCM_RELEASE_QUICK(d); 1754 break; 1755 1756 case SNDCTL_DSP_POLICY: 1757 PCM_ACQUIRE_QUICK(d); 1758 ret = dsp_oss_policy(wrch, rdch, *arg_i); 1759 PCM_RELEASE_QUICK(d); 1760 break; 1761 1762 case SNDCTL_DSP_COOKEDMODE: 1763 PCM_ACQUIRE_QUICK(d); 1764 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) 1765 ret = dsp_oss_cookedmode(wrch, rdch, *arg_i); 1766 PCM_RELEASE_QUICK(d); 1767 break; 1768 case SNDCTL_DSP_GET_CHNORDER: 1769 PCM_ACQUIRE_QUICK(d); 1770 ret = dsp_oss_getchnorder(wrch, rdch, (unsigned long long *)arg); 1771 PCM_RELEASE_QUICK(d); 1772 break; 1773 case SNDCTL_DSP_SET_CHNORDER: 1774 PCM_ACQUIRE_QUICK(d); 1775 ret = dsp_oss_setchnorder(wrch, rdch, (unsigned long long *)arg); 1776 PCM_RELEASE_QUICK(d); 1777 break; 1778 case SNDCTL_DSP_GETCHANNELMASK: /* XXX vlc */ 1779 PCM_ACQUIRE_QUICK(d); 1780 ret = dsp_oss_getchannelmask(wrch, rdch, (int *)arg); 1781 PCM_RELEASE_QUICK(d); 1782 break; 1783 case SNDCTL_DSP_BIND_CHANNEL: /* XXX what?!? */ 1784 ret = EINVAL; 1785 break; 1786 #ifdef OSSV4_EXPERIMENT 1787 /* 1788 * XXX The following ioctls are not yet supported and just return 1789 * EINVAL. 1790 */ 1791 case SNDCTL_DSP_GETOPEAKS: 1792 case SNDCTL_DSP_GETIPEAKS: 1793 chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch; 1794 if (chn == NULL) 1795 ret = EINVAL; 1796 else { 1797 oss_peaks_t *op = (oss_peaks_t *)arg; 1798 int lpeak, rpeak; 1799 1800 CHN_LOCK(chn); 1801 ret = chn_getpeaks(chn, &lpeak, &rpeak); 1802 if (ret == -1) 1803 ret = EINVAL; 1804 else { 1805 (*op)[0] = lpeak; 1806 (*op)[1] = rpeak; 1807 } 1808 CHN_UNLOCK(chn); 1809 } 1810 break; 1811 1812 /* 1813 * XXX Once implemented, revisit this for proper cv protection 1814 * (if necessary). 1815 */ 1816 case SNDCTL_GETLABEL: 1817 ret = dsp_oss_getlabel(wrch, rdch, (oss_label_t *)arg); 1818 break; 1819 case SNDCTL_SETLABEL: 1820 ret = dsp_oss_setlabel(wrch, rdch, (oss_label_t *)arg); 1821 break; 1822 case SNDCTL_GETSONG: 1823 ret = dsp_oss_getsong(wrch, rdch, (oss_longname_t *)arg); 1824 break; 1825 case SNDCTL_SETSONG: 1826 ret = dsp_oss_setsong(wrch, rdch, (oss_longname_t *)arg); 1827 break; 1828 case SNDCTL_SETNAME: 1829 ret = dsp_oss_setname(wrch, rdch, (oss_longname_t *)arg); 1830 break; 1831 #endif /* !OSSV4_EXPERIMENT */ 1832 case SNDCTL_DSP_MAPINBUF: 1833 case SNDCTL_DSP_MAPOUTBUF: 1834 case SNDCTL_DSP_SETSYNCRO: 1835 /* undocumented */ 1836 1837 case SNDCTL_DSP_SUBDIVIDE: 1838 case SOUND_PCM_WRITE_FILTER: 1839 case SOUND_PCM_READ_FILTER: 1840 /* dunno what these do, don't sound important */ 1841 1842 default: 1843 DEB(printf("default ioctl fn 0x%08lx fail\n", cmd)); 1844 ret = EINVAL; 1845 break; 1846 } 1847 1848 PCM_GIANT_LEAVE(d); 1849 1850 return (ret); 1851 } 1852 1853 static int 1854 dsp_poll(struct cdev *i_dev, int events, struct thread *td) 1855 { 1856 struct dsp_cdevpriv *priv; 1857 struct snddev_info *d; 1858 struct pcm_channel *wrch, *rdch; 1859 int ret, e, err; 1860 1861 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 1862 return (err); 1863 d = priv->sc; 1864 if (!DSP_REGISTERED(d)) { 1865 /* XXX many clients don't understand POLLNVAL */ 1866 return (events & (POLLHUP | POLLPRI | POLLIN | 1867 POLLRDNORM | POLLOUT | POLLWRNORM)); 1868 } 1869 PCM_GIANT_ENTER(d); 1870 1871 ret = 0; 1872 1873 wrch = priv->wrch; 1874 rdch = priv->rdch; 1875 1876 if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) { 1877 CHN_LOCK(wrch); 1878 e = (events & (POLLOUT | POLLWRNORM)); 1879 if (e) 1880 ret |= chn_poll(wrch, e, td); 1881 CHN_UNLOCK(wrch); 1882 } 1883 1884 if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) { 1885 CHN_LOCK(rdch); 1886 e = (events & (POLLIN | POLLRDNORM)); 1887 if (e) 1888 ret |= chn_poll(rdch, e, td); 1889 CHN_UNLOCK(rdch); 1890 } 1891 1892 PCM_GIANT_LEAVE(d); 1893 1894 return (ret); 1895 } 1896 1897 struct dsp_mmap_handle { 1898 struct cdev *cdev; 1899 struct snd_dbuf *buf; 1900 }; 1901 1902 static int 1903 dsp_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, 1904 vm_ooffset_t foff, struct ucred *cred, u_short *color) 1905 { 1906 struct dsp_mmap_handle *h = handle; 1907 1908 dev_ref(h->cdev); 1909 sndbuf_ref(h->buf); 1910 return (0); 1911 } 1912 1913 static void 1914 dsp_dev_pager_dtor(void *handle) 1915 { 1916 struct dsp_mmap_handle *h = handle; 1917 1918 sndbuf_rele(h->buf); 1919 dev_rel(h->cdev); 1920 free(h, M_DEVBUF); 1921 } 1922 1923 static int 1924 dsp_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, 1925 vm_page_t *mres) 1926 { 1927 struct dsp_mmap_handle *h = object->handle; 1928 vm_page_t m; 1929 uintptr_t addr; 1930 vm_paddr_t paddr; 1931 1932 addr = (uintptr_t)offset; 1933 if (addr < (uintptr_t)h->buf->buf || 1934 addr >= (uintptr_t)h->buf->buf + h->buf->allocsize) 1935 return (VM_PAGER_ERROR); 1936 paddr = vtophys((void *)addr); 1937 1938 if (((*mres)->flags & PG_FICTITIOUS) != 0) { 1939 m = *mres; 1940 vm_page_updatefake(m, paddr, object->memattr); 1941 } else { 1942 VM_OBJECT_WUNLOCK(object); 1943 m = vm_page_getfake(paddr, object->memattr); 1944 VM_OBJECT_WLOCK(object); 1945 vm_page_replace(m, object, (*mres)->pindex, *mres); 1946 *mres = m; 1947 } 1948 m->valid = VM_PAGE_BITS_ALL; 1949 return (VM_PAGER_OK); 1950 } 1951 1952 static void 1953 dsp_dev_pager_path(void *handle, char *path, size_t len) 1954 { 1955 struct dsp_mmap_handle *h = handle; 1956 1957 dev_copyname(h->cdev, path, len); 1958 } 1959 1960 static const struct cdev_pager_ops dsp_dev_pager_ops = { 1961 .cdev_pg_ctor = dsp_dev_pager_ctor, 1962 .cdev_pg_dtor = dsp_dev_pager_dtor, 1963 .cdev_pg_fault = dsp_dev_pager_fault, 1964 .cdev_pg_path = dsp_dev_pager_path, 1965 }; 1966 1967 static int 1968 dsp_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, 1969 vm_size_t size, struct vm_object **object, int nprot) 1970 { 1971 struct dsp_mmap_handle *handle; 1972 struct dsp_cdevpriv *priv; 1973 struct snddev_info *d; 1974 struct pcm_channel *c; 1975 int err; 1976 bool dealloc; 1977 1978 if (*offset >= *offset + size) 1979 return (EINVAL); 1980 1981 /* 1982 * https://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html 1983 */ 1984 if ((nprot & PROT_EXEC) && (dsp_mmap_allow_prot_exec < 0 || 1985 (dsp_mmap_allow_prot_exec == 0 && 1986 SV_CURPROC_ABI() != SV_ABI_LINUX))) 1987 return (EINVAL); 1988 1989 if ((nprot & (PROT_READ | PROT_WRITE)) == 0) 1990 return (EINVAL); 1991 1992 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 1993 return (err); 1994 d = priv->sc; 1995 if (!DSP_REGISTERED(d)) 1996 return (EINVAL); 1997 1998 PCM_GIANT_ENTER(d); 1999 2000 /* 2001 * PROT_READ (alone) selects the input buffer. 2002 * PROT_WRITE (alone) selects the output buffer. 2003 * PROT_WRITE|PROT_READ together select the output buffer. 2004 */ 2005 c = ((nprot & PROT_WRITE) != 0) ? priv->wrch : priv->rdch; 2006 if (c == NULL) { 2007 PCM_GIANT_EXIT(d); 2008 return (EINVAL); 2009 } 2010 2011 CHN_LOCK(c); 2012 if ((c->flags & CHN_F_MMAP_INVALID) || 2013 c->bufsoft->allocsize < *offset + size) { 2014 CHN_UNLOCK(c); 2015 PCM_GIANT_EXIT(d); 2016 return (EINVAL); 2017 } 2018 c->flags |= CHN_F_MMAP; 2019 *offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset); 2020 CHN_UNLOCK(c); 2021 2022 handle = malloc(sizeof(*handle), M_DEVBUF, M_WAITOK); 2023 handle->cdev = cdev; 2024 handle->buf = c->bufsoft; 2025 *object = cdev_pager_allocate(handle, OBJT_DEVICE, &dsp_dev_pager_ops, 2026 size, nprot, *offset, curthread->td_ucred); 2027 PCM_GIANT_LEAVE(d); 2028 if (*object != NULL) { 2029 err = 0; 2030 dealloc = false; 2031 CHN_LOCK(c); 2032 if (c->flags & CHN_F_MMAP_INVALID) { 2033 c->flags &= ~CHN_F_MMAP; 2034 err = EINVAL; 2035 dealloc = true; 2036 } 2037 CHN_UNLOCK(c); 2038 /* We use a helper bool to keep the channel locking simpler. */ 2039 if (dealloc) 2040 vm_object_deallocate(*object); 2041 } else { 2042 free(handle, M_DEVBUF); 2043 err = ENOMEM; 2044 } 2045 2046 return (err); 2047 } 2048 2049 static const char *dsp_aliases[] = { 2050 "dsp_ac3", 2051 "dsp_mmap", 2052 "dsp_multich", 2053 "dsp_spdifout", 2054 "dsp_spdifin", 2055 }; 2056 2057 static void 2058 dsp_clone(void *arg, struct ucred *cred, char *name, int namelen, 2059 struct cdev **dev) 2060 { 2061 struct snddev_info *d; 2062 size_t i; 2063 2064 if (*dev != NULL) 2065 return; 2066 if (strcmp(name, "dsp") == 0 && dsp_basename_clone) 2067 goto found; 2068 for (i = 0; i < nitems(dsp_aliases); i++) { 2069 if (strcmp(name, dsp_aliases[i]) == 0) 2070 goto found; 2071 } 2072 return; 2073 found: 2074 bus_topo_lock(); 2075 d = devclass_get_softc(pcm_devclass, snd_unit); 2076 /* 2077 * If we only have a single soundcard attached and we detach it right 2078 * before entering dsp_clone(), there is a chance pcm_unregister() will 2079 * have returned already, meaning it will have set snd_unit to -1, and 2080 * thus devclass_get_softc() will return NULL here. 2081 */ 2082 if (DSP_REGISTERED(d)) { 2083 *dev = d->dsp_dev; 2084 dev_ref(*dev); 2085 } 2086 bus_topo_unlock(); 2087 } 2088 2089 static void 2090 dsp_sysinit(void *p) 2091 { 2092 if (dsp_ehtag != NULL) 2093 return; 2094 dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000); 2095 } 2096 2097 static void 2098 dsp_sysuninit(void *p) 2099 { 2100 if (dsp_ehtag == NULL) 2101 return; 2102 EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag); 2103 dsp_ehtag = NULL; 2104 } 2105 2106 SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL); 2107 SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL); 2108 2109 static void 2110 dsp_oss_audioinfo_unavail(oss_audioinfo *ai, int unit) 2111 { 2112 bzero(ai, sizeof(*ai)); 2113 ai->dev = unit; 2114 snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit); 2115 ai->pid = -1; 2116 strlcpy(ai->cmd, CHN_COMM_UNUSED, sizeof(ai->cmd)); 2117 ai->card_number = unit; 2118 ai->port_number = unit; 2119 ai->mixer_dev = -1; 2120 ai->legacy_device = unit; 2121 } 2122 2123 /** 2124 * @brief Handler for SNDCTL_AUDIOINFO. 2125 * 2126 * Gathers information about the audio device specified in ai->dev. If 2127 * ai->dev == -1, then this function gathers information about the current 2128 * device. If the call comes in on a non-audio device and ai->dev == -1, 2129 * return EINVAL. 2130 * 2131 * This routine is supposed to go practically straight to the hardware, 2132 * getting capabilities directly from the sound card driver, side-stepping 2133 * the intermediate channel interface. 2134 * 2135 * @note 2136 * Calling threads must not hold any snddev_info or pcm_channel locks. 2137 * 2138 * @param dev device on which the ioctl was issued 2139 * @param ai ioctl request data container 2140 * @param ex flag to distinguish between SNDCTL_AUDIOINFO from 2141 * SNDCTL_AUDIOINFO_EX 2142 * 2143 * @retval 0 success 2144 * @retval EINVAL ai->dev specifies an invalid device 2145 */ 2146 int 2147 dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai, bool ex) 2148 { 2149 struct pcmchan_caps *caps; 2150 struct pcm_channel *ch; 2151 struct snddev_info *d; 2152 uint32_t fmts; 2153 int i, minch, maxch, unit; 2154 2155 /* 2156 * If probing the device that received the ioctl, make sure it's a 2157 * DSP device. (Users may use this ioctl with /dev/mixer and 2158 * /dev/midi.) 2159 */ 2160 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) 2161 return (EINVAL); 2162 2163 bus_topo_lock(); 2164 for (unit = 0; pcm_devclass != NULL && 2165 unit < devclass_get_maxunit(pcm_devclass); unit++) { 2166 d = devclass_get_softc(pcm_devclass, unit); 2167 if (!PCM_REGISTERED(d)) { 2168 if ((ai->dev == -1 && unit == snd_unit) || 2169 ai->dev == unit) { 2170 dsp_oss_audioinfo_unavail(ai, unit); 2171 bus_topo_unlock(); 2172 return (0); 2173 } else { 2174 d = NULL; 2175 continue; 2176 } 2177 } 2178 2179 PCM_UNLOCKASSERT(d); 2180 PCM_LOCK(d); 2181 if ((ai->dev == -1 && d->dsp_dev == i_dev) || 2182 (ai->dev == unit)) { 2183 PCM_UNLOCK(d); 2184 break; 2185 } else { 2186 PCM_UNLOCK(d); 2187 d = NULL; 2188 } 2189 } 2190 bus_topo_unlock(); 2191 2192 /* Exhausted the search -- nothing is locked, so return. */ 2193 if (d == NULL) 2194 return (EINVAL); 2195 2196 /* XXX Need Giant magic entry ??? */ 2197 2198 PCM_UNLOCKASSERT(d); 2199 PCM_LOCK(d); 2200 2201 bzero((void *)ai, sizeof(oss_audioinfo)); 2202 ai->dev = unit; 2203 strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name)); 2204 ai->pid = -1; 2205 strlcpy(ai->cmd, CHN_COMM_UNKNOWN, sizeof(ai->cmd)); 2206 ai->card_number = unit; 2207 ai->port_number = unit; 2208 ai->mixer_dev = MIXER_REGISTERED(d->mixer) ? unit : -1; 2209 ai->legacy_device = unit; 2210 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); 2211 ai->enabled = device_is_attached(d->dev) ? 1 : 0; 2212 ai->next_play_engine = 0; 2213 ai->next_rec_engine = 0; 2214 ai->busy = 0; 2215 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; 2216 ai->iformats = 0; 2217 ai->oformats = 0; 2218 ai->min_rate = INT_MAX; 2219 ai->max_rate = 0; 2220 ai->min_channels = INT_MAX; 2221 ai->max_channels = 0; 2222 2223 /* Gather global information about the device. */ 2224 CHN_FOREACH(ch, d, channels.pcm) { 2225 CHN_UNLOCKASSERT(ch); 2226 CHN_LOCK(ch); 2227 2228 /* 2229 * Skip physical channels if we are servicing SNDCTL_AUDIOINFO, 2230 * or VCHANs if we are servicing SNDCTL_AUDIOINFO_EX. 2231 * 2232 * For SNDCTL_AUDIOINFO do not skip the physical channels if 2233 * there are no VCHANs. 2234 */ 2235 if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) || 2236 ((!ex && (ch->flags & CHN_F_VIRTUAL) == 0) && 2237 (d->pvchancount > 0 || d->rvchancount > 0))) { 2238 CHN_UNLOCK(ch); 2239 continue; 2240 } 2241 2242 if ((ch->flags & CHN_F_BUSY) == 0) { 2243 ai->busy |= (ch->direction == PCMDIR_PLAY) ? 2244 OPEN_WRITE : OPEN_READ; 2245 } 2246 2247 ai->caps |= 2248 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | 2249 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : 2250 PCM_CAP_INPUT); 2251 2252 caps = chn_getcaps(ch); 2253 2254 minch = INT_MAX; 2255 maxch = 0; 2256 fmts = 0; 2257 for (i = 0; caps->fmtlist[i]; i++) { 2258 fmts |= AFMT_ENCODING(caps->fmtlist[i]); 2259 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); 2260 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); 2261 } 2262 2263 if (ch->direction == PCMDIR_PLAY) 2264 ai->oformats |= fmts; 2265 else 2266 ai->iformats |= fmts; 2267 2268 if (ex || (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 2269 ai->min_rate = min(ai->min_rate, caps->minspeed); 2270 ai->max_rate = max(ai->max_rate, caps->maxspeed); 2271 } else { 2272 ai->min_rate = min(ai->min_rate, feeder_rate_min); 2273 ai->max_rate = max(ai->max_rate, feeder_rate_max); 2274 } 2275 ai->min_channels = min(ai->min_channels, minch); 2276 ai->max_channels = max(ai->max_channels, maxch); 2277 2278 CHN_UNLOCK(ch); 2279 } 2280 if (ai->min_rate == INT_MAX) 2281 ai->min_rate = 0; 2282 if (ai->min_channels == INT_MAX) 2283 ai->min_channels = 0; 2284 2285 PCM_UNLOCK(d); 2286 2287 return (0); 2288 } 2289 2290 static int 2291 dsp_oss_engineinfo_cb(void *data, void *arg) 2292 { 2293 struct dsp_cdevpriv *priv = data; 2294 struct pcm_channel *ch = arg; 2295 2296 if (DSP_REGISTERED(priv->sc) && (ch == priv->rdch || ch == priv->wrch)) 2297 return (1); 2298 2299 return (0); 2300 } 2301 2302 /** 2303 * @brief Handler for SNDCTL_ENGINEINFO 2304 * 2305 * Gathers information about the audio device's engine specified in ai->dev. 2306 * If ai->dev == -1, then this function gathers information about the current 2307 * device. If the call comes in on a non-audio device and ai->dev == -1, 2308 * return EINVAL. 2309 * 2310 * This routine is supposed to go practically straight to the hardware, 2311 * getting capabilities directly from the sound card driver, side-stepping 2312 * the intermediate channel interface. 2313 * 2314 * @note 2315 * Calling threads must not hold any snddev_info or pcm_channel locks. 2316 * 2317 * @param dev device on which the ioctl was issued 2318 * @param ai ioctl request data container 2319 * 2320 * @retval 0 success 2321 * @retval EINVAL ai->dev specifies an invalid device 2322 */ 2323 int 2324 dsp_oss_engineinfo(struct cdev *i_dev, oss_audioinfo *ai) 2325 { 2326 struct pcmchan_caps *caps; 2327 struct pcm_channel *ch; 2328 struct snddev_info *d; 2329 uint32_t fmts; 2330 int i, nchan, *rates, minch, maxch, unit; 2331 2332 /* 2333 * If probing the device that received the ioctl, make sure it's a 2334 * DSP device. (Users may use this ioctl with /dev/mixer and 2335 * /dev/midi.) 2336 */ 2337 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) 2338 return (EINVAL); 2339 2340 ch = NULL; 2341 nchan = 0; 2342 2343 /* 2344 * Search for the requested audio device (channel). Start by 2345 * iterating over pcm devices. 2346 */ 2347 bus_topo_lock(); 2348 for (unit = 0; pcm_devclass != NULL && 2349 unit < devclass_get_maxunit(pcm_devclass); unit++) { 2350 d = devclass_get_softc(pcm_devclass, unit); 2351 if (!PCM_REGISTERED(d)) 2352 continue; 2353 2354 /* XXX Need Giant magic entry ??? */ 2355 2356 /* See the note in function docblock */ 2357 PCM_UNLOCKASSERT(d); 2358 PCM_LOCK(d); 2359 2360 CHN_FOREACH(ch, d, channels.pcm) { 2361 CHN_UNLOCKASSERT(ch); 2362 CHN_LOCK(ch); 2363 if ((ai->dev == -1 && devfs_foreach_cdevpriv( 2364 i_dev, dsp_oss_engineinfo_cb, ch) != 0) || 2365 ai->dev == nchan) 2366 break; 2367 CHN_UNLOCK(ch); 2368 ++nchan; 2369 } 2370 2371 if (ch == NULL) { 2372 PCM_UNLOCK(d); 2373 continue; 2374 } 2375 2376 /* 2377 * At this point, the following synchronization stuff 2378 * has happened: 2379 * - a specific PCM device is locked. 2380 * - a specific audio channel has been locked, so be 2381 * sure to unlock when exiting; 2382 */ 2383 2384 caps = chn_getcaps(ch); 2385 2386 /* 2387 * With all handles collected, zero out the user's 2388 * container and begin filling in its fields. 2389 */ 2390 bzero((void *)ai, sizeof(oss_audioinfo)); 2391 2392 ai->dev = nchan; 2393 strlcpy(ai->name, ch->name, sizeof(ai->name)); 2394 2395 if ((ch->flags & CHN_F_BUSY) == 0) 2396 ai->busy = 0; 2397 else 2398 ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; 2399 2400 ai->pid = ch->pid; 2401 strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); 2402 2403 /* 2404 * These flags stolen from SNDCTL_DSP_GETCAPS handler. 2405 * Note, however, that a single channel operates in 2406 * only one direction, so PCM_CAP_DUPLEX is out. 2407 */ 2408 /** 2409 * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep 2410 * these in pcmchan::caps? 2411 */ 2412 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | 2413 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | 2414 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); 2415 2416 /* 2417 * Collect formats supported @b natively by the 2418 * device. Also determine min/max channels. 2419 */ 2420 minch = INT_MAX; 2421 maxch = 0; 2422 fmts = 0; 2423 for (i = 0; caps->fmtlist[i]; i++) { 2424 fmts |= AFMT_ENCODING(caps->fmtlist[i]); 2425 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); 2426 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); 2427 } 2428 2429 if (ch->direction == PCMDIR_PLAY) 2430 ai->oformats = fmts; 2431 else 2432 ai->iformats = fmts; 2433 2434 /** 2435 * @note 2436 * @c magic - OSSv4 docs: "Reserved for internal use 2437 * by OSS." 2438 * 2439 * @par 2440 * @c card_number - OSSv4 docs: "Number of the sound 2441 * card where this device belongs or -1 if this 2442 * information is not available. Applications 2443 * should normally not use this field for any 2444 * purpose." 2445 */ 2446 ai->card_number = unit; 2447 /** 2448 * @todo @c song_name - depends first on 2449 * SNDCTL_[GS]ETSONG @todo @c label - depends 2450 * on SNDCTL_[GS]ETLABEL 2451 * @todo @c port_number - routing information? 2452 */ 2453 ai->port_number = unit; 2454 ai->mixer_dev = MIXER_REGISTERED(d->mixer) ? unit : -1; 2455 /** 2456 * @note 2457 * @c legacy_device - OSSv4 docs: "Obsolete." 2458 */ 2459 ai->legacy_device = unit; 2460 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); 2461 ai->enabled = device_is_attached(d->dev) ? 1 : 0; 2462 /** 2463 * @note 2464 * @c flags - OSSv4 docs: "Reserved for future use." 2465 * 2466 * @note 2467 * @c binding - OSSv4 docs: "Reserved for future use." 2468 * 2469 * @todo @c handle - haven't decided how to generate 2470 * this yet; bus, vendor, device IDs? 2471 */ 2472 2473 if ((ch->flags & CHN_F_EXCLUSIVE) || 2474 (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { 2475 ai->min_rate = caps->minspeed; 2476 ai->max_rate = caps->maxspeed; 2477 } else { 2478 ai->min_rate = feeder_rate_min; 2479 ai->max_rate = feeder_rate_max; 2480 } 2481 2482 ai->min_channels = minch; 2483 ai->max_channels = maxch; 2484 2485 ai->nrates = chn_getrates(ch, &rates); 2486 if (ai->nrates > OSS_MAX_SAMPLE_RATES) 2487 ai->nrates = OSS_MAX_SAMPLE_RATES; 2488 2489 for (i = 0; i < ai->nrates; i++) 2490 ai->rates[i] = rates[i]; 2491 2492 ai->next_play_engine = 0; 2493 ai->next_rec_engine = 0; 2494 2495 CHN_UNLOCK(ch); 2496 PCM_UNLOCK(d); 2497 bus_topo_unlock(); 2498 2499 return (0); 2500 } 2501 bus_topo_unlock(); 2502 2503 /* Exhausted the search -- nothing is locked, so return. */ 2504 return (EINVAL); 2505 } 2506 2507 /** 2508 * @brief Assigns a PCM channel to a sync group. 2509 * 2510 * Sync groups are used to enable audio operations on multiple devices 2511 * simultaneously. They may be used with any number of devices and may 2512 * span across applications. Devices are added to groups with 2513 * the SNDCTL_DSP_SYNCGROUP ioctl, and operations are triggered with the 2514 * SNDCTL_DSP_SYNCSTART ioctl. 2515 * 2516 * If the @c id field of the @c group parameter is set to zero, then a new 2517 * sync group is created. Otherwise, wrch and rdch (if set) are added to 2518 * the group specified. 2519 * 2520 * @todo As far as memory allocation, should we assume that things are 2521 * okay and allocate with M_WAITOK before acquiring channel locks, 2522 * freeing later if not? 2523 * 2524 * @param wrch output channel associated w/ device (if any) 2525 * @param rdch input channel associated w/ device (if any) 2526 * @param group Sync group parameters 2527 * 2528 * @retval 0 success 2529 * @retval non-zero error to be propagated upstream 2530 */ 2531 static int 2532 dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group) 2533 { 2534 struct pcmchan_syncmember *smrd, *smwr; 2535 struct pcmchan_syncgroup *sg; 2536 int ret, sg_ids[3]; 2537 2538 smrd = NULL; 2539 smwr = NULL; 2540 sg = NULL; 2541 ret = 0; 2542 2543 /* 2544 * Free_unr() may sleep, so store released syncgroup IDs until after 2545 * all locks are released. 2546 */ 2547 sg_ids[0] = sg_ids[1] = sg_ids[2] = 0; 2548 2549 PCM_SG_LOCK(); 2550 2551 /* 2552 * - Insert channel(s) into group's member list. 2553 * - Set CHN_F_NOTRIGGER on channel(s). 2554 * - Stop channel(s). 2555 */ 2556 2557 /* 2558 * If device's channels are already mapped to a group, unmap them. 2559 */ 2560 if (wrch) { 2561 CHN_LOCK(wrch); 2562 sg_ids[0] = chn_syncdestroy(wrch); 2563 } 2564 2565 if (rdch) { 2566 CHN_LOCK(rdch); 2567 sg_ids[1] = chn_syncdestroy(rdch); 2568 } 2569 2570 /* 2571 * Verify that mode matches character device properites. 2572 * - Bail if PCM_ENABLE_OUTPUT && wrch == NULL. 2573 * - Bail if PCM_ENABLE_INPUT && rdch == NULL. 2574 */ 2575 if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) || 2576 ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) { 2577 ret = EINVAL; 2578 goto out; 2579 } 2580 2581 /* 2582 * An id of zero indicates the user wants to create a new 2583 * syncgroup. 2584 */ 2585 if (group->id == 0) { 2586 sg = malloc(sizeof(*sg), M_DEVBUF, M_NOWAIT); 2587 if (sg != NULL) { 2588 SLIST_INIT(&sg->members); 2589 sg->id = alloc_unr(pcmsg_unrhdr); 2590 2591 group->id = sg->id; 2592 SLIST_INSERT_HEAD(&snd_pcm_syncgroups, sg, link); 2593 } else 2594 ret = ENOMEM; 2595 } else { 2596 SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) { 2597 if (sg->id == group->id) 2598 break; 2599 } 2600 if (sg == NULL) 2601 ret = EINVAL; 2602 } 2603 2604 /* Couldn't create or find a syncgroup. Fail. */ 2605 if (sg == NULL) 2606 goto out; 2607 2608 /* 2609 * Allocate a syncmember, assign it and a channel together, and 2610 * insert into syncgroup. 2611 */ 2612 if (group->mode & PCM_ENABLE_INPUT) { 2613 smrd = malloc(sizeof(*smrd), M_DEVBUF, M_NOWAIT); 2614 if (smrd == NULL) { 2615 ret = ENOMEM; 2616 goto out; 2617 } 2618 2619 SLIST_INSERT_HEAD(&sg->members, smrd, link); 2620 smrd->parent = sg; 2621 smrd->ch = rdch; 2622 2623 chn_abort(rdch); 2624 rdch->flags |= CHN_F_NOTRIGGER; 2625 rdch->sm = smrd; 2626 } 2627 2628 if (group->mode & PCM_ENABLE_OUTPUT) { 2629 smwr = malloc(sizeof(*smwr), M_DEVBUF, M_NOWAIT); 2630 if (smwr == NULL) { 2631 ret = ENOMEM; 2632 goto out; 2633 } 2634 2635 SLIST_INSERT_HEAD(&sg->members, smwr, link); 2636 smwr->parent = sg; 2637 smwr->ch = wrch; 2638 2639 chn_abort(wrch); 2640 wrch->flags |= CHN_F_NOTRIGGER; 2641 wrch->sm = smwr; 2642 } 2643 2644 out: 2645 if (ret != 0) { 2646 free(smrd, M_DEVBUF); 2647 if ((sg != NULL) && SLIST_EMPTY(&sg->members)) { 2648 sg_ids[2] = sg->id; 2649 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2650 free(sg, M_DEVBUF); 2651 } 2652 2653 if (wrch) 2654 wrch->sm = NULL; 2655 if (rdch) 2656 rdch->sm = NULL; 2657 } 2658 2659 if (wrch) 2660 CHN_UNLOCK(wrch); 2661 if (rdch) 2662 CHN_UNLOCK(rdch); 2663 2664 PCM_SG_UNLOCK(); 2665 2666 if (sg_ids[0]) 2667 free_unr(pcmsg_unrhdr, sg_ids[0]); 2668 if (sg_ids[1]) 2669 free_unr(pcmsg_unrhdr, sg_ids[1]); 2670 if (sg_ids[2]) 2671 free_unr(pcmsg_unrhdr, sg_ids[2]); 2672 2673 return (ret); 2674 } 2675 2676 /** 2677 * @brief Launch a sync group into action 2678 * 2679 * Sync groups are established via SNDCTL_DSP_SYNCGROUP. This function 2680 * iterates over all members, triggering them along the way. 2681 * 2682 * @note Caller must not hold any channel locks. 2683 * 2684 * @param sg_id sync group identifier 2685 * 2686 * @retval 0 success 2687 * @retval non-zero error worthy of propagating upstream to user 2688 */ 2689 static int 2690 dsp_oss_syncstart(int sg_id) 2691 { 2692 struct pcmchan_syncmember *sm, *sm_tmp; 2693 struct pcmchan_syncgroup *sg; 2694 struct pcm_channel *c; 2695 int ret; 2696 2697 PCM_SG_LOCK(); 2698 do { 2699 ret = 0; 2700 2701 /* Search for syncgroup by ID */ 2702 SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) { 2703 if (sg->id == sg_id) 2704 break; 2705 } 2706 2707 /* Return EINVAL if not found */ 2708 if (sg == NULL) { 2709 ret = EINVAL; 2710 break; 2711 } 2712 2713 /* Any removals resulting in an empty group should've handled this */ 2714 KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup")); 2715 2716 /* 2717 * Attempt to lock all member channels - if any are already 2718 * locked, unlock those acquired, sleep for a bit, and try 2719 * again. 2720 */ 2721 SLIST_FOREACH(sm, &sg->members, link) { 2722 if (CHN_TRYLOCK(sm->ch) == 0) { 2723 int timo = hz * 5/1000; 2724 if (timo < 1) 2725 timo = 1; 2726 2727 /* Release all locked channels so far, retry */ 2728 SLIST_FOREACH(sm_tmp, &sg->members, link) { 2729 /* sm is the member already locked */ 2730 if (sm == sm_tmp) 2731 break; 2732 CHN_UNLOCK(sm_tmp->ch); 2733 } 2734 2735 /** @todo Is PRIBIO correct/ */ 2736 ret = msleep(sm, PCM_SG_LOCKPTR(), 2737 PRIBIO | PCATCH, "pcmsg", timo); 2738 if (ret == EAGAIN) 2739 ret = 0; 2740 break; 2741 } 2742 } 2743 } while (ret == 0 && sm != NULL); 2744 2745 /* Proceed only if no errors encountered. */ 2746 if (ret == 0) { 2747 /* 2748 * Unlock all members before starting any of them. 2749 * Holding multiple channel locks while calling chn_start() 2750 * on a virtual channel can trigger the parent, which 2751 * acquires PCM_LOCK() while other virtual channels are 2752 * still locked -- a lock order reversal. 2753 */ 2754 SLIST_FOREACH(sm, &sg->members, link) { 2755 sm->ch->sm = NULL; 2756 sm->ch->flags &= ~CHN_F_NOTRIGGER; 2757 CHN_UNLOCK(sm->ch); 2758 } 2759 2760 /* 2761 * Start each channel individually, then remove it from 2762 * the sync group and free its member structure. 2763 */ 2764 while ((sm = SLIST_FIRST(&sg->members)) != NULL) { 2765 c = sm->ch; 2766 CHN_LOCK(c); 2767 chn_start(c, 1); 2768 CHN_UNLOCK(c); 2769 SLIST_REMOVE_HEAD(&sg->members, link); 2770 free(sm, M_DEVBUF); 2771 } 2772 2773 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2774 free(sg, M_DEVBUF); 2775 } 2776 2777 PCM_SG_UNLOCK(); 2778 2779 /* 2780 * Free_unr() may sleep, so be sure to give up the syncgroup lock 2781 * first. 2782 */ 2783 if (ret == 0) 2784 free_unr(pcmsg_unrhdr, sg_id); 2785 2786 return (ret); 2787 } 2788 2789 /** 2790 * @brief Handler for SNDCTL_DSP_POLICY 2791 * 2792 * The SNDCTL_DSP_POLICY ioctl is a simpler interface to control fragment 2793 * size and count like with SNDCTL_DSP_SETFRAGMENT. Instead of the user 2794 * specifying those two parameters, s/he simply selects a number from 0..10 2795 * which corresponds to a buffer size. Smaller numbers request smaller 2796 * buffers with lower latencies (at greater overhead from more frequent 2797 * interrupts), while greater numbers behave in the opposite manner. 2798 * 2799 * The 4Front spec states that a value of 5 should be the default. However, 2800 * this implementation deviates slightly by using a linear scale without 2801 * consulting drivers. I.e., even though drivers may have different default 2802 * buffer sizes, a policy argument of 5 will have the same result across 2803 * all drivers. 2804 * 2805 * See http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html for 2806 * more information. 2807 * 2808 * @todo When SNDCTL_DSP_COOKEDMODE is supported, it'll be necessary to 2809 * work with hardware drivers directly. 2810 * 2811 * @note PCM channel arguments must not be locked by caller. 2812 * 2813 * @param wrch Pointer to opened playback channel (optional; may be NULL) 2814 * @param rdch " recording channel (optional; may be NULL) 2815 * @param policy Integer from [0:10] 2816 * 2817 * @retval 0 constant (for now) 2818 */ 2819 static int 2820 dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy) 2821 { 2822 int ret; 2823 2824 if (policy < CHN_POLICY_MIN || policy > CHN_POLICY_MAX) 2825 return (EIO); 2826 2827 /* Default: success */ 2828 ret = 0; 2829 2830 if (rdch) { 2831 CHN_LOCK(rdch); 2832 ret = chn_setlatency(rdch, policy); 2833 CHN_UNLOCK(rdch); 2834 } 2835 2836 if (wrch && ret == 0) { 2837 CHN_LOCK(wrch); 2838 ret = chn_setlatency(wrch, policy); 2839 CHN_UNLOCK(wrch); 2840 } 2841 2842 if (ret) 2843 ret = EIO; 2844 2845 return (ret); 2846 } 2847 2848 /** 2849 * @brief Enable or disable "cooked" mode 2850 * 2851 * This is a handler for @c SNDCTL_DSP_COOKEDMODE. When in cooked mode, which 2852 * is the default, the sound system handles rate and format conversions 2853 * automatically (ex: user writing 11025Hz/8 bit/unsigned but card only 2854 * operates with 44100Hz/16bit/signed samples). 2855 * 2856 * Disabling cooked mode is intended for applications wanting to mmap() 2857 * a sound card's buffer space directly, bypassing the FreeBSD 2-stage 2858 * feeder architecture, presumably to gain as much control over audio 2859 * hardware as possible. 2860 * 2861 * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_COOKEDMODE.html 2862 * for more details. 2863 * 2864 * @param wrch playback channel (optional; may be NULL) 2865 * @param rdch recording channel (optional; may be NULL) 2866 * @param enabled 0 = raw mode, 1 = cooked mode 2867 * 2868 * @retval EINVAL Operation not yet supported. 2869 */ 2870 static int 2871 dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled) 2872 { 2873 2874 /* 2875 * XXX I just don't get it. Why don't they call it 2876 * "BITPERFECT" ~ SNDCTL_DSP_BITPERFECT !?!?. 2877 * This is just plain so confusing, incoherent, 2878 * <insert any non-printable characters here>. 2879 */ 2880 if (!(enabled == 1 || enabled == 0)) 2881 return (EINVAL); 2882 2883 /* 2884 * I won't give in. I'm inverting its logic here and now. 2885 * Brag all you want, but "BITPERFECT" should be the better 2886 * term here. 2887 */ 2888 enabled ^= 0x00000001; 2889 2890 if (wrch != NULL) { 2891 CHN_LOCK(wrch); 2892 wrch->flags &= ~CHN_F_BITPERFECT; 2893 wrch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; 2894 CHN_UNLOCK(wrch); 2895 } 2896 2897 if (rdch != NULL) { 2898 CHN_LOCK(rdch); 2899 rdch->flags &= ~CHN_F_BITPERFECT; 2900 rdch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; 2901 CHN_UNLOCK(rdch); 2902 } 2903 2904 return (0); 2905 } 2906 2907 /** 2908 * @brief Retrieve channel interleaving order 2909 * 2910 * This is the handler for @c SNDCTL_DSP_GET_CHNORDER. 2911 * 2912 * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_GET_CHNORDER.html 2913 * for more details. 2914 * 2915 * @note As the ioctl definition is still under construction, FreeBSD 2916 * does not currently support SNDCTL_DSP_GET_CHNORDER. 2917 * 2918 * @param wrch playback channel (optional; may be NULL) 2919 * @param rdch recording channel (optional; may be NULL) 2920 * @param map channel map (result will be stored there) 2921 * 2922 * @retval EINVAL Operation not yet supported. 2923 */ 2924 static int 2925 dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map) 2926 { 2927 struct pcm_channel *ch; 2928 int ret; 2929 2930 ch = (wrch != NULL) ? wrch : rdch; 2931 if (ch != NULL) { 2932 CHN_LOCK(ch); 2933 ret = chn_oss_getorder(ch, map); 2934 CHN_UNLOCK(ch); 2935 } else 2936 ret = EINVAL; 2937 2938 return (ret); 2939 } 2940 2941 /** 2942 * @brief Specify channel interleaving order 2943 * 2944 * This is the handler for @c SNDCTL_DSP_SET_CHNORDER. 2945 * 2946 * @note As the ioctl definition is still under construction, FreeBSD 2947 * does not currently support @c SNDCTL_DSP_SET_CHNORDER. 2948 * 2949 * @param wrch playback channel (optional; may be NULL) 2950 * @param rdch recording channel (optional; may be NULL) 2951 * @param map channel map 2952 * 2953 * @retval EINVAL Operation not yet supported. 2954 */ 2955 static int 2956 dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map) 2957 { 2958 int ret; 2959 2960 ret = 0; 2961 2962 if (wrch != NULL) { 2963 CHN_LOCK(wrch); 2964 ret = chn_oss_setorder(wrch, map); 2965 CHN_UNLOCK(wrch); 2966 } 2967 2968 if (ret == 0 && rdch != NULL) { 2969 CHN_LOCK(rdch); 2970 ret = chn_oss_setorder(rdch, map); 2971 CHN_UNLOCK(rdch); 2972 } 2973 2974 return (ret); 2975 } 2976 2977 static int 2978 dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch, 2979 int *mask) 2980 { 2981 struct pcm_channel *ch; 2982 uint32_t chnmask; 2983 int ret; 2984 2985 chnmask = 0; 2986 ch = (wrch != NULL) ? wrch : rdch; 2987 2988 if (ch != NULL) { 2989 CHN_LOCK(ch); 2990 ret = chn_oss_getmask(ch, &chnmask); 2991 CHN_UNLOCK(ch); 2992 } else 2993 ret = EINVAL; 2994 2995 if (ret == 0) 2996 *mask = chnmask; 2997 2998 return (ret); 2999 } 3000 3001 static void 3002 dsp_kqdetach(struct knote *kn) 3003 { 3004 struct pcm_channel *ch = kn->kn_hook; 3005 3006 if (ch == NULL) 3007 return; 3008 CHN_LOCK(ch); 3009 knlist_remove(&ch->bufsoft->sel.si_note, kn, 1); 3010 CHN_UNLOCK(ch); 3011 } 3012 3013 static int 3014 dsp_kqevent(struct knote *kn, long hint) 3015 { 3016 struct pcm_channel *ch = kn->kn_hook; 3017 3018 CHN_LOCKASSERT(ch); 3019 if (ch->flags & CHN_F_DEAD) { 3020 kn->kn_flags |= EV_EOF; 3021 return (1); 3022 } 3023 kn->kn_data = 0; 3024 /* 3025 * For mmaped channels pass the knote's own reference point so the 3026 * low watermark is tracked per-knote. Non-mmaped channels ignore 3027 * the reference and fire based on the current amount of ready/free 3028 * data in the buffer, so all knotes see the same live state. 3029 */ 3030 if (chn_polltrigger(ch, (uint64_t)kn->kn_sdata)) { 3031 if (kn->kn_filter == EVFILT_READ) { 3032 kn->kn_data = sndbuf_getready(ch->bufsoft); 3033 if (ch->flags & CHN_F_MMAP) 3034 kn->kn_kevent.ext[0] = sndbuf_getfreeptr(ch->bufsoft); 3035 else 3036 kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align; 3037 } else { 3038 kn->kn_data = sndbuf_getfree(ch->bufsoft); 3039 if (ch->flags & CHN_F_MMAP) 3040 kn->kn_kevent.ext[0] = sndbuf_getreadyptr(ch->bufsoft); 3041 else 3042 kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align; 3043 } 3044 kn->kn_kevent.ext[1] = ch->xruns; 3045 kn->kn_sdata = ch->bufsoft->total; 3046 } 3047 3048 return (kn->kn_data > 0); 3049 } 3050 3051 static const struct filterops dsp_filtops = { 3052 .f_isfd = 1, 3053 .f_detach = dsp_kqdetach, 3054 .f_event = dsp_kqevent, 3055 }; 3056 3057 static int 3058 dsp_kqfilter(struct cdev *dev, struct knote *kn) 3059 { 3060 struct dsp_cdevpriv *priv; 3061 struct snddev_info *d; 3062 struct pcm_channel *ch; 3063 int err = 0; 3064 3065 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 3066 return (err); 3067 3068 d = priv->sc; 3069 if (!DSP_REGISTERED(d)) 3070 return (EBADF); 3071 PCM_GIANT_ENTER(d); 3072 switch (kn->kn_filter) { 3073 case EVFILT_READ: 3074 ch = priv->rdch; 3075 break; 3076 case EVFILT_WRITE: 3077 ch = priv->wrch; 3078 break; 3079 default: 3080 kn->kn_hook = NULL; 3081 err = EINVAL; 3082 ch = NULL; 3083 break; 3084 } 3085 if (ch != NULL) { 3086 kn->kn_fop = &dsp_filtops; 3087 CHN_LOCK(ch); 3088 knlist_add(&ch->bufsoft->sel.si_note, kn, 1); 3089 CHN_UNLOCK(ch); 3090 kn->kn_hook = ch; 3091 /* 3092 * Start tracking from the current position so the first event 3093 * fires after c->lw additional bytes have been transferred. 3094 */ 3095 kn->kn_sdata = ch->bufsoft->prev_total; 3096 } else 3097 err = EINVAL; 3098 PCM_GIANT_LEAVE(d); 3099 3100 return (err); 3101 } 3102 3103 #ifdef OSSV4_EXPERIMENT 3104 /** 3105 * @brief Retrieve an audio device's label 3106 * 3107 * This is a handler for the @c SNDCTL_GETLABEL ioctl. 3108 * 3109 * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html 3110 * for more details. 3111 * 3112 * From Hannu@4Front: "For example ossxmix (just like some HW mixer 3113 * consoles) can show variable "labels" for certain controls. By default 3114 * the application name (say quake) is shown as the label but 3115 * applications may change the labels themselves." 3116 * 3117 * @note As the ioctl definition is still under construction, FreeBSD 3118 * does not currently support @c SNDCTL_GETLABEL. 3119 * 3120 * @param wrch playback channel (optional; may be NULL) 3121 * @param rdch recording channel (optional; may be NULL) 3122 * @param label label gets copied here 3123 * 3124 * @retval EINVAL Operation not yet supported. 3125 */ 3126 static int 3127 dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label) 3128 { 3129 return (EINVAL); 3130 } 3131 3132 /** 3133 * @brief Specify an audio device's label 3134 * 3135 * This is a handler for the @c SNDCTL_SETLABEL ioctl. Please see the 3136 * comments for @c dsp_oss_getlabel immediately above. 3137 * 3138 * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html 3139 * for more details. 3140 * 3141 * @note As the ioctl definition is still under construction, FreeBSD 3142 * does not currently support SNDCTL_SETLABEL. 3143 * 3144 * @param wrch playback channel (optional; may be NULL) 3145 * @param rdch recording channel (optional; may be NULL) 3146 * @param label label gets copied from here 3147 * 3148 * @retval EINVAL Operation not yet supported. 3149 */ 3150 static int 3151 dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label) 3152 { 3153 return (EINVAL); 3154 } 3155 3156 /** 3157 * @brief Retrieve name of currently played song 3158 * 3159 * This is a handler for the @c SNDCTL_GETSONG ioctl. Audio players could 3160 * tell the system the name of the currently playing song, which would be 3161 * visible in @c /dev/sndstat. 3162 * 3163 * See @c http://manuals.opensound.com/developer/SNDCTL_GETSONG.html 3164 * for more details. 3165 * 3166 * @note As the ioctl definition is still under construction, FreeBSD 3167 * does not currently support SNDCTL_GETSONG. 3168 * 3169 * @param wrch playback channel (optional; may be NULL) 3170 * @param rdch recording channel (optional; may be NULL) 3171 * @param song song name gets copied here 3172 * 3173 * @retval EINVAL Operation not yet supported. 3174 */ 3175 static int 3176 dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song) 3177 { 3178 return (EINVAL); 3179 } 3180 3181 /** 3182 * @brief Retrieve name of currently played song 3183 * 3184 * This is a handler for the @c SNDCTL_SETSONG ioctl. Audio players could 3185 * tell the system the name of the currently playing song, which would be 3186 * visible in @c /dev/sndstat. 3187 * 3188 * See @c http://manuals.opensound.com/developer/SNDCTL_SETSONG.html 3189 * for more details. 3190 * 3191 * @note As the ioctl definition is still under construction, FreeBSD 3192 * does not currently support SNDCTL_SETSONG. 3193 * 3194 * @param wrch playback channel (optional; may be NULL) 3195 * @param rdch recording channel (optional; may be NULL) 3196 * @param song song name gets copied from here 3197 * 3198 * @retval EINVAL Operation not yet supported. 3199 */ 3200 static int 3201 dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song) 3202 { 3203 return (EINVAL); 3204 } 3205 3206 /** 3207 * @brief Rename a device 3208 * 3209 * This is a handler for the @c SNDCTL_SETNAME ioctl. 3210 * 3211 * See @c http://manuals.opensound.com/developer/SNDCTL_SETNAME.html for 3212 * more details. 3213 * 3214 * From Hannu@4Front: "This call is used to change the device name 3215 * reported in /dev/sndstat and ossinfo. So instead of using some generic 3216 * 'OSS loopback audio (MIDI) driver' the device may be given a meaningfull 3217 * name depending on the current context (for example 'OSS virtual wave table 3218 * synth' or 'VoIP link to London')." 3219 * 3220 * @note As the ioctl definition is still under construction, FreeBSD 3221 * does not currently support SNDCTL_SETNAME. 3222 * 3223 * @param wrch playback channel (optional; may be NULL) 3224 * @param rdch recording channel (optional; may be NULL) 3225 * @param name new device name gets copied from here 3226 * 3227 * @retval EINVAL Operation not yet supported. 3228 */ 3229 static int 3230 dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name) 3231 { 3232 return (EINVAL); 3233 } 3234 #endif /* !OSSV4_EXPERIMENT */ 3235