1 /*- 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <dev/sound/pcm/sound.h> 28 29 #include "mixer_if.h" 30 31 SND_DECLARE_FILE("$FreeBSD$"); 32 33 MALLOC_DEFINE(M_MIXER, "mixer", "mixer"); 34 35 #define MIXER_NAMELEN 16 36 struct snd_mixer { 37 KOBJ_FIELDS; 38 void *devinfo; 39 int busy; 40 int hwvol_muted; 41 int hwvol_mixer; 42 int hwvol_step; 43 int type; 44 device_t dev; 45 u_int32_t hwvol_mute_level; 46 u_int32_t devs; 47 u_int32_t recdevs; 48 u_int32_t recsrc; 49 u_int16_t level[32]; 50 u_int8_t parent[32]; 51 u_int32_t child[32]; 52 u_int8_t realdev[32]; 53 char name[MIXER_NAMELEN]; 54 struct mtx *lock; 55 oss_mixer_enuminfo enuminfo; 56 /** 57 * Counter is incremented when applications change any of this 58 * mixer's controls. A change in value indicates that persistent 59 * mixer applications should update their displays. 60 */ 61 int modify_counter; 62 }; 63 64 static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { 65 [SOUND_MIXER_VOLUME] = 75, 66 [SOUND_MIXER_BASS] = 50, 67 [SOUND_MIXER_TREBLE] = 50, 68 [SOUND_MIXER_SYNTH] = 75, 69 [SOUND_MIXER_PCM] = 75, 70 [SOUND_MIXER_SPEAKER] = 75, 71 [SOUND_MIXER_LINE] = 75, 72 [SOUND_MIXER_MIC] = 0, 73 [SOUND_MIXER_CD] = 75, 74 [SOUND_MIXER_IGAIN] = 0, 75 [SOUND_MIXER_LINE1] = 75, 76 [SOUND_MIXER_VIDEO] = 75, 77 [SOUND_MIXER_RECLEV] = 0, 78 [SOUND_MIXER_OGAIN] = 50, 79 [SOUND_MIXER_MONITOR] = 75, 80 }; 81 82 static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 83 84 static d_open_t mixer_open; 85 static d_close_t mixer_close; 86 static d_ioctl_t mixer_ioctl; 87 88 static struct cdevsw mixer_cdevsw = { 89 .d_version = D_VERSION, 90 .d_open = mixer_open, 91 .d_close = mixer_close, 92 .d_ioctl = mixer_ioctl, 93 .d_name = "mixer", 94 }; 95 96 /** 97 * Keeps a count of mixer devices; used only by OSSv4 SNDCTL_SYSINFO ioctl. 98 */ 99 int mixer_count = 0; 100 101 #ifdef USING_DEVFS 102 static eventhandler_tag mixer_ehtag = NULL; 103 #endif 104 105 static struct cdev * 106 mixer_get_devt(device_t dev) 107 { 108 struct snddev_info *snddev; 109 110 snddev = device_get_softc(dev); 111 112 return snddev->mixer_dev; 113 } 114 115 #ifdef SND_DYNSYSCTL 116 static int 117 mixer_lookup(char *devname) 118 { 119 int i; 120 121 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 122 if (strncmp(devname, snd_mixernames[i], 123 strlen(snd_mixernames[i])) == 0) 124 return i; 125 return -1; 126 } 127 #endif 128 129 #define MIXER_SET_UNLOCK(x, y) do { \ 130 if ((y) != 0) \ 131 snd_mtxunlock((x)->lock); \ 132 } while(0) 133 134 #define MIXER_SET_LOCK(x, y) do { \ 135 if ((y) != 0) \ 136 snd_mtxlock((x)->lock); \ 137 } while(0) 138 139 static int 140 mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d, 141 unsigned left, unsigned right) 142 { 143 struct pcm_channel *c; 144 int dropmtx, acquiremtx; 145 146 if (!PCM_REGISTERED(d)) 147 return (EINVAL); 148 149 if (mtx_owned(m->lock)) 150 dropmtx = 1; 151 else 152 dropmtx = 0; 153 154 if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0) 155 acquiremtx = 0; 156 else 157 acquiremtx = 1; 158 159 /* 160 * Be careful here. If we're coming from cdev ioctl, it is OK to 161 * not doing locking AT ALL (except on individual channel) since 162 * we've been heavily guarded by pcm cv, or if we're still 163 * under Giant influence. Since we also have mix_* calls, we cannot 164 * assume such protection and just do the lock as usuall. 165 */ 166 MIXER_SET_UNLOCK(m, dropmtx); 167 MIXER_SET_LOCK(d, acquiremtx); 168 169 if (CHN_EMPTY(d, channels.pcm.busy)) { 170 CHN_FOREACH(c, d, channels.pcm) { 171 CHN_LOCK(c); 172 if (c->direction == PCMDIR_PLAY && 173 (c->feederflags & (1 << FEEDER_VOLUME))) 174 chn_setvolume(c, left, right); 175 CHN_UNLOCK(c); 176 } 177 } else { 178 CHN_FOREACH(c, d, channels.pcm.busy) { 179 CHN_LOCK(c); 180 if (c->direction == PCMDIR_PLAY && 181 (c->feederflags & (1 << FEEDER_VOLUME))) 182 chn_setvolume(c, left, right); 183 CHN_UNLOCK(c); 184 } 185 } 186 187 MIXER_SET_UNLOCK(d, acquiremtx); 188 MIXER_SET_LOCK(m, dropmtx); 189 190 return (0); 191 } 192 193 static int 194 mixer_set(struct snd_mixer *m, unsigned dev, unsigned lev) 195 { 196 struct snddev_info *d; 197 unsigned l, r, tl, tr; 198 u_int32_t parent = SOUND_MIXER_NONE, child = 0; 199 u_int32_t realdev; 200 int i, dropmtx; 201 202 if (m == NULL || dev >= SOUND_MIXER_NRDEVICES || 203 (0 == (m->devs & (1 << dev)))) 204 return -1; 205 206 l = min((lev & 0x00ff), 100); 207 r = min(((lev & 0xff00) >> 8), 100); 208 realdev = m->realdev[dev]; 209 210 d = device_get_softc(m->dev); 211 if (d == NULL) 212 return -1; 213 214 /* It is safe to drop this mutex due to Giant. */ 215 if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0) 216 dropmtx = 1; 217 else 218 dropmtx = 0; 219 220 MIXER_SET_UNLOCK(m, dropmtx); 221 222 /* TODO: recursive handling */ 223 parent = m->parent[dev]; 224 if (parent >= SOUND_MIXER_NRDEVICES) 225 parent = SOUND_MIXER_NONE; 226 if (parent == SOUND_MIXER_NONE) 227 child = m->child[dev]; 228 229 if (parent != SOUND_MIXER_NONE) { 230 tl = (l * (m->level[parent] & 0x00ff)) / 100; 231 tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100; 232 if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL)) 233 (void)mixer_set_softpcmvol(m, d, tl, tr); 234 else if (realdev != SOUND_MIXER_NONE && 235 MIXER_SET(m, realdev, tl, tr) < 0) { 236 MIXER_SET_LOCK(m, dropmtx); 237 return -1; 238 } 239 } else if (child != 0) { 240 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 241 if (!(child & (1 << i)) || m->parent[i] != dev) 242 continue; 243 realdev = m->realdev[i]; 244 tl = (l * (m->level[i] & 0x00ff)) / 100; 245 tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100; 246 if (i == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL)) 247 (void)mixer_set_softpcmvol(m, d, tl, tr); 248 else if (realdev != SOUND_MIXER_NONE) 249 MIXER_SET(m, realdev, tl, tr); 250 } 251 realdev = m->realdev[dev]; 252 if (realdev != SOUND_MIXER_NONE && 253 MIXER_SET(m, realdev, l, r) < 0) { 254 MIXER_SET_LOCK(m, dropmtx); 255 return -1; 256 } 257 } else { 258 if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL)) 259 (void)mixer_set_softpcmvol(m, d, l, r); 260 else if (realdev != SOUND_MIXER_NONE && 261 MIXER_SET(m, realdev, l, r) < 0) { 262 MIXER_SET_LOCK(m, dropmtx); 263 return -1; 264 } 265 } 266 267 m->level[dev] = l | (r << 8); 268 269 MIXER_SET_LOCK(m, dropmtx); 270 271 return 0; 272 } 273 274 static int 275 mixer_get(struct snd_mixer *mixer, int dev) 276 { 277 if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) 278 return mixer->level[dev]; 279 else 280 return -1; 281 } 282 283 static int 284 mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src) 285 { 286 struct snddev_info *d; 287 int dropmtx; 288 289 d = device_get_softc(mixer->dev); 290 if (d == NULL) 291 return -1; 292 if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0) 293 dropmtx = 1; 294 else 295 dropmtx = 0; 296 src &= mixer->recdevs; 297 if (src == 0) 298 src = SOUND_MASK_MIC; 299 /* It is safe to drop this mutex due to Giant. */ 300 MIXER_SET_UNLOCK(mixer, dropmtx); 301 mixer->recsrc = MIXER_SETRECSRC(mixer, src); 302 MIXER_SET_LOCK(mixer, dropmtx); 303 return 0; 304 } 305 306 static int 307 mixer_getrecsrc(struct snd_mixer *mixer) 308 { 309 return mixer->recsrc; 310 } 311 312 /** 313 * @brief Retrieve the route number of the current recording device 314 * 315 * OSSv4 assigns routing numbers to recording devices, unlike the previous 316 * API which relied on a fixed table of device numbers and names. This 317 * function returns the routing number of the device currently selected 318 * for recording. 319 * 320 * For now, this function is kind of a goofy compatibility stub atop the 321 * existing sound system. (For example, in theory, the old sound system 322 * allows multiple recording devices to be specified via a bitmask.) 323 * 324 * @param m mixer context container thing 325 * 326 * @retval 0 success 327 * @retval EIDRM no recording device found (generally not possible) 328 * @todo Ask about error code 329 */ 330 static int 331 mixer_get_recroute(struct snd_mixer *m, int *route) 332 { 333 int i, cnt; 334 335 cnt = 0; 336 337 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 338 /** @todo can user set a multi-device mask? (== or &?) */ 339 if ((1 << i) == m->recsrc) 340 break; 341 if ((1 << i) & m->recdevs) 342 ++cnt; 343 } 344 345 if (i == SOUND_MIXER_NRDEVICES) 346 return EIDRM; 347 348 *route = cnt; 349 return 0; 350 } 351 352 /** 353 * @brief Select a device for recording 354 * 355 * This function sets a recording source based on a recording device's 356 * routing number. Said number is translated to an old school recdev 357 * mask and passed over mixer_setrecsrc. 358 * 359 * @param m mixer context container thing 360 * 361 * @retval 0 success(?) 362 * @retval EINVAL User specified an invalid device number 363 * @retval otherwise error from mixer_setrecsrc 364 */ 365 static int 366 mixer_set_recroute(struct snd_mixer *m, int route) 367 { 368 int i, cnt, ret; 369 370 ret = 0; 371 cnt = 0; 372 373 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 374 if ((1 << i) & m->recdevs) { 375 if (route == cnt) 376 break; 377 ++cnt; 378 } 379 } 380 381 if (i == SOUND_MIXER_NRDEVICES) 382 ret = EINVAL; 383 else 384 ret = mixer_setrecsrc(m, (1 << i)); 385 386 return ret; 387 } 388 389 void 390 mix_setdevs(struct snd_mixer *m, u_int32_t v) 391 { 392 struct snddev_info *d; 393 int i; 394 395 if (m == NULL) 396 return; 397 398 d = device_get_softc(m->dev); 399 if (d != NULL && (d->flags & SD_F_SOFTPCMVOL)) 400 v |= SOUND_MASK_PCM; 401 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 402 if (m->parent[i] < SOUND_MIXER_NRDEVICES) 403 v |= 1 << m->parent[i]; 404 v |= m->child[i]; 405 } 406 m->devs = v; 407 } 408 409 /** 410 * @brief Record mask of available recording devices 411 * 412 * Calling functions are responsible for defining the mask of available 413 * recording devices. This function records that value in a structure 414 * used by the rest of the mixer code. 415 * 416 * This function also populates a structure used by the SNDCTL_DSP_*RECSRC* 417 * family of ioctls that are part of OSSV4. All recording device labels 418 * are concatenated in ascending order corresponding to their routing 419 * numbers. (Ex: a system might have 0 => 'vol', 1 => 'cd', 2 => 'line', 420 * etc.) For now, these labels are just the standard recording device 421 * names (cd, line1, etc.), but will eventually be fully dynamic and user 422 * controlled. 423 * 424 * @param m mixer device context container thing 425 * @param v mask of recording devices 426 */ 427 void 428 mix_setrecdevs(struct snd_mixer *m, u_int32_t v) 429 { 430 oss_mixer_enuminfo *ei; 431 char *loc; 432 int i, nvalues, nwrote, nleft, ncopied; 433 434 ei = &m->enuminfo; 435 436 nvalues = 0; 437 nwrote = 0; 438 nleft = sizeof(ei->strings); 439 loc = ei->strings; 440 441 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 442 if ((1 << i) & v) { 443 ei->strindex[nvalues] = nwrote; 444 ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1; 445 /* strlcpy retval doesn't include terminator */ 446 447 nwrote += ncopied; 448 nleft -= ncopied; 449 nvalues++; 450 451 /* 452 * XXX I don't think this should ever be possible. 453 * Even with a move to dynamic device/channel names, 454 * each label is limited to ~16 characters, so that'd 455 * take a LOT to fill this buffer. 456 */ 457 if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) { 458 device_printf(m->dev, 459 "mix_setrecdevs: Not enough room to store device names--please file a bug report.\n"); 460 device_printf(m->dev, 461 "mix_setrecdevs: Please include details about your sound hardware, OS version, etc.\n"); 462 break; 463 } 464 465 loc = &ei->strings[nwrote]; 466 } 467 } 468 469 /* 470 * NB: The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev 471 * and ctrl fields. 472 */ 473 ei->nvalues = nvalues; 474 m->recdevs = v; 475 } 476 477 void 478 mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs) 479 { 480 u_int32_t mask = 0; 481 int i; 482 483 if (m == NULL || parent >= SOUND_MIXER_NRDEVICES) 484 return; 485 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 486 if (i == parent) 487 continue; 488 if (childs & (1 << i)) { 489 mask |= 1 << i; 490 if (m->parent[i] < SOUND_MIXER_NRDEVICES) 491 m->child[m->parent[i]] &= ~(1 << i); 492 m->parent[i] = parent; 493 m->child[i] = 0; 494 } 495 } 496 mask &= ~(1 << parent); 497 m->child[parent] = mask; 498 } 499 500 void 501 mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev) 502 { 503 if (m == NULL || dev >= SOUND_MIXER_NRDEVICES || 504 !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES)) 505 return; 506 m->realdev[dev] = realdev; 507 } 508 509 u_int32_t 510 mix_getparent(struct snd_mixer *m, u_int32_t dev) 511 { 512 if (m == NULL || dev >= SOUND_MIXER_NRDEVICES) 513 return SOUND_MIXER_NONE; 514 return m->parent[dev]; 515 } 516 517 u_int32_t 518 mix_getchild(struct snd_mixer *m, u_int32_t dev) 519 { 520 if (m == NULL || dev >= SOUND_MIXER_NRDEVICES) 521 return 0; 522 return m->child[dev]; 523 } 524 525 u_int32_t 526 mix_getdevs(struct snd_mixer *m) 527 { 528 return m->devs; 529 } 530 531 u_int32_t 532 mix_getrecdevs(struct snd_mixer *m) 533 { 534 return m->recdevs; 535 } 536 537 void * 538 mix_getdevinfo(struct snd_mixer *m) 539 { 540 return m->devinfo; 541 } 542 543 static struct snd_mixer * 544 mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo, 545 int type, const char *desc) 546 { 547 struct snd_mixer *m; 548 int i; 549 550 KASSERT(dev != NULL && cls != NULL && devinfo != NULL, 551 ("%s(): NULL data dev=%p cls=%p devinfo=%p", 552 __func__, dev, cls, devinfo)); 553 KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY, 554 ("invalid mixer type=%d", type)); 555 556 m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO); 557 snprintf(m->name, sizeof(m->name), "%s:mixer", 558 device_get_nameunit(dev)); 559 if (desc != NULL) { 560 strlcat(m->name, ":", sizeof(m->name)); 561 strlcat(m->name, desc, sizeof(m->name)); 562 } 563 m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ? 564 "primary pcm mixer" : "secondary pcm mixer"); 565 m->type = type; 566 m->devinfo = devinfo; 567 m->busy = 0; 568 m->dev = dev; 569 for (i = 0; i < (sizeof(m->parent) / sizeof(m->parent[0])); i++) { 570 m->parent[i] = SOUND_MIXER_NONE; 571 m->child[i] = 0; 572 m->realdev[i] = i; 573 } 574 575 if (MIXER_INIT(m)) { 576 snd_mtxlock(m->lock); 577 snd_mtxfree(m->lock); 578 kobj_delete((kobj_t)m, M_MIXER); 579 return (NULL); 580 } 581 582 return (m); 583 } 584 585 int 586 mixer_delete(struct snd_mixer *m) 587 { 588 KASSERT(m != NULL, ("NULL snd_mixer")); 589 KASSERT(m->type == MIXER_TYPE_SECONDARY, 590 ("%s(): illegal mixer type=%d", __func__, m->type)); 591 592 /* mixer uninit can sleep --hps */ 593 594 MIXER_UNINIT(m); 595 596 snd_mtxfree(m->lock); 597 kobj_delete((kobj_t)m, M_MIXER); 598 599 --mixer_count; 600 601 return (0); 602 } 603 604 struct snd_mixer * 605 mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc) 606 { 607 struct snd_mixer *m; 608 609 m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc); 610 611 if (m != NULL) 612 ++mixer_count; 613 614 return (m); 615 } 616 617 int 618 mixer_init(device_t dev, kobj_class_t cls, void *devinfo) 619 { 620 struct snddev_info *snddev; 621 struct snd_mixer *m; 622 u_int16_t v; 623 struct cdev *pdev; 624 int i, unit, devunit, val; 625 626 m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL); 627 if (m == NULL) 628 return (-1); 629 630 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 631 v = snd_mixerdefaults[i]; 632 633 if (resource_int_value(device_get_name(dev), 634 device_get_unit(dev), snd_mixernames[i], &val) == 0) { 635 if (val >= 0 && val <= 100) { 636 v = (u_int16_t) val; 637 } 638 } 639 640 mixer_set(m, i, v | (v << 8)); 641 } 642 643 mixer_setrecsrc(m, SOUND_MASK_MIC); 644 645 unit = device_get_unit(dev); 646 devunit = snd_mkunit(unit, SND_DEV_CTL, 0); 647 pdev = make_dev(&mixer_cdevsw, devunit, 648 UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit); 649 pdev->si_drv1 = m; 650 snddev = device_get_softc(dev); 651 snddev->mixer_dev = pdev; 652 653 ++mixer_count; 654 655 if (bootverbose) { 656 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 657 if (!(m->devs & (1 << i))) 658 continue; 659 if (m->realdev[i] != i) { 660 device_printf(dev, "Mixer \"%s\" -> \"%s\":", 661 snd_mixernames[i], 662 (m->realdev[i] < SOUND_MIXER_NRDEVICES) ? 663 snd_mixernames[m->realdev[i]] : "none"); 664 } else { 665 device_printf(dev, "Mixer \"%s\":", 666 snd_mixernames[i]); 667 } 668 if (m->parent[i] < SOUND_MIXER_NRDEVICES) 669 printf(" parent=\"%s\"", 670 snd_mixernames[m->parent[i]]); 671 if (m->child[i] != 0) 672 printf(" child=0x%08x", m->child[i]); 673 printf("\n"); 674 } 675 if (snddev->flags & SD_F_SOFTPCMVOL) 676 device_printf(dev, "Soft PCM mixer ENABLED\n"); 677 } 678 679 return (0); 680 } 681 682 int 683 mixer_uninit(device_t dev) 684 { 685 int i; 686 struct snddev_info *d; 687 struct snd_mixer *m; 688 struct cdev *pdev; 689 690 d = device_get_softc(dev); 691 pdev = mixer_get_devt(dev); 692 if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL) 693 return EBADF; 694 695 m = pdev->si_drv1; 696 KASSERT(m != NULL, ("NULL snd_mixer")); 697 KASSERT(m->type == MIXER_TYPE_PRIMARY, 698 ("%s(): illegal mixer type=%d", __func__, m->type)); 699 700 snd_mtxlock(m->lock); 701 702 if (m->busy) { 703 snd_mtxunlock(m->lock); 704 return EBUSY; 705 } 706 707 /* destroy dev can sleep --hps */ 708 709 snd_mtxunlock(m->lock); 710 711 pdev->si_drv1 = NULL; 712 destroy_dev(pdev); 713 714 snd_mtxlock(m->lock); 715 716 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 717 mixer_set(m, i, 0); 718 719 mixer_setrecsrc(m, SOUND_MASK_MIC); 720 721 snd_mtxunlock(m->lock); 722 723 /* mixer uninit can sleep --hps */ 724 725 MIXER_UNINIT(m); 726 727 snd_mtxfree(m->lock); 728 kobj_delete((kobj_t)m, M_MIXER); 729 730 d->mixer_dev = NULL; 731 732 --mixer_count; 733 734 return 0; 735 } 736 737 int 738 mixer_reinit(device_t dev) 739 { 740 struct snd_mixer *m; 741 struct cdev *pdev; 742 int i; 743 744 pdev = mixer_get_devt(dev); 745 m = pdev->si_drv1; 746 snd_mtxlock(m->lock); 747 748 i = MIXER_REINIT(m); 749 if (i) { 750 snd_mtxunlock(m->lock); 751 return i; 752 } 753 754 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 755 mixer_set(m, i, m->level[i]); 756 757 mixer_setrecsrc(m, m->recsrc); 758 snd_mtxunlock(m->lock); 759 760 return 0; 761 } 762 763 #ifdef SND_DYNSYSCTL 764 static int 765 sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) 766 { 767 char devname[32]; 768 int error, dev; 769 struct snd_mixer *m; 770 771 m = oidp->oid_arg1; 772 snd_mtxlock(m->lock); 773 strlcpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname)); 774 snd_mtxunlock(m->lock); 775 error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req); 776 snd_mtxlock(m->lock); 777 if (error == 0 && req->newptr != NULL) { 778 dev = mixer_lookup(devname); 779 if (dev == -1) { 780 snd_mtxunlock(m->lock); 781 return EINVAL; 782 } 783 else if (dev != m->hwvol_mixer) { 784 m->hwvol_mixer = dev; 785 m->hwvol_muted = 0; 786 } 787 } 788 snd_mtxunlock(m->lock); 789 return error; 790 } 791 #endif 792 793 int 794 mixer_hwvol_init(device_t dev) 795 { 796 struct snd_mixer *m; 797 struct cdev *pdev; 798 799 pdev = mixer_get_devt(dev); 800 m = pdev->si_drv1; 801 802 m->hwvol_mixer = SOUND_MIXER_VOLUME; 803 m->hwvol_step = 5; 804 #ifdef SND_DYNSYSCTL 805 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 806 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 807 OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, ""); 808 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 809 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 810 OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0, 811 sysctl_hw_snd_hwvol_mixer, "A", ""); 812 #endif 813 return 0; 814 } 815 816 void 817 mixer_hwvol_mute(device_t dev) 818 { 819 struct snd_mixer *m; 820 struct cdev *pdev; 821 822 pdev = mixer_get_devt(dev); 823 m = pdev->si_drv1; 824 snd_mtxlock(m->lock); 825 if (m->hwvol_muted) { 826 m->hwvol_muted = 0; 827 mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level); 828 } else { 829 m->hwvol_muted++; 830 m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer); 831 mixer_set(m, m->hwvol_mixer, 0); 832 } 833 snd_mtxunlock(m->lock); 834 } 835 836 void 837 mixer_hwvol_step(device_t dev, int left_step, int right_step) 838 { 839 struct snd_mixer *m; 840 int level, left, right; 841 struct cdev *pdev; 842 843 pdev = mixer_get_devt(dev); 844 m = pdev->si_drv1; 845 snd_mtxlock(m->lock); 846 if (m->hwvol_muted) { 847 m->hwvol_muted = 0; 848 level = m->hwvol_mute_level; 849 } else 850 level = mixer_get(m, m->hwvol_mixer); 851 if (level != -1) { 852 left = level & 0xff; 853 right = level >> 8; 854 left += left_step * m->hwvol_step; 855 if (left < 0) 856 left = 0; 857 right += right_step * m->hwvol_step; 858 if (right < 0) 859 right = 0; 860 mixer_set(m, m->hwvol_mixer, left | right << 8); 861 } 862 snd_mtxunlock(m->lock); 863 } 864 865 int 866 mixer_busy(struct snd_mixer *m) 867 { 868 KASSERT(m != NULL, ("NULL snd_mixer")); 869 870 return (m->busy); 871 } 872 873 int 874 mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right) 875 { 876 int ret; 877 878 KASSERT(m != NULL, ("NULL snd_mixer")); 879 880 snd_mtxlock(m->lock); 881 ret = mixer_set(m, dev, left | (right << 8)); 882 snd_mtxunlock(m->lock); 883 884 return ((ret != 0) ? ENXIO : 0); 885 } 886 887 int 888 mix_get(struct snd_mixer *m, u_int dev) 889 { 890 int ret; 891 892 KASSERT(m != NULL, ("NULL snd_mixer")); 893 894 snd_mtxlock(m->lock); 895 ret = mixer_get(m, dev); 896 snd_mtxunlock(m->lock); 897 898 return (ret); 899 } 900 901 int 902 mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 903 { 904 int ret; 905 906 KASSERT(m != NULL, ("NULL snd_mixer")); 907 908 snd_mtxlock(m->lock); 909 ret = mixer_setrecsrc(m, src); 910 snd_mtxunlock(m->lock); 911 912 return ((ret != 0) ? ENXIO : 0); 913 } 914 915 u_int32_t 916 mix_getrecsrc(struct snd_mixer *m) 917 { 918 u_int32_t ret; 919 920 KASSERT(m != NULL, ("NULL snd_mixer")); 921 922 snd_mtxlock(m->lock); 923 ret = mixer_getrecsrc(m); 924 snd_mtxunlock(m->lock); 925 926 return (ret); 927 } 928 929 int 930 mix_get_type(struct snd_mixer *m) 931 { 932 KASSERT(m != NULL, ("NULL snd_mixer")); 933 934 return (m->type); 935 } 936 937 /* ----------------------------------------------------------------------- */ 938 939 static int 940 mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td) 941 { 942 struct snddev_info *d; 943 struct snd_mixer *m; 944 945 946 if (i_dev == NULL || i_dev->si_drv1 == NULL) 947 return (EBADF); 948 949 m = i_dev->si_drv1; 950 d = device_get_softc(m->dev); 951 if (!PCM_REGISTERED(d)) 952 return (EBADF); 953 954 /* XXX Need Giant magic entry ??? */ 955 956 snd_mtxlock(m->lock); 957 m->busy = 1; 958 snd_mtxunlock(m->lock); 959 960 return (0); 961 } 962 963 static int 964 mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td) 965 { 966 struct snddev_info *d; 967 struct snd_mixer *m; 968 int ret; 969 970 if (i_dev == NULL || i_dev->si_drv1 == NULL) 971 return (EBADF); 972 973 m = i_dev->si_drv1; 974 d = device_get_softc(m->dev); 975 if (!PCM_REGISTERED(d)) 976 return (EBADF); 977 978 /* XXX Need Giant magic entry ??? */ 979 980 snd_mtxlock(m->lock); 981 ret = (m->busy == 0) ? EBADF : 0; 982 m->busy = 0; 983 snd_mtxunlock(m->lock); 984 985 return (ret); 986 } 987 988 static int 989 mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 990 struct thread *td) 991 { 992 struct snddev_info *d; 993 int ret; 994 995 if (i_dev == NULL || i_dev->si_drv1 == NULL) 996 return (EBADF); 997 998 d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev); 999 if (!PCM_REGISTERED(d)) 1000 return (EBADF); 1001 1002 PCM_GIANT_ENTER(d); 1003 PCM_ACQUIRE_QUICK(d); 1004 1005 ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td, MIXER_CMD_CDEV); 1006 1007 PCM_RELEASE_QUICK(d); 1008 PCM_GIANT_LEAVE(d); 1009 1010 return (ret); 1011 } 1012 1013 /* 1014 * XXX Make sure you can guarantee concurrency safety before calling this 1015 * function, be it through Giant, PCM_CV_*, etc ! 1016 */ 1017 int 1018 mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 1019 struct thread *td, int from) 1020 { 1021 struct snd_mixer *m; 1022 int ret, *arg_i = (int *)arg; 1023 int v = -1, j = cmd & 0xff; 1024 1025 m = i_dev->si_drv1; 1026 1027 if (m == NULL) 1028 return (EBADF); 1029 1030 snd_mtxlock(m->lock); 1031 if (from == MIXER_CMD_CDEV && !m->busy) { 1032 snd_mtxunlock(m->lock); 1033 return (EBADF); 1034 } 1035 1036 if (cmd == SNDCTL_MIXERINFO) { 1037 snd_mtxunlock(m->lock); 1038 return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg)); 1039 } 1040 1041 if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { 1042 if (j == SOUND_MIXER_RECSRC) 1043 ret = mixer_setrecsrc(m, *arg_i); 1044 else 1045 ret = mixer_set(m, j, *arg_i); 1046 snd_mtxunlock(m->lock); 1047 return ((ret == 0) ? 0 : ENXIO); 1048 } 1049 1050 if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) { 1051 switch (j) { 1052 case SOUND_MIXER_DEVMASK: 1053 case SOUND_MIXER_CAPS: 1054 case SOUND_MIXER_STEREODEVS: 1055 v = mix_getdevs(m); 1056 break; 1057 1058 case SOUND_MIXER_RECMASK: 1059 v = mix_getrecdevs(m); 1060 break; 1061 1062 case SOUND_MIXER_RECSRC: 1063 v = mixer_getrecsrc(m); 1064 break; 1065 1066 default: 1067 v = mixer_get(m, j); 1068 } 1069 *arg_i = v; 1070 snd_mtxunlock(m->lock); 1071 return ((v != -1) ? 0 : ENXIO); 1072 } 1073 1074 ret = 0; 1075 1076 switch (cmd) { 1077 /** @todo Double check return values, error codes. */ 1078 case SNDCTL_SYSINFO: 1079 snd_mtxunlock(m->lock); 1080 sound_oss_sysinfo((oss_sysinfo *)arg); 1081 return (ret); 1082 break; 1083 case SNDCTL_AUDIOINFO: 1084 snd_mtxunlock(m->lock); 1085 return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg)); 1086 break; 1087 case SNDCTL_DSP_GET_RECSRC_NAMES: 1088 bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo)); 1089 break; 1090 case SNDCTL_DSP_GET_RECSRC: 1091 ret = mixer_get_recroute(m, arg_i); 1092 break; 1093 case SNDCTL_DSP_SET_RECSRC: 1094 ret = mixer_set_recroute(m, *arg_i); 1095 break; 1096 case OSS_GETVERSION: 1097 *arg_i = SOUND_VERSION; 1098 break; 1099 default: 1100 ret = ENXIO; 1101 break; 1102 } 1103 1104 snd_mtxunlock(m->lock); 1105 1106 return (ret); 1107 } 1108 1109 #ifdef USING_DEVFS 1110 static void 1111 mixer_clone(void *arg, 1112 #if __FreeBSD_version >= 600034 1113 struct ucred *cred, 1114 #endif 1115 char *name, int namelen, struct cdev **dev) 1116 { 1117 struct snddev_info *d; 1118 1119 if (*dev != NULL) 1120 return; 1121 if (strcmp(name, "mixer") == 0) { 1122 d = devclass_get_softc(pcm_devclass, snd_unit); 1123 if (PCM_REGISTERED(d) && d->mixer_dev != NULL) { 1124 *dev = d->mixer_dev; 1125 dev_ref(*dev); 1126 } 1127 } 1128 } 1129 1130 static void 1131 mixer_sysinit(void *p) 1132 { 1133 if (mixer_ehtag != NULL) 1134 return; 1135 mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000); 1136 } 1137 1138 static void 1139 mixer_sysuninit(void *p) 1140 { 1141 if (mixer_ehtag == NULL) 1142 return; 1143 EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag); 1144 mixer_ehtag = NULL; 1145 } 1146 1147 SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL); 1148 SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL); 1149 #endif 1150 1151 /** 1152 * @brief Handler for SNDCTL_MIXERINFO 1153 * 1154 * This function searches for a mixer based on the numeric ID stored 1155 * in oss_miserinfo::dev. If set to -1, then information about the 1156 * current mixer handling the request is provided. Note, however, that 1157 * this ioctl may be made with any sound device (audio, mixer, midi). 1158 * 1159 * @note Caller must not hold any PCM device, channel, or mixer locks. 1160 * 1161 * See http://manuals.opensound.com/developer/SNDCTL_MIXERINFO.html for 1162 * more information. 1163 * 1164 * @param i_dev character device on which the ioctl arrived 1165 * @param arg user argument (oss_mixerinfo *) 1166 * 1167 * @retval EINVAL oss_mixerinfo::dev specified a bad value 1168 * @retval 0 success 1169 */ 1170 int 1171 mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi) 1172 { 1173 struct snddev_info *d; 1174 struct snd_mixer *m; 1175 int nmix, i; 1176 1177 /* 1178 * If probing the device handling the ioctl, make sure it's a mixer 1179 * device. (This ioctl is valid on audio, mixer, and midi devices.) 1180 */ 1181 if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw) 1182 return (EINVAL); 1183 1184 d = NULL; 1185 m = NULL; 1186 nmix = 0; 1187 1188 /* 1189 * There's a 1:1 relationship between mixers and PCM devices, so 1190 * begin by iterating over PCM devices and search for our mixer. 1191 */ 1192 for (i = 0; pcm_devclass != NULL && 1193 i < devclass_get_maxunit(pcm_devclass); i++) { 1194 d = devclass_get_softc(pcm_devclass, i); 1195 if (!PCM_REGISTERED(d)) 1196 continue; 1197 1198 /* XXX Need Giant magic entry */ 1199 1200 /* See the note in function docblock. */ 1201 mtx_assert(d->lock, MA_NOTOWNED); 1202 pcm_lock(d); 1203 1204 if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL && 1205 ((mi->dev == -1 && d->mixer_dev == i_dev) || 1206 mi->dev == nmix)) { 1207 m = d->mixer_dev->si_drv1; 1208 mtx_lock(m->lock); 1209 1210 /* 1211 * At this point, the following synchronization stuff 1212 * has happened: 1213 * - a specific PCM device is locked. 1214 * - a specific mixer device has been locked, so be 1215 * sure to unlock when existing. 1216 */ 1217 bzero((void *)mi, sizeof(*mi)); 1218 mi->dev = nmix; 1219 snprintf(mi->id, sizeof(mi->id), "mixer%d", i); 1220 strlcpy(mi->name, m->name, sizeof(mi->name)); 1221 mi->modify_counter = m->modify_counter; 1222 mi->card_number = i; 1223 /* 1224 * Currently, FreeBSD assumes 1:1 relationship between 1225 * a pcm and mixer devices, so this is hardcoded to 0. 1226 */ 1227 mi->port_number = 0; 1228 1229 /** 1230 * @todo Fill in @sa oss_mixerinfo::mixerhandle. 1231 * @note From 4Front: "mixerhandle is an arbitrary 1232 * string that identifies the mixer better than 1233 * the device number (mixerinfo.dev). Device 1234 * numbers may change depending on the order the 1235 * drivers are loaded. However the handle should 1236 * remain the same provided that the sound card 1237 * is not moved to another PCI slot." 1238 */ 1239 1240 /** 1241 * @note 1242 * @sa oss_mixerinfo::magic is a reserved field. 1243 * 1244 * @par 1245 * From 4Front: "magic is usually 0. However some 1246 * devices may have dedicated setup utilities and the 1247 * magic field may contain an unique driver specific 1248 * value (managed by [4Front])." 1249 */ 1250 1251 mi->enabled = device_is_attached(m->dev) ? 1 : 0; 1252 /** 1253 * The only flag for @sa oss_mixerinfo::caps is 1254 * currently MIXER_CAP_VIRTUAL, which I'm not sure we 1255 * really worry about. 1256 */ 1257 /** 1258 * Mixer extensions currently aren't supported, so 1259 * leave @sa oss_mixerinfo::nrext blank for now. 1260 */ 1261 /** 1262 * @todo Fill in @sa oss_mixerinfo::priority (requires 1263 * touching drivers?) 1264 * @note The priority field is for mixer applets to 1265 * determine which mixer should be the default, with 0 1266 * being least preferred and 10 being most preferred. 1267 * From 4Front: "OSS drivers like ICH use higher 1268 * values (10) because such chips are known to be used 1269 * only on motherboards. Drivers for high end pro 1270 * devices use 0 because they will never be the 1271 * default mixer. Other devices use values 1 to 9 1272 * depending on the estimated probability of being the 1273 * default device. 1274 * 1275 * XXX Described by Hannu@4Front, but not found in 1276 * soundcard.h. 1277 strlcpy(mi->devnode, d->mixer_dev->si_name, 1278 sizeof(mi->devnode)); 1279 mi->legacy_device = i; 1280 */ 1281 mtx_unlock(m->lock); 1282 } else 1283 ++nmix; 1284 1285 pcm_unlock(d); 1286 1287 if (m != NULL) 1288 return (0); 1289 } 1290 1291 return (EINVAL); 1292 } 1293 1294 /* 1295 * Allow the sound driver to use the mixer lock to protect its mixer 1296 * data: 1297 */ 1298 struct mtx * 1299 mixer_get_lock(struct snd_mixer *m) 1300 { 1301 if (m->lock == NULL) { 1302 return (&Giant); 1303 } 1304 return (m->lock); 1305 } 1306