1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Sun audio(7I) and mixer(7I) personality. 28 * 29 * There are some "undocumented" details of how legacy Sun audio 30 * interfaces work. The following "rules" were derived from reading the 31 * legacy Sun mixer code, and to the best of our knowledge are not 32 * documented elsewhere. 33 * 34 * - We create a "fake" audio device, which behaves like a classic 35 * exclusive audio device, for each PID, as determined during open(2). 36 * 37 * - Different processes don't interfere with each other. Even though 38 * they are running concurrently, they each think they have exclusive 39 * control over the audio device. 40 * 41 * - Read and write directions operate independent of each other. That 42 * is, a device open for reading won't intefere with a future open for 43 * writing, and vice versa. This is true even within the same process. 44 * 45 * - Because the virtualization is by PID, strange behavior may occur 46 * if a process tries to open an audio device at the same time it 47 * has already received a file descriptor from another process (such 48 * through inheritence via fork()). 49 * 50 * - The "fake" audio device has no control over physical settings. 51 * It sees only the software attenuation-based volumes for play and 52 * record, and has no support for alternate input or output ports or 53 * access to the monitoring features of the hardware. 54 * 55 * - Explicit notificaton signals (SIGPOLL) are only ever sent up the 56 * audioctl node -- never up a regular audio node. (The stream head 57 * may still issue SIGPOLL based on readability/writability of 58 * course.) 59 * 60 * - Corollary: processes that want asynch. notifications will open 61 * /dev/audioctl as well as /dev/audio. 62 * 63 * - We don't support the MIXER mode at all. 64 * 65 * - By corollary, a process is only allowed to open /dev/audio once 66 * (in each direction.) 67 * 68 * - Attempts to open /dev/audio in duplex mode (O_RDWR) fail (EBUSY) 69 * if the device cannot support duplex operation. 70 * 71 * - Attempts to open a device with FREAD set fail if the device is not 72 * capable of recording. (Likewise for FWRITE and playback.) 73 * 74 * - No data transfer is permitted for audioctl nodes. (No actual 75 * record or play.) 76 * 77 * - Sun audio does not support any formats other than linear and 78 * ULAW/ALAW. I.e. it will never support AC3 or other "opaque" 79 * streams which require special handling. 80 * 81 * - Sun audio only supports stereo or monophonic data streams. 82 */ 83 84 #include <sys/types.h> 85 #include <sys/open.h> 86 #include <sys/errno.h> 87 #include <sys/audio.h> 88 #include <sys/mixer.h> 89 #include <sys/file.h> 90 #include <sys/stropts.h> 91 #include <sys/strsun.h> 92 #include <sys/sysmacros.h> 93 #include <sys/list.h> 94 #include <sys/note.h> 95 #include <sys/stat.h> 96 #include <sys/ddi.h> 97 #include <sys/sunddi.h> 98 #include "audio_client.h" 99 100 typedef struct daclient daclient_t; 101 typedef struct dadev dadev_t; 102 typedef struct daproc daproc_t; 103 104 /* common structure shared between both audioctl and audio nodes */ 105 struct daclient { 106 daproc_t *dc_proc; 107 dadev_t *dc_dev; 108 audio_client_t *dc_client; 109 queue_t *dc_wq; 110 unsigned dc_eof; 111 list_t dc_eofcnt; 112 kmutex_t dc_lock; 113 mblk_t *dc_draining; 114 }; 115 116 struct eofcnt { 117 list_node_t linkage; 118 uint64_t tail; 119 }; 120 121 struct dadev { 122 audio_dev_t *d_dev; 123 124 list_t d_procs; 125 kmutex_t d_mx; 126 kcondvar_t d_cv; 127 }; 128 129 struct daproc { 130 pid_t p_id; 131 struct audio_info p_info; 132 int p_refcnt; 133 int p_oflag; 134 list_node_t p_linkage; 135 dadev_t *p_dev; 136 audio_client_t *p_writer; 137 audio_client_t *p_reader; 138 }; 139 140 int devaudio_proc_hold(audio_client_t *, int); 141 void devaudio_proc_release(audio_client_t *); 142 static void devaudio_proc_update(daproc_t *); 143 144 145 static int 146 devaudio_compose_format(audio_prinfo_t *prinfo) 147 { 148 switch (prinfo->precision) { 149 case 8: 150 switch (prinfo->encoding) { 151 case AUDIO_ENCODING_ULAW: 152 return (AUDIO_FORMAT_ULAW); 153 case AUDIO_ENCODING_ALAW: 154 return (AUDIO_FORMAT_ALAW); 155 case AUDIO_ENCODING_LINEAR8: 156 return (AUDIO_FORMAT_U8); 157 case AUDIO_ENCODING_LINEAR: 158 return (AUDIO_FORMAT_S8); 159 } 160 break; 161 case 16: 162 if (prinfo->encoding == AUDIO_ENCODING_LINEAR) 163 return (AUDIO_FORMAT_S16_NE); 164 break; 165 case 32: 166 if (prinfo->encoding == AUDIO_ENCODING_LINEAR) 167 return (AUDIO_FORMAT_S32_NE); 168 break; 169 } 170 return (AUDIO_FORMAT_NONE); 171 172 } 173 174 static void 175 devaudio_decompose_format(audio_prinfo_t *prinfo, int afmt) 176 { 177 int e, p; 178 179 /* 180 * N.B.: Even though some of the formats below can't be set by 181 * this personality, reporting them (using the closest match) 182 * allows this personality to roughly approximate settings for 183 * other streams. It would be incredibly poor form for any 184 * personality to modify the format settings for a different 185 * personality, so we don't worry about that case. 186 */ 187 188 switch (afmt) { 189 case AUDIO_FORMAT_ULAW: 190 e = AUDIO_ENCODING_ULAW; 191 p = 8; 192 break; 193 194 case AUDIO_FORMAT_ALAW: 195 e = AUDIO_ENCODING_ALAW; 196 p = 8; 197 break; 198 199 case AUDIO_FORMAT_U8: 200 e = AUDIO_ENCODING_LINEAR8; 201 p = 8; 202 break; 203 204 case AUDIO_FORMAT_S8: 205 e = AUDIO_ENCODING_LINEAR; 206 p = 8; 207 break; 208 209 case AUDIO_FORMAT_S16_NE: 210 case AUDIO_FORMAT_S16_OE: 211 case AUDIO_FORMAT_U16_NE: 212 case AUDIO_FORMAT_U16_OE: 213 e = AUDIO_ENCODING_LINEAR; 214 p = 16; 215 break; 216 217 case AUDIO_FORMAT_S24_NE: 218 case AUDIO_FORMAT_S24_OE: 219 case AUDIO_FORMAT_S24_PACKED: 220 e = AUDIO_ENCODING_LINEAR; 221 p = 24; 222 break; 223 224 case AUDIO_FORMAT_S32_NE: 225 case AUDIO_FORMAT_S32_OE: 226 e = AUDIO_ENCODING_LINEAR; 227 p = 32; 228 break; 229 230 default: 231 /* all other formats (e.g. AC3) are uninterpreted */ 232 e = AUDIO_ENCODING_NONE; 233 p = 32; 234 break; 235 } 236 237 prinfo->encoding = e; 238 prinfo->precision = p; 239 } 240 241 static daproc_t * 242 devaudio_proc_alloc(audio_client_t *c) 243 { 244 audio_info_t *info; 245 audio_prinfo_t *prinfo; 246 uint32_t caps; 247 daproc_t *proc; 248 249 if ((proc = kmem_zalloc(sizeof (*proc), KM_NOSLEEP)) == NULL) { 250 return (NULL); 251 } 252 info = &proc->p_info; 253 254 /* 255 * audio(7I) says: Upon the initial open() of the audio 256 * device, the driver resets the data format of the device to 257 * the default state of 8-bit, 8Khz, mono u-Law data. 258 */ 259 prinfo = &info->play; 260 prinfo->channels = 1; 261 prinfo->sample_rate = 8000; 262 prinfo->encoding = AUDIO_ENCODING_ULAW; 263 prinfo->precision = 8; 264 prinfo->gain = AUDIO_MAX_GAIN; 265 prinfo->balance = AUDIO_MID_BALANCE; 266 prinfo->buffer_size = 8192; 267 prinfo->pause = B_FALSE; 268 prinfo->waiting = B_FALSE; 269 prinfo->open = B_FALSE; 270 prinfo->active = B_FALSE; 271 prinfo->samples = 0; 272 prinfo->eof = 0; 273 prinfo->error = 0; 274 prinfo->minordev = 0; 275 prinfo->port = AUDIO_SPEAKER; 276 prinfo->avail_ports = AUDIO_SPEAKER; 277 prinfo->mod_ports = AUDIO_NONE; 278 prinfo->_xxx = 0; 279 280 prinfo = &info->record; 281 prinfo->channels = 1; 282 prinfo->sample_rate = 8000; 283 prinfo->encoding = AUDIO_ENCODING_ULAW; 284 prinfo->precision = 8; 285 prinfo->gain = AUDIO_MAX_GAIN; 286 prinfo->balance = AUDIO_MID_BALANCE; 287 prinfo->buffer_size = 8192; 288 prinfo->waiting = B_FALSE; 289 prinfo->open = B_FALSE; 290 prinfo->active = B_FALSE; 291 prinfo->samples = 0; 292 prinfo->eof = 0; 293 prinfo->error = 0; 294 prinfo->minordev = 0; 295 prinfo->port = AUDIO_MICROPHONE; 296 prinfo->avail_ports = AUDIO_MICROPHONE; 297 prinfo->mod_ports = AUDIO_MICROPHONE; 298 299 info->output_muted = B_FALSE; 300 /* pretend we don't have a software mixer - we don't support the API */ 301 info->hw_features = 0; 302 info->sw_features = 0; 303 info->sw_features_enabled = 0; 304 305 caps = auclnt_get_dev_capab(auclnt_get_dev(c)); 306 if (caps & AUDIO_CLIENT_CAP_PLAY) 307 info->hw_features |= AUDIO_HWFEATURE_PLAY; 308 if (caps & AUDIO_CLIENT_CAP_RECORD) 309 info->hw_features |= AUDIO_HWFEATURE_RECORD; 310 if (caps & AUDIO_CLIENT_CAP_DUPLEX) 311 info->hw_features |= AUDIO_HWFEATURE_DUPLEX; 312 313 return (proc); 314 } 315 316 static void 317 devaudio_proc_free(daproc_t *proc) 318 { 319 kmem_free(proc, sizeof (*proc)); 320 } 321 322 int 323 devaudio_proc_hold(audio_client_t *c, int oflag) 324 { 325 pid_t pid; 326 daproc_t *proc; 327 dadev_t *dev; 328 daclient_t *dc; 329 list_t *l; 330 audio_dev_t *adev; 331 int rv; 332 333 adev = auclnt_get_dev(c); 334 335 /* first allocate and initialize the daclient private data */ 336 if ((dc = kmem_zalloc(sizeof (*dc), KM_NOSLEEP)) == NULL) { 337 return (ENOMEM); 338 } 339 340 mutex_init(&dc->dc_lock, NULL, MUTEX_DRIVER, NULL); 341 list_create(&dc->dc_eofcnt, sizeof (struct eofcnt), 342 offsetof(struct eofcnt, linkage)); 343 auclnt_set_private(c, dc); 344 345 dev = auclnt_get_dev_minor_data(adev, AUDIO_MINOR_DEVAUDIO); 346 l = &dev->d_procs; 347 pid = auclnt_get_pid(c); 348 349 /* set a couple of common fields */ 350 dc->dc_client = c; 351 dc->dc_dev = dev; 352 353 mutex_enter(&dev->d_mx); 354 for (proc = list_head(l); proc != NULL; proc = list_next(l, proc)) { 355 if (proc->p_id == pid) { 356 proc->p_refcnt++; 357 break; 358 } 359 } 360 if (proc == NULL) { 361 if ((proc = devaudio_proc_alloc(c)) == NULL) { 362 rv = ENOMEM; 363 goto failed; 364 } 365 proc->p_refcnt = 1; 366 proc->p_id = pid; 367 proc->p_dev = dev; 368 list_insert_tail(l, proc); 369 } 370 371 while (proc->p_oflag & oflag) { 372 373 if (oflag & (FNDELAY|FNONBLOCK)) { 374 rv = EBUSY; 375 goto failed; 376 } 377 if (oflag & FWRITE) 378 proc->p_info.play.waiting++; 379 if (oflag & FREAD) 380 proc->p_info.record.waiting++; 381 if (cv_wait_sig(&dev->d_cv, &dev->d_mx) == 0) { 382 /* interrupted! */ 383 if (oflag & FWRITE) 384 proc->p_info.play.waiting--; 385 if (oflag & FREAD) 386 proc->p_info.record.waiting--; 387 rv = EINTR; 388 goto failed; 389 } 390 if (oflag & FWRITE) 391 proc->p_info.play.waiting--; 392 if (oflag & FREAD) 393 proc->p_info.record.waiting--; 394 } 395 396 if (oflag & FWRITE) { 397 audio_prinfo_t *play = &proc->p_info.play; 398 audio_stream_t *sp = auclnt_output_stream(c); 399 400 if (((rv = auclnt_set_rate(sp, 8000)) != 0) || 401 ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) || 402 ((rv = auclnt_set_channels(sp, 1)) != 0)) { 403 goto failed; 404 } 405 406 auclnt_set_samples(sp, 0); 407 auclnt_set_errors(sp, 0); 408 play->eof = 0; 409 play->buffer_size = 8192; 410 411 auclnt_set_gain(sp, ((play->gain * 100) / AUDIO_MAX_GAIN)); 412 auclnt_set_muted(sp, proc->p_info.output_muted); 413 play->open = B_TRUE; 414 proc->p_writer = c; 415 proc->p_oflag |= FWRITE; 416 } 417 418 if (oflag & FREAD) { 419 audio_prinfo_t *rec = &proc->p_info.record; 420 audio_stream_t *sp = auclnt_input_stream(c); 421 422 if (((rv = auclnt_set_rate(sp, 8000)) != 0) || 423 ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) || 424 ((rv = auclnt_set_channels(sp, 1)) != 0)) { 425 goto failed; 426 } 427 428 auclnt_set_samples(sp, 0); 429 auclnt_set_errors(sp, 0); 430 rec->eof = 0; 431 rec->buffer_size = 8192; 432 433 auclnt_set_gain(sp, ((rec->gain * 100) / AUDIO_MAX_GAIN)); 434 rec->open = B_TRUE; 435 proc->p_reader = c; 436 proc->p_oflag |= FREAD; 437 } 438 439 440 dc->dc_wq = auclnt_get_wq(c); 441 442 /* we update the s_proc last to avoid a race */ 443 dc->dc_proc = proc; 444 445 devaudio_proc_update(proc); 446 447 mutex_exit(&dev->d_mx); 448 449 return (0); 450 451 failed: 452 mutex_exit(&dev->d_mx); 453 devaudio_proc_release(c); 454 return (rv); 455 456 } 457 458 static void 459 devaudio_clear_eof(audio_client_t *c) 460 { 461 struct eofcnt *eof; 462 daclient_t *dc; 463 464 dc = auclnt_get_private(c); 465 mutex_enter(&dc->dc_lock); 466 while ((eof = list_remove_head(&dc->dc_eofcnt)) != NULL) { 467 kmem_free(eof, sizeof (*eof)); 468 } 469 mutex_exit(&dc->dc_lock); 470 } 471 472 void 473 devaudio_proc_release(audio_client_t *c) 474 { 475 daproc_t *proc; 476 dadev_t *dev; 477 mblk_t *mp; 478 daclient_t *dc; 479 480 dc = auclnt_get_private(c); 481 proc = dc->dc_proc; 482 dev = dc->dc_dev; 483 dc->dc_proc = NULL; 484 485 mutex_enter(&dev->d_mx); 486 487 if (proc != NULL) { 488 proc->p_refcnt--; 489 ASSERT(proc->p_refcnt >= 0); 490 491 if (c == proc->p_writer) { 492 proc->p_oflag &= ~FWRITE; 493 proc->p_writer = NULL; 494 } 495 if (c == proc->p_reader) { 496 proc->p_oflag &= ~FREAD; 497 proc->p_reader = NULL; 498 } 499 cv_broadcast(&dev->d_cv); 500 501 if (proc->p_refcnt == 0) { 502 list_remove(&dev->d_procs, proc); 503 devaudio_proc_free(proc); 504 } 505 dc->dc_proc = NULL; 506 } 507 508 mutex_exit(&dev->d_mx); 509 510 devaudio_clear_eof(c); 511 512 while ((mp = dc->dc_draining) != NULL) { 513 dc->dc_draining = mp->b_next; 514 mp->b_next = NULL; 515 freemsg(mp); 516 } 517 518 mutex_destroy(&dc->dc_lock); 519 list_destroy(&dc->dc_eofcnt); 520 kmem_free(dc, sizeof (*dc)); 521 } 522 523 static void 524 devaudio_input(audio_client_t *c) 525 { 526 audio_stream_t *sp = auclnt_input_stream(c); 527 daclient_t *dc = auclnt_get_private(c); 528 unsigned framesz = auclnt_get_framesz(sp); 529 queue_t *rq = auclnt_get_rq(c); 530 mblk_t *mp; 531 unsigned nbytes = dc->dc_proc->p_info.record.buffer_size; 532 unsigned count = nbytes / framesz; 533 534 /* 535 * Potentially send a message upstream with the record data. 536 * We collect this up in chunks of the buffer size requested 537 * by the client. 538 */ 539 540 while (auclnt_get_count(sp) >= count) { 541 542 if ((!canput(rq)) || 543 ((mp = allocb(nbytes, BPRI_MED)) == NULL)) { 544 /* 545 * This will apply back pressure to the 546 * buffer. We haven't yet lost any data, we 547 * just can't send it up. The point at which 548 * we have an unrecoverable overrun is in the 549 * buffer, not in the streams queue. So, no 550 * need to do anything right now. 551 * 552 * Note that since recording is enabled, we 553 * expect that the callback routine will be 554 * called repeatedly & regularly, so we don't 555 * have to worry about leaving data orphaned 556 * in the queue. 557 */ 558 break; 559 } 560 561 (void) auclnt_consume_data(sp, (caddr_t)mp->b_wptr, count); 562 mp->b_wptr += nbytes; 563 (void) putq(rq, mp); 564 } 565 } 566 567 static void 568 devaudio_proc_update(daproc_t *proc) 569 { 570 audio_info_t *info; 571 audio_stream_t *sp; 572 audio_client_t *c; 573 574 info = &proc->p_info; 575 576 ASSERT(mutex_owned(&proc->p_dev->d_mx)); 577 578 if ((c = proc->p_writer) != NULL) { 579 sp = auclnt_output_stream(c); 580 581 info->play.sample_rate = auclnt_get_rate(sp); 582 info->play.channels = auclnt_get_channels(sp); 583 devaudio_decompose_format(&info->play, auclnt_get_format(sp)); 584 585 info->play.gain = 586 (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100; 587 info->play.pause = auclnt_is_paused(sp); 588 info->play.active = auclnt_is_running(sp); 589 info->play.samples = auclnt_get_samples(sp); 590 info->play.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE; 591 info->output_muted = auclnt_get_muted(sp); 592 } else { 593 info->play.encoding = AUDIO_ENCODING_NONE; 594 info->play.precision = 0; 595 info->play.sample_rate = 0; 596 info->play.pause = B_FALSE; 597 info->play.active = B_FALSE; 598 info->play.error = B_FALSE; 599 info->play.samples = 0; 600 } 601 602 if ((c = proc->p_reader) != NULL) { 603 sp = auclnt_input_stream(c); 604 605 info->record.sample_rate = auclnt_get_rate(sp); 606 info->record.channels = auclnt_get_channels(sp); 607 devaudio_decompose_format(&info->record, auclnt_get_format(sp)); 608 609 info->record.gain = 610 (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100; 611 info->record.pause = auclnt_is_paused(sp); 612 info->record.active = auclnt_is_running(sp); 613 info->record.samples = auclnt_get_samples(sp); 614 info->record.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE; 615 } else { 616 info->record.encoding = AUDIO_ENCODING_NONE; 617 info->record.precision = 0; 618 info->record.sample_rate = 0; 619 info->record.pause = B_FALSE; 620 info->record.active = B_FALSE; 621 info->record.error = B_FALSE; 622 info->record.samples = 0; 623 } 624 } 625 626 static void 627 devaudio_ioc_getinfo(queue_t *wq, audio_client_t *c, mblk_t *mp) 628 { 629 daclient_t *dc = auclnt_get_private(c); 630 daproc_t *proc = dc->dc_proc; 631 mblk_t *bcont; 632 633 if ((bcont = allocb(sizeof (audio_info_t), BPRI_MED)) == NULL) { 634 miocnak(wq, mp, 0, ENOMEM); 635 return; 636 } 637 638 mutex_enter(&dc->dc_dev->d_mx); 639 devaudio_proc_update(proc); 640 bcopy(&proc->p_info, bcont->b_wptr, sizeof (audio_info_t)); 641 mutex_exit(&dc->dc_dev->d_mx); 642 643 bcont->b_wptr += sizeof (audio_info_t); 644 645 mcopyout(mp, NULL, sizeof (audio_info_t), NULL, bcont); 646 qreply(wq, mp); 647 } 648 649 #define CHANGED(new, old, field) \ 650 ((new->field != ((uint32_t)~0)) && (new->field != old->field)) 651 #define CHANGED8(new, old, field) \ 652 ((new->field != ((uint8_t)~0)) && (new->field != old->field)) 653 654 static void 655 devaudio_ioc_setinfo(queue_t *wq, audio_client_t *c, mblk_t *mp) 656 { 657 daclient_t *dc; 658 daproc_t *proc; 659 audio_info_t *oinfo; 660 audio_info_t *ninfo; 661 audio_prinfo_t *npr; 662 audio_prinfo_t *opr; 663 664 int pfmt = AUDIO_FORMAT_NONE; 665 int rfmt = AUDIO_FORMAT_NONE; 666 667 boolean_t reader; 668 boolean_t writer; 669 boolean_t isctl; 670 audio_stream_t *sp; 671 int rv; 672 caddr_t uaddr; 673 mblk_t *bcont; 674 675 struct copyresp *csp; 676 677 if (DB_TYPE(mp) == M_IOCTL) { 678 /* the special value "1" indicates that this is a copyin */ 679 uaddr = *(caddr_t *)(void *)mp->b_cont->b_rptr; 680 681 mcopyin(mp, uaddr, sizeof (audio_info_t), NULL); 682 qreply(wq, mp); 683 return; 684 } 685 686 ASSERT(DB_TYPE(mp) == M_IOCDATA); 687 if (((bcont = mp->b_cont) == NULL) || 688 (MBLKL(mp->b_cont) != sizeof (audio_info_t))) { 689 miocnak(wq, mp, 0, EINVAL); 690 return; 691 } 692 693 mp->b_cont = NULL; 694 csp = (void *)mp->b_rptr; 695 uaddr = (void *)csp->cp_private; 696 dc = auclnt_get_private(c); 697 ninfo = (void *)bcont->b_rptr; 698 699 mutex_enter(&dc->dc_dev->d_mx); 700 701 proc = dc->dc_proc; 702 oinfo = &proc->p_info; 703 704 if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) { 705 /* control node can do both read and write fields */ 706 isctl = B_TRUE; 707 reader = B_TRUE; 708 writer = B_TRUE; 709 } else { 710 isctl = B_FALSE; 711 writer = (c == proc->p_writer); 712 reader = (c == proc->p_reader); 713 } 714 715 /* 716 * Start by validating settings. 717 */ 718 npr = &ninfo->play; 719 opr = &oinfo->play; 720 721 if (writer && CHANGED(npr, opr, sample_rate)) { 722 if ((isctl) || 723 (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) { 724 rv = EINVAL; 725 goto err; 726 } 727 } 728 if (writer && CHANGED(npr, opr, channels)) { 729 if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) { 730 rv = EINVAL; 731 goto err; 732 } 733 } 734 if (writer && 735 (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) { 736 if (npr->encoding == (uint32_t)~0) 737 npr->encoding = opr->encoding; 738 if (npr->precision == (uint32_t)~0) 739 npr->precision = opr->precision; 740 pfmt = devaudio_compose_format(npr); 741 if ((isctl) || (pfmt == AUDIO_FORMAT_NONE)) { 742 rv = EINVAL; 743 goto err; 744 } 745 } 746 747 /* play fields that anyone can modify */ 748 if (CHANGED(npr, opr, gain)) { 749 if (npr->gain > AUDIO_MAX_GAIN) { 750 rv = EINVAL; 751 goto err; 752 } 753 } 754 755 756 npr = &ninfo->record; 757 opr = &oinfo->record; 758 759 if (reader && CHANGED(npr, opr, sample_rate)) { 760 if ((isctl) || 761 (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) { 762 rv = EINVAL; 763 goto err; 764 } 765 } 766 if (reader && CHANGED(npr, opr, channels)) { 767 if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) { 768 rv = EINVAL; 769 goto err; 770 } 771 } 772 if (reader && 773 (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) { 774 if (npr->encoding == (uint32_t)~0) 775 npr->encoding = opr->encoding; 776 if (npr->precision == (uint32_t)~0) 777 npr->precision = opr->precision; 778 rfmt = devaudio_compose_format(npr); 779 if ((isctl) || (rfmt == AUDIO_FORMAT_NONE)) { 780 rv = EINVAL; 781 goto err; 782 } 783 } 784 if (reader && CHANGED(npr, opr, buffer_size)) { 785 if (isctl) { 786 rv = EINVAL; 787 goto err; 788 } 789 /* make sure we can support 16-bit stereo samples */ 790 if ((npr->buffer_size % 4) != 0) { 791 npr->buffer_size = (npr->buffer_size + 3) & ~3; 792 } 793 /* limit the maximum buffer size somewhat */ 794 if (npr->buffer_size > 16384) { 795 npr->buffer_size = 16384; 796 } 797 } 798 799 /* record fields that anyone can modify */ 800 if (CHANGED(npr, opr, gain)) { 801 if (npr->gain > AUDIO_MAX_GAIN) { 802 rv = EINVAL; 803 goto err; 804 } 805 } 806 807 /* 808 * Now apply the changes. 809 */ 810 if (proc->p_writer != NULL) { 811 sp = auclnt_output_stream(proc->p_writer); 812 npr = &ninfo->play; 813 opr = &oinfo->play; 814 815 if (CHANGED(npr, opr, sample_rate)) { 816 if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0) 817 goto err; 818 } 819 if (CHANGED(npr, opr, channels)) { 820 if ((rv = auclnt_set_channels(sp, npr->channels)) != 0) 821 goto err; 822 } 823 if (pfmt != AUDIO_FORMAT_NONE) { 824 if ((rv = auclnt_set_format(sp, pfmt)) != 0) 825 goto err; 826 } 827 if (CHANGED(npr, opr, samples)) { 828 auclnt_set_samples(sp, npr->samples); 829 } 830 if (CHANGED(npr, opr, eof)) { 831 /* 832 * This ugly special case code is required to 833 * prevent problems with realaudio. 834 */ 835 if (npr->eof == 0) { 836 devaudio_clear_eof(proc->p_writer); 837 } 838 opr->eof = npr->eof; 839 } 840 if (CHANGED8(npr, opr, pause)) { 841 if (npr->pause) { 842 auclnt_set_paused(sp); 843 } else { 844 auclnt_clear_paused(sp); 845 846 /* qenable to start up the playback */ 847 qenable(auclnt_get_wq(proc->p_writer)); 848 } 849 } 850 if (CHANGED8(npr, opr, waiting) && (npr->waiting)) { 851 opr->waiting = npr->waiting; 852 } 853 if (CHANGED8(npr, opr, error)) { 854 auclnt_set_errors(sp, npr->error); 855 } 856 if (CHANGED(npr, opr, gain)) { 857 auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN); 858 } 859 if (CHANGED8(ninfo, oinfo, output_muted)) { 860 auclnt_set_muted(sp, ninfo->output_muted); 861 } 862 if (CHANGED(npr, opr, buffer_size)) { 863 /* 864 * No checks on the buffer size are performed 865 * for play side. The value of the buffer size 866 * is meaningless for play side anyway. 867 */ 868 opr->buffer_size = npr->buffer_size; 869 } 870 } else { 871 /* these values are preserved even if /dev/audio not open */ 872 if (CHANGED(npr, opr, gain)) { 873 opr->gain = npr->gain; 874 } 875 if (CHANGED8(ninfo, oinfo, output_muted)) { 876 oinfo->output_muted = ninfo->output_muted; 877 } 878 } 879 880 if (proc->p_reader != NULL) { 881 sp = auclnt_input_stream(proc->p_reader); 882 npr = &ninfo->record; 883 opr = &oinfo->record; 884 885 if (CHANGED(npr, opr, sample_rate)) { 886 if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0) 887 goto err; 888 } 889 if (CHANGED(npr, opr, channels)) { 890 if ((rv = auclnt_set_channels(sp, npr->channels)) != 0) 891 goto err; 892 } 893 if (rfmt != AUDIO_FORMAT_NONE) { 894 if ((rv = auclnt_set_format(sp, rfmt)) != 0) 895 goto err; 896 } 897 if (CHANGED(npr, opr, samples)) { 898 auclnt_set_samples(sp, npr->samples); 899 } 900 if (CHANGED(npr, opr, eof)) { 901 opr->eof = npr->eof; 902 } 903 if (CHANGED8(npr, opr, pause)) { 904 if (npr->pause) { 905 auclnt_set_paused(sp); 906 } else { 907 auclnt_clear_paused(sp); 908 auclnt_start(sp); 909 } 910 } 911 if (CHANGED8(npr, opr, waiting) && (npr->waiting)) { 912 opr->waiting = npr->waiting; 913 } 914 if (CHANGED8(npr, opr, error)) { 915 auclnt_set_errors(sp, npr->error); 916 } 917 if (CHANGED(npr, opr, buffer_size)) { 918 opr->buffer_size = npr->buffer_size; 919 } 920 if (CHANGED(npr, opr, gain)) { 921 auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN); 922 } 923 } else { 924 /* these values are preserved even if /dev/audio not open */ 925 if (CHANGED(npr, opr, gain)) { 926 opr->gain = npr->gain; 927 } 928 } 929 930 devaudio_proc_update(dc->dc_proc); 931 bcopy(&dc->dc_proc->p_info, ninfo, sizeof (*ninfo)); 932 933 mutex_exit(&dc->dc_dev->d_mx); 934 mcopyout(mp, NULL, sizeof (audio_info_t), uaddr, bcont); 935 qreply(wq, mp); 936 return; 937 938 err: 939 mutex_exit(&dc->dc_dev->d_mx); 940 miocnak(wq, mp, 0, rv); 941 } 942 943 static void 944 devaudio_ioc_getdev(queue_t *wq, audio_client_t *c, mblk_t *mp) 945 { 946 audio_dev_t *d = auclnt_get_dev(c); 947 mblk_t *bcont; 948 audio_device_t *a; 949 950 if ((bcont = allocb(sizeof (*a), BPRI_MED)) == NULL) { 951 miocnak(wq, mp, 0, ENOMEM); 952 return; 953 } 954 955 a = (void *)bcont->b_wptr; 956 (void) snprintf(a->name, sizeof (a->name), 957 "SUNW,%s", auclnt_get_dev_name(d)); 958 (void) strlcpy(a->config, 959 auclnt_get_dev_description(d), sizeof (a->config)); 960 (void) strlcpy(a->version, 961 auclnt_get_dev_version(d), sizeof (a->version)); 962 bcont->b_wptr += sizeof (*a); 963 964 mcopyout(mp, NULL, sizeof (*a), NULL, bcont); 965 qreply(wq, mp); 966 } 967 968 static int 969 devaudio_sigpoll(audio_client_t *c, void *arg) 970 { 971 pid_t pid = (pid_t)(uintptr_t)arg; 972 973 if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) { 974 /* we only need to notify peers in our own process */ 975 if (auclnt_get_pid(c) == pid) { 976 (void) putctl1(auclnt_get_rq(c), M_PCSIG, SIGPOLL); 977 } 978 } 979 return (AUDIO_WALK_CONTINUE); 980 } 981 982 static void 983 devaudio_drain(audio_client_t *c) 984 { 985 daclient_t *dc = auclnt_get_private(c); 986 mblk_t *mplist, *mp; 987 988 mutex_enter(&dc->dc_lock); 989 mplist = dc->dc_draining; 990 dc->dc_draining = NULL; 991 mutex_exit(&dc->dc_lock); 992 993 while ((mp = mplist) != NULL) { 994 mplist = mp->b_next; 995 mp->b_next = NULL; 996 mioc2ack(mp, NULL, 0, 0); 997 (void) putq(auclnt_get_rq(c), mp); 998 } 999 } 1000 1001 static void 1002 devaudio_output(audio_client_t *c) 1003 { 1004 daclient_t *dc = auclnt_get_private(c); 1005 daproc_t *proc = dc->dc_proc; 1006 uint64_t tail; 1007 struct eofcnt *eof; 1008 int eofs = 0; 1009 1010 tail = auclnt_get_tail(auclnt_output_stream(c)); 1011 1012 /* get more data! (do this early) */ 1013 qenable(auclnt_get_wq(c)); 1014 1015 mutex_enter(&dc->dc_lock); 1016 while (((eof = list_head(&dc->dc_eofcnt)) != NULL) && 1017 (eof->tail <= tail)) { 1018 list_remove(&dc->dc_eofcnt, eof); 1019 kmem_free(eof, sizeof (*eof)); 1020 eofs++; 1021 } 1022 proc->p_info.play.eof += eofs; 1023 mutex_exit(&dc->dc_lock); 1024 1025 if (eofs) { 1026 auclnt_dev_walk_clients(auclnt_get_dev(c), 1027 devaudio_sigpoll, (void *)(uintptr_t)auclnt_get_pid(c)); 1028 } 1029 } 1030 1031 static void * 1032 devaudio_init(audio_dev_t *adev) 1033 { 1034 dadev_t *dev; 1035 unsigned cap; 1036 1037 cap = auclnt_get_dev_capab(adev); 1038 /* if not a play or record device, don't bother initializing it */ 1039 if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) { 1040 return (NULL); 1041 } 1042 1043 dev = kmem_zalloc(sizeof (*dev), KM_SLEEP); 1044 dev->d_dev = adev; 1045 mutex_init(&dev->d_mx, NULL, MUTEX_DRIVER, NULL); 1046 cv_init(&dev->d_cv, NULL, CV_DRIVER, NULL); 1047 list_create(&dev->d_procs, sizeof (struct daproc), 1048 offsetof(struct daproc, p_linkage)); 1049 1050 return (dev); 1051 } 1052 1053 static void 1054 devaudio_fini(void *arg) 1055 { 1056 dadev_t *dev = arg; 1057 1058 if (dev != NULL) { 1059 1060 mutex_destroy(&dev->d_mx); 1061 cv_destroy(&dev->d_cv); 1062 list_destroy(&dev->d_procs); 1063 kmem_free(dev, sizeof (*dev)); 1064 } 1065 } 1066 1067 static int 1068 devaudio_open(audio_client_t *c, int oflag) 1069 { 1070 int rv; 1071 1072 if ((rv = auclnt_open(c, AUDIO_FORMAT_PCM, oflag)) != 0) { 1073 return (rv); 1074 } 1075 1076 if ((rv = devaudio_proc_hold(c, oflag)) != 0) { 1077 auclnt_close(c); 1078 return (rv); 1079 } 1080 1081 /* start up the input */ 1082 if (oflag & FREAD) { 1083 auclnt_start(auclnt_input_stream(c)); 1084 } 1085 1086 return (0); 1087 } 1088 1089 static int 1090 devaudioctl_open(audio_client_t *c, int oflag) 1091 { 1092 int rv; 1093 1094 _NOTE(ARGUNUSED(oflag)); 1095 1096 oflag &= ~(FWRITE | FREAD); 1097 1098 if ((rv = auclnt_open(c, AUDIO_FORMAT_NONE, 0)) != 0) { 1099 return (rv); 1100 } 1101 1102 if ((rv = devaudio_proc_hold(c, oflag)) != 0) { 1103 auclnt_close(c); 1104 return (rv); 1105 } 1106 1107 return (0); 1108 } 1109 1110 static void 1111 devaudio_close(audio_client_t *c) 1112 { 1113 auclnt_stop(auclnt_output_stream(c)); 1114 auclnt_stop(auclnt_input_stream(c)); 1115 1116 auclnt_close(c); 1117 devaudio_proc_release(c); 1118 } 1119 1120 static void 1121 devaudioctl_close(audio_client_t *c) 1122 { 1123 auclnt_close(c); 1124 devaudio_proc_release(c); 1125 } 1126 1127 static void 1128 devaudio_miocdata(audio_client_t *c, mblk_t *mp) 1129 { 1130 struct copyresp *csp; 1131 queue_t *wq; 1132 1133 csp = (void *)mp->b_rptr; 1134 wq = auclnt_get_wq(c); 1135 1136 /* 1137 * If a transfer error occurred, the framework already 1138 * MIOCNAK'd it. 1139 */ 1140 if (csp->cp_rval != 0) { 1141 freemsg(mp); 1142 return; 1143 } 1144 1145 /* 1146 * If no state, then this is a response to M_COPYOUT, and we 1147 * are done. (Audio ioctls just copyout a single structure at 1148 * completion of work.) 1149 */ 1150 if (csp->cp_private == NULL) { 1151 miocack(wq, mp, 0, 0); 1152 return; 1153 } 1154 1155 /* now, call the handler ioctl */ 1156 switch (csp->cp_cmd) { 1157 case AUDIO_SETINFO: 1158 devaudio_ioc_setinfo(wq, c, mp); 1159 break; 1160 default: 1161 miocnak(wq, mp, 0, EINVAL); 1162 break; 1163 } 1164 } 1165 1166 static void 1167 devaudio_mioctl(audio_client_t *c, mblk_t *mp) 1168 { 1169 struct iocblk *iocp = (void *)mp->b_rptr; 1170 queue_t *wq = auclnt_get_wq(c); 1171 1172 /* BSD legacy here: we only support transparent ioctls */ 1173 if (iocp->ioc_count != TRANSPARENT) { 1174 miocnak(wq, mp, 0, EINVAL); 1175 return; 1176 } 1177 1178 switch (iocp->ioc_cmd) { 1179 case AUDIO_GETINFO: 1180 devaudio_ioc_getinfo(wq, c, mp); 1181 break; 1182 1183 case AUDIO_SETINFO: 1184 devaudio_ioc_setinfo(wq, c, mp); 1185 break; 1186 1187 case AUDIO_GETDEV: 1188 devaudio_ioc_getdev(wq, c, mp); 1189 break; 1190 1191 case AUDIO_DIAG_LOOPBACK: 1192 /* we don't support this one */ 1193 miocnak(wq, mp, 0, ENOTTY); 1194 break; 1195 1196 case AUDIO_MIXERCTL_GET_MODE: 1197 case AUDIO_MIXERCTL_SET_MODE: 1198 case AUDIO_MIXERCTL_GET_CHINFO: 1199 case AUDIO_MIXERCTL_SET_CHINFO: 1200 case AUDIO_MIXERCTL_GETINFO: 1201 case AUDIO_MIXERCTL_SETINFO: 1202 case AUDIO_GET_NUM_CHS: 1203 case AUDIO_GET_CH_NUMBER: 1204 case AUDIO_GET_CH_TYPE: 1205 case AUDIO_MIXER_SINGLE_OPEN: 1206 case AUDIO_MIXER_MULTIPLE_OPEN: 1207 case AUDIO_MIXER_GET_SAMPLE_RATES: 1208 default: 1209 miocnak(wq, mp, 0, EINVAL); 1210 break; 1211 } 1212 } 1213 1214 static void 1215 devaudioctl_wput(audio_client_t *c, mblk_t *mp) 1216 { 1217 queue_t *wq = auclnt_get_wq(c); 1218 1219 switch (DB_TYPE(mp)) { 1220 case M_IOCTL: 1221 /* Drain ioctl needs to be handled on the service queue */ 1222 devaudio_mioctl(c, mp); 1223 break; 1224 1225 case M_IOCDATA: 1226 devaudio_miocdata(c, mp); 1227 break; 1228 1229 case M_FLUSH: 1230 /* 1231 * We don't flush the engine. The reason is that 1232 * other streams might be using the engine. This is 1233 * fundamentally no different from the case where the 1234 * engine hardware has data buffered in an 1235 * inaccessible FIFO. 1236 * 1237 * Clients that want to ensure no more data is coming 1238 * should stop the stream before flushing. 1239 */ 1240 if (*mp->b_rptr & FLUSHW) { 1241 *mp->b_rptr &= ~FLUSHW; 1242 } 1243 if (*mp->b_rptr & FLUSHR) { 1244 qreply(wq, mp); 1245 } else { 1246 freemsg(mp); 1247 } 1248 break; 1249 1250 case M_DATA: 1251 /* 1252 * No audio data on control nodes! 1253 */ 1254 freemsg(mp); 1255 1256 default: 1257 freemsg(mp); 1258 break; 1259 } 1260 } 1261 1262 static void 1263 devaudio_wput(audio_client_t *c, mblk_t *mp) 1264 { 1265 queue_t *wq = auclnt_get_wq(c); 1266 1267 switch (DB_TYPE(mp)) { 1268 case M_IOCTL: 1269 /* Drain ioctl needs to be handled on the service queue */ 1270 if (*(int *)(void *)mp->b_rptr == AUDIO_DRAIN) { 1271 (void) putq(wq, mp); 1272 } else { 1273 devaudio_mioctl(c, mp); 1274 } 1275 break; 1276 1277 case M_IOCDATA: 1278 devaudio_miocdata(c, mp); 1279 break; 1280 1281 case M_FLUSH: 1282 /* 1283 * We don't flush the engine. The reason is that 1284 * other streams might be using the engine. This is 1285 * fundamentally no different from the case where the 1286 * engine hardware has data buffered in an 1287 * inaccessible FIFO. 1288 * 1289 * Clients that want to ensure no more data is coming 1290 * should stop the stream before flushing. 1291 */ 1292 if (*mp->b_rptr & FLUSHW) { 1293 flushq(wq, FLUSHALL); 1294 auclnt_flush(auclnt_output_stream(c)); 1295 *mp->b_rptr &= ~FLUSHW; 1296 } 1297 if (*mp->b_rptr & FLUSHR) { 1298 flushq(RD(wq), FLUSHALL); 1299 auclnt_flush(auclnt_input_stream(c)); 1300 qreply(wq, mp); 1301 } else { 1302 freemsg(mp); 1303 } 1304 break; 1305 1306 case M_DATA: 1307 /* 1308 * Defer processing to the queue. This keeps the data 1309 * ordered, and allows the wsrv routine to gather 1310 * multiple mblks at once. 1311 */ 1312 if (mp->b_cont != NULL) { 1313 1314 /* 1315 * If we need to pullup, do it here to 1316 * simplify the rest of the processing later. 1317 * This should rarely (if ever) be necessary. 1318 */ 1319 mblk_t *nmp; 1320 1321 if ((nmp = msgpullup(mp, -1)) == NULL) { 1322 freemsg(mp); 1323 } else { 1324 freemsg(mp); 1325 (void) putq(wq, nmp); 1326 } 1327 } else { 1328 (void) putq(wq, mp); 1329 } 1330 break; 1331 1332 default: 1333 freemsg(mp); 1334 break; 1335 } 1336 } 1337 1338 static void 1339 devaudio_rsrv(audio_client_t *c) 1340 { 1341 queue_t *rq = auclnt_get_rq(c); 1342 mblk_t *mp; 1343 1344 while ((mp = getq(rq)) != NULL) { 1345 1346 if ((queclass(mp) != QPCTL) && (!canputnext(rq))) { 1347 /* 1348 * Put it back in the queue so we can apply 1349 * backpressure properly. 1350 */ 1351 (void) putbq(rq, mp); 1352 return; 1353 } 1354 putnext(rq, mp); 1355 } 1356 } 1357 1358 static void 1359 devaudio_wsrv(audio_client_t *c) 1360 { 1361 queue_t *wq = auclnt_get_wq(c); 1362 daclient_t *dc = auclnt_get_private(c); 1363 audio_stream_t *sp; 1364 mblk_t *mp; 1365 unsigned framesz; 1366 1367 sp = auclnt_output_stream(c); 1368 1369 framesz = auclnt_get_framesz(sp); 1370 1371 while ((mp = getq(wq)) != NULL) { 1372 1373 unsigned count; 1374 1375 /* got a message */ 1376 1377 /* if its a drain ioctl, we need to process it here */ 1378 if (DB_TYPE(mp) == M_IOCTL) { 1379 ASSERT((*(int *)(void *)mp->b_rptr) == AUDIO_DRAIN); 1380 mutex_enter(&dc->dc_lock); 1381 mp->b_next = dc->dc_draining; 1382 dc->dc_draining = mp; 1383 mutex_exit(&dc->dc_lock); 1384 1385 if (auclnt_start_drain(c) != 0) { 1386 devaudio_drain(c); 1387 } 1388 continue; 1389 } 1390 1391 ASSERT(DB_TYPE(mp) == M_DATA); 1392 1393 /* 1394 * Empty mblk require special handling, since they 1395 * indicate EOF. We treat them separate from the main 1396 * processing loop. 1397 */ 1398 if (MBLKL(mp) == 0) { 1399 struct eofcnt *eof; 1400 1401 eof = kmem_zalloc(sizeof (*eof), KM_NOSLEEP); 1402 if (eof != NULL) { 1403 eof->tail = auclnt_get_head(sp); 1404 mutex_enter(&dc->dc_lock); 1405 list_insert_tail(&dc->dc_eofcnt, eof); 1406 mutex_exit(&dc->dc_lock); 1407 } 1408 freemsg(mp); 1409 continue; 1410 } 1411 1412 count = auclnt_produce_data(sp, (caddr_t)mp->b_rptr, 1413 MBLKL(mp) / framesz); 1414 1415 mp->b_rptr += count * framesz; 1416 1417 if (MBLKL(mp) >= framesz) { 1418 (void) putbq(wq, mp); 1419 break; 1420 } else { 1421 freemsg(mp); 1422 } 1423 } 1424 1425 /* if the stream isn't running yet, start it up */ 1426 if (!auclnt_is_paused(sp)) 1427 auclnt_start(sp); 1428 } 1429 1430 static struct audio_client_ops devaudio_ops = { 1431 "sound,audio", 1432 devaudio_init, 1433 devaudio_fini, 1434 devaudio_open, 1435 devaudio_close, 1436 NULL, /* read */ 1437 NULL, /* write */ 1438 NULL, /* ioctl */ 1439 NULL, /* chpoll */ 1440 NULL, /* mmap */ 1441 devaudio_input, 1442 devaudio_output, 1443 devaudio_drain, 1444 devaudio_wput, 1445 devaudio_wsrv, 1446 devaudio_rsrv 1447 }; 1448 1449 static struct audio_client_ops devaudioctl_ops = { 1450 "sound,audioctl", 1451 NULL, /* dev_init */ 1452 NULL, /* dev_fini */ 1453 devaudioctl_open, 1454 devaudioctl_close, 1455 NULL, /* read */ 1456 NULL, /* write */ 1457 NULL, /* ioctl */ 1458 NULL, /* chpoll */ 1459 NULL, /* mmap */ 1460 NULL, /* output */ 1461 NULL, /* input */ 1462 NULL, /* drain */ 1463 devaudioctl_wput, 1464 NULL, 1465 devaudio_rsrv 1466 }; 1467 1468 void 1469 auimpl_sun_init(void) 1470 { 1471 auclnt_register_ops(AUDIO_MINOR_DEVAUDIO, &devaudio_ops); 1472 auclnt_register_ops(AUDIO_MINOR_DEVAUDIOCTL, &devaudioctl_ops); 1473 } 1474