1 /* 2 ** Copyright 2010, The Android Open-Source Project 3 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "alsa_pcm" 19 #define LOG_NDEBUG 1 20 #ifdef ANDROID 21 /* definitions for Android logging */ 22 #include <utils/Log.h> 23 #include <cutils/properties.h> 24 #else /* ANDROID */ 25 #define strlcat g_strlcat 26 #define strlcpy g_strlcpy 27 #define ALOGI(...) fprintf(stdout, __VA_ARGS__) 28 #define ALOGE(...) fprintf(stderr, __VA_ARGS__) 29 #define ALOGV(...) fprintf(stderr, __VA_ARGS__) 30 #endif /* ANDROID */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <fcntl.h> 35 #include <stdarg.h> 36 #include <string.h> 37 #include <errno.h> 38 #include <unistd.h> 39 #include <stdint.h> 40 #include <sys/ioctl.h> 41 #include <sys/mman.h> 42 #include <sys/time.h> 43 #include <sys/poll.h> 44 #include <linux/ioctl.h> 45 #include <linux/types.h> 46 47 #include "alsa_audio.h" 48 49 #define DEBUG 1 50 51 enum format_alias { 52 S8 = 0, 53 U8, 54 S16_LE, 55 S16_BE, 56 U16_LE, 57 U16_BE, 58 S24_LE, 59 S24_BE, 60 U24_LE, 61 U24_BE, 62 S32_LE, 63 S32_BE, 64 U32_LE, 65 U32_BE, 66 FLOAT_LE, 67 FLOAT_BE, 68 FLOAT64_LE, 69 FLOAT64_BE, 70 IEC958_SUBFRAME_LE, 71 IEC958_SUBFRAME_BE, 72 MU_LAW, 73 A_LAW, 74 IMA_ADPCM, 75 MPEG, 76 GSM, 77 SPECIAL = 31, 78 S24_3LE, 79 S24_3BE, 80 U24_3LE, 81 U24_3BE, 82 S20_3LE, 83 S20_3BE, 84 U20_3LE, 85 U20_3BE, 86 S18_3LE, 87 S18_3BE, 88 U18_3LE, 89 U18_3BE, 90 FORMAT_LAST, 91 }; 92 const char *formats_list[][2] = { 93 {"S8", "Signed 8 bit"}, 94 {"U8", "Unsigned 8 bit"}, 95 {"S16_LE", "Signed 16 bit Little Endian"}, 96 {"S16_BE", "Signed 16 bit Big Endian"}, 97 {"U16_LE", "Unsigned 16 bit Little Endian"}, 98 {"U16_BE", "Unsigned 16 bit Big Endian"}, 99 {"S24_LE", "Signed 24 bit Little Endian"}, 100 {"S24_BE", "Signed 24 bit Big Endian"}, 101 {"U24_LE", "Unsigned 24 bit Little Endian"}, 102 {"U24_BE", "Unsigned 24 bit Big Endian"}, 103 {"S32_LE", "Signed 32 bit Little Endian"}, 104 {"S32_BE", "Signed 32 bit Big Endian"}, 105 {"U32_LE", "Unsigned 32 bit Little Endian"}, 106 {"U32_BE", "Unsigned 32 bit Big Endian"}, 107 {"FLOAT_LE", "Float 32 bit Little Endian"}, 108 {"FLOAT_BE", "Float 32 bit Big Endian"}, 109 {"FLOAT64_LE", "Float 64 bit Little Endian"}, 110 {"FLOAT64_BE", "Float 64 bit Big Endian"}, 111 {"IEC958_SUBFRAME_LE", "IEC-958 Little Endian"}, 112 {"IEC958_SUBFRAME_BE", "IEC-958 Big Endian"}, 113 {"MU_LAW", "Mu-Law"}, 114 {"A_LAW", "A-Law"}, 115 {"IMA_ADPCM", "Ima-ADPCM"}, 116 {"MPEG", "MPEG"}, 117 {"GSM", "GSM"}, 118 [31] = {"SPECIAL", "Special"}, 119 {"S24_3LE", "Signed 24 bit Little Endian in 3bytes"}, 120 {"S24_3BE", "Signed 24 bit Big Endian in 3bytes"}, 121 {"U24_3LE", "Unsigned 24 bit Little Endian in 3bytes"}, 122 {"U24_3BE", "Unsigned 24 bit Big Endian in 3bytes"}, 123 {"S20_3LE", "Signed 20 bit Little Endian in 3bytes"}, 124 {"S20_3BE", "Signed 20 bit Big Endian in 3bytes"}, 125 {"U20_3LE", "Unsigned 20 bit Little Endian in 3bytes"}, 126 {"U20_3BE", "Unsigned 20 bit Big Endian in 3bytes"}, 127 {"S18_3LE", "Signed 18 bit Little Endian in 3bytes"}, 128 {"S18_3BE", "Signed 18 bit Big Endian in 3bytes"}, 129 {"U18_3LE", "Unsigned 18 bit Little Endian in 3bytes"}, 130 {"U18_3BE", "Unsigned 18 bit Big Endian in 3bytes"}, 131 }; 132 133 int get_compressed_format(const char *format) 134 { 135 const char *ch = format; 136 if (strcmp(ch, "MP3") == 0) { 137 printf("MP3 is selected\n"); 138 return FORMAT_MP3; 139 } else if (strcmp(ch, "AC3_PASS_THROUGH") == 0) { 140 printf("AC3 PASS THROUGH is selected\n"); 141 return FORMAT_AC3_PASS_THROUGH; 142 } else { 143 printf("invalid format\n"); 144 return -1; 145 } 146 return 0; 147 } 148 149 int get_format(const char* name) 150 { 151 int format; 152 for (format = 0; format < FORMAT_LAST; format++) { 153 if (formats_list[format][0] && 154 strcasecmp(name, formats_list[format][0]) == 0) { 155 ALOGV("format_names %s", name); 156 return format; 157 } 158 } 159 return -EINVAL; 160 } 161 162 const char *get_format_name(int format) 163 { 164 if ((format < FORMAT_LAST) && 165 formats_list[format][0]) 166 return formats_list[format][0]; 167 return NULL; 168 } 169 170 const char *get_format_desc(int format) 171 { 172 if ((format < FORMAT_LAST) && 173 formats_list[format][1]) 174 return formats_list[format][1]; 175 return NULL; 176 } 177 178 /* alsa parameter manipulation cruft */ 179 180 #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL 181 static int oops(struct pcm *pcm, int e, const char *fmt, ...); 182 183 static inline int param_is_mask(int p) 184 { 185 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && 186 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); 187 } 188 189 static inline int param_is_interval(int p) 190 { 191 return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) && 192 (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL); 193 } 194 195 static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n) 196 { 197 return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]); 198 } 199 200 static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n) 201 { 202 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); 203 } 204 205 void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) 206 { 207 if (bit >= SNDRV_MASK_MAX) 208 return; 209 if (param_is_mask(n)) { 210 struct snd_mask *m = param_to_mask(p, n); 211 m->bits[0] = 0; 212 m->bits[1] = 0; 213 m->bits[bit >> 5] |= (1 << (bit & 31)); 214 } 215 } 216 217 void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val) 218 { 219 if (param_is_interval(n)) { 220 struct snd_interval *i = param_to_interval(p, n); 221 i->min = val; 222 } 223 } 224 225 void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val) 226 { 227 if (param_is_interval(n)) { 228 struct snd_interval *i = param_to_interval(p, n); 229 i->max = val; 230 } 231 } 232 233 void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val) 234 { 235 if (param_is_interval(n)) { 236 struct snd_interval *i = param_to_interval(p, n); 237 i->min = val; 238 i->max = val; 239 i->integer = 1; 240 } 241 } 242 243 void param_init(struct snd_pcm_hw_params *p) 244 { 245 int n; 246 memset(p, 0, sizeof(*p)); 247 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; 248 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { 249 struct snd_mask *m = param_to_mask(p, n); 250 m->bits[0] = ~0; 251 m->bits[1] = ~0; 252 } 253 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; 254 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { 255 struct snd_interval *i = param_to_interval(p, n); 256 i->min = 0; 257 i->max = ~0; 258 } 259 } 260 261 /* debugging gunk */ 262 263 #if DEBUG 264 static const char *param_name[PARAM_MAX+1] = { 265 [SNDRV_PCM_HW_PARAM_ACCESS] = "access", 266 [SNDRV_PCM_HW_PARAM_FORMAT] = "format", 267 [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat", 268 269 [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits", 270 [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits", 271 [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels", 272 [SNDRV_PCM_HW_PARAM_RATE] = "rate", 273 [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time", 274 [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size", 275 [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes", 276 [SNDRV_PCM_HW_PARAM_PERIODS] = "periods", 277 [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time", 278 [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size", 279 [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes", 280 [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time", 281 }; 282 283 void param_dump(struct snd_pcm_hw_params *p) 284 { 285 int n; 286 287 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; 288 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { 289 struct snd_mask *m = param_to_mask(p, n); 290 ALOGV("%s = %08x%08x\n", param_name[n], 291 m->bits[1], m->bits[0]); 292 } 293 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; 294 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { 295 struct snd_interval *i = param_to_interval(p, n); 296 ALOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n", 297 param_name[n], i->min, i->max, i->openmin, 298 i->openmax, i->integer, i->empty); 299 } 300 ALOGV("info = %08x\n", p->info); 301 ALOGV("msbits = %d\n", p->msbits); 302 ALOGV("rate = %d/%d\n", p->rate_num, p->rate_den); 303 ALOGV("fifo = %d\n", (int) p->fifo_size); 304 } 305 306 static void info_dump(struct snd_pcm_info *info) 307 { 308 ALOGV("device = %d\n", info->device); 309 ALOGV("subdevice = %d\n", info->subdevice); 310 ALOGV("stream = %d\n", info->stream); 311 ALOGV("card = %d\n", info->card); 312 ALOGV("id = '%s'\n", info->id); 313 ALOGV("name = '%s'\n", info->name); 314 ALOGV("subname = '%s'\n", info->subname); 315 ALOGV("dev_class = %d\n", info->dev_class); 316 ALOGV("dev_subclass = %d\n", info->dev_subclass); 317 ALOGV("subdevices_count = %d\n", info->subdevices_count); 318 ALOGV("subdevices_avail = %d\n", info->subdevices_avail); 319 } 320 #else 321 void param_dump(struct snd_pcm_hw_params *p) {} 322 static void info_dump(struct snd_pcm_info *info) {} 323 #endif 324 325 int param_set_hw_refine(struct pcm *pcm, struct snd_pcm_hw_params *params) 326 { 327 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) { 328 ALOGE("SNDRV_PCM_IOCTL_HW_REFINE failed"); 329 return -EPERM; 330 } 331 return 0; 332 } 333 334 int param_set_hw_params(struct pcm *pcm, struct snd_pcm_hw_params *params) 335 { 336 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, params)) { 337 return -EPERM; 338 } 339 pcm->hw_p = params; 340 return 0; 341 } 342 343 int param_set_sw_params(struct pcm *pcm, struct snd_pcm_sw_params *sparams) 344 { 345 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, sparams)) { 346 return -EPERM; 347 } 348 pcm->sw_p = sparams; 349 return 0; 350 } 351 352 int pcm_buffer_size(struct snd_pcm_hw_params *params) 353 { 354 struct snd_interval *i = param_to_interval(params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); 355 ALOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n", 356 param_name[SNDRV_PCM_HW_PARAM_BUFFER_BYTES], 357 i->min, i->max, i->openmin, 358 i->openmax, i->integer, i->empty); 359 return i->min; 360 } 361 362 int pcm_period_size(struct snd_pcm_hw_params *params) 363 { 364 struct snd_interval *i = param_to_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES); 365 ALOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n", 366 param_name[SNDRV_PCM_HW_PARAM_PERIOD_BYTES], 367 i->min, i->max, i->openmin, 368 i->openmax, i->integer, i->empty); 369 return i->min; 370 } 371 372 const char* pcm_error(struct pcm *pcm) 373 { 374 return pcm->error; 375 } 376 377 static int oops(struct pcm *pcm, int e, const char *fmt, ...) 378 { 379 va_list ap; 380 int sz; 381 382 va_start(ap, fmt); 383 vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap); 384 va_end(ap); 385 sz = strnlen(pcm->error, PCM_ERROR_MAX); 386 387 if (errno) 388 snprintf(pcm->error + sz, PCM_ERROR_MAX - sz, 389 ": %s", strerror(e)); 390 return -1; 391 } 392 393 long pcm_avail(struct pcm *pcm) 394 { 395 struct snd_pcm_sync_ptr *sync_ptr = pcm->sync_ptr; 396 if (pcm->flags & DEBUG_ON) { 397 ALOGV("hw_ptr = %d buf_size = %d appl_ptr = %d\n", 398 sync_ptr->s.status.hw_ptr, 399 pcm->buffer_size, 400 sync_ptr->c.control.appl_ptr); 401 } 402 if (pcm->flags & PCM_IN) { 403 long avail = sync_ptr->s.status.hw_ptr - sync_ptr->c.control.appl_ptr; 404 if (avail < 0) 405 avail += pcm->sw_p->boundary; 406 return avail; 407 } else { 408 long avail = sync_ptr->s.status.hw_ptr - sync_ptr->c.control.appl_ptr + ((pcm->flags & PCM_MONO) ? pcm->buffer_size/2 : pcm->buffer_size/4); 409 if (avail < 0) 410 avail += pcm->sw_p->boundary; 411 else if ((unsigned long) avail >= pcm->sw_p->boundary) 412 avail -= pcm->sw_p->boundary; 413 return avail; 414 } 415 } 416 417 int sync_ptr(struct pcm *pcm) 418 { 419 int err; 420 err = ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr); 421 if (err < 0) { 422 err = errno; 423 ALOGE("SNDRV_PCM_IOCTL_SYNC_PTR failed %d \n", err); 424 return err; 425 } 426 427 return 0; 428 } 429 430 int mmap_buffer(struct pcm *pcm) 431 { 432 int err, i; 433 char *ptr; 434 unsigned size; 435 struct snd_pcm_channel_info ch; 436 int channels = (pcm->flags & PCM_MONO) ? 1 : 2; 437 438 size = pcm->buffer_size; 439 if (pcm->flags & DEBUG_ON) 440 ALOGV("size = %d\n", size); 441 pcm->addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, 442 pcm->fd, 0); 443 if (pcm->addr) 444 return 0; 445 else 446 return -errno; 447 } 448 449 /* 450 * Destination offset would be mod of total data written 451 * (application pointer) and the buffer size of the driver. 452 * Hence destination address would be base address(pcm->addr) + 453 * destination offset. 454 */ 455 u_int8_t *dst_address(struct pcm *pcm) 456 { 457 unsigned long pcm_offset = 0; 458 struct snd_pcm_sync_ptr *sync_ptr = pcm->sync_ptr; 459 unsigned int appl_ptr = 0; 460 461 appl_ptr = (pcm->flags & PCM_MONO) ? sync_ptr->c.control.appl_ptr*2 : sync_ptr->c.control.appl_ptr*4; 462 pcm_offset = (appl_ptr % (unsigned long)pcm->buffer_size); 463 return pcm->addr + pcm_offset; 464 465 } 466 467 int mmap_transfer(struct pcm *pcm, void *data, unsigned offset, 468 long frames) 469 { 470 struct snd_pcm_sync_ptr *sync_ptr = pcm->sync_ptr; 471 unsigned size; 472 u_int8_t *dst_addr, *mmaped_addr; 473 u_int8_t *src_addr = data; 474 int channels = (pcm->flags & PCM_MONO) ? 1 : 2; 475 476 dst_addr = dst_address(pcm); 477 478 frames = frames * channels *2 ; 479 480 while (frames-- > 0) { 481 *(u_int8_t*)dst_addr = *(const u_int8_t*)src_addr; 482 src_addr++; 483 dst_addr++; 484 } 485 return 0; 486 } 487 488 int mmap_transfer_capture(struct pcm *pcm, void *data, unsigned offset, 489 long frames) 490 { 491 struct snd_pcm_sync_ptr *sync_ptr = pcm->sync_ptr; 492 unsigned long pcm_offset = 0; 493 unsigned size; 494 u_int8_t *dst_addr, *mmaped_addr; 495 u_int8_t *src_addr; 496 int channels = (pcm->flags & PCM_MONO) ? 1 : 2; 497 unsigned int tmp = (pcm->flags & PCM_MONO) ? sync_ptr->c.control.appl_ptr*2 : sync_ptr->c.control.appl_ptr*4; 498 499 pcm_offset = (tmp % (unsigned long)pcm->buffer_size); 500 dst_addr = data; 501 src_addr = pcm->addr + pcm_offset; 502 frames = frames * channels *2 ; 503 504 while (frames-- > 0) { 505 *(u_int8_t*)dst_addr = *(const u_int8_t*)src_addr; 506 src_addr++; 507 dst_addr++; 508 } 509 return 0; 510 } 511 512 int pcm_prepare(struct pcm *pcm) 513 { 514 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)) { 515 ALOGE("cannot prepare channel: errno =%d\n", -errno); 516 return -errno; 517 } 518 pcm->running = 1; 519 return 0; 520 } 521 522 static int pcm_write_mmap(struct pcm *pcm, void *data, unsigned count) 523 { 524 long frames; 525 int err; 526 int bytes_written; 527 528 frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4); 529 530 pcm->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL | SNDRV_PCM_SYNC_PTR_AVAIL_MIN; 531 err = sync_ptr(pcm); 532 if (err == EPIPE) { 533 ALOGE("Failed in sync_ptr\n"); 534 /* we failed to make our window -- try to restart */ 535 pcm->underruns++; 536 pcm->running = 0; 537 pcm_prepare(pcm); 538 } 539 pcm->sync_ptr->c.control.appl_ptr += frames; 540 pcm->sync_ptr->flags = 0; 541 542 err = sync_ptr(pcm); 543 if (err == EPIPE) { 544 ALOGE("Failed in sync_ptr 2 \n"); 545 /* we failed to make our window -- try to restart */ 546 pcm->underruns++; 547 pcm->running = 0; 548 pcm_prepare(pcm); 549 } 550 bytes_written = pcm->sync_ptr->c.control.appl_ptr - pcm->sync_ptr->s.status.hw_ptr; 551 if ((bytes_written >= pcm->sw_p->start_threshold) && (!pcm->start)) { 552 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { 553 err = -errno; 554 if (errno == EPIPE) { 555 ALOGE("Failed in SNDRV_PCM_IOCTL_START\n"); 556 /* we failed to make our window -- try to restart */ 557 pcm->underruns++; 558 pcm->running = 0; 559 pcm_prepare(pcm); 560 } else { 561 ALOGE("Error no %d \n", errno); 562 return -errno; 563 } 564 } else { 565 ALOGD(" start\n"); 566 pcm->start = 1; 567 } 568 } 569 return 0; 570 } 571 572 static int pcm_write_nmmap(struct pcm *pcm, void *data, unsigned count) 573 { 574 struct snd_xferi x; 575 int channels = (pcm->flags & PCM_MONO) ? 1 : ((pcm->flags & PCM_5POINT1)? 6 : 2 ); 576 577 if (pcm->flags & PCM_IN) 578 return -EINVAL; 579 x.buf = data; 580 x.frames = (count / (channels * 2)) ; 581 582 for (;;) { 583 if (!pcm->running) { 584 if (pcm_prepare(pcm)) 585 return -errno; 586 } 587 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { 588 if (errno == EPIPE) { 589 /* we failed to make our window -- try to restart */ 590 ALOGE("Underrun Error\n"); 591 pcm->underruns++; 592 pcm->running = 0; 593 continue; 594 } 595 return -errno; 596 } 597 if (pcm->flags & DEBUG_ON) 598 ALOGV("Sent frame\n"); 599 return 0; 600 } 601 } 602 603 int pcm_write(struct pcm *pcm, void *data, unsigned count) 604 { 605 if (pcm->flags & PCM_MMAP) 606 return pcm_write_mmap(pcm, data, count); 607 else 608 return pcm_write_nmmap(pcm, data, count); 609 } 610 611 int pcm_read(struct pcm *pcm, void *data, unsigned count) 612 { 613 struct snd_xferi x; 614 615 if (!(pcm->flags & PCM_IN)) 616 return -EINVAL; 617 618 x.buf = data; 619 if (pcm->flags & PCM_MONO) { 620 x.frames = (count / 2); 621 } else if (pcm->flags & PCM_QUAD) { 622 x.frames = (count / 8); 623 } else if (pcm->flags & PCM_5POINT1) { 624 x.frames = (count / 12); 625 } else { 626 x.frames = (count / 4); 627 } 628 629 for (;;) { 630 if (!pcm->running) { 631 if (pcm_prepare(pcm)) 632 return -errno; 633 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { 634 ALOGE("Arec:SNDRV_PCM_IOCTL_START failed\n"); 635 return -errno; 636 } 637 pcm->running = 1; 638 } 639 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { 640 if (errno == EPIPE) { 641 /* we failed to make our window -- try to restart */ 642 ALOGE("Arec:Overrun Error\n"); 643 pcm->underruns++; 644 pcm->running = 0; 645 continue; 646 } 647 ALOGE("Arec: error%d\n", errno); 648 return -errno; 649 } 650 return 0; 651 } 652 } 653 654 static struct pcm bad_pcm = { 655 .fd = -1, 656 }; 657 658 static int enable_timer(struct pcm *pcm) { 659 660 pcm->timer_fd = open("/dev/snd/timer", O_RDWR | O_NONBLOCK); 661 if (pcm->timer_fd < 0) { 662 close(pcm->fd); 663 ALOGE("cannot open timer device 'timer'"); 664 return &bad_pcm; 665 } 666 int arg = 1; 667 struct snd_timer_params timer_param; 668 struct snd_timer_select sel; 669 if (ioctl(pcm->timer_fd, SNDRV_TIMER_IOCTL_TREAD, &arg) < 0) { 670 ALOGE("extended read is not supported (SNDRV_TIMER_IOCTL_TREAD)\n"); 671 } 672 memset(&sel, 0, sizeof(sel)); 673 sel.id.dev_class = SNDRV_TIMER_CLASS_PCM; 674 sel.id.dev_sclass = SNDRV_TIMER_SCLASS_NONE; 675 sel.id.card = pcm->card_no; 676 sel.id.device = pcm->device_no; 677 if (pcm->flags & PCM_IN) 678 sel.id.subdevice = 1; 679 else 680 sel.id.subdevice = 0; 681 682 if (pcm->flags & DEBUG_ON) { 683 ALOGD("sel.id.dev_class= %d\n", sel.id.dev_class); 684 ALOGD("sel.id.dev_sclass = %d\n", sel.id.dev_sclass); 685 ALOGD("sel.id.card = %d\n", sel.id.card); 686 ALOGD("sel.id.device = %d\n", sel.id.device); 687 ALOGD("sel.id.subdevice = %d\n", sel.id.subdevice); 688 } 689 if (ioctl(pcm->timer_fd, SNDRV_TIMER_IOCTL_SELECT, &sel) < 0) { 690 ALOGE("SNDRV_TIMER_IOCTL_SELECT failed.\n"); 691 close(pcm->timer_fd); 692 close(pcm->fd); 693 return &bad_pcm; 694 } 695 memset(&timer_param, 0, sizeof(struct snd_timer_params)); 696 timer_param.flags |= SNDRV_TIMER_PSFLG_AUTO; 697 timer_param.ticks = 1; 698 timer_param.filter = (1<<SNDRV_TIMER_EVENT_MSUSPEND) | (1<<SNDRV_TIMER_EVENT_MRESUME) | (1<<SNDRV_TIMER_EVENT_TICK); 699 700 if (ioctl(pcm->timer_fd, SNDRV_TIMER_IOCTL_PARAMS, &timer_param)< 0) { 701 ALOGE("SNDRV_TIMER_IOCTL_PARAMS failed\n"); 702 } 703 if (ioctl(pcm->timer_fd, SNDRV_TIMER_IOCTL_START) < 0) { 704 close(pcm->timer_fd); 705 ALOGE("SNDRV_TIMER_IOCTL_START failed\n"); 706 } 707 return 0; 708 } 709 710 static int disable_timer(struct pcm *pcm) { 711 if (pcm == &bad_pcm) 712 return 0; 713 if (ioctl(pcm->timer_fd, SNDRV_TIMER_IOCTL_STOP) < 0) 714 ALOGE("SNDRV_TIMER_IOCTL_STOP failed\n"); 715 return close(pcm->timer_fd); 716 } 717 718 int pcm_close(struct pcm *pcm) 719 { 720 if (pcm == &bad_pcm) 721 return 0; 722 723 if (pcm->flags & PCM_MMAP) { 724 disable_timer(pcm); 725 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) { 726 ALOGE("Reset failed"); 727 } 728 729 if (munmap(pcm->addr, pcm->buffer_size)) 730 ALOGE("munmap failed"); 731 732 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_FREE) < 0) { 733 ALOGE("HW_FREE failed"); 734 } 735 } 736 737 if (pcm->fd >= 0) 738 close(pcm->fd); 739 pcm->running = 0; 740 pcm->buffer_size = 0; 741 pcm->fd = -1; 742 if (pcm->sw_p) 743 free(pcm->sw_p); 744 if (pcm->hw_p) 745 free(pcm->hw_p); 746 if (pcm->sync_ptr) 747 free(pcm->sync_ptr); 748 free(pcm); 749 return 0; 750 } 751 752 struct pcm *pcm_open(unsigned flags, char *device) 753 { 754 char dname[19]; 755 struct pcm *pcm; 756 struct snd_pcm_info info; 757 struct snd_pcm_hw_params params; 758 struct snd_pcm_sw_params sparams; 759 unsigned period_sz; 760 unsigned period_cnt; 761 char *tmp; 762 763 if (flags & DEBUG_ON) { 764 ALOGV("pcm_open(0x%08x)",flags); 765 ALOGV("device %s\n",device); 766 } 767 768 pcm = calloc(1, sizeof(struct pcm)); 769 if (!pcm) 770 return &bad_pcm; 771 772 tmp = device+4; 773 if ((strncmp(device, "hw:",3) != 0) || (strncmp(tmp, ",",1) != 0)){ 774 ALOGE("Wrong device fromat\n"); 775 free(pcm); 776 return -EINVAL; 777 } 778 779 if (flags & PCM_IN) { 780 strlcpy(dname, "/dev/snd/pcmC", sizeof(dname)); 781 tmp = device+3; 782 strlcat(dname, tmp, (2+strlen(dname))) ; 783 pcm->card_no = atoi(tmp); 784 strlcat(dname, "D", (sizeof("D")+strlen(dname))); 785 tmp = device+5; 786 pcm->device_no = atoi(tmp); 787 /* should be safe to assume pcm dev ID never exceed 99 */ 788 if (pcm->device_no > 9) 789 strlcat(dname, tmp, (3+strlen(dname))); 790 else 791 strlcat(dname, tmp, (2+strlen(dname))); 792 strlcat(dname, "c", (sizeof("c")+strlen(dname))); 793 } else { 794 strlcpy(dname, "/dev/snd/pcmC", sizeof(dname)); 795 tmp = device+3; 796 strlcat(dname, tmp, (2+strlen(dname))) ; 797 pcm->card_no = atoi(tmp); 798 strlcat(dname, "D", (sizeof("D")+strlen(dname))); 799 tmp = device+5; 800 pcm->device_no = atoi(tmp); 801 /* should be safe to assume pcm dev ID never exceed 99 */ 802 if (pcm->device_no > 9) 803 strlcat(dname, tmp, (3+strlen(dname))); 804 else 805 strlcat(dname, tmp, (2+strlen(dname))); 806 strlcat(dname, "p", (sizeof("p")+strlen(dname))); 807 } 808 if (pcm->flags & DEBUG_ON) 809 ALOGV("Device name %s\n", dname); 810 811 pcm->sync_ptr = calloc(1, sizeof(struct snd_pcm_sync_ptr)); 812 if (!pcm->sync_ptr) { 813 free(pcm); 814 return &bad_pcm; 815 } 816 pcm->flags = flags; 817 818 pcm->fd = open(dname, O_RDWR|O_NONBLOCK); 819 if (pcm->fd < 0) { 820 free(pcm->sync_ptr); 821 free(pcm); 822 ALOGE("cannot open device '%s', errno %d", dname, errno); 823 return &bad_pcm; 824 } 825 826 if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) & 827 ~O_NONBLOCK) < 0) { 828 close(pcm->fd); 829 free(pcm->sync_ptr); 830 free(pcm); 831 ALOGE("failed to change the flag, errno %d", errno); 832 return &bad_pcm; 833 } 834 835 if (pcm->flags & PCM_MMAP) 836 enable_timer(pcm); 837 838 if (pcm->flags & DEBUG_ON) 839 ALOGV("pcm_open() %s\n", dname); 840 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) { 841 ALOGE("cannot get info - %s", dname); 842 } 843 if (pcm->flags & DEBUG_ON) 844 info_dump(&info); 845 846 return pcm; 847 } 848 849 int pcm_ready(struct pcm *pcm) 850 { 851 return pcm->fd >= 0; 852 } 853