1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "usb_audio_hw" 18/*#define LOG_NDEBUG 0*/ 19 20#include <errno.h> 21#include <pthread.h> 22#include <stdint.h> 23#include <sys/time.h> 24#include <stdlib.h> 25 26#include <cutils/log.h> 27#include <cutils/str_parms.h> 28#include <cutils/properties.h> 29 30#include <hardware/hardware.h> 31#include <system/audio.h> 32#include <hardware/audio.h> 33 34#include <tinyalsa/asoundlib.h> 35 36struct pcm_config pcm_config = { 37 .channels = 2, 38 .rate = 44100, 39 .period_size = 1024, 40 .period_count = 4, 41 .format = PCM_FORMAT_S16_LE, 42}; 43 44struct audio_device { 45 struct audio_hw_device hw_device; 46 47 pthread_mutex_t lock; /* see note below on mutex acquisition order */ 48 int card; 49 int device; 50 bool standby; 51}; 52 53struct stream_out { 54 struct audio_stream_out stream; 55 56 pthread_mutex_t lock; /* see note below on mutex acquisition order */ 57 struct pcm *pcm; 58 bool standby; 59 60 struct audio_device *dev; 61}; 62 63/** 64 * NOTE: when multiple mutexes have to be acquired, always respect the 65 * following order: hw device > out stream 66 */ 67 68/* Helper functions */ 69 70/* must be called with hw device and output stream mutexes locked */ 71static int start_output_stream(struct stream_out *out) 72{ 73 struct audio_device *adev = out->dev; 74 int i; 75 76 if ((adev->card < 0) || (adev->device < 0)) 77 return -EINVAL; 78 79 out->pcm = pcm_open(adev->card, adev->device, PCM_OUT, &pcm_config); 80 81 if (out->pcm && !pcm_is_ready(out->pcm)) { 82 ALOGE("pcm_open() failed: %s", pcm_get_error(out->pcm)); 83 pcm_close(out->pcm); 84 return -ENOMEM; 85 } 86 87 return 0; 88} 89 90/* API functions */ 91 92static uint32_t out_get_sample_rate(const struct audio_stream *stream) 93{ 94 return pcm_config.rate; 95} 96 97static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 98{ 99 return 0; 100} 101 102static size_t out_get_buffer_size(const struct audio_stream *stream) 103{ 104 return pcm_config.period_size * 105 audio_stream_frame_size((struct audio_stream *)stream); 106} 107 108static uint32_t out_get_channels(const struct audio_stream *stream) 109{ 110 return AUDIO_CHANNEL_OUT_STEREO; 111} 112 113static audio_format_t out_get_format(const struct audio_stream *stream) 114{ 115 return AUDIO_FORMAT_PCM_16_BIT; 116} 117 118static int out_set_format(struct audio_stream *stream, audio_format_t format) 119{ 120 return 0; 121} 122 123static int out_standby(struct audio_stream *stream) 124{ 125 struct stream_out *out = (struct stream_out *)stream; 126 127 pthread_mutex_lock(&out->dev->lock); 128 pthread_mutex_lock(&out->lock); 129 130 if (!out->standby) { 131 pcm_close(out->pcm); 132 out->pcm = NULL; 133 out->standby = true; 134 } 135 136 pthread_mutex_unlock(&out->lock); 137 pthread_mutex_unlock(&out->dev->lock); 138 139 return 0; 140} 141 142static int out_dump(const struct audio_stream *stream, int fd) 143{ 144 return 0; 145} 146 147static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 148{ 149 struct stream_out *out = (struct stream_out *)stream; 150 struct audio_device *adev = out->dev; 151 struct str_parms *parms; 152 char value[32]; 153 int ret; 154 int routing = 0; 155 156 parms = str_parms_create_str(kvpairs); 157 pthread_mutex_lock(&adev->lock); 158 159 ret = str_parms_get_str(parms, "card", value, sizeof(value)); 160 if (ret >= 0) 161 adev->card = atoi(value); 162 163 ret = str_parms_get_str(parms, "device", value, sizeof(value)); 164 if (ret >= 0) 165 adev->device = atoi(value); 166 167 pthread_mutex_unlock(&adev->lock); 168 str_parms_destroy(parms); 169 170 return 0; 171} 172 173static char * out_get_parameters(const struct audio_stream *stream, const char *keys) 174{ 175 return strdup(""); 176} 177 178static uint32_t out_get_latency(const struct audio_stream_out *stream) 179{ 180 return (pcm_config.period_size * pcm_config.period_count * 1000) / 181 out_get_sample_rate(&stream->common); 182} 183 184static int out_set_volume(struct audio_stream_out *stream, float left, 185 float right) 186{ 187 return -ENOSYS; 188} 189 190static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 191 size_t bytes) 192{ 193 int ret; 194 struct stream_out *out = (struct stream_out *)stream; 195 196 pthread_mutex_lock(&out->dev->lock); 197 pthread_mutex_lock(&out->lock); 198 if (out->standby) { 199 ret = start_output_stream(out); 200 if (ret != 0) { 201 goto err; 202 } 203 out->standby = false; 204 } 205 206 pcm_write(out->pcm, (void *)buffer, bytes); 207 208 pthread_mutex_unlock(&out->lock); 209 pthread_mutex_unlock(&out->dev->lock); 210 211 return bytes; 212 213err: 214 pthread_mutex_unlock(&out->lock); 215 216 if (ret != 0) { 217 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / 218 out_get_sample_rate(&stream->common)); 219 } 220 221 return bytes; 222} 223 224static int out_get_render_position(const struct audio_stream_out *stream, 225 uint32_t *dsp_frames) 226{ 227 return -EINVAL; 228} 229 230static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 231{ 232 return 0; 233} 234 235static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 236{ 237 return 0; 238} 239 240static int out_get_next_write_timestamp(const struct audio_stream_out *stream, 241 int64_t *timestamp) 242{ 243 return -EINVAL; 244} 245 246static int adev_open_output_stream(struct audio_hw_device *dev, 247 audio_io_handle_t handle, 248 audio_devices_t devices, 249 audio_output_flags_t flags, 250 struct audio_config *config, 251 struct audio_stream_out **stream_out) 252{ 253 struct audio_device *adev = (struct audio_device *)dev; 254 struct stream_out *out; 255 int ret; 256 257 out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); 258 if (!out) 259 return -ENOMEM; 260 261 out->stream.common.get_sample_rate = out_get_sample_rate; 262 out->stream.common.set_sample_rate = out_set_sample_rate; 263 out->stream.common.get_buffer_size = out_get_buffer_size; 264 out->stream.common.get_channels = out_get_channels; 265 out->stream.common.get_format = out_get_format; 266 out->stream.common.set_format = out_set_format; 267 out->stream.common.standby = out_standby; 268 out->stream.common.dump = out_dump; 269 out->stream.common.set_parameters = out_set_parameters; 270 out->stream.common.get_parameters = out_get_parameters; 271 out->stream.common.add_audio_effect = out_add_audio_effect; 272 out->stream.common.remove_audio_effect = out_remove_audio_effect; 273 out->stream.get_latency = out_get_latency; 274 out->stream.set_volume = out_set_volume; 275 out->stream.write = out_write; 276 out->stream.get_render_position = out_get_render_position; 277 out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 278 279 out->dev = adev; 280 281 config->format = out_get_format(&out->stream.common); 282 config->channel_mask = out_get_channels(&out->stream.common); 283 config->sample_rate = out_get_sample_rate(&out->stream.common); 284 285 out->standby = true; 286 287 adev->card = -1; 288 adev->device = -1; 289 290 *stream_out = &out->stream; 291 return 0; 292 293err_open: 294 free(out); 295 *stream_out = NULL; 296 return ret; 297} 298 299static void adev_close_output_stream(struct audio_hw_device *dev, 300 struct audio_stream_out *stream) 301{ 302 struct stream_out *out = (struct stream_out *)stream; 303 304 out_standby(&stream->common); 305 free(stream); 306} 307 308static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 309{ 310 return 0; 311} 312 313static char * adev_get_parameters(const struct audio_hw_device *dev, 314 const char *keys) 315{ 316 return strdup(""); 317} 318 319static int adev_init_check(const struct audio_hw_device *dev) 320{ 321 return 0; 322} 323 324static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 325{ 326 return -ENOSYS; 327} 328 329static int adev_set_master_volume(struct audio_hw_device *dev, float volume) 330{ 331 return -ENOSYS; 332} 333 334static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 335{ 336 return 0; 337} 338 339static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 340{ 341 return -ENOSYS; 342} 343 344static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 345{ 346 return -ENOSYS; 347} 348 349static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 350 const struct audio_config *config) 351{ 352 return 0; 353} 354 355static int adev_open_input_stream(struct audio_hw_device *dev, 356 audio_io_handle_t handle, 357 audio_devices_t devices, 358 struct audio_config *config, 359 struct audio_stream_in **stream_in) 360{ 361 return -ENOSYS; 362} 363 364static void adev_close_input_stream(struct audio_hw_device *dev, 365 struct audio_stream_in *stream) 366{ 367} 368 369static int adev_dump(const audio_hw_device_t *device, int fd) 370{ 371 return 0; 372} 373 374static int adev_close(hw_device_t *device) 375{ 376 struct audio_device *adev = (struct audio_device *)device; 377 378 free(device); 379 return 0; 380} 381 382static int adev_open(const hw_module_t* module, const char* name, 383 hw_device_t** device) 384{ 385 struct audio_device *adev; 386 int ret; 387 388 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 389 return -EINVAL; 390 391 adev = calloc(1, sizeof(struct audio_device)); 392 if (!adev) 393 return -ENOMEM; 394 395 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; 396 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; 397 adev->hw_device.common.module = (struct hw_module_t *) module; 398 adev->hw_device.common.close = adev_close; 399 400 adev->hw_device.init_check = adev_init_check; 401 adev->hw_device.set_voice_volume = adev_set_voice_volume; 402 adev->hw_device.set_master_volume = adev_set_master_volume; 403 adev->hw_device.set_mode = adev_set_mode; 404 adev->hw_device.set_mic_mute = adev_set_mic_mute; 405 adev->hw_device.get_mic_mute = adev_get_mic_mute; 406 adev->hw_device.set_parameters = adev_set_parameters; 407 adev->hw_device.get_parameters = adev_get_parameters; 408 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; 409 adev->hw_device.open_output_stream = adev_open_output_stream; 410 adev->hw_device.close_output_stream = adev_close_output_stream; 411 adev->hw_device.open_input_stream = adev_open_input_stream; 412 adev->hw_device.close_input_stream = adev_close_input_stream; 413 adev->hw_device.dump = adev_dump; 414 415 *device = &adev->hw_device.common; 416 417 return 0; 418} 419 420static struct hw_module_methods_t hal_module_methods = { 421 .open = adev_open, 422}; 423 424struct audio_module HAL_MODULE_INFO_SYM = { 425 .common = { 426 .tag = HARDWARE_MODULE_TAG, 427 .module_api_version = AUDIO_MODULE_API_VERSION_0_1, 428 .hal_api_version = HARDWARE_HAL_API_VERSION, 429 .id = AUDIO_HARDWARE_MODULE_ID, 430 .name = "USB audio HW HAL", 431 .author = "The Android Open Source Project", 432 .methods = &hal_module_methods, 433 }, 434}; 435