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