audio_hw_hal.cpp revision 4765c439491ddda3de658e62cc4a64d10e726b34
1/* 2 * Copyright (C) 2011 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 "qcom_audio_hw_hal" 19//#define LOG_NDEBUG 0 20 21#include <stdint.h> 22 23#include <hardware/hardware.h> 24#include <system/audio.h> 25#include <hardware/audio.h> 26 27#include <hardware_legacy/AudioHardwareInterface.h> 28#include <hardware_legacy/AudioSystemLegacy.h> 29 30namespace android_audio_legacy { 31 32extern "C" { 33 34struct qcom_audio_module { 35 struct audio_module module; 36}; 37 38struct qcom_audio_device { 39 struct audio_hw_device device; 40 41 struct AudioHardwareInterface *hwif; 42}; 43 44struct qcom_stream_out { 45 struct audio_stream_out stream; 46 47 AudioStreamOut *qcom_out; 48}; 49 50struct qcom_stream_in { 51 struct audio_stream_in stream; 52 53 AudioStreamIn *qcom_in; 54}; 55 56/** audio_stream_out implementation **/ 57static uint32_t out_get_sample_rate(const struct audio_stream *stream) 58{ 59 const struct qcom_stream_out *out = 60 reinterpret_cast<const struct qcom_stream_out *>(stream); 61 return out->qcom_out->sampleRate(); 62} 63 64static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 65{ 66 struct qcom_stream_out *out = 67 reinterpret_cast<struct qcom_stream_out *>(stream); 68 69 LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 70 /* TODO: implement this */ 71 return 0; 72} 73 74static size_t out_get_buffer_size(const struct audio_stream *stream) 75{ 76 const struct qcom_stream_out *out = 77 reinterpret_cast<const struct qcom_stream_out *>(stream); 78 return out->qcom_out->bufferSize(); 79} 80 81static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) 82{ 83 const struct qcom_stream_out *out = 84 reinterpret_cast<const struct qcom_stream_out *>(stream); 85 return out->qcom_out->channels(); 86} 87 88static audio_format_t out_get_format(const struct audio_stream *stream) 89{ 90 const struct qcom_stream_out *out = 91 reinterpret_cast<const struct qcom_stream_out *>(stream); 92 return out->qcom_out->format(); 93} 94 95static int out_set_format(struct audio_stream *stream, audio_format_t format) 96{ 97 struct qcom_stream_out *out = 98 reinterpret_cast<struct qcom_stream_out *>(stream); 99 LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 100 /* TODO: implement me */ 101 return 0; 102} 103 104static int out_standby(struct audio_stream *stream) 105{ 106 struct qcom_stream_out *out = 107 reinterpret_cast<struct qcom_stream_out *>(stream); 108 return out->qcom_out->standby(); 109} 110 111static int out_dump(const struct audio_stream *stream, int fd) 112{ 113 const struct qcom_stream_out *out = 114 reinterpret_cast<const struct qcom_stream_out *>(stream); 115 Vector<String16> args; 116 return out->qcom_out->dump(fd, args); 117} 118 119static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 120{ 121 struct qcom_stream_out *out = 122 reinterpret_cast<struct qcom_stream_out *>(stream); 123 return out->qcom_out->setParameters(String8(kvpairs)); 124} 125 126static char * out_get_parameters(const struct audio_stream *stream, const char *keys) 127{ 128 const struct qcom_stream_out *out = 129 reinterpret_cast<const struct qcom_stream_out *>(stream); 130 String8 s8; 131 s8 = out->qcom_out->getParameters(String8(keys)); 132 return strdup(s8.string()); 133} 134 135static uint32_t out_get_latency(const struct audio_stream_out *stream) 136{ 137 const struct qcom_stream_out *out = 138 reinterpret_cast<const struct qcom_stream_out *>(stream); 139 return out->qcom_out->latency(); 140} 141 142static int out_set_volume(struct audio_stream_out *stream, float left, 143 float right) 144{ 145 struct qcom_stream_out *out = 146 reinterpret_cast<struct qcom_stream_out *>(stream); 147 return out->qcom_out->setVolume(left, right); 148} 149 150static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 151 size_t bytes) 152{ 153 struct qcom_stream_out *out = 154 reinterpret_cast<struct qcom_stream_out *>(stream); 155 return out->qcom_out->write(buffer, bytes); 156} 157 158static int out_get_render_position(const struct audio_stream_out *stream, 159 uint32_t *dsp_frames) 160{ 161 const struct qcom_stream_out *out = 162 reinterpret_cast<const struct qcom_stream_out *>(stream); 163 return out->qcom_out->getRenderPosition(dsp_frames); 164} 165 166static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 167{ 168 return 0; 169} 170 171static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 172{ 173 return 0; 174} 175 176static int out_get_next_write_timestamp(const struct audio_stream_out *stream, 177 int64_t *timestamp) 178{ 179 return -EINVAL; 180} 181 182/** audio_stream_in implementation **/ 183static uint32_t in_get_sample_rate(const struct audio_stream *stream) 184{ 185 const struct qcom_stream_in *in = 186 reinterpret_cast<const struct qcom_stream_in *>(stream); 187 return in->qcom_in->sampleRate(); 188} 189 190static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) 191{ 192 struct qcom_stream_in *in = 193 reinterpret_cast<struct qcom_stream_in *>(stream); 194 195 LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 196 /* TODO: implement this */ 197 return 0; 198} 199 200static size_t in_get_buffer_size(const struct audio_stream *stream) 201{ 202 const struct qcom_stream_in *in = 203 reinterpret_cast<const struct qcom_stream_in *>(stream); 204 return in->qcom_in->bufferSize(); 205} 206 207static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) 208{ 209 const struct qcom_stream_in *in = 210 reinterpret_cast<const struct qcom_stream_in *>(stream); 211 return in->qcom_in->channels(); 212} 213 214static audio_format_t in_get_format(const struct audio_stream *stream) 215{ 216 const struct qcom_stream_in *in = 217 reinterpret_cast<const struct qcom_stream_in *>(stream); 218 return in->qcom_in->format(); 219} 220 221static int in_set_format(struct audio_stream *stream, audio_format_t format) 222{ 223 struct qcom_stream_in *in = 224 reinterpret_cast<struct qcom_stream_in *>(stream); 225 LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 226 /* TODO: implement me */ 227 return 0; 228} 229 230static int in_standby(struct audio_stream *stream) 231{ 232 struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream); 233 return in->qcom_in->standby(); 234} 235 236static int in_dump(const struct audio_stream *stream, int fd) 237{ 238 const struct qcom_stream_in *in = 239 reinterpret_cast<const struct qcom_stream_in *>(stream); 240 Vector<String16> args; 241 return in->qcom_in->dump(fd, args); 242} 243 244static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) 245{ 246 struct qcom_stream_in *in = 247 reinterpret_cast<struct qcom_stream_in *>(stream); 248 return in->qcom_in->setParameters(String8(kvpairs)); 249} 250 251static char * in_get_parameters(const struct audio_stream *stream, 252 const char *keys) 253{ 254 const struct qcom_stream_in *in = 255 reinterpret_cast<const struct qcom_stream_in *>(stream); 256 String8 s8; 257 s8 = in->qcom_in->getParameters(String8(keys)); 258 return strdup(s8.string()); 259} 260 261static int in_set_gain(struct audio_stream_in *stream, float gain) 262{ 263 struct qcom_stream_in *in = 264 reinterpret_cast<struct qcom_stream_in *>(stream); 265 return in->qcom_in->setGain(gain); 266} 267 268static ssize_t in_read(struct audio_stream_in *stream, void* buffer, 269 size_t bytes) 270{ 271 struct qcom_stream_in *in = 272 reinterpret_cast<struct qcom_stream_in *>(stream); 273 return in->qcom_in->read(buffer, bytes); 274} 275 276static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) 277{ 278 struct qcom_stream_in *in = 279 reinterpret_cast<struct qcom_stream_in *>(stream); 280 return in->qcom_in->getInputFramesLost(); 281} 282 283static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 284{ 285 const struct qcom_stream_in *in = 286 reinterpret_cast<const struct qcom_stream_in *>(stream); 287 return in->qcom_in->addAudioEffect(effect); 288} 289 290static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 291{ 292 const struct qcom_stream_in *in = 293 reinterpret_cast<const struct qcom_stream_in *>(stream); 294 return in->qcom_in->removeAudioEffect(effect); 295} 296 297/** audio_hw_device implementation **/ 298static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev) 299{ 300 return reinterpret_cast<struct qcom_audio_device *>(dev); 301} 302 303static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev) 304{ 305 return reinterpret_cast<const struct qcom_audio_device *>(dev); 306} 307 308static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev) 309{ 310 /* XXX: The old AudioHardwareInterface interface is not smart enough to 311 * tell us this, so we'll lie and basically tell AF that we support the 312 * below input/output devices and cross our fingers. To do things properly, 313 * audio hardware interfaces that need advanced features (like this) should 314 * convert to the new HAL interface and not use this wrapper. */ 315 return (/* OUT */ 316 AUDIO_DEVICE_OUT_EARPIECE | 317 AUDIO_DEVICE_OUT_SPEAKER | 318 AUDIO_DEVICE_OUT_WIRED_HEADSET | 319 AUDIO_DEVICE_OUT_WIRED_HEADPHONE | 320 AUDIO_DEVICE_OUT_AUX_DIGITAL | 321 AUDIO_DEVICE_OUT_ALL_SCO | 322 AUDIO_DEVICE_OUT_ANC_HEADSET | 323 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET | 324 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET | 325 AUDIO_DEVICE_OUT_ANC_HEADPHONE | 326 AUDIO_DEVICE_OUT_FM | 327 AUDIO_DEVICE_OUT_FM_TX | 328 AUDIO_DEVICE_OUT_DIRECTOUTPUT | 329 AUDIO_DEVICE_OUT_PROXY | 330 AUDIO_DEVICE_OUT_DEFAULT | 331 /* IN */ 332 AUDIO_DEVICE_IN_VOICE_CALL | 333 AUDIO_DEVICE_IN_COMMUNICATION | 334 AUDIO_DEVICE_IN_AMBIENT | 335 AUDIO_DEVICE_IN_BUILTIN_MIC | 336 AUDIO_DEVICE_IN_WIRED_HEADSET | 337 AUDIO_DEVICE_IN_AUX_DIGITAL | 338 AUDIO_DEVICE_IN_BACK_MIC | 339 AUDIO_DEVICE_IN_ALL_SCO | 340 AUDIO_DEVICE_IN_ANC_HEADSET | 341 AUDIO_DEVICE_IN_FM_RX | 342 AUDIO_DEVICE_IN_FM_RX_A2DP | 343 AUDIO_DEVICE_IN_DEFAULT); 344} 345 346static int adev_init_check(const struct audio_hw_device *dev) 347{ 348 const struct qcom_audio_device *qadev = to_cladev(dev); 349 350 return qadev->hwif->initCheck(); 351} 352 353static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 354{ 355 struct qcom_audio_device *qadev = to_ladev(dev); 356 return qadev->hwif->setVoiceVolume(volume); 357} 358 359static int adev_set_master_volume(struct audio_hw_device *dev, float volume) 360{ 361 struct qcom_audio_device *qadev = to_ladev(dev); 362 return qadev->hwif->setMasterVolume(volume); 363} 364 365static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) { 366 367 return -ENOSYS; 368} 369#ifdef QUALCOMM_FEATURES_ENABLED 370static int adev_set_fm_volume(struct audio_hw_device *dev, float volume) 371{ 372 struct qcom_audio_device *qadev = to_ladev(dev); 373 return qadev->hwif->setFmVolume(volume); 374} 375#endif 376 377static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 378{ 379 struct qcom_audio_device *qadev = to_ladev(dev); 380 return qadev->hwif->setMode(mode); 381} 382 383static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 384{ 385 struct qcom_audio_device *qadev = to_ladev(dev); 386 return qadev->hwif->setMicMute(state); 387} 388 389static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 390{ 391 const struct qcom_audio_device *qadev = to_cladev(dev); 392 return qadev->hwif->getMicMute(state); 393} 394 395static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 396{ 397 struct qcom_audio_device *qadev = to_ladev(dev); 398 return qadev->hwif->setParameters(String8(kvpairs)); 399} 400 401static char * adev_get_parameters(const struct audio_hw_device *dev, 402 const char *keys) 403{ 404 const struct qcom_audio_device *qadev = to_cladev(dev); 405 String8 s8; 406 407 s8 = qadev->hwif->getParameters(String8(keys)); 408 return strdup(s8.string()); 409} 410 411static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 412 const struct audio_config *config) 413{ 414 const struct qcom_audio_device *qadev = to_cladev(dev); 415 return qadev->hwif->getInputBufferSize(sample_rate, format, channel_count); 416} 417 418#ifdef QUALCOMM_FEATURES_ENABLED 419static int adev_open_output_session(struct audio_hw_device *dev, 420 uint32_t devices, 421 int *format, 422 int sessionId, 423 uint32_t samplingRate, 424 uint32_t channels, 425 struct audio_stream_out **stream_out) 426{ 427 struct qcom_audio_device *qadev = to_ladev(dev); 428 status_t status; 429 struct qcom_stream_out *out; 430 int ret; 431 432 out = (struct qcom_stream_out *)calloc(1, sizeof(*out)); 433 if (!out) 434 return -ENOMEM; 435 436 out->qcom_out = qadev->hwif->openOutputSession(devices, format,&status,sessionId,samplingRate,channels); 437 if (!out->qcom_out) { 438 ret = status; 439 goto err_open; 440 } 441 442 out->stream.common.standby = out_standby; 443 out->stream.common.set_parameters = out_set_parameters; 444 out->stream.set_volume = out_set_volume; 445 446 *stream_out = &out->stream; 447 return 0; 448 449err_open: 450 free(out); 451 *stream_out = NULL; 452 return ret; 453} 454#endif 455 456static int adev_open_output_stream(struct audio_hw_device *dev, 457 audio_io_handle_t handle, 458 audio_devices_t devices, 459 audio_output_flags_t flags, 460 struct audio_config *config, 461 struct audio_stream_out **stream_out) 462{ 463 struct qcom_audio_device *qadev = to_ladev(dev); 464 status_t status; 465 struct qcom_stream_out *out; 466 int ret; 467 468 out = (struct qcom_stream_out *)calloc(1, sizeof(*out)); 469 if (!out) 470 return -ENOMEM; 471 472 out->qcom_out = qadev->hwif->openOutputStream(devices, config->format, config->channels_mask, 473 config->sample_rate, &status); 474 if (!out->qcom_out) { 475 ret = status; 476 goto err_open; 477 } 478 479 out->stream.common.get_sample_rate = out_get_sample_rate; 480 out->stream.common.set_sample_rate = out_set_sample_rate; 481 out->stream.common.get_buffer_size = out_get_buffer_size; 482 out->stream.common.get_channels = out_get_channels; 483 out->stream.common.get_format = out_get_format; 484 out->stream.common.set_format = out_set_format; 485 out->stream.common.standby = out_standby; 486 out->stream.common.dump = out_dump; 487 out->stream.common.set_parameters = out_set_parameters; 488 out->stream.common.get_parameters = out_get_parameters; 489 out->stream.common.add_audio_effect = out_add_audio_effect; 490 out->stream.common.remove_audio_effect = out_remove_audio_effect; 491 out->stream.get_latency = out_get_latency; 492 out->stream.set_volume = out_set_volume; 493 out->stream.write = out_write; 494 out->stream.get_render_position = out_get_render_position; 495 out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 496 497 *stream_out = &out->stream; 498 return 0; 499 500err_open: 501 free(out); 502 *stream_out = NULL; 503 return ret; 504} 505 506static void adev_close_output_stream(struct audio_hw_device *dev, 507 struct audio_stream_out* stream) 508{ 509 struct qcom_audio_device *qadev = to_ladev(dev); 510 struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream); 511 512 qadev->hwif->closeOutputStream(out->qcom_out); 513 free(out); 514} 515 516/** This method creates and opens the audio hardware input stream */ 517static int adev_open_input_stream(struct audio_hw_device *dev, 518 audio_io_handle_t handle, 519 audio_devices_t devices, 520 audio_config *config, 521 audio_stream_in **stream_in) 522{ 523 struct qcom_audio_device *qadev = to_ladev(dev); 524 status_t status; 525 struct qcom_stream_in *in; 526 int ret; 527 528 in = (struct qcom_stream_in *)calloc(1, sizeof(*in)); 529 if (!in) 530 return -ENOMEM; 531 532 in->qcom_in = qadev->hwif->openInputStream(devices, config->format, config->channels_mask, 533 config->sample_rate, &status, 534 (AudioSystem::audio_in_acoustics)acoustics); 535 if (!in->qcom_in) { 536 ret = status; 537 goto err_open; 538 } 539 540 in->stream.common.get_sample_rate = in_get_sample_rate; 541 in->stream.common.set_sample_rate = in_set_sample_rate; 542 in->stream.common.get_buffer_size = in_get_buffer_size; 543 in->stream.common.get_channels = in_get_channels; 544 in->stream.common.get_format = in_get_format; 545 in->stream.common.set_format = in_set_format; 546 in->stream.common.standby = in_standby; 547 in->stream.common.dump = in_dump; 548 in->stream.common.set_parameters = in_set_parameters; 549 in->stream.common.get_parameters = in_get_parameters; 550 in->stream.common.add_audio_effect = in_add_audio_effect; 551 in->stream.common.remove_audio_effect = in_remove_audio_effect; 552 in->stream.set_gain = in_set_gain; 553 in->stream.read = in_read; 554 in->stream.get_input_frames_lost = in_get_input_frames_lost; 555 556 *stream_in = &in->stream; 557 return 0; 558 559err_open: 560 free(in); 561 *stream_in = NULL; 562 return ret; 563} 564 565static void adev_close_input_stream(struct audio_hw_device *dev, 566 struct audio_stream_in *stream) 567{ 568 struct qcom_audio_device *qadev = to_ladev(dev); 569 struct qcom_stream_in *in = 570 reinterpret_cast<struct qcom_stream_in *>(stream); 571 572 qadev->hwif->closeInputStream(in->qcom_in); 573 free(in); 574} 575 576static int adev_dump(const struct audio_hw_device *dev, int fd) 577{ 578 const struct qcom_audio_device *qadev = to_cladev(dev); 579 Vector<String16> args; 580 581 return qadev->hwif->dumpState(fd, args); 582} 583 584static int qcom_adev_close(hw_device_t* device) 585{ 586 struct audio_hw_device *hwdev = 587 reinterpret_cast<struct audio_hw_device *>(device); 588 struct qcom_audio_device *qadev = to_ladev(hwdev); 589 590 if (!qadev) 591 return 0; 592 593 if (qadev->hwif) 594 delete qadev->hwif; 595 596 free(qadev); 597 return 0; 598} 599 600static int qcom_adev_open(const hw_module_t* module, const char* name, 601 hw_device_t** device) 602{ 603 struct qcom_audio_device *qadev; 604 int ret; 605 606 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 607 return -EINVAL; 608 609 qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev)); 610 if (!qadev) 611 return -ENOMEM; 612 613 qadev->device.common.tag = HARDWARE_DEVICE_TAG; 614 qadev->device.common.version = AUDIO_DEVICE_API_VERSION_1_0; 615 qadev->device.common.module = const_cast<hw_module_t*>(module); 616 qadev->device.common.close = qcom_adev_close; 617 618 qadev->device.get_supported_devices = adev_get_supported_devices; 619 qadev->device.init_check = adev_init_check; 620 qadev->device.set_voice_volume = adev_set_voice_volume; 621 qadev->device.set_master_volume = adev_set_master_volume; 622 qadev->device.get_master_volume = adev_get_master_volume; 623#ifdef QUALCOMM_FEATURES_ENABLED 624 qadev->device.set_fm_volume = adev_set_fm_volume; 625#endif 626 qadev->device.set_mode = adev_set_mode; 627 qadev->device.set_mic_mute = adev_set_mic_mute; 628 qadev->device.get_mic_mute = adev_get_mic_mute; 629 qadev->device.set_parameters = adev_set_parameters; 630 qadev->device.get_parameters = adev_get_parameters; 631 qadev->device.get_input_buffer_size = adev_get_input_buffer_size; 632 qadev->device.open_output_stream = adev_open_output_stream; 633#ifdef QUALCOMM_FEATURES_ENABLED 634 qadev->device.open_output_session = adev_open_output_session; 635#endif 636 qadev->device.close_output_stream = adev_close_output_stream; 637 qadev->device.open_input_stream = adev_open_input_stream; 638 qadev->device.close_input_stream = adev_close_input_stream; 639 qadev->device.dump = adev_dump; 640 641 qadev->hwif = createAudioHardware(); 642 if (!qadev->hwif) { 643 ret = -EIO; 644 goto err_create_audio_hw; 645 } 646 647 *device = &qadev->device.common; 648 649 return 0; 650 651err_create_audio_hw: 652 free(qadev); 653 return ret; 654} 655 656static struct hw_module_methods_t qcom_audio_module_methods = { 657 open: qcom_adev_open 658}; 659 660struct qcom_audio_module HAL_MODULE_INFO_SYM = { 661 module: { 662 common: { 663 tag: HARDWARE_MODULE_TAG, 664 version_major: 1, 665 version_minor: 0, 666 id: AUDIO_HARDWARE_MODULE_ID, 667 name: "QCOM Audio HW HAL", 668 author: "Code Aurora Forum", 669 methods: &qcom_audio_module_methods, 670 dso : NULL, 671 reserved : {0}, 672 }, 673 }, 674}; 675 676}; // extern "C" 677 678}; // namespace android_audio_legacy 679