1 /* pcm.c 2 ** 3 ** Copyright 2011, The Android Open Source Project 4 ** 5 ** Redistribution and use in source and binary forms, with or without 6 ** modification, are permitted provided that the following conditions are met: 7 ** * Redistributions of source code must retain the above copyright 8 ** notice, this list of conditions and the following disclaimer. 9 ** * Redistributions in binary form must reproduce the above copyright 10 ** notice, this list of conditions and the following disclaimer in the 11 ** documentation and/or other materials provided with the distribution. 12 ** * Neither the name of The Android Open Source Project nor the names of 13 ** its contributors may be used to endorse or promote products derived 14 ** from this software without specific prior written permission. 15 ** 16 ** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND 17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 ** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE 20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 ** DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <fcntl.h> 32 #include <stdarg.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <poll.h> 37 38 #include <sys/ioctl.h> 39 #include <sys/mman.h> 40 #include <sys/time.h> 41 #include <limits.h> 42 43 #include <linux/ioctl.h> 44 #define __force 45 #define __bitwise 46 #define __user 47 #include <sound/asound.h> 48 49 #include <tinyalsa/asoundlib.h> 50 51 #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL 52 #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) 53 54 /* Logs information into a string; follows snprintf() in that 55 * offset may be greater than size, and though no characters are copied 56 * into string, characters are still counted into offset. */ 57 #define STRLOG(string, offset, size, ...) \ 58 do { int temp, clipoffset = offset > size ? size : offset; \ 59 temp = snprintf(string + clipoffset, size - clipoffset, __VA_ARGS__); \ 60 if (temp > 0) offset += temp; } while (0) 61 62 #ifndef ARRAY_SIZE 63 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 64 #endif 65 66 /* refer to SNDRV_PCM_ACCESS_##index in sound/asound.h. */ 67 static const char * const access_lookup[] = { 68 "MMAP_INTERLEAVED", 69 "MMAP_NONINTERLEAVED", 70 "MMAP_COMPLEX", 71 "RW_INTERLEAVED", 72 "RW_NONINTERLEAVED", 73 }; 74 75 /* refer to SNDRV_PCM_FORMAT_##index in sound/asound.h. */ 76 static const char * const format_lookup[] = { 77 /*[0] =*/ "S8", 78 "U8", 79 "S16_LE", 80 "S16_BE", 81 "U16_LE", 82 "U16_BE", 83 "S24_LE", 84 "S24_BE", 85 "U24_LE", 86 "U24_BE", 87 "S32_LE", 88 "S32_BE", 89 "U32_LE", 90 "U32_BE", 91 "FLOAT_LE", 92 "FLOAT_BE", 93 "FLOAT64_LE", 94 "FLOAT64_BE", 95 "IEC958_SUBFRAME_LE", 96 "IEC958_SUBFRAME_BE", 97 "MU_LAW", 98 "A_LAW", 99 "IMA_ADPCM", 100 "MPEG", 101 /*[24] =*/ "GSM", 102 /* gap */ 103 [31] = "SPECIAL", 104 "S24_3LE", 105 "S24_3BE", 106 "U24_3LE", 107 "U24_3BE", 108 "S20_3LE", 109 "S20_3BE", 110 "U20_3LE", 111 "U20_3BE", 112 "S18_3LE", 113 "S18_3BE", 114 "U18_3LE", 115 /*[43] =*/ "U18_3BE", 116 #if 0 117 /* recent additions, may not be present on local asound.h */ 118 "G723_24", 119 "G723_24_1B", 120 "G723_40", 121 "G723_40_1B", 122 "DSD_U8", 123 "DSD_U16_LE", 124 #endif 125 }; 126 127 /* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */ 128 static const char * const subformat_lookup[] = { 129 "STD", 130 }; 131 132 static inline int param_is_mask(int p) 133 { 134 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && 135 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); 136 } 137 138 static inline int param_is_interval(int p) 139 { 140 return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) && 141 (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL); 142 } 143 144 static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n) 145 { 146 return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]); 147 } 148 149 static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n) 150 { 151 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); 152 } 153 154 static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit) 155 { 156 if (bit >= SNDRV_MASK_MAX) 157 return; 158 if (param_is_mask(n)) { 159 struct snd_mask *m = param_to_mask(p, n); 160 m->bits[0] = 0; 161 m->bits[1] = 0; 162 m->bits[bit >> 5] |= (1 << (bit & 31)); 163 } 164 } 165 166 static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val) 167 { 168 if (param_is_interval(n)) { 169 struct snd_interval *i = param_to_interval(p, n); 170 i->min = val; 171 } 172 } 173 174 static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n) 175 { 176 if (param_is_interval(n)) { 177 struct snd_interval *i = param_to_interval(p, n); 178 return i->min; 179 } 180 return 0; 181 } 182 183 static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned int val) 184 { 185 if (param_is_interval(n)) { 186 struct snd_interval *i = param_to_interval(p, n); 187 i->max = val; 188 } 189 } 190 191 static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n) 192 { 193 if (param_is_interval(n)) { 194 struct snd_interval *i = param_to_interval(p, n); 195 return i->max; 196 } 197 return 0; 198 } 199 200 static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val) 201 { 202 if (param_is_interval(n)) { 203 struct snd_interval *i = param_to_interval(p, n); 204 i->min = val; 205 i->max = val; 206 i->integer = 1; 207 } 208 } 209 210 static unsigned int param_get_int(struct snd_pcm_hw_params *p, int n) 211 { 212 if (param_is_interval(n)) { 213 struct snd_interval *i = param_to_interval(p, n); 214 if (i->integer) 215 return i->max; 216 } 217 return 0; 218 } 219 220 static void param_init(struct snd_pcm_hw_params *p) 221 { 222 int n; 223 224 memset(p, 0, sizeof(*p)); 225 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; 226 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { 227 struct snd_mask *m = param_to_mask(p, n); 228 m->bits[0] = ~0; 229 m->bits[1] = ~0; 230 } 231 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; 232 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { 233 struct snd_interval *i = param_to_interval(p, n); 234 i->min = 0; 235 i->max = ~0; 236 } 237 p->rmask = ~0U; 238 p->cmask = 0; 239 p->info = ~0U; 240 } 241 242 #define PCM_ERROR_MAX 128 243 244 struct pcm { 245 int fd; 246 unsigned int flags; 247 int running:1; 248 int prepared:1; 249 int underruns; 250 unsigned int buffer_size; 251 unsigned int boundary; 252 char error[PCM_ERROR_MAX]; 253 struct pcm_config config; 254 struct snd_pcm_mmap_status *mmap_status; 255 struct snd_pcm_mmap_control *mmap_control; 256 struct snd_pcm_sync_ptr *sync_ptr; 257 void *mmap_buffer; 258 unsigned int noirq_frames_per_msec; 259 int wait_for_avail_min; 260 }; 261 262 unsigned int pcm_get_buffer_size(struct pcm *pcm) 263 { 264 return pcm->buffer_size; 265 } 266 267 const char* pcm_get_error(struct pcm *pcm) 268 { 269 return pcm->error; 270 } 271 272 static int oops(struct pcm *pcm, int e, const char *fmt, ...) 273 { 274 va_list ap; 275 int sz; 276 277 va_start(ap, fmt); 278 vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap); 279 va_end(ap); 280 sz = strlen(pcm->error); 281 282 if (errno) 283 snprintf(pcm->error + sz, PCM_ERROR_MAX - sz, 284 ": %s", strerror(e)); 285 return -1; 286 } 287 288 static unsigned int pcm_format_to_alsa(enum pcm_format format) 289 { 290 switch (format) { 291 case PCM_FORMAT_S32_LE: 292 return SNDRV_PCM_FORMAT_S32_LE; 293 case PCM_FORMAT_S8: 294 return SNDRV_PCM_FORMAT_S8; 295 case PCM_FORMAT_S24_3LE: 296 return SNDRV_PCM_FORMAT_S24_3LE; 297 case PCM_FORMAT_S24_LE: 298 return SNDRV_PCM_FORMAT_S24_LE; 299 default: 300 case PCM_FORMAT_S16_LE: 301 return SNDRV_PCM_FORMAT_S16_LE; 302 }; 303 } 304 305 unsigned int pcm_format_to_bits(enum pcm_format format) 306 { 307 switch (format) { 308 case PCM_FORMAT_S32_LE: 309 case PCM_FORMAT_S24_LE: 310 return 32; 311 case PCM_FORMAT_S24_3LE: 312 return 24; 313 default: 314 case PCM_FORMAT_S16_LE: 315 return 16; 316 }; 317 } 318 319 unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes) 320 { 321 return bytes / (pcm->config.channels * 322 (pcm_format_to_bits(pcm->config.format) >> 3)); 323 } 324 325 unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames) 326 { 327 return frames * pcm->config.channels * 328 (pcm_format_to_bits(pcm->config.format) >> 3); 329 } 330 331 static int pcm_sync_ptr(struct pcm *pcm, int flags) { 332 if (pcm->sync_ptr) { 333 pcm->sync_ptr->flags = flags; 334 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0) 335 return -1; 336 } 337 return 0; 338 } 339 340 static int pcm_hw_mmap_status(struct pcm *pcm) { 341 342 if (pcm->sync_ptr) 343 return 0; 344 345 int page_size = sysconf(_SC_PAGE_SIZE); 346 pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED, 347 pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); 348 if (pcm->mmap_status == MAP_FAILED) 349 pcm->mmap_status = NULL; 350 if (!pcm->mmap_status) 351 goto mmap_error; 352 353 pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE, 354 MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); 355 if (pcm->mmap_control == MAP_FAILED) 356 pcm->mmap_control = NULL; 357 if (!pcm->mmap_control) { 358 munmap(pcm->mmap_status, page_size); 359 pcm->mmap_status = NULL; 360 goto mmap_error; 361 } 362 if (pcm->flags & PCM_MMAP) 363 pcm->mmap_control->avail_min = pcm->config.avail_min; 364 else 365 pcm->mmap_control->avail_min = 1; 366 367 return 0; 368 369 mmap_error: 370 371 pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr)); 372 if (!pcm->sync_ptr) 373 return -ENOMEM; 374 pcm->mmap_status = &pcm->sync_ptr->s.status; 375 pcm->mmap_control = &pcm->sync_ptr->c.control; 376 if (pcm->flags & PCM_MMAP) 377 pcm->mmap_control->avail_min = pcm->config.avail_min; 378 else 379 pcm->mmap_control->avail_min = 1; 380 381 pcm_sync_ptr(pcm, 0); 382 383 return 0; 384 } 385 386 static void pcm_hw_munmap_status(struct pcm *pcm) { 387 if (pcm->sync_ptr) { 388 free(pcm->sync_ptr); 389 pcm->sync_ptr = NULL; 390 } else { 391 int page_size = sysconf(_SC_PAGE_SIZE); 392 if (pcm->mmap_status) 393 munmap(pcm->mmap_status, page_size); 394 if (pcm->mmap_control) 395 munmap(pcm->mmap_control, page_size); 396 } 397 pcm->mmap_status = NULL; 398 pcm->mmap_control = NULL; 399 } 400 401 static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset, 402 char *buf, unsigned int src_offset, 403 unsigned int frames) 404 { 405 int size_bytes = pcm_frames_to_bytes(pcm, frames); 406 int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset); 407 int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset); 408 409 /* interleaved only atm */ 410 if (pcm->flags & PCM_IN) 411 memcpy(buf + src_offset_bytes, 412 (char*)pcm->mmap_buffer + pcm_offset_bytes, 413 size_bytes); 414 else 415 memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes, 416 buf + src_offset_bytes, 417 size_bytes); 418 return 0; 419 } 420 421 static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf, 422 unsigned int offset, unsigned int size) 423 { 424 void *pcm_areas; 425 int commit; 426 unsigned int pcm_offset, frames, count = 0; 427 428 while (size > 0) { 429 frames = size; 430 pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); 431 pcm_areas_copy(pcm, pcm_offset, buf, offset, frames); 432 commit = pcm_mmap_commit(pcm, pcm_offset, frames); 433 if (commit < 0) { 434 oops(pcm, commit, "failed to commit %d frames\n", frames); 435 return commit; 436 } 437 438 offset += commit; 439 count += commit; 440 size -= commit; 441 } 442 return count; 443 } 444 445 int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, 446 struct timespec *tstamp) 447 { 448 int frames; 449 int rc; 450 snd_pcm_uframes_t hw_ptr; 451 452 if (!pcm_is_ready(pcm)) 453 return -1; 454 455 rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC); 456 if (rc < 0) 457 return -1; 458 459 if ((pcm->mmap_status->state != PCM_STATE_RUNNING) && 460 (pcm->mmap_status->state != PCM_STATE_DRAINING)) 461 return -1; 462 463 *tstamp = pcm->mmap_status->tstamp; 464 if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0) 465 return -1; 466 467 hw_ptr = pcm->mmap_status->hw_ptr; 468 if (pcm->flags & PCM_IN) 469 frames = hw_ptr - pcm->mmap_control->appl_ptr; 470 else 471 frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; 472 473 if (frames < 0) 474 frames += pcm->boundary; 475 else if (frames > (int)pcm->boundary) 476 frames -= pcm->boundary; 477 478 *avail = (unsigned int)frames; 479 480 return 0; 481 } 482 483 int pcm_write(struct pcm *pcm, const void *data, unsigned int count) 484 { 485 struct snd_xferi x; 486 487 if (pcm->flags & PCM_IN) 488 return -EINVAL; 489 490 x.buf = (void*)data; 491 x.frames = count / (pcm->config.channels * 492 pcm_format_to_bits(pcm->config.format) / 8); 493 494 for (;;) { 495 if (!pcm->running) { 496 int prepare_error = pcm_prepare(pcm); 497 if (prepare_error) 498 return prepare_error; 499 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) 500 return oops(pcm, errno, "cannot write initial data"); 501 pcm->running = 1; 502 return 0; 503 } 504 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { 505 pcm->prepared = 0; 506 pcm->running = 0; 507 if (errno == EPIPE) { 508 /* we failed to make our window -- try to restart if we are 509 * allowed to do so. Otherwise, simply allow the EPIPE error to 510 * propagate up to the app level */ 511 pcm->underruns++; 512 if (pcm->flags & PCM_NORESTART) 513 return -EPIPE; 514 continue; 515 } 516 return oops(pcm, errno, "cannot write stream data"); 517 } 518 return 0; 519 } 520 } 521 522 int pcm_read(struct pcm *pcm, void *data, unsigned int count) 523 { 524 struct snd_xferi x; 525 526 if (!(pcm->flags & PCM_IN)) 527 return -EINVAL; 528 529 x.buf = data; 530 x.frames = count / (pcm->config.channels * 531 pcm_format_to_bits(pcm->config.format) / 8); 532 533 for (;;) { 534 if (!pcm->running) { 535 if (pcm_start(pcm) < 0) { 536 fprintf(stderr, "start error"); 537 return -errno; 538 } 539 } 540 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { 541 pcm->prepared = 0; 542 pcm->running = 0; 543 if (errno == EPIPE) { 544 /* we failed to make our window -- try to restart */ 545 pcm->underruns++; 546 continue; 547 } 548 return oops(pcm, errno, "cannot read stream data"); 549 } 550 return 0; 551 } 552 } 553 554 static struct pcm bad_pcm = { 555 .fd = -1, 556 }; 557 558 struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, 559 unsigned int flags) 560 { 561 struct snd_pcm_hw_params *params; 562 char fn[256]; 563 int fd; 564 565 snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device, 566 flags & PCM_IN ? 'c' : 'p'); 567 568 fd = open(fn, O_RDWR); 569 if (fd < 0) { 570 fprintf(stderr, "cannot open device '%s'\n", fn); 571 goto err_open; 572 } 573 574 params = calloc(1, sizeof(struct snd_pcm_hw_params)); 575 if (!params) 576 goto err_calloc; 577 578 param_init(params); 579 if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) { 580 fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno); 581 goto err_hw_refine; 582 } 583 584 close(fd); 585 586 return (struct pcm_params *)params; 587 588 err_hw_refine: 589 free(params); 590 err_calloc: 591 close(fd); 592 err_open: 593 return NULL; 594 } 595 596 void pcm_params_free(struct pcm_params *pcm_params) 597 { 598 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 599 600 if (params) 601 free(params); 602 } 603 604 static int pcm_param_to_alsa(enum pcm_param param) 605 { 606 switch (param) { 607 case PCM_PARAM_ACCESS: 608 return SNDRV_PCM_HW_PARAM_ACCESS; 609 case PCM_PARAM_FORMAT: 610 return SNDRV_PCM_HW_PARAM_FORMAT; 611 case PCM_PARAM_SUBFORMAT: 612 return SNDRV_PCM_HW_PARAM_SUBFORMAT; 613 case PCM_PARAM_SAMPLE_BITS: 614 return SNDRV_PCM_HW_PARAM_SAMPLE_BITS; 615 break; 616 case PCM_PARAM_FRAME_BITS: 617 return SNDRV_PCM_HW_PARAM_FRAME_BITS; 618 break; 619 case PCM_PARAM_CHANNELS: 620 return SNDRV_PCM_HW_PARAM_CHANNELS; 621 break; 622 case PCM_PARAM_RATE: 623 return SNDRV_PCM_HW_PARAM_RATE; 624 break; 625 case PCM_PARAM_PERIOD_TIME: 626 return SNDRV_PCM_HW_PARAM_PERIOD_TIME; 627 break; 628 case PCM_PARAM_PERIOD_SIZE: 629 return SNDRV_PCM_HW_PARAM_PERIOD_SIZE; 630 break; 631 case PCM_PARAM_PERIOD_BYTES: 632 return SNDRV_PCM_HW_PARAM_PERIOD_BYTES; 633 break; 634 case PCM_PARAM_PERIODS: 635 return SNDRV_PCM_HW_PARAM_PERIODS; 636 break; 637 case PCM_PARAM_BUFFER_TIME: 638 return SNDRV_PCM_HW_PARAM_BUFFER_TIME; 639 break; 640 case PCM_PARAM_BUFFER_SIZE: 641 return SNDRV_PCM_HW_PARAM_BUFFER_SIZE; 642 break; 643 case PCM_PARAM_BUFFER_BYTES: 644 return SNDRV_PCM_HW_PARAM_BUFFER_BYTES; 645 break; 646 case PCM_PARAM_TICK_TIME: 647 return SNDRV_PCM_HW_PARAM_TICK_TIME; 648 break; 649 650 default: 651 return -1; 652 } 653 } 654 655 struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, 656 enum pcm_param param) 657 { 658 int p; 659 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 660 if (params == NULL) { 661 return NULL; 662 } 663 664 p = pcm_param_to_alsa(param); 665 if (p < 0 || !param_is_mask(p)) { 666 return NULL; 667 } 668 669 return (struct pcm_mask *)param_to_mask(params, p); 670 } 671 672 unsigned int pcm_params_get_min(struct pcm_params *pcm_params, 673 enum pcm_param param) 674 { 675 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 676 int p; 677 678 if (!params) 679 return 0; 680 681 p = pcm_param_to_alsa(param); 682 if (p < 0) 683 return 0; 684 685 return param_get_min(params, p); 686 } 687 688 void pcm_params_set_min(struct pcm_params *pcm_params, 689 enum pcm_param param, unsigned int val) 690 { 691 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 692 int p; 693 694 if (!params) 695 return; 696 697 p = pcm_param_to_alsa(param); 698 if (p < 0) 699 return; 700 701 param_set_min(params, p, val); 702 } 703 704 unsigned int pcm_params_get_max(struct pcm_params *pcm_params, 705 enum pcm_param param) 706 { 707 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 708 int p; 709 710 if (!params) 711 return 0; 712 713 p = pcm_param_to_alsa(param); 714 if (p < 0) 715 return 0; 716 717 return param_get_max(params, p); 718 } 719 720 void pcm_params_set_max(struct pcm_params *pcm_params, 721 enum pcm_param param, unsigned int val) 722 { 723 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; 724 int p; 725 726 if (!params) 727 return; 728 729 p = pcm_param_to_alsa(param); 730 if (p < 0) 731 return; 732 733 param_set_max(params, p, val); 734 } 735 736 static int pcm_mask_test(struct pcm_mask *m, unsigned int index) 737 { 738 const unsigned int bitshift = 5; /* for 32 bit integer */ 739 const unsigned int bitmask = (1 << bitshift) - 1; 740 unsigned int element; 741 742 element = index >> bitshift; 743 if (element >= ARRAY_SIZE(m->bits)) 744 return 0; /* for safety, but should never occur */ 745 return (m->bits[element] >> (index & bitmask)) & 1; 746 } 747 748 static int pcm_mask_to_string(struct pcm_mask *m, char *string, unsigned int size, 749 char *mask_name, 750 const char * const *bit_array_name, size_t bit_array_size) 751 { 752 unsigned int i; 753 unsigned int offset = 0; 754 755 if (m == NULL) 756 return 0; 757 if (bit_array_size < 32) { 758 STRLOG(string, offset, size, "%12s:\t%#08x\n", mask_name, m->bits[0]); 759 } else { /* spans two or more bitfields, print with an array index */ 760 for (i = 0; i < (bit_array_size + 31) >> 5; ++i) { 761 STRLOG(string, offset, size, "%9s[%d]:\t%#08x\n", 762 mask_name, i, m->bits[i]); 763 } 764 } 765 for (i = 0; i < bit_array_size; ++i) { 766 if (pcm_mask_test(m, i)) { 767 STRLOG(string, offset, size, "%12s \t%s\n", "", bit_array_name[i]); 768 } 769 } 770 return offset; 771 } 772 773 int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size) 774 { 775 struct pcm_mask *m; 776 unsigned int min, max; 777 unsigned int clipoffset, offset; 778 779 m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); 780 offset = pcm_mask_to_string(m, string, size, 781 "Access", access_lookup, ARRAY_SIZE(access_lookup)); 782 m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); 783 clipoffset = offset > size ? size : offset; 784 offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, 785 "Format", format_lookup, ARRAY_SIZE(format_lookup)); 786 m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); 787 clipoffset = offset > size ? size : offset; 788 offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, 789 "Subformat", subformat_lookup, ARRAY_SIZE(subformat_lookup)); 790 min = pcm_params_get_min(params, PCM_PARAM_RATE); 791 max = pcm_params_get_max(params, PCM_PARAM_RATE); 792 STRLOG(string, offset, size, " Rate:\tmin=%uHz\tmax=%uHz\n", min, max); 793 min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); 794 max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); 795 STRLOG(string, offset, size, " Channels:\tmin=%u\t\tmax=%u\n", min, max); 796 min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); 797 max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); 798 STRLOG(string, offset, size, " Sample bits:\tmin=%u\t\tmax=%u\n", min, max); 799 min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); 800 max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); 801 STRLOG(string, offset, size, " Period size:\tmin=%u\t\tmax=%u\n", min, max); 802 min = pcm_params_get_min(params, PCM_PARAM_PERIODS); 803 max = pcm_params_get_max(params, PCM_PARAM_PERIODS); 804 STRLOG(string, offset, size, "Period count:\tmin=%u\t\tmax=%u\n", min, max); 805 return offset; 806 } 807 808 int pcm_params_format_test(struct pcm_params *params, enum pcm_format format) 809 { 810 unsigned int alsa_format = pcm_format_to_alsa(format); 811 812 if (alsa_format == SNDRV_PCM_FORMAT_S16_LE && format != PCM_FORMAT_S16_LE) 813 return 0; /* caution: format not recognized is equivalent to S16_LE */ 814 return pcm_mask_test(pcm_params_get_mask(params, PCM_PARAM_FORMAT), alsa_format); 815 } 816 817 int pcm_close(struct pcm *pcm) 818 { 819 if (pcm == &bad_pcm) 820 return 0; 821 822 pcm_hw_munmap_status(pcm); 823 824 if (pcm->flags & PCM_MMAP) { 825 pcm_stop(pcm); 826 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); 827 } 828 829 if (pcm->fd >= 0) 830 close(pcm->fd); 831 pcm->prepared = 0; 832 pcm->running = 0; 833 pcm->buffer_size = 0; 834 pcm->fd = -1; 835 free(pcm); 836 return 0; 837 } 838 839 struct pcm *pcm_open(unsigned int card, unsigned int device, 840 unsigned int flags, struct pcm_config *config) 841 { 842 struct pcm *pcm; 843 struct snd_pcm_info info; 844 struct snd_pcm_hw_params params; 845 struct snd_pcm_sw_params sparams; 846 char fn[256]; 847 int rc; 848 849 pcm = calloc(1, sizeof(struct pcm)); 850 if (!pcm || !config) 851 return &bad_pcm; /* TODO: could support default config here */ 852 853 pcm->config = *config; 854 855 snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device, 856 flags & PCM_IN ? 'c' : 'p'); 857 858 pcm->flags = flags; 859 pcm->fd = open(fn, O_RDWR); 860 if (pcm->fd < 0) { 861 oops(pcm, errno, "cannot open device '%s'", fn); 862 return pcm; 863 } 864 865 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) { 866 oops(pcm, errno, "cannot get info"); 867 goto fail_close; 868 } 869 870 param_init(¶ms); 871 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, 872 pcm_format_to_alsa(config->format)); 873 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT, 874 SNDRV_PCM_SUBFORMAT_STD); 875 param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size); 876 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 877 pcm_format_to_bits(config->format)); 878 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS, 879 pcm_format_to_bits(config->format) * config->channels); 880 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, 881 config->channels); 882 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count); 883 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, config->rate); 884 885 if (flags & PCM_NOIRQ) { 886 if (!(flags & PCM_MMAP)) { 887 oops(pcm, -EINVAL, "noirq only currently supported with mmap()."); 888 goto fail; 889 } 890 891 params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP; 892 pcm->noirq_frames_per_msec = config->rate / 1000; 893 } 894 895 if (flags & PCM_MMAP) 896 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, 897 SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); 898 else 899 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, 900 SNDRV_PCM_ACCESS_RW_INTERLEAVED); 901 902 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) { 903 oops(pcm, errno, "cannot set hw params"); 904 goto fail_close; 905 } 906 907 /* get our refined hw_params */ 908 config->period_size = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 909 config->period_count = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS); 910 pcm->buffer_size = config->period_count * config->period_size; 911 912 if (flags & PCM_MMAP) { 913 pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size), 914 PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0); 915 if (pcm->mmap_buffer == MAP_FAILED) { 916 oops(pcm, -errno, "failed to mmap buffer %d bytes\n", 917 pcm_frames_to_bytes(pcm, pcm->buffer_size)); 918 goto fail_close; 919 } 920 } 921 922 memset(&sparams, 0, sizeof(sparams)); 923 sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE; 924 sparams.period_step = 1; 925 926 if (!config->start_threshold) { 927 if (pcm->flags & PCM_IN) 928 pcm->config.start_threshold = sparams.start_threshold = 1; 929 else 930 pcm->config.start_threshold = sparams.start_threshold = 931 config->period_count * config->period_size / 2; 932 } else 933 sparams.start_threshold = config->start_threshold; 934 935 /* pick a high stop threshold - todo: does this need further tuning */ 936 if (!config->stop_threshold) { 937 if (pcm->flags & PCM_IN) 938 pcm->config.stop_threshold = sparams.stop_threshold = 939 config->period_count * config->period_size * 10; 940 else 941 pcm->config.stop_threshold = sparams.stop_threshold = 942 config->period_count * config->period_size; 943 } 944 else 945 sparams.stop_threshold = config->stop_threshold; 946 947 if (!pcm->config.avail_min) { 948 if (pcm->flags & PCM_MMAP) 949 pcm->config.avail_min = sparams.avail_min = pcm->config.period_size; 950 else 951 pcm->config.avail_min = sparams.avail_min = 1; 952 } else 953 sparams.avail_min = config->avail_min; 954 955 sparams.xfer_align = config->period_size / 2; /* needed for old kernels */ 956 sparams.silence_size = 0; 957 sparams.silence_threshold = config->silence_threshold; 958 pcm->boundary = sparams.boundary = pcm->buffer_size; 959 960 while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size) 961 pcm->boundary *= 2; 962 963 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) { 964 oops(pcm, errno, "cannot set sw params"); 965 goto fail; 966 } 967 968 rc = pcm_hw_mmap_status(pcm); 969 if (rc < 0) { 970 oops(pcm, rc, "mmap status failed"); 971 goto fail; 972 } 973 974 #ifdef SNDRV_PCM_IOCTL_TTSTAMP 975 if (pcm->flags & PCM_MONOTONIC) { 976 int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; 977 rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg); 978 if (rc < 0) { 979 oops(pcm, rc, "cannot set timestamp type"); 980 goto fail; 981 } 982 } 983 #endif 984 985 pcm->underruns = 0; 986 return pcm; 987 988 fail: 989 if (flags & PCM_MMAP) 990 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); 991 fail_close: 992 close(pcm->fd); 993 pcm->fd = -1; 994 return pcm; 995 } 996 997 int pcm_is_ready(struct pcm *pcm) 998 { 999 return pcm->fd >= 0; 1000 } 1001 1002 int pcm_prepare(struct pcm *pcm) 1003 { 1004 if (pcm->prepared) 1005 return 0; 1006 1007 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0) 1008 return oops(pcm, errno, "cannot prepare channel"); 1009 1010 pcm->prepared = 1; 1011 return 0; 1012 } 1013 1014 int pcm_start(struct pcm *pcm) 1015 { 1016 int prepare_error = pcm_prepare(pcm); 1017 if (prepare_error) 1018 return prepare_error; 1019 1020 if (pcm->flags & PCM_MMAP) 1021 pcm_sync_ptr(pcm, 0); 1022 1023 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0) 1024 return oops(pcm, errno, "cannot start channel"); 1025 1026 pcm->running = 1; 1027 return 0; 1028 } 1029 1030 int pcm_stop(struct pcm *pcm) 1031 { 1032 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) 1033 return oops(pcm, errno, "cannot stop channel"); 1034 1035 pcm->prepared = 0; 1036 pcm->running = 0; 1037 return 0; 1038 } 1039 1040 static inline int pcm_mmap_playback_avail(struct pcm *pcm) 1041 { 1042 int avail; 1043 1044 avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; 1045 1046 if (avail < 0) 1047 avail += pcm->boundary; 1048 else if (avail > (int)pcm->boundary) 1049 avail -= pcm->boundary; 1050 1051 return avail; 1052 } 1053 1054 static inline int pcm_mmap_capture_avail(struct pcm *pcm) 1055 { 1056 int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr; 1057 if (avail < 0) 1058 avail += pcm->boundary; 1059 return avail; 1060 } 1061 1062 static inline int pcm_mmap_avail(struct pcm *pcm) 1063 { 1064 pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC); 1065 if (pcm->flags & PCM_IN) 1066 return pcm_mmap_capture_avail(pcm); 1067 else 1068 return pcm_mmap_playback_avail(pcm); 1069 } 1070 1071 static void pcm_mmap_appl_forward(struct pcm *pcm, int frames) 1072 { 1073 unsigned int appl_ptr = pcm->mmap_control->appl_ptr; 1074 appl_ptr += frames; 1075 1076 /* check for boundary wrap */ 1077 if (appl_ptr > pcm->boundary) 1078 appl_ptr -= pcm->boundary; 1079 pcm->mmap_control->appl_ptr = appl_ptr; 1080 } 1081 1082 int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, 1083 unsigned int *frames) 1084 { 1085 unsigned int continuous, copy_frames, avail; 1086 1087 /* return the mmap buffer */ 1088 *areas = pcm->mmap_buffer; 1089 1090 /* and the application offset in frames */ 1091 *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size; 1092 1093 avail = pcm_mmap_avail(pcm); 1094 if (avail > pcm->buffer_size) 1095 avail = pcm->buffer_size; 1096 continuous = pcm->buffer_size - *offset; 1097 1098 /* we can only copy frames if the are availabale and continuos */ 1099 copy_frames = *frames; 1100 if (copy_frames > avail) 1101 copy_frames = avail; 1102 if (copy_frames > continuous) 1103 copy_frames = continuous; 1104 *frames = copy_frames; 1105 1106 return 0; 1107 } 1108 1109 int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames) 1110 { 1111 /* update the application pointer in userspace and kernel */ 1112 pcm_mmap_appl_forward(pcm, frames); 1113 pcm_sync_ptr(pcm, 0); 1114 1115 return frames; 1116 } 1117 1118 int pcm_avail_update(struct pcm *pcm) 1119 { 1120 pcm_sync_ptr(pcm, 0); 1121 return pcm_mmap_avail(pcm); 1122 } 1123 1124 int pcm_state(struct pcm *pcm) 1125 { 1126 int err = pcm_sync_ptr(pcm, 0); 1127 if (err < 0) 1128 return err; 1129 1130 return pcm->mmap_status->state; 1131 } 1132 1133 int pcm_set_avail_min(struct pcm *pcm, int avail_min) 1134 { 1135 if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ)) 1136 return -ENOSYS; 1137 1138 pcm->config.avail_min = avail_min; 1139 return 0; 1140 } 1141 1142 int pcm_wait(struct pcm *pcm, int timeout) 1143 { 1144 struct pollfd pfd; 1145 int err; 1146 1147 pfd.fd = pcm->fd; 1148 pfd.events = POLLOUT | POLLERR | POLLNVAL; 1149 1150 do { 1151 /* let's wait for avail or timeout */ 1152 err = poll(&pfd, 1, timeout); 1153 if (err < 0) 1154 return -errno; 1155 1156 /* timeout ? */ 1157 if (err == 0) 1158 return 0; 1159 1160 /* have we been interrupted ? */ 1161 if (errno == -EINTR) 1162 continue; 1163 1164 /* check for any errors */ 1165 if (pfd.revents & (POLLERR | POLLNVAL)) { 1166 switch (pcm_state(pcm)) { 1167 case PCM_STATE_XRUN: 1168 return -EPIPE; 1169 case PCM_STATE_SUSPENDED: 1170 return -ESTRPIPE; 1171 case PCM_STATE_DISCONNECTED: 1172 return -ENODEV; 1173 default: 1174 return -EIO; 1175 } 1176 } 1177 /* poll again if fd not ready for IO */ 1178 } while (!(pfd.revents & (POLLIN | POLLOUT))); 1179 1180 return 1; 1181 } 1182 1183 int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int bytes) 1184 { 1185 int err = 0, frames, avail; 1186 unsigned int offset = 0, count; 1187 1188 if (bytes == 0) 1189 return 0; 1190 1191 count = pcm_bytes_to_frames(pcm, bytes); 1192 1193 while (count > 0) { 1194 1195 /* get the available space for writing new frames */ 1196 avail = pcm_avail_update(pcm); 1197 if (avail < 0) { 1198 fprintf(stderr, "cannot determine available mmap frames"); 1199 return err; 1200 } 1201 1202 /* start the audio if we reach the threshold */ 1203 if (!pcm->running && 1204 (pcm->buffer_size - avail) >= pcm->config.start_threshold) { 1205 if (pcm_start(pcm) < 0) { 1206 fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n", 1207 (unsigned int)pcm->mmap_status->hw_ptr, 1208 (unsigned int)pcm->mmap_control->appl_ptr, 1209 avail); 1210 return -errno; 1211 } 1212 pcm->wait_for_avail_min = 0; 1213 } 1214 1215 /* sleep until we have space to write new frames */ 1216 if (pcm->running) { 1217 /* enable waiting for avail_min threshold when less frames than we have to write 1218 * are available. */ 1219 if (!pcm->wait_for_avail_min && (count > (unsigned int)avail)) 1220 pcm->wait_for_avail_min = 1; 1221 1222 if (pcm->wait_for_avail_min && (avail < pcm->config.avail_min)) { 1223 int time = -1; 1224 1225 /* disable waiting for avail_min threshold to allow small amounts of data to be 1226 * written without waiting as long as there is enough room in buffer. */ 1227 pcm->wait_for_avail_min = 0; 1228 1229 if (pcm->flags & PCM_NOIRQ) 1230 time = (pcm->config.avail_min - avail) / pcm->noirq_frames_per_msec; 1231 1232 err = pcm_wait(pcm, time); 1233 if (err < 0) { 1234 pcm->prepared = 0; 1235 pcm->running = 0; 1236 oops(pcm, err, "wait error: hw 0x%x app 0x%x avail 0x%x\n", 1237 (unsigned int)pcm->mmap_status->hw_ptr, 1238 (unsigned int)pcm->mmap_control->appl_ptr, 1239 avail); 1240 pcm->mmap_control->appl_ptr = 0; 1241 return err; 1242 } 1243 continue; 1244 } 1245 } 1246 1247 frames = count; 1248 if (frames > avail) 1249 frames = avail; 1250 1251 if (!frames) 1252 break; 1253 1254 /* copy frames from buffer */ 1255 frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames); 1256 if (frames < 0) { 1257 fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n", 1258 (unsigned int)pcm->mmap_status->hw_ptr, 1259 (unsigned int)pcm->mmap_control->appl_ptr, 1260 avail); 1261 return frames; 1262 } 1263 1264 offset += frames; 1265 count -= frames; 1266 } 1267 1268 return 0; 1269 } 1270 1271 int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) 1272 { 1273 if ((~pcm->flags) & (PCM_OUT | PCM_MMAP)) 1274 return -ENOSYS; 1275 1276 return pcm_mmap_transfer(pcm, (void *)data, count); 1277 } 1278 1279 int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) 1280 { 1281 if ((~pcm->flags) & (PCM_IN | PCM_MMAP)) 1282 return -ENOSYS; 1283 1284 return pcm_mmap_transfer(pcm, data, count); 1285 } 1286 1287 int pcm_ioctl(struct pcm *pcm, int request, ...) 1288 { 1289 va_list ap; 1290 void * arg; 1291 1292 if (!pcm_is_ready(pcm)) 1293 return -1; 1294 1295 va_start(ap, request); 1296 arg = va_arg(ap, void *); 1297 va_end(ap); 1298 1299 return ioctl(pcm->fd, request, arg); 1300 } 1301