1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2012-2022 Hans Petter Selasky 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/queue.h> 29 #include <sys/types.h> 30 #include <sys/filio.h> 31 #include <sys/linker.h> 32 #include <sys/rtprio.h> 33 #include <sys/nv.h> 34 #include <sys/sndstat.h> 35 #include <sys/soundcard.h> 36 #include <sys/sysctl.h> 37 38 #include <dlfcn.h> 39 #include <errno.h> 40 #include <grp.h> 41 #include <stdio.h> 42 #include <stdint.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <unistd.h> 46 #include <err.h> 47 #include <sysexits.h> 48 #include <signal.h> 49 #include <fcntl.h> 50 #include <paths.h> 51 52 #include <cuse.h> 53 #include <pthread.h> 54 55 #include "backend.h" 56 #include "int.h" 57 #include "virtual_oss.h" 58 59 #define SYSCTL_BASECLONE "hw.snd.basename_clone" 60 61 pthread_mutex_t atomic_mtx; 62 pthread_cond_t atomic_cv; 63 64 static void 65 atomic_init(void) 66 { 67 if (pthread_mutex_init(&atomic_mtx, NULL) != 0) 68 err(1, "pthread_mutex_init"); 69 if (pthread_cond_init(&atomic_cv, NULL) != 0) 70 err(1, "pthread_cond_init"); 71 } 72 73 uint32_t 74 vclient_sample_bytes(vclient_t *pvc) 75 { 76 uint32_t fmt = pvc->format; 77 78 if (fmt & AFMT_16BIT) 79 return (2); 80 else if (fmt & AFMT_24BIT) 81 return (3); 82 else if (fmt & AFMT_32BIT) 83 return (4); 84 else if (fmt & AFMT_8BIT) 85 return (1); 86 else 87 return (0); 88 /* TODO AFMT_BPS */ 89 } 90 91 static uint32_t 92 vclient_output_delay(vclient_t *pvc) 93 { 94 uint64_t size; 95 uint64_t mod; 96 97 if (pvc->tx_busy == 0) 98 vclient_import_write_locked(pvc); 99 100 mod = pvc->channels * vclient_sample_bytes(pvc); 101 102 size = vring_total_read_len(&pvc->tx_ring[0]); 103 size = (size / 8) * vclient_sample_bytes(pvc); 104 105 size = (size * (uint64_t)pvc->sample_rate) / 106 (uint64_t)voss_dsp_sample_rate; 107 size += vring_total_read_len(&pvc->tx_ring[1]); 108 size -= size % mod; 109 110 return (size); 111 } 112 113 static uint32_t 114 vclient_input_delay(vclient_t *pvc) 115 { 116 if (pvc->rx_busy == 0) 117 vclient_export_read_locked(pvc); 118 return (vring_total_read_len(&pvc->rx_ring[1])); 119 } 120 121 uint32_t 122 vclient_bufsize_scaled(vclient_t *pvc) 123 { 124 uint32_t samples_scaled = ((uint64_t)voss_dsp_samples * 125 (uint64_t)pvc->sample_rate) / (uint64_t)voss_dsp_sample_rate; 126 if (samples_scaled == 0) 127 samples_scaled = 1; 128 return (pvc->channels * samples_scaled * vclient_sample_bytes(pvc)); 129 } 130 131 static uint64_t 132 vclient_bufsize_consumed(vclient_t *pvc, uint64_t ts) 133 { 134 int64_t delta; 135 int64_t samples_scaled; 136 int64_t retval; 137 138 delta = virtual_oss_timestamp() - ts; 139 if (delta < 0) 140 delta = 0; 141 samples_scaled = (delta * (uint64_t)pvc->sample_rate) / 1000000000ULL; 142 if (samples_scaled < 0) 143 samples_scaled = 0; 144 retval = pvc->channels * samples_scaled * vclient_sample_bytes(pvc); 145 if (retval < 0) 146 retval = 0; 147 return (retval); 148 } 149 150 /* 151 * VLC and some other audio player use this value for jitter 152 * computations and expect it to be very accurate. VirtualOSS is block 153 * based and does not have sample accuracy. Use the system clock to 154 * update this value as we go along instead: 155 */ 156 static uint32_t 157 vclient_output_delay_adjusted(vclient_t *pvc) 158 { 159 int64_t retval = vclient_output_delay(pvc) - 160 vclient_bufsize_consumed(pvc, pvc->tx_timestamp); 161 if (retval < 0) 162 retval = 0; 163 return (retval); 164 } 165 166 vmonitor_t * 167 vmonitor_alloc(int *pid, vmonitor_head_t *phead) 168 { 169 int id = 0; 170 vmonitor_t *pvm; 171 172 TAILQ_FOREACH(pvm, phead, entry) 173 id++; 174 175 if (id >= 64) { 176 *pid = 0; 177 return (NULL); 178 } 179 pvm = malloc(sizeof(*pvm)); 180 if (pvm == NULL) { 181 *pid = 0; 182 return (NULL); 183 } 184 memset(pvm, 0, sizeof(*pvm)); 185 186 pvm->mute = 1; 187 188 TAILQ_INSERT_TAIL(phead, pvm, entry); 189 190 *pid = id; 191 return (pvm); 192 } 193 194 int64_t 195 vclient_noise(uint32_t *pnoise, int64_t volume, int8_t shift) 196 { 197 const uint32_t prime = 0xFFFF1DU; 198 int64_t temp; 199 200 /* compute next noise sample */ 201 temp = *pnoise; 202 if (temp & 1) 203 temp += prime; 204 temp /= 2; 205 *pnoise = temp; 206 207 /* unsigned to signed conversion */ 208 temp ^= 0x800000ULL; 209 if (temp & 0x800000U) 210 temp |= -0x800000ULL; 211 212 /* properly amplify */ 213 temp *= volume; 214 215 /* bias shift */ 216 shift -= 23 + VVOLUME_UNIT_SHIFT; 217 218 /* range check and shift noise */ 219 if (__predict_false(shift < -63 || shift > 63)) 220 temp = 0; 221 else if (shift < 0) 222 temp >>= -shift; 223 else 224 temp <<= shift; 225 226 return (temp); 227 } 228 229 static void 230 vresample_free(vresample_t *pvr) 231 { 232 if (pvr->state != NULL) 233 src_delete(pvr->state); 234 free(pvr->data_in); 235 free(pvr->data_out); 236 memset(pvr, 0, sizeof(*pvr)); 237 } 238 239 static int 240 vresample_setup(vclient_t *pvc, vresample_t *pvr, int samples) 241 { 242 int code = 0; 243 244 if (pvr->state != NULL) 245 return (0); 246 pvr->state = src_new(voss_libsamplerate_quality, pvc->channels, &code); 247 if (pvr->state == NULL) 248 goto error; 249 pvr->data_in = malloc(sizeof(float) * samples); 250 if (pvr->data_in == NULL) 251 goto error; 252 pvr->data_out = malloc(sizeof(float) * samples); 253 if (pvr->data_out == NULL) 254 goto error; 255 pvr->data.data_in = pvr->data_in; 256 pvr->data.data_out = pvr->data_out; 257 return (0); 258 error: 259 vresample_free(pvr); 260 return (CUSE_ERR_NO_MEMORY); 261 } 262 263 void 264 vclient_free(vclient_t *pvc) 265 { 266 vresample_free(&pvc->rx_resample); 267 vresample_free(&pvc->tx_resample); 268 269 /* free equalizer */ 270 vclient_eq_free(pvc); 271 272 /* free ring buffers */ 273 vring_free(&pvc->rx_ring[0]); 274 vring_free(&pvc->rx_ring[1]); 275 vring_free(&pvc->tx_ring[0]); 276 vring_free(&pvc->tx_ring[1]); 277 278 free(pvc); 279 } 280 281 vclient_t * 282 vclient_alloc(void) 283 { 284 vclient_t *pvc; 285 286 pvc = malloc(sizeof(*pvc)); 287 if (pvc == NULL) 288 return (NULL); 289 290 memset(pvc, 0, sizeof(*pvc)); 291 292 pvc->rx_noise_rem = 1; 293 pvc->tx_noise_rem = 1; 294 pvc->rx_volume = 1 << VVOLUME_UNIT_SHIFT; 295 pvc->tx_volume = 1 << VVOLUME_UNIT_SHIFT; 296 297 return (pvc); 298 } 299 300 int 301 vclient_get_default_fmt(vprofile_t *pvp, int type) 302 { 303 int retval; 304 305 if (type == VTYPE_WAV_HDR) { 306 switch (pvp->bits) { 307 case 16: 308 retval = AFMT_S16_LE; 309 break; 310 case 24: 311 retval = AFMT_S24_LE; 312 break; 313 case 32: 314 retval = AFMT_S32_LE; 315 break; 316 default: 317 retval = AFMT_S8; 318 break; 319 } 320 } else { 321 switch (pvp->bits) { 322 case 16: 323 retval = AFMT_S16_NE; 324 break; 325 case 24: 326 retval = AFMT_S24_NE; 327 break; 328 case 32: 329 retval = AFMT_S32_NE; 330 break; 331 default: 332 retval = AFMT_S8; 333 break; 334 } 335 } 336 return (retval); 337 } 338 339 int 340 vclient_setup_buffers(vclient_t *pvc, int size, int frags, 341 int channels, int format, int sample_rate) 342 { 343 size_t bufsize_internal; 344 size_t bufsize_min; 345 size_t mod_internal; 346 size_t mod; 347 uint64_t ts; 348 int bufsize; 349 350 /* check we are not busy */ 351 if (pvc->rx_busy || pvc->tx_busy) 352 return (CUSE_ERR_BUSY); 353 354 /* free equalizer */ 355 vclient_eq_free(pvc); 356 357 /* free existing ring buffers */ 358 vring_free(&pvc->rx_ring[0]); 359 vring_free(&pvc->rx_ring[1]); 360 vring_free(&pvc->tx_ring[0]); 361 vring_free(&pvc->tx_ring[1]); 362 363 /* reset resampler */ 364 vresample_free(&pvc->rx_resample); 365 vresample_free(&pvc->tx_resample); 366 367 if (sample_rate > 0) 368 pvc->sample_rate = sample_rate; 369 if (format != 0) 370 pvc->format = format; 371 if (channels > 0) 372 pvc->channels = channels; 373 374 mod = pvc->channels * vclient_sample_bytes(pvc); 375 mod_internal = pvc->channels * 8; 376 377 if (size > 0) { 378 size += mod - 1; 379 size -= size % mod; 380 381 pvc->buffer_size = size; 382 pvc->buffer_size_set = 1; 383 } else if (pvc->buffer_size_set == 0) 384 pvc->buffer_size = vclient_bufsize_scaled(pvc); 385 386 pvc->low_water = pvc->buffer_size; 387 388 if (frags > 0) { 389 pvc->buffer_frags = frags; 390 pvc->buffer_frags_set = 1; 391 } else if (pvc->buffer_frags_set == 0) 392 pvc->buffer_frags = 2; 393 394 /* sanity checks */ 395 if (frags < 0 || size < 0) 396 return (CUSE_ERR_INVALID); 397 if (pvc->format == 0) 398 return (CUSE_ERR_INVALID); 399 if (pvc->buffer_frags <= 0 || pvc->buffer_frags >= 1024) 400 return (CUSE_ERR_INVALID); 401 if (pvc->buffer_size <= 0 || pvc->buffer_size >= (1024 * 1024)) 402 return (CUSE_ERR_INVALID); 403 if ((pvc->buffer_size * pvc->buffer_frags) >= (128 * 1024 * 1024)) 404 return (CUSE_ERR_INVALID); 405 if (pvc->channels <= 0 || pvc->channels > pvc->profile->channels) 406 return (CUSE_ERR_INVALID); 407 408 /* get buffer sizes */ 409 bufsize = pvc->buffer_frags * pvc->buffer_size; 410 bufsize_internal = ((uint64_t)bufsize * (uint64_t)voss_dsp_sample_rate * 8ULL) / 411 ((uint64_t)pvc->sample_rate * (uint64_t)vclient_sample_bytes(pvc)); 412 413 bufsize_min = voss_dsp_samples * pvc->channels * 8; 414 415 /* check for too small buffer size */ 416 if (bufsize_internal < bufsize_min) 417 return (CUSE_ERR_INVALID); 418 419 /* allow for jitter */ 420 bufsize_internal *= 2ULL; 421 422 /* align buffer size */ 423 bufsize_internal += (mod_internal - 1); 424 bufsize_internal -= (bufsize_internal % mod_internal); 425 426 /* allocate new buffers */ 427 if (vring_alloc(&pvc->rx_ring[0], bufsize_internal)) 428 goto err_0; 429 if (vring_alloc(&pvc->rx_ring[1], bufsize)) 430 goto err_1; 431 if (vring_alloc(&pvc->tx_ring[0], bufsize_internal)) 432 goto err_2; 433 if (vring_alloc(&pvc->tx_ring[1], bufsize)) 434 goto err_3; 435 if (vclient_eq_alloc(pvc)) 436 goto err_4; 437 438 ts = virtual_oss_timestamp(); 439 440 pvc->rx_samples = 0; 441 pvc->tx_samples = 0; 442 pvc->tx_timestamp = ts; 443 pvc->rx_timestamp = ts; 444 445 return (0); 446 447 err_4: 448 vring_free(&pvc->tx_ring[1]); 449 err_3: 450 vring_free(&pvc->tx_ring[0]); 451 err_2: 452 vring_free(&pvc->rx_ring[1]); 453 err_1: 454 vring_free(&pvc->rx_ring[0]); 455 err_0: 456 return (CUSE_ERR_NO_MEMORY); 457 } 458 459 static int 460 vclient_open_sub(struct cuse_dev *pdev, int fflags __unused, int type) 461 { 462 vclient_t *pvc; 463 vprofile_t *pvp; 464 int error; 465 466 pvp = cuse_dev_get_priv0(pdev); 467 468 pvc = vclient_alloc(); 469 if (pvc == NULL) 470 return (CUSE_ERR_NO_MEMORY); 471 472 pvc->profile = pvp; 473 474 /* setup buffers */ 475 error = vclient_setup_buffers(pvc, 0, 0, pvp->channels, 476 vclient_get_default_fmt(pvp, type), voss_dsp_sample_rate); 477 if (error != 0) { 478 vclient_free(pvc); 479 return (error); 480 } 481 482 pvc->type = type; 483 484 cuse_dev_set_per_file_handle(pdev, pvc); 485 486 atomic_lock(); 487 /* only allow one synchronization source at a time */ 488 if (pvc->profile->synchronized) { 489 if (voss_has_synchronization != 0) 490 error = CUSE_ERR_BUSY; 491 else 492 voss_has_synchronization++; 493 } 494 if (error == 0) 495 TAILQ_INSERT_TAIL(&pvc->profile->head, pvc, entry); 496 atomic_unlock(); 497 498 return (error); 499 } 500 501 static int 502 vclient_open_wav(struct cuse_dev *pdev, int fflags) 503 { 504 return (vclient_open_sub(pdev, fflags, VTYPE_WAV_HDR)); 505 } 506 507 static int 508 vclient_open_oss(struct cuse_dev *pdev, int fflags) 509 { 510 return (vclient_open_sub(pdev, fflags, VTYPE_OSS_DAT)); 511 } 512 513 static int 514 vclient_close(struct cuse_dev *pdev, int fflags __unused) 515 { 516 vclient_t *pvc; 517 518 pvc = cuse_dev_get_per_file_handle(pdev); 519 if (pvc == NULL) 520 return (CUSE_ERR_INVALID); 521 522 atomic_lock(); 523 if (pvc->profile->synchronized) { 524 voss_has_synchronization--; 525 526 /* wait for virtual_oss_process(), if any */ 527 while (pvc->sync_busy) { 528 pvc->sync_wakeup = 1; 529 atomic_wakeup(); 530 atomic_wait(); 531 } 532 } 533 TAILQ_REMOVE(&pvc->profile->head, pvc, entry); 534 atomic_unlock(); 535 536 vclient_free(pvc); 537 538 return (0); 539 } 540 541 static int 542 vclient_read_silence_locked(vclient_t *pvc) 543 { 544 size_t size; 545 int delta_in; 546 547 delta_in = pvc->profile->rec_delay - pvc->rec_delay; 548 if (delta_in < 1) 549 return (0); 550 551 size = delta_in * pvc->channels * 8; 552 size = vring_write_zero(&pvc->rx_ring[0], size); 553 pvc->rec_delay += size / (pvc->channels * 8); 554 555 delta_in = pvc->profile->rec_delay - pvc->rec_delay; 556 if (delta_in < 1) 557 return (0); 558 559 return (1); 560 } 561 562 static int 563 vclient_generate_wav_header_locked(vclient_t *pvc) 564 { 565 uint8_t *ptr; 566 size_t mod; 567 size_t len; 568 569 vring_get_write(&pvc->rx_ring[1], &ptr, &len); 570 571 mod = pvc->channels * vclient_sample_bytes(pvc); 572 573 if (mod == 0 || len < (44 + mod - 1)) 574 return (CUSE_ERR_INVALID); 575 576 /* align to next sample */ 577 len = 44 + mod - 1; 578 len -= len % mod; 579 580 /* pre-advance write pointer */ 581 vring_inc_write(&pvc->rx_ring[1], len); 582 583 /* clear block */ 584 memset(ptr, 0, len); 585 586 /* fill out data header */ 587 ptr[len - 8] = 'd'; 588 ptr[len - 7] = 'a'; 589 ptr[len - 6] = 't'; 590 ptr[len - 5] = 'a'; 591 592 /* magic for unspecified length */ 593 ptr[len - 4] = 0x00; 594 ptr[len - 3] = 0xF0; 595 ptr[len - 2] = 0xFF; 596 ptr[len - 1] = 0x7F; 597 598 /* fill out header */ 599 *ptr++ = 'R'; 600 *ptr++ = 'I'; 601 *ptr++ = 'F'; 602 *ptr++ = 'F'; 603 604 /* total chunk size - unknown */ 605 606 *ptr++ = 0; 607 *ptr++ = 0; 608 *ptr++ = 0; 609 *ptr++ = 0; 610 611 *ptr++ = 'W'; 612 *ptr++ = 'A'; 613 *ptr++ = 'V'; 614 *ptr++ = 'E'; 615 *ptr++ = 'f'; 616 *ptr++ = 'm'; 617 *ptr++ = 't'; 618 *ptr++ = ' '; 619 620 /* make sure header fits in PCM block */ 621 len -= 28; 622 623 *ptr++ = len; 624 *ptr++ = len >> 8; 625 *ptr++ = len >> 16; 626 *ptr++ = len >> 24; 627 628 /* audioformat = PCM */ 629 630 *ptr++ = 0x01; 631 *ptr++ = 0x00; 632 633 /* number of channels */ 634 635 len = pvc->channels; 636 637 *ptr++ = len; 638 *ptr++ = len >> 8; 639 640 /* sample rate */ 641 642 len = pvc->sample_rate; 643 644 *ptr++ = len; 645 *ptr++ = len >> 8; 646 *ptr++ = len >> 16; 647 *ptr++ = len >> 24; 648 649 /* byte rate */ 650 651 len = pvc->sample_rate * pvc->channels * vclient_sample_bytes(pvc); 652 653 *ptr++ = len; 654 *ptr++ = len >> 8; 655 *ptr++ = len >> 16; 656 *ptr++ = len >> 24; 657 658 /* block align */ 659 660 len = pvc->channels * vclient_sample_bytes(pvc); 661 662 *ptr++ = len; 663 *ptr++ = len >> 8; 664 665 /* bits per sample */ 666 667 len = vclient_sample_bytes(pvc) * 8; 668 669 *ptr++ = len; 670 *ptr++ = len >> 8; 671 672 return (0); 673 } 674 675 int 676 vclient_export_read_locked(vclient_t *pvc) __requires_exclusive(atomic_mtx) 677 { 678 enum { MAX_FRAME = 1024 }; 679 size_t dst_mod; 680 size_t src_mod; 681 int error; 682 683 if (pvc->type == VTYPE_WAV_HDR) { 684 error = vclient_generate_wav_header_locked(pvc); 685 if (error != 0) 686 return (error); 687 /* only write header once */ 688 pvc->type = VTYPE_WAV_DAT; 689 } 690 error = vclient_read_silence_locked(pvc); 691 if (error != 0) 692 return (0); 693 694 dst_mod = pvc->channels * vclient_sample_bytes(pvc); 695 src_mod = pvc->channels * 8; 696 697 if (pvc->sample_rate == (int)voss_dsp_sample_rate) { 698 while (1) { 699 uint8_t *src_ptr; 700 size_t src_len; 701 uint8_t *dst_ptr; 702 size_t dst_len; 703 704 vring_get_read(&pvc->rx_ring[0], &src_ptr, &src_len); 705 vring_get_write(&pvc->rx_ring[1], &dst_ptr, &dst_len); 706 707 src_len /= src_mod; 708 dst_len /= dst_mod; 709 710 /* compare number of samples */ 711 if (dst_len > src_len) 712 dst_len = src_len; 713 else 714 src_len = dst_len; 715 716 if (dst_len == 0) 717 break; 718 719 src_len *= src_mod; 720 dst_len *= dst_mod; 721 722 format_export(pvc->format, 723 (const int64_t *)(uintptr_t)src_ptr, 724 dst_ptr, dst_len); 725 726 vring_inc_read(&pvc->rx_ring[0], src_len); 727 vring_inc_write(&pvc->rx_ring[1], dst_len); 728 } 729 } else { 730 vresample_t *pvr = &pvc->rx_resample; 731 732 if (vresample_setup(pvc, pvr, MAX_FRAME * pvc->channels) != 0) 733 return (CUSE_ERR_NO_MEMORY); 734 735 while (1) { 736 uint8_t *src_ptr; 737 size_t src_len; 738 uint8_t *dst_ptr; 739 size_t dst_len; 740 int64_t temp[MAX_FRAME * pvc->channels]; 741 size_t samples; 742 size_t y; 743 744 vring_get_read(&pvc->rx_ring[0], &src_ptr, &src_len); 745 vring_get_write(&pvc->rx_ring[1], &dst_ptr, &dst_len); 746 747 src_len /= src_mod; 748 dst_len /= dst_mod; 749 750 /* compare number of samples */ 751 if (dst_len > src_len) 752 dst_len = src_len; 753 else 754 src_len = dst_len; 755 756 if (dst_len > MAX_FRAME) 757 dst_len = src_len = MAX_FRAME; 758 759 if (dst_len == 0) 760 break; 761 762 src_len *= src_mod; 763 dst_len *= dst_mod; 764 765 for (y = 0; y != src_len; y += 8) { 766 pvr->data_in[y / 8] = 767 *(int64_t *)(uintptr_t)(src_ptr + y); 768 } 769 770 /* setup parameters for transform */ 771 pvr->data.input_frames = src_len / src_mod; 772 pvr->data.output_frames = dst_len / dst_mod; 773 pvr->data.src_ratio = (float)pvc->sample_rate / (float)voss_dsp_sample_rate; 774 775 pvc->rx_busy = 1; 776 atomic_unlock(); 777 error = src_process(pvr->state, &pvr->data); 778 atomic_lock(); 779 pvc->rx_busy = 0; 780 781 if (error != 0) 782 break; 783 784 src_len = pvr->data.input_frames_used * src_mod; 785 dst_len = pvr->data.output_frames_gen * dst_mod; 786 787 samples = pvr->data.output_frames_gen * pvc->channels; 788 789 for (y = 0; y != samples; y++) 790 temp[y] = pvr->data_out[y]; 791 792 format_export(pvc->format, temp, dst_ptr, dst_len); 793 794 vring_inc_read(&pvc->rx_ring[0], src_len); 795 vring_inc_write(&pvc->rx_ring[1], dst_len); 796 797 /* check if no data was moved */ 798 if (src_len == 0 && dst_len == 0) 799 break; 800 } 801 } 802 if (pvc->sync_busy) 803 atomic_wakeup(); 804 return (0); 805 } 806 807 static int 808 vclient_read(struct cuse_dev *pdev, int fflags, 809 void *peer_ptr, int len) 810 { 811 vclient_t *pvc; 812 813 int error; 814 int retval; 815 816 pvc = cuse_dev_get_per_file_handle(pdev); 817 if (pvc == NULL) 818 return (CUSE_ERR_INVALID); 819 820 atomic_lock(); 821 822 if (pvc->rx_busy) { 823 atomic_unlock(); 824 return (CUSE_ERR_BUSY); 825 } 826 pvc->rx_enabled = 1; 827 828 retval = 0; 829 830 while (len > 0) { 831 uint8_t *buf_ptr; 832 size_t buf_len; 833 834 error = vclient_export_read_locked(pvc); 835 if (error != 0) { 836 retval = error; 837 break; 838 } 839 840 vring_get_read(&pvc->rx_ring[1], &buf_ptr, &buf_len); 841 842 if (buf_len == 0) { 843 /* out of data */ 844 if (fflags & CUSE_FFLAG_NONBLOCK) { 845 if (retval == 0) 846 retval = CUSE_ERR_WOULDBLOCK; 847 break; 848 } 849 pvc->rx_busy = 1; 850 atomic_wait(); 851 pvc->rx_busy = 0; 852 if (cuse_got_peer_signal() == 0) { 853 if (retval == 0) 854 retval = CUSE_ERR_SIGNAL; 855 break; 856 } 857 continue; 858 } 859 if ((int)buf_len > len) 860 buf_len = len; 861 862 pvc->rx_busy = 1; 863 atomic_unlock(); 864 error = cuse_copy_out(buf_ptr, peer_ptr, buf_len); 865 atomic_lock(); 866 pvc->rx_busy = 0; 867 868 if (error != 0) { 869 retval = error; 870 break; 871 } 872 peer_ptr = ((uint8_t *)peer_ptr) + buf_len; 873 retval += buf_len; 874 len -= buf_len; 875 876 vring_inc_read(&pvc->rx_ring[1], buf_len); 877 } 878 atomic_unlock(); 879 880 return (retval); 881 } 882 883 void 884 vclient_import_write_locked(vclient_t *pvc) __requires_exclusive(atomic_mtx) 885 { 886 enum { MAX_FRAME = 1024 }; 887 size_t dst_mod; 888 size_t src_mod; 889 890 dst_mod = pvc->channels * 8; 891 src_mod = pvc->channels * vclient_sample_bytes(pvc); 892 893 if (pvc->sample_rate == (int)voss_dsp_sample_rate) { 894 while (1) { 895 uint8_t *src_ptr; 896 size_t src_len; 897 uint8_t *dst_ptr; 898 size_t dst_len; 899 900 vring_get_read(&pvc->tx_ring[1], &src_ptr, &src_len); 901 vring_get_write(&pvc->tx_ring[0], &dst_ptr, &dst_len); 902 903 src_len /= src_mod; 904 dst_len /= dst_mod; 905 906 /* compare number of samples */ 907 if (dst_len > src_len) 908 dst_len = src_len; 909 else 910 src_len = dst_len; 911 912 if (dst_len == 0) 913 break; 914 915 src_len *= src_mod; 916 dst_len *= dst_mod; 917 918 format_import(pvc->format, src_ptr, src_len, 919 (int64_t *)(uintptr_t)dst_ptr); 920 921 vring_inc_read(&pvc->tx_ring[1], src_len); 922 vring_inc_write(&pvc->tx_ring[0], dst_len); 923 } 924 } else { 925 vresample_t *pvr = &pvc->tx_resample; 926 927 if (vresample_setup(pvc, pvr, MAX_FRAME * pvc->channels) != 0) 928 return; 929 930 while (1) { 931 uint8_t *src_ptr; 932 size_t src_len; 933 uint8_t *dst_ptr; 934 size_t dst_len; 935 int64_t temp[MAX_FRAME * pvc->channels]; 936 size_t samples; 937 size_t y; 938 int error; 939 940 vring_get_read(&pvc->tx_ring[1], &src_ptr, &src_len); 941 vring_get_write(&pvc->tx_ring[0], &dst_ptr, &dst_len); 942 943 src_len /= src_mod; 944 dst_len /= dst_mod; 945 946 /* compare number of samples */ 947 if (dst_len > src_len) 948 dst_len = src_len; 949 else 950 src_len = dst_len; 951 952 if (dst_len > MAX_FRAME) 953 dst_len = src_len = MAX_FRAME; 954 955 if (dst_len == 0) 956 break; 957 958 src_len *= src_mod; 959 dst_len *= dst_mod; 960 961 format_import(pvc->format, src_ptr, src_len, temp); 962 963 src_len /= vclient_sample_bytes(pvc); 964 965 for (y = 0; y != src_len; y++) 966 pvr->data_in[y] = temp[y]; 967 968 src_len *= vclient_sample_bytes(pvc); 969 970 /* setup parameters for transform */ 971 pvr->data.input_frames = src_len / src_mod; 972 pvr->data.output_frames = dst_len / dst_mod; 973 pvr->data.src_ratio = (float)voss_dsp_sample_rate / (float)pvc->sample_rate; 974 975 pvc->tx_busy = 1; 976 atomic_unlock(); 977 error = src_process(pvr->state, &pvr->data); 978 atomic_lock(); 979 pvc->tx_busy = 0; 980 981 if (error != 0) 982 break; 983 984 src_len = pvr->data.input_frames_used * src_mod; 985 dst_len = pvr->data.output_frames_gen * dst_mod; 986 987 samples = pvr->data.output_frames_gen * pvc->channels; 988 989 for (y = 0; y != samples; y++) { 990 ((int64_t *)(uintptr_t)dst_ptr)[y] = 991 pvr->data_out[y]; 992 } 993 994 vring_inc_read(&pvc->tx_ring[1], src_len); 995 vring_inc_write(&pvc->tx_ring[0], dst_len); 996 997 /* check if no data was moved */ 998 if (src_len == 0 && dst_len == 0) 999 break; 1000 } 1001 } 1002 if (pvc->sync_busy) 1003 atomic_wakeup(); 1004 } 1005 1006 static int 1007 vclient_write_oss(struct cuse_dev *pdev, int fflags, 1008 const void *peer_ptr, int len) 1009 { 1010 vclient_t *pvc; 1011 1012 int error; 1013 int retval; 1014 1015 pvc = cuse_dev_get_per_file_handle(pdev); 1016 if (pvc == NULL) 1017 return (CUSE_ERR_INVALID); 1018 1019 retval = 0; 1020 1021 atomic_lock(); 1022 1023 if (pvc->tx_busy) { 1024 atomic_unlock(); 1025 return (CUSE_ERR_BUSY); 1026 } 1027 pvc->tx_enabled = 1; 1028 1029 while (1) { 1030 uint8_t *buf_ptr; 1031 size_t buf_len; 1032 1033 vclient_import_write_locked(pvc); 1034 1035 if (len < 1) 1036 break; 1037 1038 vring_get_write(&pvc->tx_ring[1], &buf_ptr, &buf_len); 1039 1040 if (buf_len == 0) { 1041 /* out of data */ 1042 if (fflags & CUSE_FFLAG_NONBLOCK) { 1043 if (retval == 0) 1044 retval = CUSE_ERR_WOULDBLOCK; 1045 break; 1046 } 1047 pvc->tx_busy = 1; 1048 atomic_wait(); 1049 pvc->tx_busy = 0; 1050 if (cuse_got_peer_signal() == 0) { 1051 if (retval == 0) 1052 retval = CUSE_ERR_SIGNAL; 1053 break; 1054 } 1055 continue; 1056 } 1057 if ((int)buf_len > len) 1058 buf_len = len; 1059 1060 pvc->tx_busy = 1; 1061 atomic_unlock(); 1062 error = cuse_copy_in(peer_ptr, buf_ptr, buf_len); 1063 atomic_lock(); 1064 pvc->tx_busy = 0; 1065 1066 if (error != 0) { 1067 retval = error; 1068 break; 1069 } 1070 peer_ptr = ((const uint8_t *)peer_ptr) + buf_len; 1071 retval += buf_len; 1072 len -= buf_len; 1073 1074 vring_inc_write(&pvc->tx_ring[1], buf_len); 1075 } 1076 atomic_unlock(); 1077 1078 return (retval); 1079 } 1080 1081 static int 1082 vclient_write_wav(struct cuse_dev *pdev __unused, int fflags __unused, 1083 const void *peer_ptr __unused, int len __unused) 1084 { 1085 return (CUSE_ERR_INVALID); 1086 } 1087 1088 static int 1089 vclient_set_channels(vclient_t *pvc, int channels) 1090 { 1091 if (pvc->channels == channels) 1092 return (0); 1093 return (vclient_setup_buffers(pvc, 0, 0, channels, 0, 0)); 1094 } 1095 1096 /* greatest common divisor, Euclid equation */ 1097 static uint64_t 1098 vclient_gcd_64(uint64_t a, uint64_t b) 1099 { 1100 uint64_t an; 1101 uint64_t bn; 1102 1103 while (b != 0) { 1104 an = b; 1105 bn = a % b; 1106 a = an; 1107 b = bn; 1108 } 1109 return (a); 1110 } 1111 1112 static uint64_t 1113 vclient_scale(uint64_t value, uint64_t mul, uint64_t div) 1114 { 1115 uint64_t gcd = vclient_gcd_64(mul, div); 1116 1117 mul /= gcd; 1118 div /= gcd; 1119 1120 return ((value * mul) / div); 1121 } 1122 1123 static int 1124 vclient_ioctl_oss(struct cuse_dev *pdev, int fflags __unused, 1125 unsigned long cmd, void *peer_data) 1126 { 1127 union { 1128 int val; 1129 unsigned long long lval; 1130 oss_sysinfo sysinfo; 1131 oss_card_info card_info; 1132 oss_audioinfo audioinfo; 1133 audio_buf_info buf_info; 1134 oss_count_t oss_count; 1135 count_info oss_count_info; 1136 audio_errinfo errinfo; 1137 oss_label_t label; 1138 oss_longname_t longname; 1139 } data; 1140 1141 vclient_t *pvc; 1142 1143 uint64_t bytes; 1144 1145 int len; 1146 int error; 1147 int temp; 1148 1149 pvc = cuse_dev_get_per_file_handle(pdev); 1150 if (pvc == NULL) 1151 return (CUSE_ERR_INVALID); 1152 1153 len = IOCPARM_LEN(cmd); 1154 1155 if (len < 0 || len > (int)sizeof(data)) 1156 return (CUSE_ERR_INVALID); 1157 1158 if (cmd & IOC_IN) { 1159 error = cuse_copy_in(peer_data, &data, len); 1160 if (error) 1161 return (error); 1162 } else { 1163 error = 0; 1164 } 1165 1166 atomic_lock(); 1167 1168 switch (cmd) { 1169 case OSS_GETVERSION: 1170 data.val = SOUND_VERSION; 1171 break; 1172 case SNDCTL_SYSINFO: 1173 memset(&data.sysinfo, 0, sizeof(data.sysinfo)); 1174 strcpy(data.sysinfo.product, "VOSS"); 1175 strcpy(data.sysinfo.version, "1.0"); 1176 data.sysinfo.versionnum = SOUND_VERSION; 1177 data.sysinfo.numaudios = 1; 1178 data.sysinfo.numcards = 1; 1179 data.sysinfo.numaudioengines = 1; 1180 strcpy(data.sysinfo.license, "BSD"); 1181 memset(data.sysinfo.filler, -1, sizeof(data.sysinfo.filler)); 1182 break; 1183 case SNDCTL_CARDINFO: 1184 memset(&data.card_info, 0, sizeof(data.card_info)); 1185 strlcpy(data.card_info.shortname, pvc->profile->oss_name, 1186 sizeof(data.card_info.shortname)); 1187 break; 1188 case SNDCTL_AUDIOINFO: 1189 case SNDCTL_AUDIOINFO_EX: 1190 case SNDCTL_ENGINEINFO: 1191 memset(&data.audioinfo, 0, sizeof(data.audioinfo)); 1192 strlcpy(data.audioinfo.name, pvc->profile->oss_name, 1193 sizeof(data.audioinfo.name)); 1194 snprintf(data.audioinfo.devnode, sizeof(data.audioinfo.devnode), 1195 "/dev/%s", pvc->profile->oss_name); 1196 data.audioinfo.caps = DSP_CAP_INPUT | DSP_CAP_OUTPUT; 1197 data.audioinfo.iformats = VSUPPORTED_AFMT; 1198 data.audioinfo.oformats = VSUPPORTED_AFMT; 1199 data.audioinfo.enabled = 1; 1200 data.audioinfo.min_rate = (int)8000; 1201 data.audioinfo.max_rate = (int)voss_dsp_sample_rate; 1202 data.audioinfo.max_channels = pvc->profile->channels; 1203 /* range check */ 1204 if (voss_libsamplerate_enable == 0 || 1205 data.audioinfo.min_rate > data.audioinfo.max_rate) 1206 data.audioinfo.min_rate = data.audioinfo.max_rate; 1207 data.audioinfo.nrates = 1; 1208 data.audioinfo.rates[0] = (int)voss_dsp_sample_rate; 1209 if (voss_libsamplerate_enable != 0 && 1210 96000 != voss_dsp_sample_rate) 1211 data.audioinfo.rates[data.audioinfo.nrates++] = 96000; 1212 if (voss_libsamplerate_enable != 0 && 1213 48000 != voss_dsp_sample_rate) 1214 data.audioinfo.rates[data.audioinfo.nrates++] = 48000; 1215 if (voss_libsamplerate_enable != 0 && 1216 44100 != voss_dsp_sample_rate) 1217 data.audioinfo.rates[data.audioinfo.nrates++] = 44100; 1218 if (voss_libsamplerate_enable != 0 && 1219 24000 != voss_dsp_sample_rate) 1220 data.audioinfo.rates[data.audioinfo.nrates++] = 24000; 1221 if (voss_libsamplerate_enable != 0 && 1222 16000 != voss_dsp_sample_rate) 1223 data.audioinfo.rates[data.audioinfo.nrates++] = 16000; 1224 if (voss_libsamplerate_enable != 0 && 1225 8000 != voss_dsp_sample_rate) 1226 data.audioinfo.rates[data.audioinfo.nrates++] = 8000; 1227 data.audioinfo.latency = -1; 1228 break; 1229 case FIONREAD: 1230 data.val = vclient_input_delay(pvc); 1231 break; 1232 case FIONWRITE: 1233 data.val = vring_total_read_len(&pvc->tx_ring[1]); 1234 break; 1235 case FIOASYNC: 1236 case SNDCTL_DSP_NONBLOCK: 1237 case FIONBIO: 1238 break; 1239 case SNDCTL_DSP_SETBLKSIZE: 1240 case _IOWR('P', 4, int): 1241 error = vclient_setup_buffers(pvc, data.val, 0, 0, 0, 0); 1242 /* FALLTHROUGH */ 1243 case SNDCTL_DSP_GETBLKSIZE: 1244 data.val = pvc->buffer_size; 1245 break; 1246 case SNDCTL_DSP_SETFRAGMENT: 1247 if ((data.val & 0xFFFF) < 4) { 1248 /* need at least 16 bytes of buffer */ 1249 data.val &= ~0xFFFF; 1250 data.val |= 4; 1251 } else if ((data.val & 0xFFFF) > 24) { 1252 /* no more than 16MBytes of buffer */ 1253 data.val &= ~0xFFFF; 1254 data.val |= 24; 1255 } 1256 error = vclient_setup_buffers(pvc, 1257 (1 << (data.val & 0xFFFF)), (data.val >> 16), 0, 0, 0); 1258 if (error) { 1259 /* fallback to defaults */ 1260 pvc->buffer_size_set = 0; 1261 pvc->buffer_frags_set = 0; 1262 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, 0); 1263 if (error) 1264 break; 1265 /* figure out log2() of actual buffer size */ 1266 for (data.val = 0; 1267 data.val < 24 && (1U << data.val) < pvc->buffer_size; 1268 data.val++) 1269 ; 1270 /* or in the actual number of fragments */ 1271 data.val |= (pvc->buffer_frags << 16); 1272 } 1273 break; 1274 case SNDCTL_DSP_RESET: 1275 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, 0); 1276 break; 1277 case SNDCTL_DSP_SYNC: 1278 break; 1279 case SNDCTL_DSP_SPEED: 1280 if (data.val >= 8000 && data.val <= 96000 && 1281 voss_libsamplerate_enable != 0) { 1282 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, data.val); 1283 } 1284 /* return current speed */ 1285 data.val = (int)pvc->sample_rate; 1286 break; 1287 case SOUND_PCM_READ_RATE: 1288 data.val = (int)pvc->sample_rate; 1289 break; 1290 case SNDCTL_DSP_STEREO: 1291 if (data.val != 0) { 1292 error = vclient_set_channels(pvc, 2); 1293 } else { 1294 error = vclient_set_channels(pvc, 1); 1295 } 1296 data.val = (pvc->channels == 2); 1297 break; 1298 case SOUND_PCM_WRITE_CHANNELS: 1299 if (data.val < 0) { 1300 data.val = 0; 1301 error = CUSE_ERR_INVALID; 1302 break; 1303 } 1304 if (data.val == 0) { 1305 data.val = pvc->channels; 1306 } else { 1307 error = vclient_set_channels(pvc, data.val); 1308 } 1309 break; 1310 case SOUND_PCM_READ_CHANNELS: 1311 data.val = pvc->channels; 1312 break; 1313 case AIOGFMT: 1314 case SNDCTL_DSP_GETFMTS: 1315 data.val = VSUPPORTED_AFMT | AFMT_FULLDUPLEX | 1316 (pvc->profile->channels > 1 ? AFMT_STEREO : 0); 1317 break; 1318 case AIOSFMT: 1319 case SNDCTL_DSP_SETFMT: 1320 if (data.val != AFMT_QUERY) { 1321 temp = data.val & VSUPPORTED_AFMT; 1322 if (temp == 0 || (temp & (temp - 1)) != 0) { 1323 error = CUSE_ERR_INVALID; 1324 } else { 1325 error = vclient_setup_buffers(pvc, 0, 0, 0, temp, 0); 1326 } 1327 } else { 1328 data.val = pvc->format; 1329 } 1330 break; 1331 case SNDCTL_DSP_GETISPACE: 1332 memset(&data.buf_info, 0, sizeof(data.buf_info)); 1333 data.buf_info.fragsize = pvc->buffer_size; 1334 data.buf_info.fragstotal = pvc->buffer_frags; 1335 bytes = (pvc->buffer_size * pvc->buffer_frags); 1336 temp = vclient_input_delay(pvc); 1337 if (temp < 0 || (uint64_t)temp > bytes) 1338 temp = bytes; 1339 data.buf_info.fragments = temp / pvc->buffer_size; 1340 data.buf_info.bytes = temp; 1341 break; 1342 case SNDCTL_DSP_GETOSPACE: 1343 memset(&data.buf_info, 0, sizeof(data.buf_info)); 1344 data.buf_info.fragsize = pvc->buffer_size; 1345 data.buf_info.fragstotal = pvc->buffer_frags; 1346 bytes = (pvc->buffer_size * pvc->buffer_frags); 1347 temp = vclient_output_delay(pvc); 1348 if (temp < 0 || (uint64_t)temp >= bytes) { 1349 /* buffer is full */ 1350 data.buf_info.fragments = 0; 1351 data.buf_info.bytes = 0; 1352 } else { 1353 /* buffer is not full */ 1354 bytes -= temp; 1355 data.buf_info.fragments = bytes / pvc->buffer_size; 1356 data.buf_info.bytes = bytes; 1357 } 1358 break; 1359 case SNDCTL_DSP_GETCAPS: 1360 data.val = PCM_CAP_REALTIME | PCM_CAP_DUPLEX | 1361 PCM_CAP_INPUT | PCM_CAP_OUTPUT | PCM_CAP_TRIGGER | 1362 PCM_CAP_VIRTUAL; 1363 break; 1364 case SOUND_PCM_READ_BITS: 1365 data.val = vclient_sample_bytes(pvc) * 8; 1366 break; 1367 case SNDCTL_DSP_SETTRIGGER: 1368 if (data.val & PCM_ENABLE_INPUT) { 1369 pvc->rx_enabled = 1; 1370 } else { 1371 pvc->rx_enabled = 0; 1372 vring_reset(&pvc->rx_ring[1]); 1373 } 1374 1375 if (data.val & PCM_ENABLE_OUTPUT) { 1376 pvc->tx_enabled = 1; 1377 } else { 1378 pvc->tx_enabled = 0; 1379 vring_reset(&pvc->tx_ring[1]); 1380 } 1381 break; 1382 case SNDCTL_DSP_GETTRIGGER: 1383 data.val = 0; 1384 if (pvc->rx_enabled) 1385 data.val |= PCM_ENABLE_INPUT; 1386 if (pvc->tx_enabled) 1387 data.val |= PCM_ENABLE_OUTPUT; 1388 break; 1389 case SNDCTL_DSP_GETODELAY: 1390 data.val = vclient_output_delay_adjusted(pvc); 1391 break; 1392 case SNDCTL_DSP_POST: 1393 break; 1394 case SNDCTL_DSP_SETDUPLEX: 1395 break; 1396 case SNDCTL_DSP_GETRECVOL: 1397 temp = (pvc->rx_volume * 100) >> VVOLUME_UNIT_SHIFT; 1398 data.val = (temp & 0x00FF) | 1399 ((temp << 8) & 0xFF00); 1400 break; 1401 case SNDCTL_DSP_SETRECVOL: 1402 pvc->rx_volume = ((data.val & 0xFF) << VVOLUME_UNIT_SHIFT) / 100; 1403 break; 1404 case SNDCTL_DSP_GETPLAYVOL: 1405 temp = (pvc->tx_volume * 100) >> VVOLUME_UNIT_SHIFT; 1406 data.val = (temp & 0x00FF) | 1407 ((temp << 8) & 0xFF00); 1408 break; 1409 case SNDCTL_DSP_SETPLAYVOL: 1410 pvc->tx_volume = ((data.val & 0xFF) << VVOLUME_UNIT_SHIFT) / 100; 1411 break; 1412 case SNDCTL_DSP_CURRENT_IPTR: 1413 memset(&data.oss_count, 0, sizeof(data.oss_count)); 1414 /* compute input samples per channel */ 1415 data.oss_count.samples = 1416 vclient_scale(pvc->rx_samples, pvc->sample_rate, voss_dsp_sample_rate); 1417 data.oss_count.samples /= pvc->channels; 1418 data.oss_count.fifo_samples = 1419 vclient_input_delay(pvc) / (pvc->channels * vclient_sample_bytes(pvc)); 1420 break; 1421 case SNDCTL_DSP_CURRENT_OPTR: 1422 memset(&data.oss_count, 0, sizeof(data.oss_count)); 1423 /* compute output samples per channel */ 1424 data.oss_count.samples = 1425 vclient_scale(pvc->tx_samples, pvc->sample_rate, voss_dsp_sample_rate); 1426 data.oss_count.samples /= pvc->channels; 1427 data.oss_count.fifo_samples = 1428 vclient_output_delay(pvc) / (pvc->channels * vclient_sample_bytes(pvc)); 1429 break; 1430 case SNDCTL_DSP_GETIPTR: 1431 memset(&data.oss_count_info, 0, sizeof(data.oss_count_info)); 1432 /* compute input bytes */ 1433 bytes = 1434 vclient_scale(pvc->rx_samples, pvc->sample_rate, voss_dsp_sample_rate) * 1435 vclient_sample_bytes(pvc); 1436 data.oss_count_info.bytes = bytes; 1437 data.oss_count_info.blocks = bytes / pvc->buffer_size; 1438 data.oss_count_info.ptr = bytes % (pvc->buffer_size * pvc->buffer_frags); 1439 break; 1440 case SNDCTL_DSP_GETOPTR: 1441 memset(&data.oss_count_info, 0, sizeof(data.oss_count_info)); 1442 /* compute output bytes */ 1443 bytes = 1444 vclient_scale(pvc->tx_samples, pvc->sample_rate, voss_dsp_sample_rate) * 1445 vclient_sample_bytes(pvc); 1446 data.oss_count_info.bytes = bytes; 1447 data.oss_count_info.blocks = bytes / pvc->buffer_size; 1448 data.oss_count_info.ptr = bytes % (pvc->buffer_size * pvc->buffer_frags); 1449 break; 1450 case SNDCTL_DSP_HALT_OUTPUT: 1451 pvc->tx_enabled = 0; 1452 break; 1453 case SNDCTL_DSP_HALT_INPUT: 1454 pvc->rx_enabled = 0; 1455 break; 1456 case SNDCTL_DSP_LOW_WATER: 1457 if (data.val > 0 && data.val < 1458 (int)(pvc->buffer_frags * pvc->buffer_size)) { 1459 pvc->low_water = data.val; 1460 } else { 1461 error = CUSE_ERR_INVALID; 1462 } 1463 break; 1464 case SNDCTL_DSP_GETERROR: 1465 memset(&data.errinfo, 0, sizeof(data.errinfo)); 1466 break; 1467 case SNDCTL_DSP_SYNCGROUP: 1468 case SNDCTL_DSP_SYNCSTART: 1469 break; 1470 case SNDCTL_DSP_POLICY: 1471 break; 1472 case SNDCTL_DSP_COOKEDMODE: 1473 break; 1474 case SNDCTL_DSP_GET_CHNORDER: 1475 data.lval = CHNORDER_NORMAL; 1476 break; 1477 case SNDCTL_DSP_GETCHANNELMASK: 1478 data.val = DSP_BIND_FRONT; 1479 break; 1480 case SNDCTL_DSP_BIND_CHANNEL: 1481 break; 1482 case SNDCTL_GETLABEL: 1483 memset(&data.label, 0, sizeof(data.label)); 1484 break; 1485 case SNDCTL_SETLABEL: 1486 break; 1487 case SNDCTL_GETSONG: 1488 memset(&data.longname, 0, sizeof(data.longname)); 1489 break; 1490 case SNDCTL_SETSONG: 1491 break; 1492 case SNDCTL_SETNAME: 1493 break; 1494 default: 1495 error = CUSE_ERR_INVALID; 1496 break; 1497 } 1498 atomic_unlock(); 1499 1500 if (error == 0) { 1501 if (cmd & IOC_OUT) 1502 error = cuse_copy_out(&data, peer_data, len); 1503 } 1504 return (error); 1505 } 1506 1507 static int 1508 vclient_ioctl_wav(struct cuse_dev *pdev, int fflags __unused, 1509 unsigned long cmd, void *peer_data) 1510 { 1511 union { 1512 int val; 1513 } data; 1514 1515 vclient_t *pvc; 1516 int len; 1517 int error; 1518 1519 pvc = cuse_dev_get_per_file_handle(pdev); 1520 if (pvc == NULL) 1521 return (CUSE_ERR_INVALID); 1522 1523 len = IOCPARM_LEN(cmd); 1524 1525 if (len < 0 || len > (int)sizeof(data)) 1526 return (CUSE_ERR_INVALID); 1527 1528 if (cmd & IOC_IN) { 1529 error = cuse_copy_in(peer_data, &data, len); 1530 if (error) 1531 return (error); 1532 } else { 1533 error = 0; 1534 } 1535 1536 atomic_lock(); 1537 switch (cmd) { 1538 case FIONREAD: 1539 data.val = vclient_input_delay(pvc); 1540 break; 1541 case FIOASYNC: 1542 case SNDCTL_DSP_NONBLOCK: 1543 case FIONBIO: 1544 break; 1545 default: 1546 error = CUSE_ERR_INVALID; 1547 break; 1548 } 1549 atomic_unlock(); 1550 1551 if (error == 0) { 1552 if (cmd & IOC_OUT) 1553 error = cuse_copy_out(&data, peer_data, len); 1554 } 1555 return (error); 1556 } 1557 1558 static int 1559 vclient_poll(struct cuse_dev *pdev, int fflags, int events) 1560 { 1561 vclient_t *pvc; 1562 1563 int retval = CUSE_POLL_NONE; 1564 1565 pvc = cuse_dev_get_per_file_handle(pdev); 1566 if (pvc == NULL) 1567 return (retval); 1568 1569 atomic_lock(); 1570 if ((events & CUSE_POLL_READ) && (fflags & CUSE_FFLAG_READ)) { 1571 pvc->rx_enabled = 1; 1572 if (vclient_input_delay(pvc) >= pvc->low_water) 1573 retval |= CUSE_POLL_READ; 1574 } 1575 if ((events & CUSE_POLL_WRITE) && (fflags & CUSE_FFLAG_WRITE)) { 1576 const uint32_t out_dly = vclient_output_delay(pvc); 1577 const uint32_t out_buf = (pvc->buffer_frags * pvc->buffer_size); 1578 1579 if (out_dly < out_buf && (out_buf - out_dly) >= pvc->low_water) 1580 retval |= CUSE_POLL_WRITE; 1581 } 1582 atomic_unlock(); 1583 1584 return (retval); 1585 } 1586 1587 static const struct cuse_methods vclient_oss_methods = { 1588 .cm_open = vclient_open_oss, 1589 .cm_close = vclient_close, 1590 .cm_read = vclient_read, 1591 .cm_write = vclient_write_oss, 1592 .cm_ioctl = vclient_ioctl_oss, 1593 .cm_poll = vclient_poll, 1594 }; 1595 1596 static const struct cuse_methods vclient_wav_methods = { 1597 .cm_open = vclient_open_wav, 1598 .cm_close = vclient_close, 1599 .cm_read = vclient_read, 1600 .cm_write = vclient_write_wav, 1601 .cm_ioctl = vclient_ioctl_wav, 1602 .cm_poll = vclient_poll, 1603 }; 1604 1605 vprofile_head_t virtual_profile_client_head; 1606 vprofile_head_t virtual_profile_loopback_head; 1607 1608 vmonitor_head_t virtual_monitor_input; 1609 vmonitor_head_t virtual_monitor_output; 1610 vmonitor_head_t virtual_monitor_local; 1611 1612 uint32_t voss_max_channels; 1613 uint32_t voss_mix_channels; 1614 uint32_t voss_dsp_samples; 1615 uint32_t voss_dsp_max_channels; 1616 uint32_t voss_dsp_sample_rate; 1617 uint32_t voss_dsp_bits; 1618 uint8_t voss_libsamplerate_enable; 1619 uint8_t voss_libsamplerate_quality = SRC_SINC_FASTEST; 1620 int voss_is_recording = 1; 1621 int voss_has_synchronization; 1622 volatile sig_atomic_t voss_exit = 0; 1623 1624 static int voss_do_background; 1625 static int voss_baseclone = 0; 1626 static const char *voss_pid_path; 1627 1628 uint32_t voss_dsp_rx_refresh; 1629 uint32_t voss_dsp_tx_refresh; 1630 char voss_dsp_rx_device[VMAX_STRING]; 1631 char voss_dsp_tx_device[VMAX_STRING]; 1632 char voss_ctl_device[VMAX_STRING]; 1633 1634 uint32_t voss_jitter_up; 1635 uint32_t voss_jitter_down; 1636 1637 struct voss_backend *voss_rx_backend; 1638 struct voss_backend *voss_tx_backend; 1639 1640 static int voss_dups; 1641 static int voss_ntds; 1642 static pthread_t *voss_tds; 1643 static int voss_fd_sta = -1; 1644 1645 static gid_t voss_gid; 1646 static int voss_perm = 0660; 1647 1648 /* XXX I do not like the prefix argument... */ 1649 static struct voss_backend * 1650 voss_load_backend(const char *prefix, const char *name, const char *dir) 1651 { 1652 struct voss_backend *backend; 1653 void *hdl; 1654 char lpath[64], bsym[64]; 1655 1656 snprintf(lpath, sizeof(lpath), "%s/lib/virtual_oss/voss_%s.so", 1657 prefix, name); 1658 snprintf(bsym, sizeof(bsym), "voss_backend_%s_%s", name, dir); 1659 1660 if ((hdl = dlopen(lpath, RTLD_NOW)) == NULL) 1661 errx(1, "%s", dlerror()); 1662 if ((backend = dlsym(hdl, bsym)) == NULL) { 1663 warnx("%s", dlerror()); 1664 dlclose(hdl); 1665 exit(EXIT_FAILURE); 1666 } 1667 1668 return (backend); 1669 } 1670 1671 static void 1672 voss_rx_backend_refresh(void) 1673 { 1674 /* setup RX backend */ 1675 if (strcmp(voss_dsp_rx_device, "/dev/null") == 0) { 1676 voss_rx_backend = voss_load_backend("/usr", "null", "rec"); 1677 } else if (strstr(voss_dsp_rx_device, "/dev/bluetooth/") == voss_dsp_rx_device) { 1678 voss_rx_backend = voss_load_backend("/usr/local", "bt", "rec"); 1679 } else if (strstr(voss_dsp_rx_device, "/dev/sndio/") == voss_dsp_rx_device) { 1680 voss_rx_backend = voss_load_backend("/usr/local", "sndio", "rec"); 1681 } else { 1682 voss_rx_backend = voss_load_backend("/usr", "oss", "rec"); 1683 } 1684 } 1685 1686 static void 1687 voss_tx_backend_refresh(void) 1688 { 1689 /* setup TX backend */ 1690 if (strcmp(voss_dsp_tx_device, "/dev/null") == 0) { 1691 voss_tx_backend = voss_load_backend("/usr", "null", "play"); 1692 } else if (strstr(voss_dsp_tx_device, "/dev/bluetooth/") == voss_dsp_tx_device) { 1693 voss_tx_backend = voss_load_backend("/usr/local", "bt", "play"); 1694 } else if (strstr(voss_dsp_tx_device, "/dev/sndio/") == voss_dsp_tx_device) { 1695 voss_tx_backend = voss_load_backend("/usr/local", "sndio", "play"); 1696 } else { 1697 voss_tx_backend = voss_load_backend("/usr", "oss", "play"); 1698 } 1699 } 1700 1701 static void 1702 usage(void) 1703 { 1704 fprintf(stderr, "Usage: virtual_oss [options...] [device] \\\n" 1705 "\t" "-C 2 -c 2 -r 48000 -b 16 -s 100.0ms -f /dev/dsp3 \\\n" 1706 "\t" "-P /dev/dsp3 -R /dev/dsp1 \\\n" 1707 "\t" "-O /dev/dsp3 -R /dev/null \\\n" 1708 "\t" "-c 1 -m 0,0 [-w wav.0] -d dsp100.0 \\\n" 1709 "\t" "-c 1 -m 0,0 [-w wav.0] -d vdsp.0 \\\n" 1710 "\t" "-c 2 -m 0,0,1,1 [-w wav.1] -d vdsp.1 \\\n" 1711 "\t" "-c 2 -m 0,0,1,1 [-w wav.loopback] -l vdsp.loopback \\\n" 1712 "\t" "-c 2 -m 0,0,1,1 [-w wav.loopback] -L vdsp.loopback \\\n" 1713 "\t" "-B # run in background \\\n" 1714 "\t" "-s <samples> or <milliseconds>ms \\\n" 1715 "\t" "-S # enable automatic resampling using libsamplerate \\\n" 1716 "\t" "-Q <0,1,2> # quality of resampling 0=best,1=medium,2=fastest (default) \\\n" 1717 "\t" "-b <bits> \\\n" 1718 "\t" "-r <rate> \\\n" 1719 "\t" "-i <rtprio> \\\n" 1720 "\t" "-a <amp -63..63> \\\n" 1721 "\t" "-a i,<rx_amp -63..63> \\\n" 1722 "\t" "-a o,<tx_amp -63..63> \\\n" 1723 "\t" "-g <knee,attack,decay> # enable device RX compressor\\\n" 1724 "\t" "-x <knee,attack,decay> # enable output compressor\\\n" 1725 "\t" "-p <pol 0..1> \\\n" 1726 "\t" "-e <rxtx_mute 0..1> \\\n" 1727 "\t" "-e <rx_mute 0..1>,<tx_mute 0..1> \\\n" 1728 "\t" "-m <mapping> \\\n" 1729 "\t" "-m <rx0,tx0,rx1,tx1...rxN,txN> \\\n" 1730 "\t" "-C <mixchans>\\\n" 1731 "\t" "-c <dspchans> \\\n" 1732 "\t" "-M <monitorfilter> \\\n" 1733 "\t" "-M i,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1734 "\t" "-M o,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1735 "\t" "-M x,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1736 "\t" "-F <rx_filter_samples> or <milliseconds>ms \\\n" 1737 "\t" "-G <tx_filter_samples> or <milliseconds>ms \\\n" 1738 "\t" "-E <enable_recording, 0 or 1> \\\n" 1739 "\t" "-N <max HTTP connections, default is 1> \\\n" 1740 "\t" "-H <bind HTTP server to this host> \\\n" 1741 "\t" "-o <bind HTTP server to this port, default is 80> \\\n" 1742 "\t" "-J <bind RTP server to this network interface> \\\n" 1743 "\t" "-k <bind RTP server to this port, default is 8080> \\\n" 1744 "\t" "-t vdsp.ctl \n" 1745 "\t" "Left channel = 0\n" 1746 "\t" "Right channel = 1\n" 1747 "\t" "Max channels = %d\n", VMAX_CHAN); 1748 1749 exit(EX_USAGE); 1750 } 1751 1752 /* 1753 * Restore hw.snd.basename_clone if it was disabled by us. 1754 */ 1755 static void 1756 restore_baseclone(void) 1757 { 1758 if (voss_baseclone) { 1759 if (sysctlbyname(SYSCTL_BASECLONE, NULL, NULL, &voss_baseclone, 1760 sizeof(int)) < 0) 1761 warn("Could not enable " SYSCTL_BASECLONE); 1762 printf(SYSCTL_BASECLONE ": 0 -> %d\n", voss_baseclone); 1763 } 1764 } 1765 1766 static void 1767 init_compressor(struct virtual_profile *pvp) 1768 { 1769 int x; 1770 1771 memset(&pvp->rx_compressor_param, 0, sizeof(pvp->rx_compressor_param)); 1772 1773 pvp->rx_compressor_param.knee = 85; 1774 pvp->rx_compressor_param.attack = 3; 1775 pvp->rx_compressor_param.decay = 20; 1776 1777 for (x = 0; x != VMAX_CHAN; x++) 1778 pvp->rx_compressor_gain[x] = 1.0; 1779 } 1780 1781 static void 1782 init_mapping(struct virtual_profile *pvp) 1783 { 1784 int x; 1785 1786 for (x = 0; x != VMAX_CHAN; x++) { 1787 pvp->rx_src[x] = x; 1788 pvp->tx_dst[x] = x; 1789 } 1790 } 1791 1792 static void 1793 init_sndstat(vprofile_t *ptr) 1794 { 1795 int err; 1796 nvlist_t *nvl; 1797 nvlist_t *di = NULL, *dichild = NULL; 1798 struct sndstioc_nv_arg arg; 1799 unsigned int min_rate, max_rate; 1800 1801 nvl = nvlist_create(0); 1802 if (nvl == NULL) { 1803 warn("Failed to create nvlist"); 1804 goto done; 1805 } 1806 1807 di = nvlist_create(0); 1808 if (di == NULL) { 1809 warn("Failed to create nvlist"); 1810 goto done; 1811 } 1812 1813 dichild = nvlist_create(0); 1814 if (dichild == NULL) { 1815 warn("Failed to create nvlist"); 1816 goto done; 1817 } 1818 1819 nvlist_add_string(di, SNDST_DSPS_PROVIDER, "virtual_oss"); 1820 nvlist_add_string(di, SNDST_DSPS_DESC, "virtual_oss device"); 1821 nvlist_add_number(di, SNDST_DSPS_PCHAN, 1); 1822 nvlist_add_number(di, SNDST_DSPS_RCHAN, 1); 1823 min_rate = 8000; 1824 max_rate = voss_dsp_sample_rate; 1825 if (voss_libsamplerate_enable == 0 || 1826 min_rate > max_rate) 1827 min_rate = max_rate; 1828 if (voss_libsamplerate_enable != 0 && max_rate < 96000) 1829 max_rate = 96000; 1830 nvlist_add_number(dichild, SNDST_DSPS_INFO_MIN_RATE, min_rate); 1831 nvlist_add_number(dichild, SNDST_DSPS_INFO_MAX_RATE, max_rate); 1832 nvlist_add_number(dichild, SNDST_DSPS_INFO_FORMATS, VSUPPORTED_AFMT); 1833 nvlist_add_number(dichild, SNDST_DSPS_INFO_MIN_CHN, ptr->channels); 1834 nvlist_add_number(dichild, SNDST_DSPS_INFO_MAX_CHN, ptr->channels); 1835 nvlist_add_nvlist(di, SNDST_DSPS_INFO_PLAY, dichild); 1836 nvlist_add_nvlist(di, SNDST_DSPS_INFO_REC, dichild); 1837 1838 nvlist_add_string(di, SNDST_DSPS_DEVNODE, 1839 ptr->oss_name); 1840 nvlist_append_nvlist_array(nvl, SNDST_DSPS, di); 1841 1842 if (nvlist_error(nvl)) { 1843 warn("Failed building nvlist"); 1844 goto done; 1845 } 1846 1847 arg.buf = nvlist_pack(nvl, &arg.nbytes); 1848 if (arg.buf == NULL) { 1849 warn("Failed to pack nvlist"); 1850 goto done; 1851 } 1852 err = ioctl(voss_fd_sta, SNDSTIOC_ADD_USER_DEVS, &arg); 1853 free(arg.buf); 1854 if (err != 0) { 1855 warn("Failed to issue ioctl(SNDSTIOC_ADD_USER_DEVS)"); 1856 goto done; 1857 } 1858 1859 done: 1860 nvlist_destroy(di); 1861 nvlist_destroy(dichild); 1862 nvlist_destroy(nvl); 1863 } 1864 1865 static void 1866 cleanup_profile(vprofile_t *pvp) 1867 { 1868 if (pvp->oss_dev != NULL) 1869 cuse_dev_destroy(pvp->oss_dev); 1870 if (pvp->wav_dev != NULL) 1871 cuse_dev_destroy(pvp->wav_dev); 1872 } 1873 1874 static const char * 1875 dup_profile(vprofile_t *pvp, int *pamp, int pol, int rx_mute, 1876 int tx_mute, int synchronized, int is_client) 1877 { 1878 vprofile_t *ptr; 1879 struct cuse_dev *pdev; 1880 const char *errstr; 1881 int x; 1882 1883 rx_mute = rx_mute ? 1 : 0; 1884 tx_mute = tx_mute ? 1 : 0; 1885 pol = pol ? 1 : 0; 1886 1887 /* Range check amplitude argument. */ 1888 for (x = 0; x != 2; x++) { 1889 if (pamp[x] < -63) 1890 pamp[x] = -63; 1891 else if (pamp[x] > 63) 1892 pamp[x] = 63; 1893 } 1894 1895 ptr = malloc(sizeof(*ptr)); 1896 if (ptr == NULL) 1897 return ("Out of memory"); 1898 1899 memcpy(ptr, pvp, sizeof(*ptr)); 1900 1901 ptr->synchronized = synchronized; 1902 TAILQ_INIT(&ptr->head); 1903 1904 for (x = 0; x != ptr->channels; x++) { 1905 ptr->tx_mute[x] = tx_mute; 1906 ptr->rx_mute[x] = rx_mute; 1907 ptr->tx_shift[x] = pamp[1]; 1908 ptr->rx_shift[x] = pamp[0]; 1909 ptr->tx_pol[x] = pol; 1910 ptr->rx_pol[x] = pol; 1911 } 1912 1913 /* create DSP device */ 1914 if (ptr->oss_name[0] != 0) { 1915 /* 1916 * Detect /dev/dsp creation and try to disable system 1917 * basename cloning automatically: 1918 */ 1919 if (strcmp(ptr->oss_name, "dsp") == 0) { 1920 size_t size; 1921 1922 x = 0; 1923 size = sizeof(int); 1924 if (sysctlbyname(SYSCTL_BASECLONE, &voss_baseclone, 1925 &size, &x, size) < 0) 1926 return ("Could not disable " SYSCTL_BASECLONE); 1927 printf(SYSCTL_BASECLONE ": %d -> 0\n", voss_baseclone); 1928 if (atexit(restore_baseclone) < 0) 1929 return ("Could not set atexit callback"); 1930 } 1931 1932 /* create DSP character device */ 1933 pdev = cuse_dev_create(&vclient_oss_methods, ptr, NULL, 1934 0, voss_gid, voss_perm, ptr->oss_name); 1935 if (pdev == NULL) { 1936 errstr = "Could not create CUSE DSP device"; 1937 goto err; 1938 } 1939 ptr->oss_dev = pdev; 1940 1941 /* register to sndstat */ 1942 if (voss_fd_sta < 0) { 1943 if ((voss_fd_sta = open("/dev/sndstat", O_WRONLY)) < 0) { 1944 errstr = "Could not open /dev/sndstat"; 1945 goto err; 1946 } 1947 } 1948 init_sndstat(ptr); 1949 } 1950 /* create WAV device */ 1951 if (ptr->wav_name[0] != 0) { 1952 pdev = cuse_dev_create(&vclient_wav_methods, ptr, NULL, 1953 0, voss_gid, voss_perm, ptr->wav_name); 1954 if (pdev == NULL) { 1955 errstr = "Could not create CUSE WAV device"; 1956 goto err; 1957 } 1958 ptr->wav_dev = pdev; 1959 } 1960 1961 atomic_lock(); 1962 if (is_client) 1963 TAILQ_INSERT_TAIL(&virtual_profile_client_head, ptr, entry); 1964 else 1965 TAILQ_INSERT_TAIL(&virtual_profile_loopback_head, ptr, entry); 1966 atomic_unlock(); 1967 1968 voss_dups++; 1969 1970 /* need new names next time */ 1971 memset(pvp->oss_name, 0, sizeof(pvp->oss_name)); 1972 memset(pvp->wav_name, 0, sizeof(pvp->wav_name)); 1973 1974 /* need to set new filter sizes */ 1975 pvp->rx_filter_size = 0; 1976 pvp->tx_filter_size = 0; 1977 1978 /* need to specify new HTTP parameters next time */ 1979 pvp->http.host = NULL; 1980 pvp->http.port = NULL; 1981 pvp->http.nstate = 0; 1982 pvp->http.rtp_ifname = NULL; 1983 pvp->http.rtp_port = NULL; 1984 1985 /* need to specify new amplification next time */ 1986 pamp[0] = 0; 1987 pamp[1] = 0; 1988 1989 /* need to set new compressor parameters next time */ 1990 init_compressor(pvp); 1991 1992 return (voss_httpd_start(ptr)); 1993 1994 err: 1995 cleanup_profile(ptr); 1996 free(ptr); 1997 1998 return (errstr); 1999 2000 } 2001 2002 static void 2003 virtual_pipe(int sig __unused) 2004 { 2005 voss_dsp_tx_refresh = 1; 2006 voss_dsp_rx_refresh = 1; 2007 } 2008 2009 static void 2010 virtual_cuse_hup(int sig __unused) 2011 { 2012 atomic_wakeup(); 2013 } 2014 2015 static void * 2016 virtual_cuse_process(void *arg __unused) 2017 { 2018 signal(SIGHUP, &virtual_cuse_hup); 2019 2020 while (1) { 2021 if (cuse_wait_and_process() != 0) 2022 break; 2023 } 2024 return (NULL); 2025 } 2026 2027 static void 2028 virtual_cuse_init_profile(struct virtual_profile *pvp) 2029 { 2030 memset(pvp, 0, sizeof(*pvp)); 2031 2032 init_compressor(pvp); 2033 init_mapping(pvp); 2034 } 2035 2036 static void 2037 virtual_sig_exit(int sig __unused) 2038 { 2039 voss_exit = 1; 2040 } 2041 2042 static const char * 2043 parse_options(int narg, char **pparg, int is_main) 2044 { 2045 const char *ptr; 2046 int a, b, c; 2047 int val; 2048 int idx; 2049 int type; 2050 int opt_mute[2] = {0, 0}; 2051 int opt_amp[2] = {0, 0}; 2052 int opt_pol = 0; 2053 const char *optstr; 2054 struct virtual_profile profile; 2055 struct rtprio rtp; 2056 float samples_ms; 2057 2058 if (is_main) 2059 optstr = "N:J:k:H:o:F:G:w:e:p:a:C:c:r:b:f:g:x:i:m:M:d:l:L:s:t:h?O:P:Q:R:SBD:E:"; 2060 else 2061 optstr = "F:G:w:e:p:a:c:b:f:m:M:d:l:L:s:O:P:R:E:"; 2062 2063 virtual_cuse_init_profile(&profile); 2064 2065 /* reset getopt parsing */ 2066 optreset = 1; 2067 optind = 1; 2068 2069 while ((c = getopt(narg, pparg, optstr)) != -1) { 2070 switch (c) { 2071 case 'B': 2072 voss_do_background = 1; 2073 break; 2074 case 'D': 2075 voss_pid_path = optarg; 2076 break; 2077 case 'C': 2078 if (voss_mix_channels != 0) { 2079 return ("The -C argument may only be used once"); 2080 } 2081 voss_mix_channels = atoi(optarg); 2082 if (voss_mix_channels >= VMAX_CHAN) { 2083 return ("Number of mixing channels is too high"); 2084 } 2085 break; 2086 case 'a': 2087 switch (optarg[0]) { 2088 case '-': 2089 case '0': 2090 case '1': 2091 case '2': 2092 case '3': 2093 case '4': 2094 case '5': 2095 case '6': 2096 case '7': 2097 case '8': 2098 case '9': 2099 opt_amp[0] = -(opt_amp[1] = atoi(optarg)); 2100 break; 2101 case 'i': 2102 if (optarg[1] != ',') 2103 return ("Expected comma after 'i'"); 2104 opt_amp[0] = atoi(optarg + 2); 2105 break; 2106 case 'o': 2107 if (optarg[1] != ',') 2108 return ("Expected comma after 'o'"); 2109 opt_amp[1] = atoi(optarg + 2); 2110 break; 2111 default: 2112 return ("Invalid syntax for amplitude argument"); 2113 } 2114 break; 2115 case 'E': 2116 voss_is_recording = (atoi(optarg) != 0); 2117 break; 2118 case 'e': 2119 idx = 0; 2120 ptr = optarg; 2121 memset(opt_mute, 0, sizeof(opt_mute)); 2122 while (1) { 2123 c = *ptr++; 2124 if (c == ',' || c == 0) { 2125 idx++; 2126 if (c == 0) 2127 break; 2128 continue; 2129 } 2130 if (idx < 2 && c >= '0' && c <= '1') { 2131 opt_mute[idx] = c - '0'; 2132 } else { 2133 return ("Invalid -e parameter"); 2134 } 2135 } 2136 switch (idx) { 2137 case 1: 2138 opt_mute[1] = opt_mute[0]; 2139 break; 2140 case 2: 2141 break; 2142 default: 2143 return ("Invalid -e parameter"); 2144 } 2145 break; 2146 case 'p': 2147 opt_pol = atoi(optarg); 2148 break; 2149 case 'c': 2150 profile.channels = atoi(optarg); 2151 if (profile.channels == 0) 2152 return ("Number of channels is zero"); 2153 if (profile.channels > VMAX_CHAN) 2154 return ("Number of channels is too high"); 2155 break; 2156 case 'r': 2157 voss_dsp_sample_rate = atoi(optarg); 2158 if (voss_dsp_sample_rate < 8000) 2159 return ("Sample rate is too low, 8000 Hz"); 2160 if (voss_dsp_sample_rate > 0xFFFFFF) 2161 return ("Sample rate is too high"); 2162 break; 2163 case 'i': 2164 memset(&rtp, 0, sizeof(rtp)); 2165 rtp.type = RTP_PRIO_REALTIME; 2166 rtp.prio = atoi(optarg); 2167 if (rtprio(RTP_SET, getpid(), &rtp) != 0) 2168 printf("Cannot set realtime priority\n"); 2169 break; 2170 case 'b': 2171 profile.bits = atoi(optarg); 2172 switch (profile.bits) { 2173 case 8: 2174 case 16: 2175 case 24: 2176 case 32: 2177 break; 2178 default: 2179 return ("Invalid number of sample bits"); 2180 } 2181 break; 2182 case 'g': 2183 if (profile.rx_compressor_param.enabled) 2184 return ("Compressor already enabled for this device"); 2185 if (sscanf(optarg, "%d,%d,%d", &a, &b, &c) != 3 || 2186 a < VIRTUAL_OSS_KNEE_MIN || 2187 a > VIRTUAL_OSS_KNEE_MAX || 2188 b < VIRTUAL_OSS_ATTACK_MIN || 2189 b > VIRTUAL_OSS_ATTACK_MAX || 2190 c < VIRTUAL_OSS_DECAY_MIN || 2191 c > VIRTUAL_OSS_DECAY_MAX) 2192 return ("Invalid device compressor argument(s)"); 2193 profile.rx_compressor_param.enabled = 1; 2194 profile.rx_compressor_param.knee = a; 2195 profile.rx_compressor_param.attack = b; 2196 profile.rx_compressor_param.decay = c; 2197 break; 2198 case 'x': 2199 if (voss_output_compressor_param.enabled) 2200 return ("Compressor already enabled for output"); 2201 if (sscanf(optarg, "%d,%d,%d", &a, &b, &c) != 3 || 2202 a < VIRTUAL_OSS_KNEE_MIN || 2203 a > VIRTUAL_OSS_KNEE_MAX || 2204 b < VIRTUAL_OSS_ATTACK_MIN || 2205 b > VIRTUAL_OSS_ATTACK_MAX || 2206 c < VIRTUAL_OSS_DECAY_MIN || 2207 c > VIRTUAL_OSS_DECAY_MAX) 2208 return ("Invalid output compressor argument(s)"); 2209 voss_output_compressor_param.enabled = 1; 2210 voss_output_compressor_param.knee = a; 2211 voss_output_compressor_param.attack = b; 2212 voss_output_compressor_param.decay = c; 2213 break; 2214 case 'f': 2215 case 'O': 2216 case 'P': 2217 case 'R': 2218 if (voss_dsp_sample_rate == 0 || voss_dsp_samples == 0) 2219 return ("Missing -r or -s parameters"); 2220 if (voss_dsp_bits == 0) { 2221 if (profile.bits == 0) 2222 return ("Missing -b parameter"); 2223 voss_dsp_bits = profile.bits; 2224 } 2225 if (voss_dsp_max_channels == 0) { 2226 if (profile.channels == 0) 2227 return ("Missing -c parameter"); 2228 voss_dsp_max_channels = profile.channels; 2229 } 2230 if (c == 'f' || c == 'R') { 2231 if (strlen(optarg) > VMAX_STRING - 1) 2232 return ("Device name too long"); 2233 strncpy(voss_dsp_rx_device, optarg, sizeof(voss_dsp_rx_device)); 2234 voss_rx_backend_refresh(); 2235 voss_dsp_rx_refresh = 1; 2236 } 2237 if (c == 'f' || c == 'P' || c == 'O') { 2238 if (strlen(optarg) > VMAX_STRING - 1) 2239 return ("Device name too long"); 2240 strncpy(voss_dsp_tx_device, optarg, sizeof(voss_dsp_tx_device)); 2241 voss_tx_backend_refresh(); 2242 voss_dsp_tx_refresh = 1; 2243 2244 if (c == 'O' && voss_has_synchronization == 0) 2245 voss_has_synchronization++; 2246 } 2247 break; 2248 case 'w': 2249 if (strlen(optarg) > VMAX_STRING - 1) 2250 return ("Device name too long"); 2251 strncpy(profile.wav_name, optarg, sizeof(profile.wav_name)); 2252 break; 2253 case 'd': 2254 case 'L': 2255 case 'l': 2256 if (strlen(optarg) > VMAX_STRING - 1) 2257 return ("Device name too long"); 2258 strncpy(profile.oss_name, optarg, sizeof(profile.oss_name)); 2259 2260 if (profile.bits == 0 || voss_dsp_sample_rate == 0 || 2261 profile.channels == 0 || voss_dsp_samples == 0) 2262 return ("Missing -b, -r, -c or -s parameters"); 2263 2264 val = (voss_dsp_samples * 2265 profile.bits * profile.channels) / 8; 2266 if (val <= 0 || val >= (1024 * 1024)) 2267 return ("-s option value is too big"); 2268 2269 ptr = dup_profile(&profile, opt_amp, opt_pol, 2270 opt_mute[0], opt_mute[1], c == 'L', c == 'd'); 2271 if (ptr != NULL) 2272 return (ptr); 2273 break; 2274 case 'S': 2275 voss_libsamplerate_enable = 1; 2276 break; 2277 case 'Q': 2278 c = atoi(optarg); 2279 switch (c) { 2280 case 0: 2281 voss_libsamplerate_quality = SRC_SINC_BEST_QUALITY; 2282 break; 2283 case 1: 2284 voss_libsamplerate_quality = SRC_SINC_MEDIUM_QUALITY; 2285 break; 2286 default: 2287 voss_libsamplerate_quality = SRC_SINC_FASTEST; 2288 break; 2289 } 2290 break; 2291 case 's': 2292 if (voss_dsp_samples != 0) 2293 return ("-s option may only be used once"); 2294 if (profile.bits == 0 || profile.channels == 0) 2295 return ("-s option requires -b and -c options"); 2296 if (strlen(optarg) > 2 && 2297 sscanf(optarg, "%f", &samples_ms) == 1 && 2298 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2299 if (voss_dsp_sample_rate == 0) 2300 return ("-s <X>ms option requires -r option"); 2301 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2302 return ("-s <X>ms option has invalid value"); 2303 voss_dsp_samples = voss_dsp_sample_rate * samples_ms / 1000.0; 2304 } else { 2305 voss_dsp_samples = atoi(optarg); 2306 } 2307 if (voss_dsp_samples >= (1U << 24)) 2308 return ("-s option requires a non-zero positive value"); 2309 break; 2310 case 't': 2311 if (voss_ctl_device[0]) 2312 return ("-t parameter may only be used once"); 2313 2314 strlcpy(voss_ctl_device, optarg, sizeof(voss_ctl_device)); 2315 break; 2316 case 'm': 2317 ptr = optarg; 2318 val = 0; 2319 idx = 0; 2320 init_mapping(&profile); 2321 while (1) { 2322 c = *ptr++; 2323 if (c == ',' || c == 0) { 2324 if (idx >= (2 * VMAX_CHAN)) 2325 return ("Too many channels in mask"); 2326 if (idx & 1) 2327 profile.tx_dst[idx / 2] = val; 2328 else 2329 profile.rx_src[idx / 2] = val; 2330 if (c == 0) 2331 break; 2332 val = 0; 2333 idx++; 2334 continue; 2335 } 2336 if (c >= '0' && c <= '9') { 2337 val *= 10; 2338 val += c - '0'; 2339 } 2340 } 2341 break; 2342 case 'M': 2343 ptr = optarg; 2344 type = *ptr; 2345 if (type == 'i' || type == 'o' || type == 'x') { 2346 vmonitor_t *pvm; 2347 2348 int src = 0; 2349 int dst = 0; 2350 int pol = 0; 2351 int mute = 0; 2352 int amp = 0; 2353 int neg; 2354 2355 ptr++; 2356 if (*ptr == ',') 2357 ptr++; 2358 else if (type == 'i') 2359 return ("Expected comma after 'i'"); 2360 else if (type == 'o') 2361 return ("Expected comma after 'o'"); 2362 else 2363 return ("Expected comma after 'x'"); 2364 2365 val = 0; 2366 neg = 0; 2367 idx = 0; 2368 while (1) { 2369 c = *ptr++; 2370 if (c == '-') { 2371 neg = 1; 2372 continue; 2373 } 2374 if (c == ',' || c == 0) { 2375 switch (idx) { 2376 case 0: 2377 src = val; 2378 break; 2379 case 1: 2380 dst = val; 2381 break; 2382 case 2: 2383 pol = val ? 1 : 0; 2384 break; 2385 case 3: 2386 mute = val ? 1 : 0; 2387 break; 2388 case 4: 2389 if (val > 31) { 2390 return ("Absolute amplitude " 2391 "for -M parameter " 2392 "cannot exceed 31"); 2393 } 2394 amp = neg ? -val : val; 2395 break; 2396 default: 2397 break; 2398 } 2399 if (c == 0) 2400 break; 2401 val = 0; 2402 neg = 0; 2403 idx++; 2404 continue; 2405 } 2406 if (c >= '0' && c <= '9') { 2407 val *= 10; 2408 val += c - '0'; 2409 } 2410 } 2411 if (idx < 4) 2412 return ("Too few parameters for -M"); 2413 2414 pvm = vmonitor_alloc(&idx, 2415 (type == 'i') ? &virtual_monitor_input : 2416 (type == 'x') ? &virtual_monitor_local : 2417 &virtual_monitor_output); 2418 2419 if (pvm == NULL) 2420 return ("Out of memory"); 2421 2422 pvm->src_chan = src; 2423 pvm->dst_chan = dst; 2424 pvm->pol = pol; 2425 pvm->mute = mute; 2426 pvm->shift = amp; 2427 } else { 2428 return ("Invalid -M parameter"); 2429 } 2430 break; 2431 case 'F': 2432 if (strlen(optarg) > 2 && 2433 sscanf(optarg, "%f", &samples_ms) == 1 && 2434 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2435 if (voss_dsp_sample_rate == 0) 2436 return ("-F <X>ms option requires -r option"); 2437 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2438 return ("-F <X>ms option has invalid value"); 2439 profile.rx_filter_size = voss_dsp_sample_rate * samples_ms / 1000.0; 2440 } else { 2441 profile.rx_filter_size = atoi(optarg); 2442 } 2443 /* make value power of two */ 2444 while ((profile.rx_filter_size - 1) & profile.rx_filter_size) 2445 profile.rx_filter_size += ~(profile.rx_filter_size - 1) & profile.rx_filter_size; 2446 /* range check */ 2447 if (profile.rx_filter_size > VIRTUAL_OSS_FILTER_MAX) 2448 return ("Invalid -F parameter is out of range"); 2449 break; 2450 case 'G': 2451 if (strlen(optarg) > 2 && 2452 sscanf(optarg, "%f", &samples_ms) == 1 && 2453 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2454 if (voss_dsp_sample_rate == 0) 2455 return ("-G <X>ms option requires -r option"); 2456 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2457 return ("-G <X>ms option has invalid value"); 2458 profile.tx_filter_size = voss_dsp_sample_rate * samples_ms / 1000.0; 2459 } else { 2460 profile.tx_filter_size = atoi(optarg); 2461 } 2462 /* make value power of two */ 2463 while ((profile.tx_filter_size - 1) & profile.tx_filter_size) 2464 profile.tx_filter_size += ~(profile.tx_filter_size - 1) & profile.tx_filter_size; 2465 /* range check */ 2466 if (profile.tx_filter_size > VIRTUAL_OSS_FILTER_MAX) 2467 return ("Invalid -F parameter is out of range"); 2468 break; 2469 case 'N': 2470 profile.http.nstate = atoi(optarg); 2471 break; 2472 case 'H': 2473 profile.http.host = optarg; 2474 if (profile.http.port == NULL) 2475 profile.http.port = "80"; 2476 if (profile.http.nstate == 0) 2477 profile.http.nstate = 1; 2478 break; 2479 case 'o': 2480 profile.http.port = optarg; 2481 break; 2482 case 'J': 2483 profile.http.rtp_ifname = optarg; 2484 if (profile.http.rtp_port == NULL) 2485 profile.http.rtp_port = "8080"; 2486 break; 2487 case 'k': 2488 profile.http.rtp_port = optarg; 2489 break; 2490 default: 2491 if (is_main) 2492 usage(); 2493 else 2494 return ("Invalid option detected"); 2495 break; 2496 } 2497 } 2498 return (NULL); 2499 } 2500 2501 static void 2502 create_threads(void) 2503 { 2504 int idx; 2505 2506 /* Give each DSP device 4 threads */ 2507 voss_ntds = voss_dups * 4; 2508 voss_tds = malloc(voss_ntds * sizeof(pthread_t)); 2509 if (voss_tds == NULL) 2510 err(1, "malloc"); 2511 2512 for (idx = 0; idx < voss_ntds; idx++) { 2513 if (pthread_create(&voss_tds[idx], NULL, &virtual_cuse_process, 2514 NULL) != 0) 2515 err(1, "pthread_create"); 2516 } 2517 2518 /* Reset until next time called */ 2519 voss_dups = 0; 2520 } 2521 2522 static void 2523 destroy_threads(void) 2524 { 2525 int idx; 2526 2527 for (idx = 0; idx < voss_ntds; idx++) 2528 pthread_cancel(voss_tds[idx]); 2529 free(voss_tds); 2530 } 2531 2532 void 2533 voss_add_options(char *str) 2534 { 2535 static char name[] = { "virtual_oss" }; 2536 const char sep[] = "\t "; 2537 const char *ptrerr; 2538 char *parg[64]; 2539 char *word; 2540 char *brkt; 2541 int narg = 0; 2542 2543 parg[narg++] = name; 2544 2545 for (word = strtok_r(str, sep, &brkt); word != NULL; 2546 word = strtok_r(NULL, sep, &brkt)) { 2547 if (narg >= 64) { 2548 ptrerr = "Too many arguments"; 2549 goto done; 2550 } 2551 parg[narg++] = word; 2552 } 2553 ptrerr = parse_options(narg, parg, 0); 2554 done: 2555 if (ptrerr != NULL) { 2556 strlcpy(str, ptrerr, VIRTUAL_OSS_OPTIONS_MAX); 2557 } else { 2558 str[0] = 0; 2559 create_threads(); 2560 } 2561 } 2562 2563 int 2564 main(int argc, char **argv) 2565 { 2566 const char *ptrerr; 2567 struct sigaction sa; 2568 struct cuse_dev *pdev = NULL; 2569 struct virtual_profile *pvp; 2570 struct group *gr; 2571 2572 /* Devices can be used only by users who part of the audio group. */ 2573 if ((gr = getgrnam("audio")) == NULL) 2574 err(EX_USAGE, "getgrnam"); 2575 voss_gid = gr->gr_gid; 2576 2577 TAILQ_INIT(&virtual_profile_client_head); 2578 TAILQ_INIT(&virtual_profile_loopback_head); 2579 2580 TAILQ_INIT(&virtual_monitor_input); 2581 TAILQ_INIT(&virtual_monitor_output); 2582 TAILQ_INIT(&virtual_monitor_local); 2583 2584 atomic_init(); 2585 2586 if (kldload("cuse.ko") < 0 && errno != EEXIST) 2587 err(1, "Failed to load cuse kernel module"); 2588 2589 if (cuse_init() != 0) 2590 errx(EX_USAGE, "Could not connect to cuse module"); 2591 2592 signal(SIGPIPE, &virtual_pipe); 2593 2594 memset(&sa, 0, sizeof(sa)); 2595 sigfillset(&sa.sa_mask); 2596 sa.sa_handler = virtual_sig_exit; 2597 if (sigaction(SIGINT, &sa, NULL) < 0) 2598 err(1, "sigaction(SIGINT)"); 2599 if (sigaction(SIGTERM, &sa, NULL) < 0) 2600 err(1, "sigaction(SIGTERM)"); 2601 2602 ptrerr = parse_options(argc, argv, 1); 2603 if (ptrerr != NULL) 2604 errx(EX_USAGE, "%s", ptrerr); 2605 2606 if (voss_dsp_rx_device[0] == 0 || voss_dsp_tx_device[0] == 0) 2607 errx(EX_USAGE, "Missing -f argument"); 2608 2609 /* use DSP channels as default */ 2610 if (voss_mix_channels == 0) 2611 voss_mix_channels = voss_dsp_max_channels; 2612 2613 if (voss_mix_channels > voss_dsp_max_channels) 2614 voss_max_channels = voss_mix_channels; 2615 else 2616 voss_max_channels = voss_dsp_max_channels; 2617 2618 if (voss_dsp_samples > (voss_dsp_sample_rate / 4)) 2619 errx(EX_USAGE, "Too many buffer samples given by -s argument"); 2620 2621 /* check if daemon mode is requested */ 2622 if (voss_do_background != 0 && daemon(0, 0) != 0) 2623 errx(EX_SOFTWARE, "Cannot become daemon"); 2624 2625 if (voss_pid_path != NULL) { 2626 int pidfile = open(voss_pid_path, O_RDWR | O_CREAT | O_TRUNC, 0600); 2627 pid_t mypid = getpid(); 2628 char mypidstr[8]; 2629 snprintf(mypidstr, sizeof(mypidstr), "%d\n", mypid); 2630 if (pidfile < 0) 2631 errx(EX_SOFTWARE, "Cannot create PID file '%s'", voss_pid_path); 2632 if (write(pidfile, mypidstr, strlen(mypidstr)) != 2633 (ssize_t)strlen(mypidstr)) 2634 errx(EX_SOFTWARE, "Cannot write PID file"); 2635 close(pidfile); 2636 } 2637 2638 /* setup audio delay unit */ 2639 voss_ad_init(voss_dsp_sample_rate); 2640 2641 /* Create CTL device */ 2642 2643 if (voss_ctl_device[0] != 0) { 2644 pdev = cuse_dev_create(&vctl_methods, NULL, NULL, 2645 0, voss_gid, voss_perm, voss_ctl_device); 2646 if (pdev == NULL) 2647 errx(EX_USAGE, "Could not create '/dev/%s'", voss_ctl_device); 2648 2649 voss_dups++; 2650 } 2651 2652 /* Create worker threads */ 2653 create_threads(); 2654 2655 /* Run DSP threads */ 2656 2657 virtual_oss_process(NULL); 2658 2659 destroy_threads(); 2660 2661 /* Destroy CUSE devices */ 2662 2663 if (voss_ctl_device[0] != 0) 2664 cuse_dev_destroy(pdev); 2665 2666 TAILQ_FOREACH(pvp, &virtual_profile_client_head, entry) { 2667 cleanup_profile(pvp); 2668 } 2669 TAILQ_FOREACH(pvp, &virtual_profile_loopback_head, entry) { 2670 cleanup_profile(pvp); 2671 } 2672 2673 cuse_uninit(); 2674 close(voss_fd_sta); 2675 2676 return (0); 2677 } 2678