1/****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 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 19/***************************************************************************** 20 * 21 * Filename: audio_a2dp_hw.c 22 * 23 * Description: Implements hal for bluedroid a2dp audio device 24 * 25 *****************************************************************************/ 26 27#include <errno.h> 28#include <pthread.h> 29#include <stdint.h> 30#include <sys/time.h> 31#include <sys/socket.h> 32#include <sys/un.h> 33#include <sys/poll.h> 34#include <sys/errno.h> 35#include <sys/stat.h> 36#include <unistd.h> 37#include <fcntl.h> 38#include <cutils/str_parms.h> 39#include <cutils/sockets.h> 40 41#include <system/audio.h> 42#include <hardware/audio.h> 43 44#include <hardware/hardware.h> 45#include "audio_a2dp_hw.h" 46 47#define LOG_TAG "audio_a2dp_hw" 48/* #define LOG_NDEBUG 0 */ 49#include <cutils/log.h> 50 51/***************************************************************************** 52** Constants & Macros 53******************************************************************************/ 54 55#define CTRL_CHAN_RETRY_COUNT 3 56#define USEC_PER_SEC 1000000L 57 58#define CASE_RETURN_STR(const) case const: return #const; 59 60#define FNLOG() ALOGV("%s", __FUNCTION__); 61#define DEBUG(fmt, ...) ALOGV("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) 62#define INFO(fmt, ...) ALOGI("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) 63#define ERROR(fmt, ...) ALOGE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) 64 65#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);} 66 67/***************************************************************************** 68** Local type definitions 69******************************************************************************/ 70 71typedef enum { 72 AUDIO_A2DP_STATE_STARTING, 73 AUDIO_A2DP_STATE_STARTED, 74 AUDIO_A2DP_STATE_STOPPING, 75 AUDIO_A2DP_STATE_STOPPED, 76 AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */ 77 AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */ 78} a2dp_state_t; 79 80struct a2dp_stream_out; 81 82struct a2dp_audio_device { 83 struct audio_hw_device device; 84 struct a2dp_stream_out *output; 85}; 86 87struct a2dp_config { 88 uint32_t rate; 89 uint32_t channel_flags; 90 int format; 91}; 92 93/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */ 94 95struct a2dp_stream_out { 96 struct audio_stream_out stream; 97 pthread_mutex_t lock; 98 int ctrl_fd; 99 int audio_fd; 100 size_t buffer_sz; 101 a2dp_state_t state; 102 struct a2dp_config cfg; 103}; 104 105struct a2dp_stream_in { 106 struct audio_stream_in stream; 107}; 108 109/***************************************************************************** 110** Static variables 111******************************************************************************/ 112 113/***************************************************************************** 114** Static functions 115******************************************************************************/ 116 117static size_t out_get_buffer_size(const struct audio_stream *stream); 118 119/***************************************************************************** 120** Externs 121******************************************************************************/ 122 123/***************************************************************************** 124** Functions 125******************************************************************************/ 126 127/***************************************************************************** 128** Miscellaneous helper functions 129******************************************************************************/ 130 131static const char* dump_a2dp_ctrl_event(char event) 132{ 133 switch(event) 134 { 135 CASE_RETURN_STR(A2DP_CTRL_CMD_NONE) 136 CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY) 137 CASE_RETURN_STR(A2DP_CTRL_CMD_START) 138 CASE_RETURN_STR(A2DP_CTRL_CMD_STOP) 139 CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND) 140 default: 141 return "UNKNOWN MSG ID"; 142 } 143} 144 145/* logs timestamp with microsec precision 146 pprev is optional in case a dedicated diff is required */ 147static void ts_log(char *tag, int val, struct timespec *pprev_opt) 148{ 149 struct timespec now; 150 static struct timespec prev = {0,0}; 151 unsigned long long now_us; 152 unsigned long long diff_us; 153 154 clock_gettime(CLOCK_MONOTONIC, &now); 155 156 now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000; 157 158 if (pprev_opt) 159 { 160 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; 161 *pprev_opt = now; 162 DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val); 163 } 164 else 165 { 166 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; 167 prev = now; 168 DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val); 169 } 170} 171 172static int calc_audiotime(struct a2dp_config cfg, int bytes) 173{ 174 int chan_count = popcount(cfg.channel_flags); 175 176 ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT, 177 "unsupported sample sz", cfg.format); 178 179 return bytes*(1000000/(chan_count*2))/cfg.rate; 180} 181 182/***************************************************************************** 183** 184** bluedroid stack adaptation 185** 186*****************************************************************************/ 187 188static int skt_connect(struct a2dp_stream_out *out, char *path) 189{ 190 int ret; 191 int skt_fd; 192 struct sockaddr_un remote; 193 int len; 194 195 INFO("connect to %s (sz %d)", path, out->buffer_sz); 196 197 skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0); 198 199 if(socket_local_client_connect(skt_fd, path, 200 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0) 201 { 202 ERROR("failed to connect (%s)", strerror(errno)); 203 close(skt_fd); 204 return -1; 205 } 206 207 len = out->buffer_sz; 208 ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len)); 209 210 /* only issue warning if failed */ 211 if (ret < 0) 212 ERROR("setsockopt failed (%s)", strerror(errno)); 213 214 INFO("connected to stack fd = %d", skt_fd); 215 216 return skt_fd; 217} 218 219static int skt_write(int fd, const void *p, size_t len) 220{ 221 int sent; 222 struct pollfd pfd; 223 224 FNLOG(); 225 226 pfd.fd = fd; 227 pfd.events = POLLOUT; 228 229 /* poll for 500 ms */ 230 231 /* send time out */ 232 if (poll(&pfd, 1, 500) == 0) 233 return 0; 234 235 ts_log("skt_write", len, NULL); 236 237 if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1) 238 { 239 ERROR("write failed with errno=%d\n", errno); 240 return -1; 241 } 242 243 return sent; 244} 245 246static int skt_disconnect(int fd) 247{ 248 INFO("fd %d", fd); 249 250 if (fd != AUDIO_SKT_DISCONNECTED) 251 { 252 shutdown(fd, SHUT_RDWR); 253 close(fd); 254 } 255 return 0; 256} 257 258 259 260/***************************************************************************** 261** 262** AUDIO CONTROL PATH 263** 264*****************************************************************************/ 265 266static int a2dp_command(struct a2dp_stream_out *out, char cmd) 267{ 268 char ack; 269 270 DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd)); 271 272 /* send command */ 273 if (send(out->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1) 274 { 275 ERROR("cmd failed (%s)", strerror(errno)); 276 skt_disconnect(out->ctrl_fd); 277 out->ctrl_fd = AUDIO_SKT_DISCONNECTED; 278 return -1; 279 } 280 281 /* wait for ack byte */ 282 if (recv(out->ctrl_fd, &ack, 1, MSG_NOSIGNAL) < 0) 283 { 284 ERROR("ack failed (%s)", strerror(errno)); 285 skt_disconnect(out->ctrl_fd); 286 out->ctrl_fd = AUDIO_SKT_DISCONNECTED; 287 return -1; 288 } 289 290 DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack); 291 292 if (ack != A2DP_CTRL_ACK_SUCCESS) 293 return -1; 294 295 return 0; 296} 297 298/***************************************************************************** 299** 300** AUDIO DATA PATH 301** 302*****************************************************************************/ 303 304static void a2dp_stream_out_init(struct a2dp_stream_out *out) 305{ 306 pthread_mutexattr_t lock_attr; 307 308 FNLOG(); 309 310 pthread_mutexattr_init(&lock_attr); 311 pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE); 312 pthread_mutex_init(&out->lock, &lock_attr); 313 314 out->ctrl_fd = AUDIO_SKT_DISCONNECTED; 315 out->audio_fd = AUDIO_SKT_DISCONNECTED; 316 out->state = AUDIO_A2DP_STATE_STOPPED; 317 318 out->cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG; 319 out->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; 320 out->cfg.rate = AUDIO_STREAM_DEFAULT_RATE; 321 322 /* manages max capacity of socket pipe */ 323 out->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; 324} 325 326static int start_audio_datapath(struct a2dp_stream_out *out) 327{ 328 int oldstate = out->state; 329 330 INFO("state %d", out->state); 331 332 if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED) 333 return -1; 334 335 out->state = AUDIO_A2DP_STATE_STARTING; 336 337 if (a2dp_command(out, A2DP_CTRL_CMD_START) < 0) 338 { 339 ERROR("audiopath start failed"); 340 341 out->state = oldstate; 342 return -1; 343 } 344 345 /* connect socket if not yet connected */ 346 if (out->audio_fd == AUDIO_SKT_DISCONNECTED) 347 { 348 out->audio_fd = skt_connect(out, A2DP_DATA_PATH); 349 350 if (out->audio_fd < 0) 351 { 352 out->state = oldstate; 353 return -1; 354 } 355 356 out->state = AUDIO_A2DP_STATE_STARTED; 357 } 358 359 return 0; 360} 361 362 363static int stop_audio_datapath(struct a2dp_stream_out *out) 364{ 365 int oldstate = out->state; 366 367 INFO("state %d", out->state); 368 369 if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED) 370 return -1; 371 372 /* prevent any stray output writes from autostarting the stream 373 while stopping audiopath */ 374 out->state = AUDIO_A2DP_STATE_STOPPING; 375 376 if (a2dp_command(out, A2DP_CTRL_CMD_STOP) < 0) 377 { 378 ERROR("audiopath stop failed"); 379 out->state = oldstate; 380 return -1; 381 } 382 383 out->state = AUDIO_A2DP_STATE_STOPPED; 384 385 /* disconnect audio path */ 386 skt_disconnect(out->audio_fd); 387 out->audio_fd = AUDIO_SKT_DISCONNECTED; 388 389 return 0; 390} 391 392static int suspend_audio_datapath(struct a2dp_stream_out *out, bool standby) 393{ 394 INFO("state %d", out->state); 395 396 if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED) 397 return -1; 398 399 if (out->state == AUDIO_A2DP_STATE_STOPPING) 400 return -1; 401 402 if (a2dp_command(out, A2DP_CTRL_CMD_SUSPEND) < 0) 403 return -1; 404 405 if (standby) 406 out->state = AUDIO_A2DP_STATE_STANDBY; 407 else 408 out->state = AUDIO_A2DP_STATE_SUSPENDED; 409 410 /* disconnect audio path */ 411 skt_disconnect(out->audio_fd); 412 413 out->audio_fd = AUDIO_SKT_DISCONNECTED; 414 415 return 0; 416} 417 418static int check_a2dp_ready(struct a2dp_stream_out *out) 419{ 420 INFO("state %d", out->state); 421 422 if (a2dp_command(out, A2DP_CTRL_CMD_CHECK_READY) < 0) 423 { 424 ERROR("check a2dp ready failed"); 425 return -1; 426 } 427 return 0; 428} 429 430 431/***************************************************************************** 432** 433** audio output callbacks 434** 435*****************************************************************************/ 436 437static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 438 size_t bytes) 439{ 440 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 441 int sent; 442 443 DEBUG("write %d bytes (fd %d)", bytes, out->audio_fd); 444 445 if (out->state == AUDIO_A2DP_STATE_SUSPENDED) 446 { 447 DEBUG("stream suspended"); 448 return -1; 449 } 450 451 /* only allow autostarting if we are in stopped or standby */ 452 if ((out->state == AUDIO_A2DP_STATE_STOPPED) || 453 (out->state == AUDIO_A2DP_STATE_STANDBY)) 454 { 455 pthread_mutex_lock(&out->lock); 456 457 if (start_audio_datapath(out) < 0) 458 { 459 /* emulate time this write represents to avoid very fast write 460 failures during transition periods or remote suspend */ 461 462 int us_delay = calc_audiotime(out->cfg, bytes); 463 464 DEBUG("emulate a2dp write delay (%d us)", us_delay); 465 466 usleep(us_delay); 467 pthread_mutex_unlock(&out->lock); 468 return -1; 469 } 470 471 pthread_mutex_unlock(&out->lock); 472 } 473 else if (out->state != AUDIO_A2DP_STATE_STARTED) 474 { 475 ERROR("stream not in stopped or standby"); 476 return -1; 477 } 478 479 sent = skt_write(out->audio_fd, buffer, bytes); 480 481 if (sent == -1) 482 { 483 skt_disconnect(out->audio_fd); 484 out->audio_fd = AUDIO_SKT_DISCONNECTED; 485 out->state = AUDIO_A2DP_STATE_STOPPED; 486 } 487 488 DEBUG("wrote %d bytes out of %d bytes", sent, bytes); 489 return sent; 490} 491 492 493static uint32_t out_get_sample_rate(const struct audio_stream *stream) 494{ 495 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 496 497 DEBUG("rate %d", out->cfg.rate); 498 499 return out->cfg.rate; 500} 501 502static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 503{ 504 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 505 506 DEBUG("out_set_sample_rate : %d", rate); 507 508 if (rate != AUDIO_STREAM_DEFAULT_RATE) 509 { 510 ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE); 511 return -1; 512 } 513 514 out->cfg.rate = rate; 515 516 return 0; 517} 518 519static size_t out_get_buffer_size(const struct audio_stream *stream) 520{ 521 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 522 523 DEBUG("buffer_size : %d", out->buffer_sz); 524 525 return out->buffer_sz; 526} 527 528static uint32_t out_get_channels(const struct audio_stream *stream) 529{ 530 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 531 532 DEBUG("channels 0x%x", out->cfg.channel_flags); 533 534 return out->cfg.channel_flags; 535} 536 537static audio_format_t out_get_format(const struct audio_stream *stream) 538{ 539 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 540 DEBUG("format 0x%x", out->cfg.format); 541 return out->cfg.format; 542} 543 544static int out_set_format(struct audio_stream *stream, audio_format_t format) 545{ 546 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 547 DEBUG("setting format not yet supported (0x%x)", format); 548 return -ENOSYS; 549} 550 551static int out_standby(struct audio_stream *stream) 552{ 553 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 554 int retval = 0; 555 556 int retVal = 0; 557 558 FNLOG(); 559 560 pthread_mutex_lock(&out->lock); 561 562 if (out->state == AUDIO_A2DP_STATE_STARTED) 563 retVal = suspend_audio_datapath(out, true); 564 else 565 retVal = 0; 566 pthread_mutex_unlock (&out->lock); 567 568 return retVal; 569} 570 571static int out_dump(const struct audio_stream *stream, int fd) 572{ 573 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 574 FNLOG(); 575 return 0; 576} 577 578static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 579{ 580 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 581 struct str_parms *parms; 582 char keyval[16]; 583 int retval = 0; 584 585 INFO("state %d", out->state); 586 587 pthread_mutex_lock(&out->lock); 588 589 parms = str_parms_create_str(kvpairs); 590 591 /* dump params */ 592 str_parms_dump(parms); 593 594 retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval)); 595 596 if (retval >= 0) 597 { 598 if (strcmp(keyval, "true") == 0) 599 { 600 DEBUG("stream closing, disallow any writes"); 601 out->state = AUDIO_A2DP_STATE_STOPPING; 602 } 603 } 604 605 retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval)); 606 607 if (retval >= 0) 608 { 609 if (strcmp(keyval, "true") == 0) 610 { 611 if (out->state == AUDIO_A2DP_STATE_STARTED) 612 retval = suspend_audio_datapath(out, false); 613 } 614 else 615 { 616 /* Do not start the streaming automatically. If the phone was streaming 617 * prior to being suspended, the next out_write shall trigger the 618 * AVDTP start procedure */ 619 if (out->state == AUDIO_A2DP_STATE_SUSPENDED) 620 out->state = AUDIO_A2DP_STATE_STANDBY; 621 /* Irrespective of the state, return 0 */ 622 retval = 0; 623 } 624 } 625 626 pthread_mutex_unlock(&out->lock); 627 str_parms_destroy(parms); 628 629 return retval; 630} 631 632static char * out_get_parameters(const struct audio_stream *stream, const char *keys) 633{ 634 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 635 636 FNLOG(); 637 638 /* add populating param here */ 639 640 return strdup(""); 641} 642 643static uint32_t out_get_latency(const struct audio_stream_out *stream) 644{ 645 int latency_us; 646 647 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 648 649 FNLOG(); 650 651 latency_us = ((out->buffer_sz * 1000 ) / 652 audio_stream_frame_size(&out->stream.common) / 653 out->cfg.rate) * 1000; 654 655 656 return (latency_us / 1000) + 200; 657} 658 659static int out_set_volume(struct audio_stream_out *stream, float left, 660 float right) 661{ 662 FNLOG(); 663 664 /* volume controlled in audioflinger mixer (digital) */ 665 666 return -ENOSYS; 667} 668 669 670 671static int out_get_render_position(const struct audio_stream_out *stream, 672 uint32_t *dsp_frames) 673{ 674 FNLOG(); 675 return -EINVAL; 676} 677 678static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 679{ 680 FNLOG(); 681 return 0; 682} 683 684static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 685{ 686 FNLOG(); 687 return 0; 688} 689 690/* 691 * AUDIO INPUT STREAM 692 */ 693 694static uint32_t in_get_sample_rate(const struct audio_stream *stream) 695{ 696 FNLOG(); 697 return 8000; 698} 699 700static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) 701{ 702 FNLOG(); 703 return 0; 704} 705 706static size_t in_get_buffer_size(const struct audio_stream *stream) 707{ 708 FNLOG(); 709 return 320; 710} 711 712static uint32_t in_get_channels(const struct audio_stream *stream) 713{ 714 FNLOG(); 715 return AUDIO_CHANNEL_IN_MONO; 716} 717 718static audio_format_t in_get_format(const struct audio_stream *stream) 719{ 720 FNLOG(); 721 return AUDIO_FORMAT_PCM_16_BIT; 722} 723 724static int in_set_format(struct audio_stream *stream, audio_format_t format) 725{ 726 FNLOG(); 727 return 0; 728} 729 730static int in_standby(struct audio_stream *stream) 731{ 732 FNLOG(); 733 return 0; 734} 735 736static int in_dump(const struct audio_stream *stream, int fd) 737{ 738 FNLOG(); 739 return 0; 740} 741 742static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) 743{ 744 FNLOG(); 745 return 0; 746} 747 748static char * in_get_parameters(const struct audio_stream *stream, 749 const char *keys) 750{ 751 FNLOG(); 752 return strdup(""); 753} 754 755static int in_set_gain(struct audio_stream_in *stream, float gain) 756{ 757 FNLOG(); 758 return 0; 759} 760 761static ssize_t in_read(struct audio_stream_in *stream, void* buffer, 762 size_t bytes) 763{ 764 FNLOG(); 765 return bytes; 766} 767 768static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) 769{ 770 FNLOG(); 771 return 0; 772} 773 774static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 775{ 776 FNLOG(); 777 return 0; 778} 779 780static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 781{ 782 FNLOG(); 783 784 return 0; 785} 786 787static int adev_open_output_stream(struct audio_hw_device *dev, 788 audio_io_handle_t handle, 789 audio_devices_t devices, 790 audio_output_flags_t flags, 791 struct audio_config *config, 792 struct audio_stream_out **stream_out) 793 794{ 795 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; 796 struct a2dp_stream_out *out; 797 int ret = 0; 798 int i; 799 800 INFO("opening output"); 801 802 out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out)); 803 804 if (!out) 805 return -ENOMEM; 806 807 out->stream.common.get_sample_rate = out_get_sample_rate; 808 out->stream.common.set_sample_rate = out_set_sample_rate; 809 out->stream.common.get_buffer_size = out_get_buffer_size; 810 out->stream.common.get_channels = out_get_channels; 811 out->stream.common.get_format = out_get_format; 812 out->stream.common.set_format = out_set_format; 813 out->stream.common.standby = out_standby; 814 out->stream.common.dump = out_dump; 815 out->stream.common.set_parameters = out_set_parameters; 816 out->stream.common.get_parameters = out_get_parameters; 817 out->stream.common.add_audio_effect = out_add_audio_effect; 818 out->stream.common.remove_audio_effect = out_remove_audio_effect; 819 out->stream.get_latency = out_get_latency; 820 out->stream.set_volume = out_set_volume; 821 out->stream.write = out_write; 822 out->stream.get_render_position = out_get_render_position; 823 824 /* initialize a2dp specifics */ 825 a2dp_stream_out_init(out); 826 827 /* set output config values */ 828 if (config) 829 { 830 config->format = out_get_format((const struct audio_stream *)&out->stream); 831 config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream); 832 config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream); 833 } 834 *stream_out = &out->stream; 835 a2dp_dev->output = out; 836 837 /* retry logic to catch any timing variations on control channel */ 838 for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++) 839 { 840 /* connect control channel if not already connected */ 841 if ((out->ctrl_fd = skt_connect(out, A2DP_CTRL_PATH)) > 0) 842 { 843 /* success, now check if stack is ready */ 844 if (check_a2dp_ready(out) == 0) 845 break; 846 847 ERROR("error : a2dp not ready, wait 250 ms and retry"); 848 usleep(250000); 849 skt_disconnect(out->ctrl_fd); 850 } 851 852 /* ctrl channel not ready, wait a bit */ 853 usleep(250000); 854 } 855 856 if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED) 857 { 858 ERROR("ctrl socket failed to connect (%s)", strerror(errno)); 859 ret = -1; 860 goto err_open; 861 } 862 863 DEBUG("success"); 864 return 0; 865 866err_open: 867 free(out); 868 *stream_out = NULL; 869 ERROR("failed"); 870 return ret; 871} 872 873static void adev_close_output_stream(struct audio_hw_device *dev, 874 struct audio_stream_out *stream) 875{ 876 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; 877 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; 878 879 INFO("closing output (state %d)", out->state); 880 881 if ((out->state == AUDIO_A2DP_STATE_STARTED) || (out->state == AUDIO_A2DP_STATE_STOPPING)) 882 stop_audio_datapath(out); 883 884 skt_disconnect(out->ctrl_fd); 885 free(stream); 886 a2dp_dev->output = NULL; 887 888 DEBUG("done"); 889} 890 891static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 892{ 893 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; 894 struct a2dp_stream_out *out = a2dp_dev->output; 895 int retval = 0; 896 897 if (out == NULL) 898 return retval; 899 900 INFO("state %d", out->state); 901 902 retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs); 903 904 return retval; 905} 906 907static char * adev_get_parameters(const struct audio_hw_device *dev, 908 const char *keys) 909{ 910 struct str_parms *parms; 911 912 FNLOG(); 913 914 parms = str_parms_create_str(keys); 915 916 str_parms_dump(parms); 917 918 str_parms_destroy(parms); 919 920 return strdup(""); 921} 922 923static int adev_init_check(const struct audio_hw_device *dev) 924{ 925 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev; 926 927 FNLOG(); 928 929 return 0; 930} 931 932static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 933{ 934 FNLOG(); 935 936 return -ENOSYS; 937} 938 939static int adev_set_master_volume(struct audio_hw_device *dev, float volume) 940{ 941 FNLOG(); 942 943 return -ENOSYS; 944} 945 946static int adev_set_mode(struct audio_hw_device *dev, int mode) 947{ 948 FNLOG(); 949 950 return 0; 951} 952 953static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 954{ 955 FNLOG(); 956 957 return -ENOSYS; 958} 959 960static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 961{ 962 FNLOG(); 963 964 return -ENOSYS; 965} 966 967static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 968 const struct audio_config *config) 969{ 970 FNLOG(); 971 972 return 320; 973} 974 975static int adev_open_input_stream(struct audio_hw_device *dev, 976 audio_io_handle_t handle, 977 audio_devices_t devices, 978 struct audio_config *config, 979 struct audio_stream_in **stream_in) 980{ 981 struct a2dp_audio_device *ladev = (struct a2dp_audio_device *)dev; 982 struct a2dp_stream_in *in; 983 int ret; 984 985 FNLOG(); 986 987 in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in)); 988 989 if (!in) 990 return -ENOMEM; 991 992 in->stream.common.get_sample_rate = in_get_sample_rate; 993 in->stream.common.set_sample_rate = in_set_sample_rate; 994 in->stream.common.get_buffer_size = in_get_buffer_size; 995 in->stream.common.get_channels = in_get_channels; 996 in->stream.common.get_format = in_get_format; 997 in->stream.common.set_format = in_set_format; 998 in->stream.common.standby = in_standby; 999 in->stream.common.dump = in_dump; 1000 in->stream.common.set_parameters = in_set_parameters; 1001 in->stream.common.get_parameters = in_get_parameters; 1002 in->stream.common.add_audio_effect = in_add_audio_effect; 1003 in->stream.common.remove_audio_effect = in_remove_audio_effect; 1004 in->stream.set_gain = in_set_gain; 1005 in->stream.read = in_read; 1006 in->stream.get_input_frames_lost = in_get_input_frames_lost; 1007 1008 *stream_in = &in->stream; 1009 return 0; 1010 1011err_open: 1012 free(in); 1013 *stream_in = NULL; 1014 return ret; 1015} 1016 1017static void adev_close_input_stream(struct audio_hw_device *dev, 1018 struct audio_stream_in *in) 1019{ 1020 FNLOG(); 1021 1022 return; 1023} 1024 1025static int adev_dump(const audio_hw_device_t *device, int fd) 1026{ 1027 FNLOG(); 1028 1029 return 0; 1030} 1031 1032static int adev_close(hw_device_t *device) 1033{ 1034 FNLOG(); 1035 1036 free(device); 1037 return 0; 1038} 1039 1040static int adev_open(const hw_module_t* module, const char* name, 1041 hw_device_t** device) 1042{ 1043 struct a2dp_audio_device *adev; 1044 int ret; 1045 1046 INFO(" adev_open in A2dp_hw module"); 1047 FNLOG(); 1048 1049 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 1050 { 1051 ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE); 1052 return -EINVAL; 1053 } 1054 1055 adev = calloc(1, sizeof(struct a2dp_audio_device)); 1056 1057 if (!adev) 1058 return -ENOMEM; 1059 1060 adev->device.common.tag = HARDWARE_DEVICE_TAG; 1061 adev->device.common.version = AUDIO_DEVICE_API_VERSION_CURRENT; 1062 adev->device.common.module = (struct hw_module_t *) module; 1063 adev->device.common.close = adev_close; 1064 1065 adev->device.init_check = adev_init_check; 1066 adev->device.set_voice_volume = adev_set_voice_volume; 1067 adev->device.set_master_volume = adev_set_master_volume; 1068 adev->device.set_mode = adev_set_mode; 1069 adev->device.set_mic_mute = adev_set_mic_mute; 1070 adev->device.get_mic_mute = adev_get_mic_mute; 1071 adev->device.set_parameters = adev_set_parameters; 1072 adev->device.get_parameters = adev_get_parameters; 1073 adev->device.get_input_buffer_size = adev_get_input_buffer_size; 1074 adev->device.open_output_stream = adev_open_output_stream; 1075 adev->device.close_output_stream = adev_close_output_stream; 1076 adev->device.open_input_stream = adev_open_input_stream; 1077 adev->device.close_input_stream = adev_close_input_stream; 1078 adev->device.dump = adev_dump; 1079 1080 adev->output = NULL; 1081 1082 1083 *device = &adev->device.common; 1084 1085 return 0; 1086} 1087 1088static struct hw_module_methods_t hal_module_methods = { 1089 .open = adev_open, 1090}; 1091 1092struct audio_module HAL_MODULE_INFO_SYM = { 1093 .common = { 1094 .tag = HARDWARE_MODULE_TAG, 1095 .version_major = 1, 1096 .version_minor = 0, 1097 .id = AUDIO_HARDWARE_MODULE_ID, 1098 .name = "A2DP Audio HW HAL", 1099 .author = "The Android Open Source Project", 1100 .methods = &hal_module_methods, 1101 }, 1102}; 1103 1104