Restructure files 70/70470/8 accepted/tizen/mobile/20160602.022129 submit/tizen/20160530.013417
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 19 May 2016 08:14:22 +0000 (17:14 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Fri, 27 May 2016 06:48:02 +0000 (15:48 +0900)
 - add tizen-audio-impl.h and tizen-audio-impl-xxx.c for implemetation layer that could be code variation as per HW
 - rename files
 - remove unused functions
 - rename functions according to rules("__" prefix for static functions)

[Version] 0.1.10
[Profile] Mobile
[Issue Type] Refactoring

Change-Id: Ib222389161b53efc58832384b1a86542f1de42df
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
17 files changed:
Makefile.am
packaging/audio-hal-sc7727.spec
tizen-audio-comm.c
tizen-audio-device.c [deleted file]
tizen-audio-impl-ctrl.c [new file with mode: 0644]
tizen-audio-impl-pcm.c [new file with mode: 0644]
tizen-audio-impl-ucm.c [moved from tizen-audio-ucm.c with 84% similarity]
tizen-audio-impl.h [new file with mode: 0644]
tizen-audio-internal.h
tizen-audio-modem.c
tizen-audio-pcm.c [new file with mode: 0644]
tizen-audio-routing.c [new file with mode: 0644]
tizen-audio-stream.c [new file with mode: 0644]
tizen-audio-util.c
tizen-audio-volume.c
tizen-audio.c
tizen-audio.h

index 87e669b..089ad7a 100644 (file)
@@ -1,12 +1,16 @@
 lib_LTLIBRARIES = libtizen-audio.la
 
 libtizen_audio_la_SOURCES = tizen-audio.c \
-               tizen-audio-device.c \
                tizen-audio-volume.c \
-               tizen-audio-ucm.c \
+               tizen-audio-routing.c \
+               tizen-audio-stream.c \
+               tizen-audio-pcm.c \
                tizen-audio-modem.c \
                tizen-audio-comm.c \
-               tizen-audio-util.c
+               tizen-audio-util.c \
+               tizen-audio-impl-pcm.c \
+               tizen-audio-impl-ucm.c \
+               tizen-audio-impl-ctrl.c
 libtizen_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version
 libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS) $(EXPAT_LIBS)
 libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) $(EXPAT_CFLAGS) -DUSE_DLOG
index 109226f..4bb1fe2 100644 (file)
@@ -1,6 +1,6 @@
 Name:       audio-hal-sc7727
 Summary:    TIZEN Audio HAL for SC7727
-Version:    0.1.9
+Version:    0.1.10
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index d94aa22..628e8d9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include "tizen-audio-internal.h"
 
-audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(name, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_DEBUG("send message : name(%s), value(%d)", name, value);
-    if (ah->comm.msg_cb) {
-        ah->comm.msg_cb(name, value, ah->comm.user_data);
-    }
-
-    return audio_ret;
-}
-
-audio_return_t _audio_comm_set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data)
+static audio_return_t __set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
 
@@ -52,7 +37,7 @@ audio_return_t _audio_comm_set_message_callback(audio_hal_t *ah, message_cb call
     return audio_ret;
 }
 
-audio_return_t _audio_comm_unset_message_callback(audio_hal_t *ah)
+static audio_return_t __unset_message_callback(audio_hal_t *ah)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
 
@@ -89,3 +74,44 @@ audio_return_t _audio_comm_deinit(audio_hal_t *ah)
 
     return audio_ret;
 }
+
+audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(name, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_DEBUG("send message : name(%s), value(%d)", name, value);
+    if (ah->comm.msg_cb) {
+        ah->comm.msg_cb(name, value, ah->comm.user_data);
+    }
+
+    return audio_ret;
+}
+
+audio_return_t audio_add_message_cb(void *audio_handle, message_cb callback, void *user_data)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
+
+    /* NOTE: Management of several callbacks could be implemented.
+             But we do not care of it for now.*/
+    ret = __set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
+
+    return ret;
+}
+
+audio_return_t audio_remove_message_cb(void *audio_handle, message_cb callback)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
+
+    ret = __unset_message_callback((audio_hal_t *)audio_handle);
+
+    return ret;
+}
\ No newline at end of file
diff --git a/tizen-audio-device.c b/tizen-audio-device.c
deleted file mode 100644 (file)
index db6c1ac..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-/*
- * audio-hal
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "tizen-audio-internal.h"
-
-#ifndef __USE_TINYALSA__
-/* FIXME : To avoid build warning... */
-int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
-#endif
-
-/* #define DEBUG_TIMING */
-
-static device_type_t outDeviceTypes[] = {
-    { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
-    { AUDIO_DEVICE_OUT_RECEIVER, "Earpiece" },
-    { AUDIO_DEVICE_OUT_JACK, "Headphones" },
-    { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
-    { 0, 0 },
-};
-
-static device_type_t inDeviceTypes[] = {
-    { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
-    { AUDIO_DEVICE_IN_SUB_MIC, "SubMic" },
-    { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
-    { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
-    { 0, 0 },
-};
-
-static const char* mode_to_verb_str[] = {
-    AUDIO_USE_CASE_VERB_HIFI,
-    AUDIO_USE_CASE_VERB_VOICECALL,
-    AUDIO_USE_CASE_VERB_VIDEOCALL,
-    AUDIO_USE_CASE_VERB_VOIP,
-};
-
-static int _voice_pcm_open(audio_hal_t *ah);
-static int _voice_pcm_close(audio_hal_t *ah, uint32_t direction);
-static void _reset_pcm_devices(audio_hal_t *ah);
-static void _reset_voice_devices_info(audio_hal_t *ah);
-
-static uint32_t convert_device_string_to_enum(const char* device_str, uint32_t direction)
-{
-    uint32_t device = 0;
-
-    if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
-        device = AUDIO_DEVICE_OUT_SPEAKER;
-    } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
-        device = AUDIO_DEVICE_OUT_RECEIVER;
-    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
-        device = AUDIO_DEVICE_OUT_JACK;
-    } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
-        device = AUDIO_DEVICE_OUT_BT_SCO;
-    } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
-        device = AUDIO_DEVICE_IN_MAIN_MIC;
-    /* To Do : SUB_MIC */
-    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
-        device = AUDIO_DEVICE_IN_JACK;
-    } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
-        device = AUDIO_DEVICE_IN_BT_SCO;
-    } else {
-        device = AUDIO_DEVICE_NONE;
-    }
-    AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
-    return device;
-}
-
-static audio_return_t set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    uint32_t new_device = 0;
-    const char *active_devices[MAX_DEVICES] = {NULL,};
-    int i = 0, j = 0, dev_idx = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
-
-    if (num_of_devices > MAX_DEVICES) {
-        num_of_devices = MAX_DEVICES;
-        AUDIO_LOG_ERROR("error: num_of_devices");
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if (devices[0].direction == AUDIO_DIRECTION_OUT) {
-        ah->device.active_out &= 0x0;
-        if (ah->device.active_in) {
-            /* check the active in devices */
-            for (j = 0; j < inDeviceTypes[j].type; j++) {
-                if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
-                    active_devices[dev_idx++] = inDeviceTypes[j].name;
-            }
-        }
-    } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
-        ah->device.active_in &= 0x0;
-        if (ah->device.active_out) {
-            /* check the active out devices */
-            for (j = 0; j < outDeviceTypes[j].type; j++) {
-                if (ah->device.active_out & outDeviceTypes[j].type)
-                    active_devices[dev_idx++] = outDeviceTypes[j].name;
-            }
-        }
-    }
-
-    for (i = 0; i < num_of_devices; i++) {
-        new_device = convert_device_string_to_enum(devices[i].type, devices[i].direction);
-        if (new_device & AUDIO_DEVICE_IN) {
-            for (j = 0; j < inDeviceTypes[j].type; j++) {
-                if (new_device == inDeviceTypes[j].type) {
-                    active_devices[dev_idx++] = inDeviceTypes[j].name;
-                    ah->device.active_in |= new_device;
-                }
-            }
-        } else {
-            for (j = 0; j < outDeviceTypes[j].type; j++) {
-                if (new_device == outDeviceTypes[j].type) {
-                    active_devices[dev_idx++] = outDeviceTypes[j].name;
-                    ah->device.active_out |= new_device;
-                }
-            }
-        }
-    }
-
-    if (active_devices[0] == NULL) {
-        AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    audio_ret = _audio_ucm_set_devices(ah, verb, active_devices);
-    if (audio_ret)
-        AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret);
-
-    return audio_ret;
-}
-
-audio_return_t _audio_device_init(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    ah->device.active_in = 0x0;
-    ah->device.active_out = 0x0;
-    ah->device.pcm_in = NULL;
-    ah->device.pcm_out = NULL;
-    ah->device.mode = VERB_NORMAL;
-    pthread_mutex_init(&ah->device.pcm_lock, NULL);
-    pthread_mutex_init(&ah->device.device_lock, NULL);
-    pthread_cond_init(&ah->device.device_cond, NULL);
-    ah->device.pcm_count = 0;
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_device_deinit(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    pthread_mutex_destroy(&ah->device.pcm_lock);
-    pthread_mutex_destroy(&ah->device.device_lock);
-    pthread_cond_destroy(&ah->device.device_cond);
-    return AUDIO_RET_OK;
-}
-
-static audio_return_t _update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    device_info_t *devices = NULL;
-    const char *verb = mode_to_verb_str[VERB_NORMAL];
-#if 0  /* Disable setting modifiers, because driver does not support it yet */
-    int mod_idx = 0;
-    const char *modifiers[MAX_MODIFIERS] = {NULL,};
-#endif
-
-    if (ah->modem.is_connected) {
-        AUDIO_LOG_INFO("modem is connected, skip verb[%s]", verb);
-        return audio_ret;
-    }
-
-    if (ah->device.mode != VERB_NORMAL) {
-        if (ah->device.mode == VERB_VOICECALL) {
-            _reset_voice_devices_info(ah);
-            COND_SIGNAL(ah->device.device_cond, "device_cond");
-        }
-        _reset_pcm_devices(ah);
-        ah->device.mode = VERB_NORMAL;
-    }
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
-
-    devices = route_info->device_infos;
-
-    AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
-
-    audio_ret = set_devices(ah, verb, devices, route_info->num_of_devices);
-    if (audio_ret) {
-        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
-        return audio_ret;
-    }
-    ah->device.mode = VERB_NORMAL;
-
-#if 0 /* Disable setting modifiers, because driver does not support it yet */
-    /* Set modifiers */
-    if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) {
-        modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH;
-    } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) {
-        if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK)
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA;
-        else
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
-    } else if (!strncmp("ringtone", route_info->role, MAX_NAME_LEN)) {
-        if (ah->device.active_out)
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_RINGTONE;
-    } else {
-        if (ah->device.active_in)
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING;
-        else
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
-    }
-    audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers);
-#endif
-    return audio_ret;
-}
-
-static audio_return_t _update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    const char *verb = mode_to_verb_str[VERB_VOICECALL];
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    /* if both params are 0, return error for invalid state,
-         * this error would be used to tizen-audio-modem.c */
-    AUDIO_RETURN_VAL_IF_FAIL((devices||num_of_devices), AUDIO_ERR_INVALID_STATE);
-    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("update_route_voicecall++");
-
-    audio_ret = set_devices(ah, verb, devices, num_of_devices);
-    if (audio_ret) {
-        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
-        return audio_ret;
-    }
-
-    if (ah->device.mode != VERB_VOICECALL) {
-        _voice_pcm_open(ah);
-        ah->device.mode = VERB_VOICECALL;
-        /* FIXME. Get network info and configure rate in pcm device */
-    }
-
-    return audio_ret;
-}
-
-static audio_return_t _update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    const char *verb = mode_to_verb_str[VERB_NORMAL];
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("update_route_voip++");
-
-    audio_ret = set_devices(ah, verb, devices, num_of_devices);
-    if (audio_ret) {
-        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
-        return audio_ret;
-    }
-    /* FIXME. If necessary, set VERB_VOIP */
-    ah->device.mode = VERB_NORMAL;
-
-    /* TO DO: Set modifiers */
-    return audio_ret;
-}
-
-static audio_return_t _update_route_reset(audio_hal_t *ah, uint32_t direction)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    const char *active_devices[MAX_DEVICES] = {NULL,};
-    int i = 0, dev_idx = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
-
-    if (direction == AUDIO_DIRECTION_OUT) {
-        ah->device.active_out &= 0x0;
-        if (ah->device.active_in) {
-            /* check the active in devices */
-            for (i = 0; i < inDeviceTypes[i].type; i++) {
-                if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
-                    active_devices[dev_idx++] = inDeviceTypes[i].name;
-                    AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
-                }
-            }
-        }
-    } else {
-        ah->device.active_in &= 0x0;
-        if (ah->device.active_out) {
-            /* check the active out devices */
-            for (i = 0; i < outDeviceTypes[i].type; i++) {
-                if (ah->device.active_out & outDeviceTypes[i].type) {
-                    active_devices[dev_idx++] = outDeviceTypes[i].name;
-                    AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
-                }
-            }
-        }
-    }
-    if (ah->device.mode == VERB_VOICECALL) {
-        _voice_pcm_close(ah, direction);
-        if (!ah->device.active_in && !ah->device.active_out)
-            ah->device.mode = VERB_NORMAL;
-        _reset_voice_devices_info(ah);
-        COND_SIGNAL(ah->device.device_cond, "device_cond");
-    }
-
-    if (active_devices[0] == NULL) {
-        AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
-        return AUDIO_RET_OK;
-    }
-
-    audio_ret = _audio_ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices);
-    if (audio_ret)
-        AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret);
-
-    return audio_ret;
-}
-
-audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    audio_hal_t *ah = (audio_hal_t *)audio_handle;
-    device_info_t *devices = NULL;
-    uint32_t prev_size;
-    int32_t i;
-    int32_t j;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("role:%s", info->role);
-
-    devices = info->device_infos;
-
-    if (!strncmp("call-voice", info->role, MAX_NAME_LEN)) {
-        if (!ah->modem.is_connected) {
-            if (info->num_of_devices) {
-                if (!ah->device.num_of_call_devices) {
-                    if ((ah->device.init_call_devices = (device_info_t*)calloc(info->num_of_devices, sizeof(device_info_t)))) {
-                        memcpy(ah->device.init_call_devices, devices, info->num_of_devices*sizeof(device_info_t));
-                        ah->device.num_of_call_devices = info->num_of_devices;
-                    } else {
-                        AUDIO_LOG_ERROR("failed to calloc");
-                        audio_ret = AUDIO_ERR_RESOURCE;
-                        goto ERROR;
-                    }
-                } else if (ah->device.num_of_call_devices) {
-                    prev_size = ah->device.num_of_call_devices;
-                    if (prev_size == 2) {
-                        /* There's a chance to be requested to change routing from user
-                         * though two devices(for input/output) has already been set for call-voice routing.
-                         * In this case, exchange an old device for a new device if it's direction is same as an old one's. */
-                        for (i = 0; i < prev_size; i++) {
-                            for (j = 0; j < info->num_of_devices; j++) {
-                                if (devices[j].direction == ah->device.init_call_devices[i].direction &&
-                                    devices[j].id != ah->device.init_call_devices[i].id)
-                                    memcpy(&ah->device.init_call_devices[i], &devices[j], sizeof(device_info_t));
-                            }
-                        }
-                    } else if (prev_size < 2) {
-                        /* A device has already been added for call-voice routing,
-                         * and now it is about to add a new device(input or output device). */
-                        ah->device.num_of_call_devices += info->num_of_devices;
-                        if ((ah->device.init_call_devices = (device_info_t*)realloc(ah->device.init_call_devices, sizeof(device_info_t)*ah->device.num_of_call_devices))) {
-                            memcpy((void*)&(ah->device.init_call_devices[prev_size]), devices, info->num_of_devices*sizeof(device_info_t));
-                        } else {
-                            AUDIO_LOG_ERROR("failed to realloc");
-                            audio_ret = AUDIO_ERR_RESOURCE;
-                            goto ERROR;
-                        }
-                    } else {
-                        AUDIO_LOG_ERROR("invaild previous num. of call devices");
-                        audio_ret = AUDIO_ERR_INTERNAL;
-                        goto ERROR;
-                    }
-                }
-            } else {
-                AUDIO_LOG_ERROR("failed to do route for call-voice, num_of_devices is 0");
-                audio_ret = AUDIO_ERR_PARAMETER;
-                goto ERROR;
-            }
-            AUDIO_LOG_INFO("modem is not ready, skip...");
-        } else {
-            audio_ret = _update_route_voicecall(ah, devices, info->num_of_devices);
-            if (AUDIO_IS_ERROR(audio_ret)) {
-                AUDIO_LOG_WARN("set voicecall route return 0x%x", audio_ret);
-            }
-            COND_SIGNAL(ah->device.device_cond, "device_cond");
-        }
-    } else if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
-        audio_ret = _update_route_voip(ah, devices, info->num_of_devices);
-        if (AUDIO_IS_ERROR(audio_ret)) {
-            AUDIO_LOG_WARN("set voip route return 0x%x", audio_ret);
-        }
-    } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
-        audio_ret = _update_route_reset(ah, devices->direction);
-        if (AUDIO_IS_ERROR(audio_ret)) {
-            AUDIO_LOG_WARN("set reset return 0x%x", audio_ret);
-        }
-    } else {
-        /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
-        audio_ret = _update_route_ap_playback_capture(ah, info);
-        if (AUDIO_IS_ERROR(audio_ret)) {
-            AUDIO_LOG_WARN("set playback route return 0x%x", audio_ret);
-        }
-    }
-
-ERROR:
-    return audio_ret;
-}
-
-audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    audio_hal_t *ah = (audio_hal_t *)audio_handle;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected);
-
-    return audio_ret;
-}
-
-audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option)
-{
-    audio_return_t audio_ret = AUDIO_RET_OK;
-    audio_hal_t *ah = (audio_hal_t *)audio_handle;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
-
-    return audio_ret;
-}
-
-static int __voice_pcm_set_params(audio_hal_t *ah, snd_pcm_t *pcm)
-{
-    snd_pcm_hw_params_t *params = NULL;
-    int err = 0;
-    unsigned int val = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
-
-    /* Skip parameter setting to null device. */
-    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
-        return AUDIO_ERR_IOCTL;
-
-    /* Allocate a hardware parameters object. */
-    snd_pcm_hw_params_alloca(&params);
-
-    /* Fill it in with default values. */
-    if (snd_pcm_hw_params_any(pcm, params) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
-        goto error;
-    }
-
-    /* Set the desired hardware parameters. */
-    /* Interleaved mode */
-    err = snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() : failed! - %s\n", snd_strerror(err));
-        goto error;
-    }
-    err = snd_pcm_hw_params_set_rate(pcm, params, 8000, 0);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
-    }
-    err = snd_pcm_hw_params(pcm, params);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
-        goto error;
-    }
-
-    /* Dump current param */
-    snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val);
-    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
-
-    snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&val);
-    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
-                    snd_pcm_format_name((snd_pcm_format_t)val),
-                    snd_pcm_format_description((snd_pcm_format_t)val));
-
-    snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val);
-    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
-                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
-                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
-
-    snd_pcm_hw_params_get_channels(params, &val);
-    AUDIO_LOG_DEBUG("channels = %d\n", val);
-
-    return 0;
-
-error:
-    return -1;
-}
-
-static int _voice_pcm_open(audio_hal_t *ah)
-{
-    int err, ret = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("open voice pcm handles");
-
-    /* Get playback voice-pcm from ucm conf. Open and set-params */
-    if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_out, VOICE_PCM_DEVICE, AUDIO_DIRECTION_OUT, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err));
-        return AUDIO_ERR_IOCTL;
-    }
-    ret = __voice_pcm_set_params(ah, ah->device.pcm_out);
-
-    AUDIO_LOG_INFO("pcm playback device open success device(%s)", VOICE_PCM_DEVICE);
-
-    /* Get capture voice-pcm from ucm conf. Open and set-params */
-    if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_in, VOICE_PCM_DEVICE, AUDIO_DIRECTION_IN, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err));
-        return AUDIO_ERR_IOCTL;
-    }
-    ret = __voice_pcm_set_params(ah, ah->device.pcm_in);
-    AUDIO_LOG_INFO("pcm captures device open success device(%s)", VOICE_PCM_DEVICE);
-
-    return ret;
-}
-
-static int _voice_pcm_close(audio_hal_t *ah, uint32_t direction)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("close voice pcm handles");
-
-    if (ah->device.pcm_out && (direction == AUDIO_DIRECTION_OUT)) {
-        audio_pcm_close((void *)ah, ah->device.pcm_out);
-        ah->device.pcm_out = NULL;
-        AUDIO_LOG_INFO("voice pcm_out handle close success");
-    } else if (ah->device.pcm_in && (direction == AUDIO_DIRECTION_IN)) {
-        audio_pcm_close((void *)ah, ah->device.pcm_in);
-        ah->device.pcm_in = NULL;
-        AUDIO_LOG_INFO("voice pcm_in handle close success");
-    }
-
-    return AUDIO_RET_OK;
-}
-
-static void _reset_pcm_devices(audio_hal_t *ah)
-{
-    AUDIO_RETURN_IF_FAIL(ah);
-
-    if (ah->device.pcm_out) {
-        audio_pcm_close((void *)ah, ah->device.pcm_out);
-        ah->device.pcm_out = NULL;
-        AUDIO_LOG_INFO("pcm_out handle close success");
-    }
-    if (ah->device.pcm_in) {
-        audio_pcm_close((void *)ah, ah->device.pcm_in);
-        ah->device.pcm_in = NULL;
-        AUDIO_LOG_INFO("pcm_in handle close success");
-    }
-
-    return;
-}
-
-static void _reset_voice_devices_info(audio_hal_t *ah)
-{
-    AUDIO_RETURN_IF_FAIL(ah);
-
-    AUDIO_LOG_INFO("reset voice device info");
-    if (ah->device.init_call_devices) {
-        free(ah->device.init_call_devices);
-        ah->device.init_call_devices = NULL;
-        ah->device.num_of_call_devices = 0;
-    }
-
-    return;
-}
-
-#ifdef __USE_TINYALSA__
-static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction)
-{
-    struct pcm *pcm = NULL;
-    struct pcm_config config;
-
-    AUDIO_RETURN_NULL_IF_FAIL(ss);
-
-    config.channels          = ss->channels;
-    config.rate              = ss->rate;
-    config.period_size       = period_size;
-    config.period_count      = period_count;
-    config.format            = ss->format;
-    config.start_threshold   = period_size;
-    config.stop_threshold    = 0xFFFFFFFF;
-    config.silence_threshold = 0;
-
-    AUDIO_LOG_INFO("direction %d, channels %d, rate %d, format %d, period_size %d, period_count %d", direction, ss->channels, ss->rate, ss->format, period_size, period_count);
-
-    pcm = pcm_open((direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_CARD_ID : CAPTURE_CARD_ID,
-                   (direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_PCM_DEVICE_ID : CAPTURE_PCM_DEVICE_ID,
-                   (direction == AUDIO_DIRECTION_OUT) ? PCM_OUT : PCM_IN,
-                   &config);
-    if (!pcm || !pcm_is_ready(pcm)) {
-        AUDIO_LOG_ERROR("Unable to open device (%s)", pcm_get_error(pcm));
-        pcm_close(pcm);
-        return NULL;
-    }
-
-    return pcm;
-}
-#endif
-
-audio_return_t _audio_update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
-{
-    return _update_route_voicecall(ah, devices, num_of_devices);
-}
-
-audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
-{
-#ifdef __USE_TINYALSA__
-    audio_hal_t *ah;
-    audio_pcm_sample_spec_t *ss;
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
-
-    ah = (audio_hal_t *)audio_handle;
-    ss = (audio_pcm_sample_spec_t *)sample_spec;
-    ss->format = _convert_format((audio_sample_format_t)ss->format);
-
-    *pcm_handle = __tinyalsa_open_device(ss, (size_t)period_size, (size_t)periods, direction);
-    if (*pcm_handle == NULL) {
-        AUDIO_LOG_ERROR("Error opening PCM device");
-        return AUDIO_ERR_RESOURCE;
-    }
-
-    if ((err = pcm_prepare((struct pcm *)*pcm_handle)) != 0) {
-        AUDIO_LOG_ERROR("Error prepare PCM device : %d", err);
-    }
-
-    ah->device.pcm_count++;
-    AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle);
-#else  /* alsa-lib */
-    audio_hal_t *ah;
-    int err, mode;
-    char *device_name = NULL;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
-
-    ah = (audio_hal_t *)audio_handle;
-    mode =  SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
-
-    if (direction == AUDIO_DIRECTION_OUT)
-        device_name = PLAYBACK_PCM_DEVICE;
-    else if (direction == AUDIO_DIRECTION_IN)
-        device_name = CAPTURE_PCM_DEVICE;
-    else {
-        AUDIO_LOG_ERROR("Error get device_name, direction : %d", direction);
-        return AUDIO_ERR_RESOURCE;
-    }
-
-    if ((err = snd_pcm_open((snd_pcm_t **)pcm_handle, device_name, (direction == AUDIO_DIRECTION_OUT) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, mode)) < 0) {
-        AUDIO_LOG_ERROR("Error opening PCM device %s : %s", device_name, snd_strerror(err));
-        return AUDIO_ERR_RESOURCE;
-    }
-
-    if ((err = audio_pcm_set_params(audio_handle, *pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) {
-        AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", err);
-        return err;
-    }
-
-    ah->device.pcm_count++;
-    AUDIO_LOG_INFO("Opening PCM handle 0x%x, PCM device %s", *pcm_handle, device_name);
-#endif
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle)
-{
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-#ifdef __USE_TINYALSA__
-    if ((err = pcm_start(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error starting PCM handle : %d", err);
-        return AUDIO_ERR_RESOURCE;
-    }
-#else  /* alsa-lib */
-    if ((err = snd_pcm_start(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error starting PCM handle : %s", snd_strerror(err));
-        return AUDIO_ERR_RESOURCE;
-    }
-#endif
-
-    AUDIO_LOG_INFO("PCM handle 0x%x start", pcm_handle);
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle)
-{
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-#ifdef __USE_TINYALSA__
-    if ((err = pcm_stop(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error stopping PCM handle : %d", err);
-        return AUDIO_ERR_RESOURCE;
-    }
-#else  /* alsa-lib */
-    if ((err = snd_pcm_drop(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error stopping PCM handle : %s", snd_strerror(err));
-        return AUDIO_ERR_RESOURCE;
-    }
-#endif
-
-    AUDIO_LOG_INFO("PCM handle 0x%x stop", pcm_handle);
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle)
-{
-    audio_hal_t *ah = (audio_hal_t *)audio_handle;
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle);
-
-#ifdef __USE_TINYALSA__
-    if ((err = pcm_close(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error closing PCM handle : %d", err);
-        return AUDIO_ERR_RESOURCE;
-    }
-#else  /* alsa-lib */
-    if ((err = snd_pcm_close(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Error closing PCM handle : %s", snd_strerror(err));
-        return AUDIO_ERR_RESOURCE;
-    }
-#endif
-
-    pcm_handle = NULL;
-    ah->device.pcm_count--;
-    AUDIO_LOG_INFO("PCM handle close success (count:%d)", ah->device.pcm_count);
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail)
-{
-#ifdef __USE_TINYALSA__
-    struct timespec tspec;
-    unsigned int frames_avail = 0;
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
-
-    err = pcm_get_htimestamp(pcm_handle, &frames_avail, &tspec);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle 0x%x : %d", pcm_handle, err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("avail = %d", frames_avail);
-#endif
-
-    *avail = (uint32_t)frames_avail;
-#else  /* alsa-lib */
-    snd_pcm_sframes_t frames_avail;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
-
-    if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("Could not get avail at PCM handle 0x%x : %d", pcm_handle, frames_avail);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("avail = %d", frames_avail);
-#endif
-
-    *avail = (uint32_t)frames_avail;
-#endif
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames)
-{
-#ifdef __USE_TINYALSA__
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    err = pcm_write(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
-    if (err < 0) {
-        AUDIO_LOG_ERROR("Failed to write pcm : %d", err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("audio_pcm_write = %d", frames);
-#endif
-#else  /* alsa-lib */
-    snd_pcm_sframes_t frames_written;
-
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    frames_written = snd_pcm_writei(pcm_handle, buffer, (snd_pcm_uframes_t) frames);
-    if (frames_written < 0) {
-        AUDIO_LOG_ERROR("Failed to write pcm : %d", frames_written);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("audio_pcm_write = (%d / %d)", frames_written, frames);
-#endif
-#endif
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames)
-{
-#ifdef __USE_TINYALSA__
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    err = pcm_read(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
-    if (err < 0) {
-        AUDIO_LOG_ERROR("Failed to read pcm : %d", err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("audio_pcm_read = %d", frames);
-#endif
-#else  /* alsa-lib */
-    snd_pcm_sframes_t frames_read;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames);
-    if (frames_read < 0) {
-        AUDIO_LOG_ERROR("Failed to read pcm : %d", frames_read);
-        return AUDIO_ERR_IOCTL;
-    }
-
-#ifdef DEBUG_TIMING
-    AUDIO_LOG_DEBUG("audio_pcm_read = (%d / %d)", frames_read, frames);
-#endif
-#endif
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER);
-    /* we use an internal API of the (tiny)alsa library, so it causes warning message during compile */
-#ifdef __USE_TINYALSA__
-    *fd = _pcm_poll_descriptor((struct pcm *)pcm_handle);
-#else  /* alsa-lib */
-    *fd = _snd_pcm_poll_descriptor((snd_pcm_t *)pcm_handle);
-#endif
-    return AUDIO_RET_OK;
-}
-
-#ifdef __USE_TINYALSA__
-static int __tinyalsa_pcm_recover(struct pcm *pcm, int err)
-{
-    if (err > 0)
-        err = -err;
-    if (err == -EINTR)  /* nothing to do, continue */
-        return 0;
-    if (err == -EPIPE) {
-        AUDIO_LOG_INFO("XRUN occurred");
-        err = pcm_prepare(pcm);
-        if (err < 0) {
-            AUDIO_LOG_ERROR("Could not recover from XRUN occurred, prepare failed : %d", err);
-            return err;
-        }
-        return 0;
-    }
-    if (err == -ESTRPIPE) {
-        /* tinyalsa does not support pcm resume, dont't care suspend case */
-        AUDIO_LOG_ERROR("Could not recover from suspend : %d", err);
-        return err;
-    }
-    return err;
-}
-#endif
-
-audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents)
-{
-    int state, err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
-    if (revents & POLLERR)
-        AUDIO_LOG_DEBUG("Got POLLERR from ALSA");
-    if (revents & POLLNVAL)
-        AUDIO_LOG_DEBUG("Got POLLNVAL from ALSA");
-    if (revents & POLLHUP)
-        AUDIO_LOG_DEBUG("Got POLLHUP from ALSA");
-    if (revents & POLLPRI)
-        AUDIO_LOG_DEBUG("Got POLLPRI from ALSA");
-    if (revents & POLLIN)
-        AUDIO_LOG_DEBUG("Got POLLIN from ALSA");
-    if (revents & POLLOUT)
-        AUDIO_LOG_DEBUG("Got POLLOUT from ALSA");
-
-#ifdef __USE_TINYALSA__
-    state = pcm_state(pcm_handle);
-    AUDIO_LOG_DEBUG("PCM state is %d", state);
-
-    switch (state) {
-        case PCM_STATE_XRUN:
-            if ((err = __tinyalsa_pcm_recover(pcm_handle, -EPIPE)) != 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-            break;
-
-        case PCM_STATE_SUSPENDED:
-            if ((err = __tinyalsa_pcm_recover(pcm_handle, -ESTRPIPE)) != 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-            break;
-
-        default:
-            pcm_stop(pcm_handle);
-            if ((err = pcm_prepare(pcm_handle)) < 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with pcm_prepare() : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-    }
-#else  /* alsa-lib */
-    state = snd_pcm_state(pcm_handle);
-    AUDIO_LOG_DEBUG("PCM state is %s", snd_pcm_state_name(state));
-
-    /* Try to recover from this error */
-
-    switch (state) {
-        case SND_PCM_STATE_XRUN:
-            if ((err = snd_pcm_recover(pcm_handle, -EPIPE, 1)) != 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-            break;
-
-        case SND_PCM_STATE_SUSPENDED:
-            if ((err = snd_pcm_recover(pcm_handle, -ESTRPIPE, 1)) != 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-            break;
-
-        default:
-            snd_pcm_drop(pcm_handle);
-            if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
-                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare() : %d", err);
-                return AUDIO_ERR_IOCTL;
-            }
-            break;
-    }
-#endif
-
-    AUDIO_LOG_DEBUG("audio_pcm_recover");
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
-{
-#ifdef __USE_TINYALSA__
-    audio_pcm_sample_spec_t *ss;
-    unsigned int _period_size, _buffer_size, _periods, _format, _rate, _channels;
-    unsigned int _start_threshold, _stop_threshold, _silence_threshold;
-    struct pcm_config *config;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
-    ss = (audio_pcm_sample_spec_t *)*sample_spec;
-
-    /* we use an internal API of the tiny alsa library, so it causes warning message during compile */
-    _pcm_config(pcm_handle, &config);
-
-    *period_size = config->period_size;
-    *periods     = config->period_count;
-    _buffer_size = config->period_size * config->period_count;
-    ss->format   = config->format;
-    ss->rate     = config->rate;
-    ss->channels = config->channels;
-    _start_threshold   = config->start_threshold;
-    _stop_threshold    = config->stop_threshold;
-    _silence_threshold = config->silence_threshold;
-
-    AUDIO_LOG_DEBUG("audio_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size);
-#else  /* alsa-lib */
-    int err;
-    audio_pcm_sample_spec_t *ss;
-    int dir;
-    snd_pcm_uframes_t _period_size, _buffer_size;
-    snd_pcm_format_t _format;
-    unsigned int _rate, _channels;
-    snd_pcm_uframes_t _start_threshold, _stop_threshold, _silence_threshold, _avail_min;
-    unsigned int _periods;
-    snd_pcm_hw_params_t *hwparams;
-    snd_pcm_sw_params_t *swparams;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
-    ss = (audio_pcm_sample_spec_t *)*sample_spec;
-
-    snd_pcm_hw_params_alloca(&hwparams);
-    snd_pcm_sw_params_alloca(&swparams);
-
-    if ((err = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_current() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
-        (err = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0 ||
-        (err = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0 ||
-        (err = snd_pcm_hw_params_get_format(hwparams, &_format)) < 0 ||
-        (err = snd_pcm_hw_params_get_rate(hwparams, &_rate, &dir)) < 0 ||
-        (err = snd_pcm_hw_params_get_channels(hwparams, &_channels)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %s", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    *period_size = _period_size;
-    *periods     = _periods;
-    ss->format   = _format;
-    ss->rate     = _rate;
-    ss->channels = _channels;
-
-    if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_sw_params_current() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params_get_start_threshold(swparams, &_start_threshold)) < 0  ||
-        (err = snd_pcm_sw_params_get_stop_threshold(swparams, &_stop_threshold)) < 0  ||
-        (err = snd_pcm_sw_params_get_silence_threshold(swparams, &_silence_threshold)) < 0  ||
-        (err = snd_pcm_sw_params_get_avail_min(swparams, &_avail_min)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %s", err);
-    }
-
-    AUDIO_LOG_DEBUG("audio_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size);
-#endif
-
-    return AUDIO_RET_OK;
-}
-
-audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
-{
-#ifdef __USE_TINYALSA__
-    /* Parameters are only acceptable in pcm_open() function */
-    AUDIO_LOG_DEBUG("audio_pcm_set_params");
-#else  /* alsa-lib */
-    int err;
-    audio_pcm_sample_spec_t ss;
-    snd_pcm_uframes_t _buffer_size;
-    snd_pcm_hw_params_t *hwparams;
-    snd_pcm_sw_params_t *swparams;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
-    ss = *(audio_pcm_sample_spec_t *)sample_spec;
-
-    snd_pcm_hw_params_alloca(&hwparams);
-    snd_pcm_sw_params_alloca(&swparams);
-
-    /* Set hw params */
-    if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate_resample() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    ss.format = _convert_format((audio_sample_format_t)ss.format);
-    if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, ss.format)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_format() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, ss.rate, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss.channels)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, period_size, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_periods(%u) failed : %d", periods, err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    _buffer_size = period_size * periods;
-    if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, _buffer_size)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", periods * periods, err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params failed : %d", err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-    /* Set sw params */
-    if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) {
-        AUDIO_LOG_ERROR("Unable to determine current swparams : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm_handle, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
-        AUDIO_LOG_ERROR("Unable to enable time stamping : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xFFFFFFFF)) < 0) {
-        AUDIO_LOG_ERROR("Unable to set stop threshold : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, period_size / 2)) < 0) {
-        AUDIO_LOG_ERROR("Unable to set start threshold : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, 1024)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_sw_params_set_avail_min() failed : %d", err);
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if ((err = snd_pcm_sw_params(pcm_handle, swparams)) < 0) {
-        AUDIO_LOG_ERROR("Unable to set sw params : %d", err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-    /* Prepare device */
-    if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_prepare() failed : %d", err);
-        return AUDIO_ERR_IOCTL;
-    }
-
-    AUDIO_LOG_DEBUG("audio_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size);
-#endif
-
-    return AUDIO_RET_OK;
-}
diff --git a/tizen-audio-impl-ctrl.c b/tizen-audio-impl-ctrl.c
new file mode 100644 (file)
index 0000000..253eaab
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "tizen-audio-internal.h"
+
+#ifdef __MIXER_PARAM_DUMP
+static void __dump_mixer_param(char *dump, long *param, int size)
+{
+    int i, len;
+
+    for (i = 0; i < size; i++) {
+        len = sprintf(dump, "%ld", *param);
+        if (len > 0)
+            dump += len;
+        if (i != size -1) {
+            *dump++ = ',';
+        }
+
+        param++;
+    }
+    *dump = '\0';
+}
+#endif
+
+audio_return_t _control_init(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    pthread_mutex_init(&(ah->mixer.mutex), NULL);
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _control_deinit(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    pthread_mutex_destroy(&(ah->mixer.mutex));
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    /* TODO. */
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val)
+{
+    snd_ctl_t *handle;
+    snd_ctl_elem_value_t *control;
+    snd_ctl_elem_id_t *id;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_type_t type;
+
+    int ret = 0, count = 0, i = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    pthread_mutex_lock(&(ah->mixer.mutex));
+
+    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
+    if (ret < 0) {
+        AUDIO_LOG_ERROR("snd_ctl_open error, %s\n", snd_strerror(ret));
+        pthread_mutex_unlock(&(ah->mixer.mutex));
+        return AUDIO_ERR_IOCTL;
+    }
+
+    // Get Element Info
+
+    snd_ctl_elem_id_alloca(&id);
+    snd_ctl_elem_info_alloca(&info);
+    snd_ctl_elem_value_alloca(&control);
+
+    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+    snd_ctl_elem_id_set_name(id, ctl_name);
+
+    snd_ctl_elem_info_set_id(info, id);
+    if (snd_ctl_elem_info(handle, info) < 0) {
+        AUDIO_LOG_ERROR("Cannot find control element: %s\n", ctl_name);
+        goto close;
+    }
+    snd_ctl_elem_info_get_id(info, id);
+
+    type = snd_ctl_elem_info_get_type(info);
+    count = snd_ctl_elem_info_get_count(info);
+
+    snd_ctl_elem_value_set_id(control, id);
+
+    if (snd_ctl_elem_read(handle, control) < 0) {
+        AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
+        goto close;
+}
+
+    switch (type) {
+    case SND_CTL_ELEM_TYPE_BOOLEAN:
+        *val = snd_ctl_elem_value_get_boolean(control, i);
+        break;
+    case SND_CTL_ELEM_TYPE_INTEGER:
+        for (i = 0; i < count; i++)
+        *val = snd_ctl_elem_value_get_integer(control, i);
+        break;
+    case SND_CTL_ELEM_TYPE_ENUMERATED:
+        for (i = 0; i < count; i++)
+        *val = snd_ctl_elem_value_get_enumerated(control, i);
+        break;
+    default:
+        AUDIO_LOG_WARN("unsupported control element type\n");
+        goto close;
+    }
+
+    snd_ctl_close(handle);
+
+#ifdef AUDIO_DEBUG
+    AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
+#endif
+
+    pthread_mutex_unlock(&(ah->mixer.mutex));
+    return AUDIO_RET_OK;
+
+close:
+    AUDIO_LOG_ERROR("Error\n");
+    snd_ctl_close(handle);
+    pthread_mutex_unlock(&(ah->mixer.mutex));
+    return AUDIO_ERR_UNDEFINED;
+}
+
+audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val)
+{
+    snd_ctl_t *handle;
+    snd_ctl_elem_value_t *control;
+    snd_ctl_elem_id_t *id;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_type_t type;
+    int ret = 0, count = 0, i = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+
+    pthread_mutex_lock(&(ah->mixer.mutex));
+
+    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
+    if (ret < 0) {
+        AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", ALSA_DEFAULT_CARD, snd_strerror(ret));
+        pthread_mutex_unlock(&(ah->mixer.mutex));
+        return AUDIO_ERR_IOCTL;
+    }
+
+    // Get Element Info
+
+    snd_ctl_elem_id_alloca(&id);
+    snd_ctl_elem_info_alloca(&info);
+    snd_ctl_elem_value_alloca(&control);
+
+    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+    snd_ctl_elem_id_set_name(id, ctl_name);
+
+    snd_ctl_elem_info_set_id(info, id);
+    if (snd_ctl_elem_info(handle, info) < 0) {
+        AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
+        goto close;
+    }
+    snd_ctl_elem_info_get_id(info, id);
+
+    type = snd_ctl_elem_info_get_type(info);
+    count = snd_ctl_elem_info_get_count(info);
+
+    snd_ctl_elem_value_set_id(control, id);
+
+    snd_ctl_elem_read(handle, control);
+
+    switch (type) {
+    case SND_CTL_ELEM_TYPE_BOOLEAN:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_boolean(control, i, val);
+        break;
+    case SND_CTL_ELEM_TYPE_INTEGER:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_integer(control, i, val);
+        break;
+    case SND_CTL_ELEM_TYPE_ENUMERATED:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_enumerated(control, i, val);
+        break;
+
+    default:
+        AUDIO_LOG_WARN("unsupported control element type");
+        goto close;
+    }
+
+    snd_ctl_elem_write(handle, control);
+
+    snd_ctl_close(handle);
+
+    AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
+
+    pthread_mutex_unlock(&(ah->mixer.mutex));
+    return AUDIO_RET_OK;
+
+close:
+    AUDIO_LOG_ERROR("Error");
+    snd_ctl_close(handle);
+    pthread_mutex_unlock(&(ah->mixer.mutex));
+    return AUDIO_ERR_UNDEFINED;
+}
+
+audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+
+    /* TODO. */
+    return AUDIO_RET_OK;
+}
+
+
+audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER);
+
+    /* TODO. */
+    return AUDIO_RET_OK;
+}
\ No newline at end of file
diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c
new file mode 100644 (file)
index 0000000..a478143
--- /dev/null
@@ -0,0 +1,898 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
+
+#ifdef __USE_TINYALSA__
+/* Convert pcm format from pulse to alsa */
+static const uint32_t g_format_convert_table[] = {
+    [AUDIO_SAMPLE_U8]        = PCM_FORMAT_S8,
+    [AUDIO_SAMPLE_S16LE]     = PCM_FORMAT_S16_LE,
+    [AUDIO_SAMPLE_S32LE]     = PCM_FORMAT_S32_LE,
+    [AUDIO_SAMPLE_S24_32LE]  = PCM_FORMAT_S24_LE
+};
+#else  /* alsa-lib */
+/* FIXME : To avoid build warning... */
+int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
+/* Convert pcm format from pulse to alsa */
+static const uint32_t g_format_convert_table[] = {
+    [AUDIO_SAMPLE_U8]        = SND_PCM_FORMAT_U8,
+    [AUDIO_SAMPLE_ALAW]      = SND_PCM_FORMAT_A_LAW,
+    [AUDIO_SAMPLE_ULAW]      = SND_PCM_FORMAT_MU_LAW,
+    [AUDIO_SAMPLE_S16LE]     = SND_PCM_FORMAT_S16_LE,
+    [AUDIO_SAMPLE_S16BE]     = SND_PCM_FORMAT_S16_BE,
+    [AUDIO_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
+    [AUDIO_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
+    [AUDIO_SAMPLE_S32LE]     = SND_PCM_FORMAT_S32_LE,
+    [AUDIO_SAMPLE_S32BE]     = SND_PCM_FORMAT_S32_BE,
+    [AUDIO_SAMPLE_S24LE]     = SND_PCM_FORMAT_S24_3LE,
+    [AUDIO_SAMPLE_S24BE]     = SND_PCM_FORMAT_S24_3BE,
+    [AUDIO_SAMPLE_S24_32LE]  = SND_PCM_FORMAT_S24_LE,
+    [AUDIO_SAMPLE_S24_32BE]  = SND_PCM_FORMAT_S24_BE
+};
+#endif
+
+static uint32_t __convert_format(audio_sample_format_t format)
+{
+    return g_format_convert_table[format];
+}
+
+/* #define DEBUG_TIMING */
+
+static int __voice_pcm_set_params(audio_hal_t *ah, snd_pcm_t *pcm)
+{
+    snd_pcm_hw_params_t *params = NULL;
+    int err = 0;
+    unsigned int val = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    /* Skip parameter setting to null device. */
+    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+        return AUDIO_ERR_IOCTL;
+
+    /* Allocate a hardware parameters object. */
+    snd_pcm_hw_params_alloca(&params);
+
+    /* Fill it in with default values. */
+    if (snd_pcm_hw_params_any(pcm, params) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Set the desired hardware parameters. */
+    /* Interleaved mode */
+    err = snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+    err = snd_pcm_hw_params_set_rate(pcm, params, 8000, 0);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+    }
+    err = snd_pcm_hw_params(pcm, params);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Dump current param */
+    snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val);
+    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+    snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&val);
+    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+                    snd_pcm_format_name((snd_pcm_format_t)val),
+                    snd_pcm_format_description((snd_pcm_format_t)val));
+
+    snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val);
+    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
+
+    snd_pcm_hw_params_get_channels(params, &val);
+    AUDIO_LOG_DEBUG("channels = %d\n", val);
+
+    return 0;
+
+error:
+    return -1;
+}
+
+#ifdef __USE_TINYALSA__
+static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction)
+{
+    struct pcm *pcm = NULL;
+    struct pcm_config config;
+
+    AUDIO_RETURN_NULL_IF_FAIL(ss);
+
+    config.channels          = ss->channels;
+    config.rate              = ss->rate;
+    config.period_size       = period_size;
+    config.period_count      = period_count;
+    config.format            = ss->format;
+    config.start_threshold   = period_size;
+    config.stop_threshold    = 0xFFFFFFFF;
+    config.silence_threshold = 0;
+
+    AUDIO_LOG_INFO("direction %d, channels %d, rate %d, format %d, period_size %d, period_count %d", direction, ss->channels, ss->rate, ss->format, period_size, period_count);
+
+    pcm = pcm_open((direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_CARD_ID : CAPTURE_CARD_ID,
+                   (direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_PCM_DEVICE_ID : CAPTURE_PCM_DEVICE_ID,
+                   (direction == AUDIO_DIRECTION_OUT) ? PCM_OUT : PCM_IN,
+                   &config);
+    if (!pcm || !pcm_is_ready(pcm)) {
+        AUDIO_LOG_ERROR("Unable to open device (%s)", pcm_get_error(pcm));
+        pcm_close(pcm);
+        return NULL;
+    }
+
+    return pcm;
+}
+
+static int __tinyalsa_pcm_recover(struct pcm *pcm, int err)
+{
+    if (err > 0)
+        err = -err;
+    if (err == -EINTR)  /* nothing to do, continue */
+        return 0;
+    if (err == -EPIPE) {
+        AUDIO_LOG_INFO("XRUN occurred");
+        err = pcm_prepare(pcm);
+        if (err < 0) {
+            AUDIO_LOG_ERROR("Could not recover from XRUN occurred, prepare failed : %d", err);
+            return err;
+        }
+        return 0;
+    }
+    if (err == -ESTRPIPE) {
+        /* tinyalsa does not support pcm resume, dont't care suspend case */
+        AUDIO_LOG_ERROR("Could not recover from suspend : %d", err);
+        return err;
+    }
+    return err;
+}
+#endif
+
+int _voice_pcm_open(audio_hal_t *ah)
+{
+    int err, ret = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("open voice pcm handles");
+
+    /* Get playback voice-pcm from ucm conf. Open and set-params */
+    if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_out, VOICE_PCM_DEVICE, AUDIO_DIRECTION_OUT, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err));
+        return AUDIO_ERR_IOCTL;
+    }
+    ret = __voice_pcm_set_params(ah, ah->device.pcm_out);
+
+    AUDIO_LOG_INFO("pcm playback device open success device(%s)", VOICE_PCM_DEVICE);
+
+    /* Get capture voice-pcm from ucm conf. Open and set-params */
+    if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_in, VOICE_PCM_DEVICE, AUDIO_DIRECTION_IN, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err));
+        return AUDIO_ERR_IOCTL;
+    }
+    ret = __voice_pcm_set_params(ah, ah->device.pcm_in);
+    AUDIO_LOG_INFO("pcm captures device open success device(%s)", VOICE_PCM_DEVICE);
+
+    return ret;
+}
+
+int _voice_pcm_close(audio_hal_t *ah, uint32_t direction)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("close voice pcm handles");
+
+    if (ah->device.pcm_out && (direction == AUDIO_DIRECTION_OUT)) {
+        _pcm_close(ah->device.pcm_out);
+        ah->device.pcm_out = NULL;
+        AUDIO_LOG_INFO("voice pcm_out handle close success");
+    } else if (ah->device.pcm_in && (direction == AUDIO_DIRECTION_IN)) {
+        _pcm_close(ah->device.pcm_in);
+        ah->device.pcm_in = NULL;
+        AUDIO_LOG_INFO("voice pcm_in handle close success");
+    }
+
+    return AUDIO_RET_OK;
+}
+
+void _reset_pcm_devices(audio_hal_t *ah)
+{
+    AUDIO_RETURN_IF_FAIL(ah);
+
+    if (ah->device.pcm_out) {
+        _pcm_close(ah->device.pcm_out);
+        ah->device.pcm_out = NULL;
+        AUDIO_LOG_INFO("pcm_out handle close success");
+    }
+    if (ah->device.pcm_in) {
+        _pcm_close(ah->device.pcm_in);
+        ah->device.pcm_in = NULL;
+        AUDIO_LOG_INFO("pcm_in handle close success");
+    }
+
+    return;
+}
+
+audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+#ifdef __USE_TINYALSA__
+    audio_pcm_sample_spec_t *ss;
+    int err;
+
+    ss = (audio_pcm_sample_spec_t *)sample_spec;
+    ss->format = __convert_format((audio_sample_format_t)ss->format);
+
+    *pcm_handle = __tinyalsa_open_device(ss, (size_t)period_size, (size_t)periods, direction);
+    if (*pcm_handle == NULL) {
+        AUDIO_LOG_ERROR("Error opening PCM device");
+        return AUDIO_ERR_RESOURCE;
+    }
+
+    if ((err = pcm_prepare((struct pcm *)*pcm_handle)) != 0) {
+        AUDIO_LOG_ERROR("Error prepare PCM device : %d", err);
+    }
+
+#else  /* alsa-lib */
+    int err, mode;
+    char *device_name = NULL;
+
+    mode =  SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
+
+    if (direction == AUDIO_DIRECTION_OUT)
+        device_name = PLAYBACK_PCM_DEVICE;
+    else if (direction == AUDIO_DIRECTION_IN)
+        device_name = CAPTURE_PCM_DEVICE;
+    else {
+        AUDIO_LOG_ERROR("Error get device_name, direction : %d", direction);
+        return AUDIO_ERR_RESOURCE;
+    }
+
+    if ((err = snd_pcm_open((snd_pcm_t **)pcm_handle, device_name, (direction == AUDIO_DIRECTION_OUT) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, mode)) < 0) {
+        AUDIO_LOG_ERROR("Error opening PCM device %s : %s", device_name, snd_strerror(err));
+        return AUDIO_ERR_RESOURCE;
+    }
+
+    if ((err = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) {
+        AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", err);
+        return err;
+    }
+
+    AUDIO_LOG_INFO("PCM device %s", device_name);
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_start(void *pcm_handle)
+{
+    int err;
+
+#ifdef __USE_TINYALSA__
+    if ((err = pcm_start(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error starting PCM handle : %d", err);
+        return AUDIO_ERR_RESOURCE;
+    }
+#else  /* alsa-lib */
+    if ((err = snd_pcm_start(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error starting PCM handle : %s", snd_strerror(err));
+        return AUDIO_ERR_RESOURCE;
+    }
+#endif
+
+    AUDIO_LOG_INFO("PCM handle 0x%x start", pcm_handle);
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_stop(void *pcm_handle)
+{
+    int err;
+
+#ifdef __USE_TINYALSA__
+    if ((err = pcm_stop(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error stopping PCM handle : %d", err);
+        return AUDIO_ERR_RESOURCE;
+    }
+#else  /* alsa-lib */
+    if ((err = snd_pcm_drop(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error stopping PCM handle : %s", snd_strerror(err));
+        return AUDIO_ERR_RESOURCE;
+    }
+#endif
+
+    AUDIO_LOG_INFO("PCM handle 0x%x stop", pcm_handle);
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_close(void *pcm_handle)
+{
+    int err;
+
+    AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle);
+
+#ifdef __USE_TINYALSA__
+    if ((err = pcm_close(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error closing PCM handle : %d", err);
+        return AUDIO_ERR_RESOURCE;
+    }
+#else  /* alsa-lib */
+    if ((err = snd_pcm_close(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error closing PCM handle : %s", snd_strerror(err));
+        return AUDIO_ERR_RESOURCE;
+    }
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail)
+{
+#ifdef __USE_TINYALSA__
+    struct timespec tspec;
+    unsigned int frames_avail = 0;
+    int err;
+
+    err = pcm_get_htimestamp(pcm_handle, &frames_avail, &tspec);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle 0x%x : %d", pcm_handle, err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("avail = %d", frames_avail);
+#endif
+
+    *avail = (uint32_t)frames_avail;
+#else  /* alsa-lib */
+    snd_pcm_sframes_t frames_avail;
+
+    if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Could not get avail at PCM handle 0x%x : %d", pcm_handle, frames_avail);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("avail = %d", frames_avail);
+#endif
+
+    *avail = (uint32_t)frames_avail;
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames)
+{
+#ifdef __USE_TINYALSA__
+    int err;
+
+    err = pcm_write(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
+    if (err < 0) {
+        AUDIO_LOG_ERROR("Failed to write pcm : %d", err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("_pcm_write = %d", frames);
+#endif
+#else  /* alsa-lib */
+    snd_pcm_sframes_t frames_written;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    frames_written = snd_pcm_writei(pcm_handle, buffer, (snd_pcm_uframes_t) frames);
+    if (frames_written < 0) {
+        AUDIO_LOG_ERROR("Failed to write pcm : %d", frames_written);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("_pcm_write = (%d / %d)", frames_written, frames);
+#endif
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames)
+{
+#ifdef __USE_TINYALSA__
+    int err;
+
+    err = pcm_read(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
+    if (err < 0) {
+        AUDIO_LOG_ERROR("Failed to read pcm : %d", err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("audio_pcm_read = %d", frames);
+#endif
+#else  /* alsa-lib */
+    snd_pcm_sframes_t frames_read;
+
+    frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames);
+    if (frames_read < 0) {
+        AUDIO_LOG_ERROR("Failed to read pcm : %d", frames_read);
+        return AUDIO_ERR_IOCTL;
+    }
+
+#ifdef DEBUG_TIMING
+    AUDIO_LOG_DEBUG("_pcm_read = (%d / %d)", frames_read, frames);
+#endif
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_get_fd(void *pcm_handle, int *fd)
+{
+    /* we use an internal API of the (tiny)alsa library, so it causes warning message during compile */
+#ifdef __USE_TINYALSA__
+    *fd = _pcm_poll_descriptor((struct pcm *)pcm_handle);
+#else  /* alsa-lib */
+    *fd = _snd_pcm_poll_descriptor((snd_pcm_t *)pcm_handle);
+#endif
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_recover(void *pcm_handle, int revents)
+{
+    int state, err;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    if (revents & POLLERR)
+        AUDIO_LOG_DEBUG("Got POLLERR from ALSA");
+    if (revents & POLLNVAL)
+        AUDIO_LOG_DEBUG("Got POLLNVAL from ALSA");
+    if (revents & POLLHUP)
+        AUDIO_LOG_DEBUG("Got POLLHUP from ALSA");
+    if (revents & POLLPRI)
+        AUDIO_LOG_DEBUG("Got POLLPRI from ALSA");
+    if (revents & POLLIN)
+        AUDIO_LOG_DEBUG("Got POLLIN from ALSA");
+    if (revents & POLLOUT)
+        AUDIO_LOG_DEBUG("Got POLLOUT from ALSA");
+
+#ifdef __USE_TINYALSA__
+    state = pcm_state(pcm_handle);
+    AUDIO_LOG_DEBUG("PCM state is %d", state);
+
+    switch (state) {
+        case PCM_STATE_XRUN:
+            if ((err = __tinyalsa_pcm_recover(pcm_handle, -EPIPE)) != 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+            break;
+
+        case PCM_STATE_SUSPENDED:
+            if ((err = __tinyalsa_pcm_recover(pcm_handle, -ESTRPIPE)) != 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+            break;
+
+        default:
+            pcm_stop(pcm_handle);
+            if ((err = pcm_prepare(pcm_handle)) < 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with pcm_prepare() : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+    }
+#else  /* alsa-lib */
+    state = snd_pcm_state(pcm_handle);
+    AUDIO_LOG_DEBUG("PCM state is %s", snd_pcm_state_name(state));
+
+    /* Try to recover from this error */
+
+    switch (state) {
+        case SND_PCM_STATE_XRUN:
+            if ((err = snd_pcm_recover(pcm_handle, -EPIPE, 1)) != 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+            break;
+
+        case SND_PCM_STATE_SUSPENDED:
+            if ((err = snd_pcm_recover(pcm_handle, -ESTRPIPE, 1)) != 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+            break;
+
+        default:
+            snd_pcm_drop(pcm_handle);
+            if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
+                AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare() : %d", err);
+                return AUDIO_ERR_IOCTL;
+            }
+            break;
+    }
+#endif
+
+    AUDIO_LOG_DEBUG("_pcm_recover");
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
+{
+#ifdef __USE_TINYALSA__
+    audio_pcm_sample_spec_t *ss;
+    unsigned int _period_size, _buffer_size, _periods, _format, _rate, _channels;
+    unsigned int _start_threshold, _stop_threshold, _silence_threshold;
+    struct pcm_config *config;
+
+    ss = (audio_pcm_sample_spec_t *)*sample_spec;
+
+    /* we use an internal API of the tiny alsa library, so it causes warning message during compile */
+    _pcm_config(pcm_handle, &config);
+
+    *period_size = config->period_size;
+    *periods     = config->period_count;
+    _buffer_size = config->period_size * config->period_count;
+    ss->format   = config->format;
+    ss->rate     = config->rate;
+    ss->channels = config->channels;
+    _start_threshold   = config->start_threshold;
+    _stop_threshold    = config->stop_threshold;
+    _silence_threshold = config->silence_threshold;
+
+    AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size);
+#else  /* alsa-lib */
+    int err;
+    audio_pcm_sample_spec_t *ss;
+    int dir;
+    snd_pcm_uframes_t _period_size, _buffer_size;
+    snd_pcm_format_t _format;
+    unsigned int _rate, _channels;
+    snd_pcm_uframes_t _start_threshold, _stop_threshold, _silence_threshold, _avail_min;
+    unsigned int _periods;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+
+    ss = (audio_pcm_sample_spec_t *)*sample_spec;
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    if ((err = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_current() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+        (err = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0 ||
+        (err = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0 ||
+        (err = snd_pcm_hw_params_get_format(hwparams, &_format)) < 0 ||
+        (err = snd_pcm_hw_params_get_rate(hwparams, &_rate, &dir)) < 0 ||
+        (err = snd_pcm_hw_params_get_channels(hwparams, &_channels)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %s", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    *period_size = _period_size;
+    *periods     = _periods;
+    ss->format   = _format;
+    ss->rate     = _rate;
+    ss->channels = _channels;
+
+    if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_sw_params_current() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params_get_start_threshold(swparams, &_start_threshold)) < 0  ||
+        (err = snd_pcm_sw_params_get_stop_threshold(swparams, &_stop_threshold)) < 0  ||
+        (err = snd_pcm_sw_params_get_silence_threshold(swparams, &_silence_threshold)) < 0  ||
+        (err = snd_pcm_sw_params_get_avail_min(swparams, &_avail_min)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %s", err);
+    }
+
+    AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size);
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+#ifdef __USE_TINYALSA__
+    /* Parameters are only acceptable in pcm_open() function */
+    AUDIO_LOG_DEBUG("_pcm_set_params");
+#else  /* alsa-lib */
+    int err;
+    audio_pcm_sample_spec_t ss;
+    snd_pcm_uframes_t _buffer_size;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+
+    ss = *(audio_pcm_sample_spec_t *)sample_spec;
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    /* Set hw params */
+    if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate_resample() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    ss.format = __convert_format((audio_sample_format_t)ss.format);
+    if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, ss.format)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_format() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, ss.rate, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss.channels)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, period_size, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_periods(%u) failed : %d", periods, err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    _buffer_size = period_size * periods;
+    if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, _buffer_size)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", periods * periods, err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params failed : %d", err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+    /* Set sw params */
+    if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) {
+        AUDIO_LOG_ERROR("Unable to determine current swparams : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm_handle, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
+        AUDIO_LOG_ERROR("Unable to enable time stamping : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xFFFFFFFF)) < 0) {
+        AUDIO_LOG_ERROR("Unable to set stop threshold : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, period_size / 2)) < 0) {
+        AUDIO_LOG_ERROR("Unable to set start threshold : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, 1024)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_sw_params_set_avail_min() failed : %d", err);
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if ((err = snd_pcm_sw_params(pcm_handle, swparams)) < 0) {
+        AUDIO_LOG_ERROR("Unable to set sw params : %d", err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+    /* Prepare device */
+    if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_prepare() failed : %d", err);
+        return AUDIO_ERR_IOCTL;
+    }
+
+    AUDIO_LOG_DEBUG("_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size);
+#endif
+
+    return AUDIO_RET_OK;
+}
+
+/* Generic snd pcm interface APIs */
+audio_return_t _pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+    snd_pcm_hw_params_t *hwparams;
+    int err = 0;
+    int dir;
+    unsigned int val = 0;
+    snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
+    snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
+    uint8_t _use_mmap = use_mmap && *use_mmap;
+    uint32_t channels = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Skip parameter setting to null device. */
+    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+        return AUDIO_ERR_IOCTL;
+
+    /* Allocate a hardware parameters object. */
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Fill it in with default values. */
+    if (snd_pcm_hw_params_any(pcm, hwparams) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Set the desired hardware parameters. */
+
+    if (_use_mmap) {
+
+        if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
+
+            /* mmap() didn't work, fall back to interleaved */
+
+            if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+                AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+                goto error;
+            }
+
+            _use_mmap = 0;
+        }
+
+    } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+        AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+    AUDIO_LOG_DEBUG("setting rate - %d", sample_spec->rate);
+    err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+    }
+
+    err = snd_pcm_hw_params(pcm, hwparams);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Dump current param */
+
+    if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+
+    if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+        (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+
+    snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
+    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+    snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
+    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+                    snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
+                    snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
+
+    snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
+    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
+
+    snd_pcm_hw_params_get_channels(hwparams, &channels);
+    sample_spec->channels = (uint8_t)channels;
+    AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
+
+    if (buffer_size)
+        *buffer_size = _buffer_size;
+
+    if (period_size)
+        *period_size = _period_size;
+
+    if (use_mmap)
+        *use_mmap = _use_mmap;
+
+    return AUDIO_RET_OK;
+
+error:
+    return AUDIO_ERR_RESOURCE;
+}
+
+audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event)
+{
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t boundary;
+    int err;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    snd_pcm_sw_params_alloca(&swparams);
+
+    if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
+        AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
+        AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
+        AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
+        AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
+        AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) {
+        AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
+        AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
+        AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err));
+        goto error;
+    }
+    return AUDIO_RET_OK;
+error:
+    return err;
+}
\ No newline at end of file
similarity index 84%
rename from tizen-audio-ucm.c
rename to tizen-audio-impl-ucm.c
index e1dba8f..1dfe50a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #define UCM_PREFIX_REQUESTED "> UCM requested"
 #define UCM_PREFIX_CHANGED   "<<< UCM changed"
 
-audio_return_t _audio_ucm_init(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    snd_use_case_mgr_open(&ah->ucm.uc_mgr, ALSA_DEFAULT_CARD);
-
-    if (!ah->ucm.uc_mgr) {
-        AUDIO_LOG_ERROR("uc_mgr open failed");
-        return AUDIO_ERR_RESOURCE;
-    }
-    return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_ucm_deinit(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
-
-    snd_use_case_mgr_close(ah->ucm.uc_mgr);
-    ah->ucm.uc_mgr = NULL;
-
-    return AUDIO_RET_OK;
-}
-
-void _audio_ucm_get_device_name(audio_hal_t *ah, const char *use_case, audio_direction_t direction, const char **value)
-{
-    char identifier[70] = { 0, };
-
-    AUDIO_RETURN_IF_FAIL(ah);
-    AUDIO_RETURN_IF_FAIL(ah->ucm.uc_mgr);
-
-    snprintf(identifier, sizeof(identifier), "%sPCM//%s",
-             (direction == AUDIO_DIRECTION_IN) ? "Capture" : "Playback", use_case);
-
-    snd_use_case_get(ah->ucm.uc_mgr, identifier, value);
-}
-
-static inline void __add_ucm_device_info(audio_hal_t *ah, const char *use_case, audio_direction_t direction, audio_device_info_t *device_info_list, int *device_info_count)
-{
-    audio_device_info_t *device_info;
-    const char *device_name = NULL;
-    char *needle = NULL;
-
-    AUDIO_RETURN_IF_FAIL(ah);
-    AUDIO_RETURN_IF_FAIL(ah->ucm.uc_mgr);
-    AUDIO_RETURN_IF_FAIL(device_info_list);
-    AUDIO_RETURN_IF_FAIL(device_info_count);
-
-    _audio_ucm_get_device_name(ah, use_case, direction, &device_name);
-    if (device_name) {
-        device_info = &device_info_list[(*device_info_count)++];
-
-        memset(device_info, 0x00, sizeof(audio_device_info_t));
-        device_info->api = AUDIO_DEVICE_API_ALSA;
-        device_info->direction = direction;
-        needle = strstr(&device_name[3], ",");
-        if (needle) {
-            device_info->alsa.device_idx = *(needle+1) - '0';
-            device_info->alsa.card_name = strndup(&device_name[3], needle - (device_name+3));
-            device_info->alsa.card_idx = snd_card_get_index(device_info->alsa.card_name);
-            AUDIO_LOG_DEBUG("Card name: %s", device_info->alsa.card_name);
-        }
-
-        free((void *)device_name);
-    }
-}
-
-int _audio_ucm_fill_device_info_list(audio_hal_t *ah, audio_device_info_t *device_info_list, const char *verb)
-{
-    int device_info_count = 0;
-    const char *curr_verb = NULL;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, device_info_count);
-    AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, device_info_count);
-    AUDIO_RETURN_VAL_IF_FAIL(device_info_list, device_info_count);
-
-    if (!verb) {
-        snd_use_case_get(ah->ucm.uc_mgr, "_verb", &curr_verb);
-        verb = curr_verb;
-    }
-
-    /* prepare destination */
-    /*If the devices are VOICECALL LOOPBACK or FMRADIO then pulseaudio need not get the device notification*/
-    if (verb) {
-        if (strncmp(verb, AUDIO_USE_CASE_VERB_VOICECALL, strlen(AUDIO_USE_CASE_VERB_VOICECALL)) &&
-            strncmp(verb, AUDIO_USE_CASE_VERB_LOOPBACK, strlen(AUDIO_USE_CASE_VERB_LOOPBACK))) {
-            __add_ucm_device_info(ah, verb, AUDIO_DIRECTION_IN, device_info_list, &device_info_count);
-#if 0 /* disable temporarily */
-            if (strncmp(verb, AUDIO_USE_CASE_VERB_FMRADIO, strlen(AUDIO_USE_CASE_VERB_FMRADIO))) {
-                __add_ucm_device_info(ah, verb, AUDIO_DIRECTION_OUT, device_info_list, &device_info_count);
-            }
-#endif
-        }
-
-        if (curr_verb)
-            free((void *)curr_verb);
-
-    }
-
-    return device_info_count;
-}
-
 #define DUMP_LEN 512
 
 static void __dump_use_case(const char* prefix, const char *verb, const char *devices[], int dev_count, const char *modifiers[], int mod_count)
@@ -150,33 +48,33 @@ static void __dump_use_case(const char* prefix, const char *verb, const char *de
     int i;
     dump_data_t* dump = NULL;
 
-    if (!(dump = dump_new(DUMP_LEN))) {
+    if (!(dump = _audio_dump_new(DUMP_LEN))) {
         AUDIO_LOG_ERROR("Failed to create dump string...");
         return;
     }
 
     /* Verb */
-    dump_add_str(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE);
+    _audio_dump_add_str(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE);
 
     /* Devices */
     if (devices) {
         for (i = 0; i < dev_count; i++) {
-            dump_add_str(dump, (i != dev_count - 1) ? "%s, " : "%s", devices[i]);
+            _audio_dump_add_str(dump, (i != dev_count - 1) ? "%s, " : "%s", devices[i]);
         }
     }
-    dump_add_str(dump, " ] Modifier [ ");
+    _audio_dump_add_str(dump, " ] Modifier [ ");
 
     /* Modifiers */
     if (modifiers) {
         for (i = 0; i < mod_count; i++) {
-            dump_add_str(dump, (i != mod_count - 1) ? "%s, " : "%s", modifiers[i]);
+            _audio_dump_add_str(dump, (i != mod_count - 1) ? "%s, " : "%s", modifiers[i]);
         }
     }
-    dump_add_str(dump, " ]");
+    _audio_dump_add_str(dump, " ]");
 
-    AUDIO_LOG_INFO("TEST %s : %s", prefix, dump_get_str(dump));
+    AUDIO_LOG_INFO("TEST %s : %s", prefix, _audio_dump_get_str(dump));
 
-    dump_free(dump);
+    _audio_dump_free(dump);
 }
 
 #ifdef ALSA_UCM_DEBUG_TIME
@@ -198,6 +96,32 @@ static inline int __set_use_case_with_time(snd_use_case_mgr_t *uc_mgr, const cha
 }
 #endif
 
+audio_return_t _ucm_init(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    snd_use_case_mgr_open(&ah->ucm.uc_mgr, ALSA_DEFAULT_CARD);
+
+    if (!ah->ucm.uc_mgr) {
+        AUDIO_LOG_ERROR("uc_mgr open failed");
+        return AUDIO_ERR_RESOURCE;
+    }
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _ucm_deinit(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
+
+    if (ah->ucm.uc_mgr) {
+        snd_use_case_mgr_close(ah->ucm.uc_mgr);
+        ah->ucm.uc_mgr = NULL;
+    }
+
+    return AUDIO_RET_OK;
+}
+
 /* UCM sequence
     1) If verb is null or verb is not changed
     1-1) If device is changed
@@ -211,7 +135,7 @@ static inline int __set_use_case_with_time(snd_use_case_mgr_t *uc_mgr, const cha
    2) If verb is changed
       -> Reset, set new verb, enable devices & modifiers
  */
-audio_return_t _audio_ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[])
+audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[])
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
     int is_verb_changed = 0, is_dev_changed = 0, is_mod_changed = 0;
@@ -425,7 +349,7 @@ exit:
     return audio_ret;
 }
 
-audio_return_t _audio_ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[])
+audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[])
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
     int is_verb_changed = 0, is_dev_changed = 0;
@@ -560,7 +484,7 @@ exit:
 
 }
 
-audio_return_t _audio_ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[])
+audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[])
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
     int is_verb_changed = 0, is_mod_changed = 0;
@@ -693,7 +617,7 @@ exit:
     return audio_ret;
 }
 
-audio_return_t _audio_ucm_get_verb(audio_hal_t *ah, const char **value)
+audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value)
 {
     audio_return_t ret = AUDIO_RET_OK;
 
@@ -709,8 +633,7 @@ audio_return_t _audio_ucm_get_verb(audio_hal_t *ah, const char **value)
     return ret;
 }
 
-
-audio_return_t _audio_ucm_reset_use_case(audio_hal_t *ah)
+audio_return_t _ucm_reset_use_case(audio_hal_t *ah)
 {
     audio_return_t ret = AUDIO_RET_OK;
 
@@ -725,5 +648,4 @@ audio_return_t _audio_ucm_reset_use_case(audio_hal_t *ah)
     }
 
     return ret;
-}
-
+}
\ No newline at end of file
diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h
new file mode 100644 (file)
index 0000000..4410541
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef footizenaudioimplfoo
+#define footizenaudioimplfoo
+
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* PCM */
+int _voice_pcm_open(audio_hal_t *ah);
+int _voice_pcm_close(audio_hal_t *ah, uint32_t direction);
+void _reset_pcm_devices(audio_hal_t *ah);
+audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+audio_return_t _pcm_start(void *pcm_handle);
+audio_return_t _pcm_stop(void *pcm_handle);
+audio_return_t _pcm_close(void *pcm_handle);
+audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail);
+audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames);
+audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames);
+audio_return_t _pcm_get_fd(void *pcm_handle, int *fd);
+audio_return_t _pcm_recover(void *pcm_handle, int revents);
+audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
+audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event);
+audio_return_t _pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size);
+
+/* Control */
+audio_return_t _control_init(audio_hal_t *ah);
+audio_return_t _control_deinit(audio_hal_t *ah);
+audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size);
+audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val);
+audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value);
+audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val);
+audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem);
+
+/* UCM  */
+audio_return_t _ucm_init(audio_hal_t *ah);
+audio_return_t _ucm_deinit(audio_hal_t *ah);
+#define _ucm_update_use_case _ucm_set_use_case
+audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[]);
+audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]);
+audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]);
+audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value);
+audio_return_t _ucm_reset_use_case(audio_hal_t *ah);
+
+#endif
index e603abf..e9f0647 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -171,42 +171,14 @@ typedef struct device_type {
 /* type definitions */
 typedef signed char int8_t;
 
-/* pcm */
+/* PCM */
 typedef struct {
     snd_pcm_format_t format;
     uint32_t rate;
     uint8_t channels;
 } audio_pcm_sample_spec_t;
 
-/* Device */
-typedef enum audio_device_api {
-    AUDIO_DEVICE_API_UNKNOWN,
-    AUDIO_DEVICE_API_ALSA,
-    AUDIO_DEVICE_API_BLUEZ,
-} audio_device_api_t;
-
-typedef struct audio_device_alsa_info {
-    char *card_name;
-    uint32_t card_idx;
-    uint32_t device_idx;
-} audio_device_alsa_info_t;
-
-typedef struct audio_device_bluz_info {
-    char *protocol;
-    uint32_t nrec;
-} audio_device_bluez_info_t;
-
-typedef struct audio_device_info {
-    audio_device_api_t api;
-    audio_direction_t direction;
-    char *name;
-    uint8_t is_default_device;
-    union {
-        audio_device_alsa_info_t alsa;
-        audio_device_bluez_info_t bluez;
-    };
-} audio_device_info_t;
-
+/* Routing */
 typedef enum audio_route_mode {
     VERB_NORMAL,
     VERB_VOICECALL,
@@ -228,7 +200,7 @@ typedef struct audio_hal_device {
     pthread_mutex_t device_lock;
 } audio_hal_device_t;
 
-/* Stream */
+/* Volume */
 #define AUDIO_VOLUME_LEVEL_MAX 16
 
 typedef enum audio_volume {
@@ -274,10 +246,12 @@ typedef struct audio_hal_volume {
     audio_volume_value_table_t *volume_value_table;
 } audio_hal_volume_t;
 
+/* UCM */
 typedef struct audio_hal_ucm {
     snd_use_case_mgr_t* uc_mgr;
 } audio_hal_ucm_t;
 
+/* Mixer */
 typedef struct audio_hal_mixer {
     snd_mixer_t *mixer;
     pthread_mutex_t mutex;
@@ -307,8 +281,8 @@ typedef enum audio_sample_format {
     AUDIO_SAMPLE_INVALID = -1
 } audio_sample_format_t;
 
+/* Modem */
 typedef struct audio_hal_modem {
-
     struct {
         pthread_t voice_thread_handle;
         pthread_t voip_thread_handle;
@@ -349,38 +323,20 @@ typedef struct audio_hal {
 
 audio_return_t _audio_volume_init(audio_hal_t *ah);
 audio_return_t _audio_volume_deinit(audio_hal_t *ah);
-audio_return_t _audio_device_init(audio_hal_t *ah);
-audio_return_t _audio_device_deinit(audio_hal_t *ah);
-audio_return_t _audio_ucm_init(audio_hal_t *ah);
-audio_return_t _audio_ucm_deinit(audio_hal_t *ah);
+audio_return_t _audio_routing_init(audio_hal_t *ah);
+audio_return_t _audio_routing_deinit(audio_hal_t *ah);
+audio_return_t _audio_stream_init(audio_hal_t *ah);
+audio_return_t _audio_stream_deinit(audio_hal_t *ah);
+audio_return_t _audio_pcm_init(audio_hal_t *ah);
+audio_return_t _audio_pcm_deinit(audio_hal_t *ah);
 audio_return_t _audio_modem_init(audio_hal_t *ah);
 audio_return_t _audio_modem_deinit(audio_hal_t *ah);
 audio_return_t _audio_comm_init(audio_hal_t *ah);
 audio_return_t _audio_comm_deinit(audio_hal_t *ah);
-audio_return_t _audio_util_init(audio_hal_t *ah);
-audio_return_t _audio_util_deinit(audio_hal_t *ah);
 
 audio_return_t _audio_update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices);
-void _audio_ucm_get_device_name(audio_hal_t *ah, const char *use_case, audio_direction_t direction, const char **value);
-#define _audio_ucm_update_use_case _audio_ucm_set_use_case
-audio_return_t _audio_ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[]);
-audio_return_t _audio_ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]);
-audio_return_t _audio_ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]);
-int _audio_ucm_fill_device_info_list(audio_hal_t *ah, audio_device_info_t *device_info_list, const char *verb);
-audio_return_t _audio_ucm_get_verb(audio_hal_t *ah, const char **value);
-audio_return_t _audio_ucm_reset_use_case(audio_hal_t *ah);
 int _audio_modem_is_call_connected(audio_hal_t *ah);
 audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value);
-audio_return_t _audio_comm_set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data);
-audio_return_t _audio_comm_unset_message_callback(audio_hal_t *ah);
-audio_return_t _audio_mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size);
-audio_return_t _audio_mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val);
-audio_return_t _audio_mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value);
-audio_return_t _audio_mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val);
-audio_return_t _audio_mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem);
-audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event);
-audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size);
-uint32_t _convert_format(audio_sample_format_t format);
 
 typedef struct _dump_data {
     char *strbuf;
@@ -388,9 +344,9 @@ typedef struct _dump_data {
     char *p;
 } dump_data_t;
 
-dump_data_t* dump_new(int length);
-void dump_add_str(dump_data_t *dump, const char *fmt, ...);
-char* dump_get_str(dump_data_t *dump);
-void dump_free(dump_data_t *dump);
+dump_data_t* _audio_dump_new(int length);
+void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...);
+char* _audio_dump_get_str(dump_data_t *dump);
+void _audio_dump_free(dump_data_t *dump);
 
 #endif
index 6769350..9ad85a7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  *
@@ -31,6 +31,7 @@
 #include <vconf.h>
 
 #include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
 
 #define vbc_thread_new pthread_create
 #define MIXER_VBC_SWITCH                            "VBC Switch"
@@ -176,7 +177,7 @@ int _audio_modem_is_call_connected(audio_hal_t *ah)
 {
     int val = -1; /* Mixer values 0 - cp [3g] ,1 - cp [2g] ,2 - ap */
 
-    _audio_mixer_control_get_value(ah, MIXER_VBC_SWITCH, &val);
+    _mixer_control_get_value(ah, MIXER_VBC_SWITCH, &val);
     AUDIO_LOG_INFO("modem is connected for call = %d", (val == VBC_TD_CHANNELID));
 
     return (val == VBC_TD_CHANNELID) ? 1 : 0;
@@ -202,7 +203,7 @@ static int __vbc_write_response(int fd, unsigned int cmd, uint32_t paras_size)
 }
 
 #define FM_IIS                                      0x10
-static void i2s_pin_mux_sel(audio_hal_t *ah, int type)
+static void __i2s_pin_mux_sel(audio_hal_t *ah, int type)
 {
     audio_return_t ret = AUDIO_RET_OK;
     audio_modem_t *modem;
@@ -216,7 +217,7 @@ static void i2s_pin_mux_sel(audio_hal_t *ah, int type)
     modem = ah->modem.cp;
 
     if (type == FM_IIS) {
-        _audio_mixer_control_set_value(ah,
+        _mixer_control_set_value(ah,
                     PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_VBC_ID);
         return;
     }
@@ -224,21 +225,21 @@ static void i2s_pin_mux_sel(audio_hal_t *ah, int type)
        if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
             if(modem->i2s_bt.is_ext) {
                 if(modem->i2s_bt.is_switch) {
-                    ret = _audio_mixer_control_set_value(ah,
+                    ret = _mixer_control_set_value(ah,
                             PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP0_ID);
                 }
             } else {
                 if(modem->i2s_bt.is_switch) {
                     int value = 0;
-                    _audio_mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
+                    _mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
                     if(value == PIN_SWITCH_IIS0_CP0_ID) {
-                        ret = _audio_mixer_control_set_value(ah,
+                        ret = _mixer_control_set_value(ah,
                                 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_AP_ID);
                     }
                 }
                 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
                     if(modem->i2s_bt.is_switch) {
-                        ret = _audio_mixer_control_set_value(ah,
+                        ret = _mixer_control_set_value(ah,
                                 PIN_SWITCH_BT_IIS_SYS_SEL, PIN_SWITCH_BT_IIS_CP0_IIS0_ID);
                     }
                 }
@@ -248,21 +249,21 @@ static void i2s_pin_mux_sel(audio_hal_t *ah, int type)
         if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
             if(modem->i2s_bt.is_ext) {
                 if(modem->i2s_bt.is_switch) {
-                    ret = _audio_mixer_control_set_value(ah,
+                    ret = _mixer_control_set_value(ah,
                             PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP1_ID);
                 }
             } else {
                 if(modem->i2s_bt.is_switch) {
                     int value = 0;
-                    _audio_mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
+                    _mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
                     if(value == PIN_SWITCH_IIS0_CP1_ID) {
-                        ret = _audio_mixer_control_set_value(ah,
+                        ret = _mixer_control_set_value(ah,
                                 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP2_ID);
                     }
                 }
                 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
                     if(modem->i2s_bt.is_switch) {
-                        ret = _audio_mixer_control_set_value(ah,
+                        ret = _mixer_control_set_value(ah,
                                 PIN_SWITCH_BT_IIS_SYS_SEL, PIN_SWITCH_BT_IIS_CP1_IIS0_ID);
                     }
                 }
@@ -354,8 +355,7 @@ again:
                     AUDIO_LOG_INFO("[voice] Received VBC_CMD_PCM_OPEN");
 
                     ah->modem.is_connected = 1;
-                    audio_ret = _audio_update_route_voicecall(ah, ah->device.init_call_devices, ah->device.num_of_call_devices);
-                    if (AUDIO_IS_ERROR(audio_ret)) {
+                    if ((audio_ret = _audio_update_route_voicecall(ah, ah->device.init_call_devices, ah->device.num_of_call_devices))) {
                         AUDIO_LOG_WARN("set voicecall route return 0x%x", audio_ret);
                         if (audio_ret == AUDIO_ERR_INVALID_STATE) {
                             /* send signal and wait for the ucm setting,
@@ -375,9 +375,9 @@ again:
 
                     if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
                         if (ah->modem.cp_type == CP_TG)
-                            i2s_pin_mux_sel(ah, 1);
+                            __i2s_pin_mux_sel(ah, 1);
                         else if(ah->modem.cp_type == CP_W)
-                            i2s_pin_mux_sel(ah, 0);
+                            __i2s_pin_mux_sel(ah, 0);
                     }
 
                     AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_PCM_OPEN");
@@ -396,7 +396,7 @@ again:
                     COND_TIMEDWAIT(ah->device.device_cond, ah->device.device_lock, "device_cond", TIMEOUT_SEC);
                     MUTEX_UNLOCK(ah->device.device_lock, "device_lock");
 
-                    _audio_mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_ARM_CHANNELID);
+                    _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_ARM_CHANNELID);
 
                     AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_PCM_CLOSE");
                     __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_CLOSE, 0);
@@ -416,9 +416,9 @@ again:
 
                     if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
                         if (ah->modem.cp_type == CP_TG)
-                            i2s_pin_mux_sel(ah, 1);
+                            __i2s_pin_mux_sel(ah, 1);
                         else if(ah->modem.cp_type == CP_W)
-                            i2s_pin_mux_sel(ah, 0);
+                            __i2s_pin_mux_sel(ah, 0);
                     }
                     /* To do: set mode params : __vbc_set_mode_params(ah, vbpipe_fd); */
 
@@ -448,7 +448,7 @@ again:
                     else
                         AUDIO_LOG_INFO("is_switch:%d", switch_ctrl_params.is_switch);
 
-                    _audio_mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
+                    _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
 
                     AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_SET_GAIN");
                     __vbc_write_response(vbpipe_fd, VBC_CMD_SWITCH_CTRL, 0);
@@ -595,9 +595,9 @@ again:
 
                     if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
                         if (ah->modem.cp_type == CP_TG)
-                            i2s_pin_mux_sel(ah, 1);
+                            __i2s_pin_mux_sel(ah, 1);
                         else if(ah->modem.cp_type == CP_W)
-                            i2s_pin_mux_sel(ah, 0);
+                            __i2s_pin_mux_sel(ah, 0);
                     }
                     /* To do: set mode params : __vbc_set_mode_params(ah, vbpipe_fd); */
                     AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SET_MODE");
@@ -624,7 +624,7 @@ again:
                     else
                         AUDIO_LOG_INFO("is_switch:%d", switch_ctrl_params.is_switch);
 
-                    _audio_mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
+                    _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
 
                     AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SWITCH_CTRL");
                     __vbc_write_response(vbpipe_fd, VBC_CMD_SWITCH_CTRL, 0);
@@ -692,7 +692,7 @@ static audio_return_t __vbc_control_open(audio_hal_t *ah)
     return AUDIO_RET_OK;
 }
 
-static audio_return_t __vbc_control_close(audio_hal_t *ah)
+void __vbc_control_close(audio_hal_t *ah)
 {
     /* TODO. Make sure we always receive CLOSE command from modem and then close pcm device */
     ah->modem.vbc.exit_vbc_thread = 1;
@@ -701,7 +701,7 @@ static audio_return_t __vbc_control_close(audio_hal_t *ah)
     pthread_cancel(ah->modem.vbc.voice_thread_handle);
     pthread_cancel(ah->modem.vbc.voip_thread_handle);
 
-    return AUDIO_RET_OK;
+    return;
 }
 
 static void __audio_modem_create(audio_modem_t *modem, const char *num)
@@ -940,8 +940,7 @@ audio_return_t _audio_modem_init(audio_hal_t *ah)
     ah->modem.vbc.vbpipe_count = 0;
 
     /* Initialize vbc interface */
-    audio_ret = __vbc_control_open(ah);
-    if (AUDIO_IS_ERROR(audio_ret)) {
+    if ((audio_ret = __vbc_control_open(ah))) {
         AUDIO_LOG_ERROR("__vbc_control_open failed");
         goto exit;
     }
@@ -956,7 +955,7 @@ audio_return_t _audio_modem_init(audio_hal_t *ah)
     ah->modem.cp_type = ah->modem.cp->vbc_ctrl_pipe_info->cp_type;
 
     /* This ctrl need to be set "0" always - SPRD */
-    _audio_mixer_control_set_value(ah, PIN_SWITCH_BT_IIS_CON_SWITCH, 0);
+    _mixer_control_set_value(ah, PIN_SWITCH_BT_IIS_CON_SWITCH, 0);
 
 exit:
     return audio_ret;
diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c
new file mode 100644 (file)
index 0000000..08dc5ab
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
+
+audio_return_t _audio_pcm_init(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    ah->device.pcm_in = NULL;
+    ah->device.pcm_out = NULL;
+    pthread_mutex_init(&ah->device.pcm_lock, NULL);
+    pthread_mutex_init(&ah->device.device_lock, NULL);
+    pthread_cond_init(&ah->device.device_cond, NULL);
+    ah->device.pcm_count = 0;
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_pcm_deinit(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    pthread_mutex_destroy(&ah->device.pcm_lock);
+    pthread_mutex_destroy(&ah->device.device_lock);
+    pthread_cond_destroy(&ah->device.device_cond);
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_hal_t *ah = NULL;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
+
+    if ((audio_ret = _pcm_open(pcm_handle, direction, sample_spec, period_size, periods)))
+        return audio_ret;
+
+    ah = (audio_hal_t*)audio_handle;
+    ah->device.pcm_count++;
+    AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle);
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_start(pcm_handle);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_stop(pcm_handle);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_hal_t *ah = NULL;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    if ((audio_ret = _pcm_close(pcm_handle)))
+        return audio_ret;
+
+    pcm_handle = NULL;
+    ah = (audio_hal_t*)audio_handle;
+    ah->device.pcm_count--;
+
+    AUDIO_LOG_INFO("PCM handle close success (count:%d)", ah->device.pcm_count);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_avail(pcm_handle, avail);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_write(pcm_handle, buffer, frames);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_read(pcm_handle, buffer, frames);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_get_fd(pcm_handle, fd);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_recover(pcm_handle, revents);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_get_params(pcm_handle, direction, sample_spec, period_size, periods);
+
+    return audio_ret;
+}
+
+audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
+
+    audio_ret = _pcm_set_params(pcm_handle, direction, sample_spec, period_size, periods);
+
+    return audio_ret;
+}
\ No newline at end of file
diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c
new file mode 100644 (file)
index 0000000..c2d03ea
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
+
+/* #define DEBUG_TIMING */
+
+static device_type_t outDeviceTypes[] = {
+    { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
+    { AUDIO_DEVICE_OUT_RECEIVER, "Earpiece" },
+    { AUDIO_DEVICE_OUT_JACK, "Headphones" },
+    { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
+    { 0, 0 },
+};
+
+static device_type_t inDeviceTypes[] = {
+    { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
+    { AUDIO_DEVICE_IN_SUB_MIC, "SubMic" },
+    { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
+    { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
+    { 0, 0 },
+};
+
+static const char* mode_to_verb_str[] = {
+    AUDIO_USE_CASE_VERB_HIFI,
+    AUDIO_USE_CASE_VERB_VOICECALL,
+    AUDIO_USE_CASE_VERB_VIDEOCALL,
+    AUDIO_USE_CASE_VERB_VOIP,
+};
+
+static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
+{
+    uint32_t device = 0;
+
+    if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
+        device = AUDIO_DEVICE_OUT_SPEAKER;
+    } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
+        device = AUDIO_DEVICE_OUT_RECEIVER;
+    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
+        device = AUDIO_DEVICE_OUT_JACK;
+    } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
+        device = AUDIO_DEVICE_OUT_BT_SCO;
+    } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
+        device = AUDIO_DEVICE_IN_MAIN_MIC;
+    /* To Do : SUB_MIC */
+    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
+        device = AUDIO_DEVICE_IN_JACK;
+    } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
+        device = AUDIO_DEVICE_IN_BT_SCO;
+    } else {
+        device = AUDIO_DEVICE_NONE;
+    }
+    AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
+    return device;
+}
+
+static void __reset_voice_devices_info(audio_hal_t *ah)
+{
+    AUDIO_RETURN_IF_FAIL(ah);
+
+    AUDIO_LOG_INFO("reset voice device info");
+    if (ah->device.init_call_devices) {
+        free(ah->device.init_call_devices);
+        ah->device.init_call_devices = NULL;
+        ah->device.num_of_call_devices = 0;
+    }
+
+    return;
+}
+
+static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    uint32_t new_device = 0;
+    const char *active_devices[MAX_DEVICES] = {NULL,};
+    int i = 0, j = 0, dev_idx = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
+
+    if (num_of_devices > MAX_DEVICES) {
+        num_of_devices = MAX_DEVICES;
+        AUDIO_LOG_ERROR("error: num_of_devices");
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if (devices[0].direction == AUDIO_DIRECTION_OUT) {
+        ah->device.active_out &= 0x0;
+        if (ah->device.active_in) {
+            /* check the active in devices */
+            for (j = 0; j < inDeviceTypes[j].type; j++) {
+                if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
+                    active_devices[dev_idx++] = inDeviceTypes[j].name;
+            }
+        }
+    } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
+        ah->device.active_in &= 0x0;
+        if (ah->device.active_out) {
+            /* check the active out devices */
+            for (j = 0; j < outDeviceTypes[j].type; j++) {
+                if (ah->device.active_out & outDeviceTypes[j].type)
+                    active_devices[dev_idx++] = outDeviceTypes[j].name;
+            }
+        }
+    }
+
+    for (i = 0; i < num_of_devices; i++) {
+        new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
+        if (new_device & AUDIO_DEVICE_IN) {
+            for (j = 0; j < inDeviceTypes[j].type; j++) {
+                if (new_device == inDeviceTypes[j].type) {
+                    active_devices[dev_idx++] = inDeviceTypes[j].name;
+                    ah->device.active_in |= new_device;
+                }
+            }
+        } else {
+            for (j = 0; j < outDeviceTypes[j].type; j++) {
+                if (new_device == outDeviceTypes[j].type) {
+                    active_devices[dev_idx++] = outDeviceTypes[j].name;
+                    ah->device.active_out |= new_device;
+                }
+            }
+        }
+    }
+
+    if (active_devices[0] == NULL) {
+        AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    audio_ret = _ucm_set_devices(ah, verb, active_devices);
+    if (audio_ret)
+        AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret);
+
+    return audio_ret;
+}
+
+static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    device_info_t *devices = NULL;
+    const char *verb = mode_to_verb_str[VERB_NORMAL];
+#if 0  /* Disable setting modifiers, because driver does not support it yet */
+    int mod_idx = 0;
+    const char *modifiers[MAX_MODIFIERS] = {NULL,};
+#endif
+
+    if (ah->modem.is_connected) {
+        AUDIO_LOG_INFO("modem is connected, skip verb[%s]", verb);
+        return audio_ret;
+    }
+
+    if (ah->device.mode != VERB_NORMAL) {
+        if (ah->device.mode == VERB_VOICECALL) {
+            __reset_voice_devices_info(ah);
+            COND_SIGNAL(ah->device.device_cond, "device_cond");
+        }
+        _reset_pcm_devices(ah);
+        ah->device.mode = VERB_NORMAL;
+    }
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
+
+    devices = route_info->device_infos;
+
+    AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
+
+    audio_ret = __set_devices(ah, verb, devices, route_info->num_of_devices);
+    if (audio_ret) {
+        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
+        return audio_ret;
+    }
+    ah->device.mode = VERB_NORMAL;
+
+#if 0 /* Disable setting modifiers, because driver does not support it yet */
+    /* Set modifiers */
+    if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) {
+        modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH;
+    } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) {
+        if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK)
+            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA;
+        else
+            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
+    } else if (!strncmp("ringtone", route_info->role, MAX_NAME_LEN)) {
+        if (ah->device.active_out)
+            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_RINGTONE;
+    } else {
+        if (ah->device.active_in)
+            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING;
+        else
+            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
+    }
+    audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers);
+#endif
+    return audio_ret;
+}
+
+static audio_return_t __update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    const char *verb = mode_to_verb_str[VERB_VOICECALL];
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    /* if both params are 0, return error for invalid state,
+         * this error would be used to tizen-audio-modem.c */
+    AUDIO_RETURN_VAL_IF_FAIL((devices||num_of_devices), AUDIO_ERR_INVALID_STATE);
+    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("update_route_voicecall++");
+
+    audio_ret = __set_devices(ah, verb, devices, num_of_devices);
+    if (audio_ret) {
+        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
+        return audio_ret;
+    }
+
+    if (ah->device.mode != VERB_VOICECALL) {
+        _voice_pcm_open(ah);
+        ah->device.mode = VERB_VOICECALL;
+        /* FIXME. Get network info and configure rate in pcm device */
+    }
+
+    return audio_ret;
+}
+
+static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    const char *verb = mode_to_verb_str[VERB_NORMAL];
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("update_route_voip++");
+
+    audio_ret = __set_devices(ah, verb, devices, num_of_devices);
+    if (audio_ret) {
+        AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
+        return audio_ret;
+    }
+    /* FIXME. If necessary, set VERB_VOIP */
+    ah->device.mode = VERB_NORMAL;
+
+    /* TO DO: Set modifiers */
+    return audio_ret;
+}
+
+static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    const char *active_devices[MAX_DEVICES] = {NULL,};
+    int i = 0, dev_idx = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
+
+    if (direction == AUDIO_DIRECTION_OUT) {
+        ah->device.active_out &= 0x0;
+        if (ah->device.active_in) {
+            /* check the active in devices */
+            for (i = 0; i < inDeviceTypes[i].type; i++) {
+                if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
+                    active_devices[dev_idx++] = inDeviceTypes[i].name;
+                    AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
+                }
+            }
+        }
+    } else {
+        ah->device.active_in &= 0x0;
+        if (ah->device.active_out) {
+            /* check the active out devices */
+            for (i = 0; i < outDeviceTypes[i].type; i++) {
+                if (ah->device.active_out & outDeviceTypes[i].type) {
+                    active_devices[dev_idx++] = outDeviceTypes[i].name;
+                    AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
+                }
+            }
+        }
+    }
+    if (ah->device.mode == VERB_VOICECALL) {
+        _voice_pcm_close(ah, direction);
+        if (!ah->device.active_in && !ah->device.active_out)
+            ah->device.mode = VERB_NORMAL;
+        __reset_voice_devices_info(ah);
+        COND_SIGNAL(ah->device.device_cond, "device_cond");
+    }
+
+    if (active_devices[0] == NULL) {
+        AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
+        return AUDIO_RET_OK;
+    }
+
+    if ((audio_ret = _ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices)))
+        AUDIO_LOG_ERROR("failed to _ucm_set_devices(), ret(0x%x)", audio_ret);
+
+    return audio_ret;
+}
+
+audio_return_t _audio_update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
+{
+    return __update_route_voicecall(ah, devices, num_of_devices);
+}
+
+audio_return_t _audio_routing_init(audio_hal_t *ah)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    ah->device.active_in = 0x0;
+    ah->device.active_out = 0x0;
+    ah->device.mode = VERB_NORMAL;
+
+    if ((audio_ret = _ucm_init(ah)))
+        AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret);
+
+    return audio_ret;
+}
+
+audio_return_t _audio_routing_deinit(audio_hal_t *ah)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    if ((audio_ret = _ucm_deinit(ah)))
+        AUDIO_LOG_ERROR("failed to _ucm_deinit(), ret(0x%x)", audio_ret);
+
+    return audio_ret;
+}
+
+audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_hal_t *ah = (audio_hal_t *)audio_handle;
+    device_info_t *devices = NULL;
+    uint32_t prev_size;
+    int32_t i;
+    int32_t j;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("role:%s", info->role);
+
+    devices = info->device_infos;
+
+    if (!strncmp("call-voice", info->role, MAX_NAME_LEN)) {
+        if (!ah->modem.is_connected) {
+            if (info->num_of_devices) {
+                if (!ah->device.num_of_call_devices) {
+                    if ((ah->device.init_call_devices = (device_info_t*)calloc(info->num_of_devices, sizeof(device_info_t)))) {
+                        memcpy(ah->device.init_call_devices, devices, info->num_of_devices*sizeof(device_info_t));
+                        ah->device.num_of_call_devices = info->num_of_devices;
+                    } else {
+                        AUDIO_LOG_ERROR("failed to calloc");
+                        audio_ret = AUDIO_ERR_RESOURCE;
+                        goto ERROR;
+                    }
+                } else if (ah->device.num_of_call_devices) {
+                    prev_size = ah->device.num_of_call_devices;
+                    if (prev_size == 2) {
+                        /* There's a chance to be requested to change routing from user
+                         * though two devices(for input/output) has already been set for call-voice routing.
+                         * In this case, exchange an old device for a new device if it's direction is same as an old one's. */
+                        for (i = 0; i < prev_size; i++) {
+                            for (j = 0; j < info->num_of_devices; j++) {
+                                if (devices[j].direction == ah->device.init_call_devices[i].direction &&
+                                    devices[j].id != ah->device.init_call_devices[i].id)
+                                    memcpy(&ah->device.init_call_devices[i], &devices[j], sizeof(device_info_t));
+                            }
+                        }
+                    } else if (prev_size < 2) {
+                        /* A device has already been added for call-voice routing,
+                         * and now it is about to add a new device(input or output device). */
+                        ah->device.num_of_call_devices += info->num_of_devices;
+                        if ((ah->device.init_call_devices = (device_info_t*)realloc(ah->device.init_call_devices, sizeof(device_info_t)*ah->device.num_of_call_devices))) {
+                            memcpy((void*)&(ah->device.init_call_devices[prev_size]), devices, info->num_of_devices*sizeof(device_info_t));
+                        } else {
+                            AUDIO_LOG_ERROR("failed to realloc");
+                            audio_ret = AUDIO_ERR_RESOURCE;
+                            goto ERROR;
+                        }
+                    } else {
+                        AUDIO_LOG_ERROR("invaild previous num. of call devices");
+                        audio_ret = AUDIO_ERR_INTERNAL;
+                        goto ERROR;
+                    }
+                }
+            } else {
+                AUDIO_LOG_ERROR("failed to update route for call-voice, num_of_devices is 0");
+                audio_ret = AUDIO_ERR_PARAMETER;
+                goto ERROR;
+            }
+            AUDIO_LOG_INFO("modem is not ready, skip...");
+        } else {
+            if ((audio_ret = __update_route_voicecall(ah, devices, info->num_of_devices)))
+                AUDIO_LOG_WARN("update voicecall route return 0x%x", audio_ret);
+
+            COND_SIGNAL(ah->device.device_cond, "device_cond");
+        }
+    } else if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
+        if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
+            AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
+
+    } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
+        if ((audio_ret = __update_route_reset(ah, devices->direction)))
+            AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
+
+    } else {
+        /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
+        if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
+            AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
+    }
+
+ERROR:
+    return audio_ret;
+}
+
+audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_hal_t *ah = (audio_hal_t *)audio_handle;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
+
+    return audio_ret;
+}
\ No newline at end of file
diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c
new file mode 100644 (file)
index 0000000..f89a0b6
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+
+/* Audio latency */
+static const char* AUDIO_LATENCY_LOW  = "low";
+static const char* AUDIO_LATENCY_MID  = "mid";
+static const char* AUDIO_LATENCY_HIGH = "high";
+static const char* AUDIO_LATENCY_VOIP = "voip";
+
+/* Latency msec */
+static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC  = 20;
+static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC   = 25;
+static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC   = 50;
+static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC  = 75;
+static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
+static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC  = 20;
+
+static const uint32_t g_size_table[] = {
+    [AUDIO_SAMPLE_U8]        = 1,
+    [AUDIO_SAMPLE_ULAW]      = 1,
+    [AUDIO_SAMPLE_ALAW]      = 1,
+    [AUDIO_SAMPLE_S16LE]     = 2,
+    [AUDIO_SAMPLE_S16BE]     = 2,
+    [AUDIO_SAMPLE_FLOAT32LE] = 4,
+    [AUDIO_SAMPLE_FLOAT32BE] = 4,
+    [AUDIO_SAMPLE_S32LE]     = 4,
+    [AUDIO_SAMPLE_S32BE]     = 4,
+    [AUDIO_SAMPLE_S24LE]     = 3,
+    [AUDIO_SAMPLE_S24BE]     = 3,
+    [AUDIO_SAMPLE_S24_32LE]  = 4,
+    [AUDIO_SAMPLE_S24_32BE]  = 4
+};
+
+static int __sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
+{
+    if ((rate <= 0                 ||
+        rate > (48000U*4U)         ||
+        channels <= 0              ||
+        channels > 32U             ||
+        format >= AUDIO_SAMPLE_MAX ||
+        format <  AUDIO_SAMPLE_U8))
+        return 0;
+
+    AUDIO_LOG_ERROR("hal-latency - __sample_spec_valid() -> return true");
+
+    return 1;
+}
+
+static uint32_t __usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
+{
+    uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
+    AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
+    return ret;
+}
+
+static uint32_t __sample_size(audio_sample_format_t format)
+{
+    return g_size_table[format];
+}
+
+audio_return_t _audio_stream_init(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_stream_deinit(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    return AUDIO_RET_OK;
+}
+
+audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_hal_t *ah = (audio_hal_t *)audio_handle;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected);
+
+    return audio_ret;
+}
+
+audio_return_t audio_get_buffer_attr(void                  *audio_handle,
+                                     uint32_t              direction,
+                                     const char            *latency,
+                                     uint32_t              samplerate,
+                                     audio_sample_format_t format,
+                                     uint32_t              channels,
+                                     uint32_t              *maxlength,
+                                     uint32_t              *tlength,
+                                     uint32_t              *prebuf,
+                                     uint32_t              *minreq,
+                                     uint32_t              *fragsize)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
+
+    uint32_t period_time        = 0,
+             sample_per_period  = 0;
+
+    if (__sample_spec_valid(samplerate, format, channels) == 0) {
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    if (direction == AUDIO_DIRECTION_IN) {
+        if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
+            period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = -1;
+            *maxlength         = -1;
+            *fragsize          = sample_per_period * __sample_size(format);
+        } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
+            period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = -1;
+            *maxlength         = -1;
+            *fragsize          = sample_per_period * __sample_size(format);
+        } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
+            period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = -1;
+            *maxlength         = -1;
+            *fragsize          = sample_per_period * __sample_size(format);
+        } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
+            period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = -1;
+            *maxlength         = -1;
+            *fragsize          = sample_per_period * __sample_size(format);
+        } else {
+            AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
+            return AUDIO_ERR_UNDEFINED;
+        }
+    } else {  /* AUDIO_DIRECTION_OUT */
+        if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
+            period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = (samplerate / 10) * __sample_size(format) * channels;  /* 100ms */
+            *maxlength         = -1;
+            *fragsize          = 0;
+        } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
+            period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = (uint32_t) __usec_to_bytes(200000, samplerate, format, channels);
+            *maxlength         = -1;
+            *fragsize          = -1;
+        } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
+            period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = -1;
+            *tlength           = (uint32_t) __usec_to_bytes(400000, samplerate, format, channels);
+            *maxlength         = -1;
+            *fragsize          = -1;
+        } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
+            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
+            period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
+            sample_per_period  = (samplerate * period_time) / 1000;
+            *prebuf            = 0;
+            *minreq            = __usec_to_bytes(20000, samplerate, format, channels);
+            *tlength           = __usec_to_bytes(100000, samplerate, format, channels);
+            *maxlength         = -1;
+            *fragsize          = 0;
+        } else {
+            AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
+            return AUDIO_ERR_UNDEFINED;
+        }
+    }
+
+    AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
+    return AUDIO_RET_OK;
+}
index 20b79eb..6ab4aa0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <pthread.h>
 
 #include "tizen-audio-internal.h"
 
-audio_return_t _audio_util_init(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    pthread_mutex_init(&(ah->mixer.mutex), NULL);
-    return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_util_deinit(audio_hal_t *ah)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    pthread_mutex_destroy(&(ah->mixer.mutex));
-    return AUDIO_RET_OK;
-}
-
-#ifdef __MIXER_PARAM_DUMP
-
-static void __dump_mixer_param(char *dump, long *param, int size)
-{
-    int i, len;
-
-    for (i = 0; i < size; i++) {
-        len = sprintf(dump, "%ld", *param);
-        if (len > 0)
-            dump += len;
-        if (i != size -1) {
-            *dump++ = ',';
-        }
-
-        param++;
-    }
-    *dump = '\0';
-}
-
-#endif
-
-audio_return_t _audio_mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    /* TODO. */
-    return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val)
-{
-    snd_ctl_t *handle;
-    snd_ctl_elem_value_t *control;
-    snd_ctl_elem_id_t *id;
-    snd_ctl_elem_info_t *info;
-    snd_ctl_elem_type_t type;
-
-    int ret = 0, count = 0, i = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
-    pthread_mutex_lock(&(ah->mixer.mutex));
-
-    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
-    if (ret < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_open error, %s\n", snd_strerror(ret));
-        pthread_mutex_unlock(&(ah->mixer.mutex));
-        return AUDIO_ERR_IOCTL;
-    }
-
-    // Get Element Info
-
-    snd_ctl_elem_id_alloca(&id);
-    snd_ctl_elem_info_alloca(&info);
-    snd_ctl_elem_value_alloca(&control);
-
-    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
-    snd_ctl_elem_id_set_name(id, ctl_name);
-
-    snd_ctl_elem_info_set_id(info, id);
-    if (snd_ctl_elem_info(handle, info) < 0) {
-        AUDIO_LOG_ERROR("Cannot find control element: %s\n", ctl_name);
-        goto close;
-    }
-    snd_ctl_elem_info_get_id(info, id);
-
-    type = snd_ctl_elem_info_get_type(info);
-    count = snd_ctl_elem_info_get_count(info);
-
-    snd_ctl_elem_value_set_id(control, id);
-
-    if (snd_ctl_elem_read(handle, control) < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
-        goto close;
-}
-
-    switch (type) {
-    case SND_CTL_ELEM_TYPE_BOOLEAN:
-        *val = snd_ctl_elem_value_get_boolean(control, i);
-        break;
-    case SND_CTL_ELEM_TYPE_INTEGER:
-        for (i = 0; i < count; i++)
-        *val = snd_ctl_elem_value_get_integer(control, i);
-        break;
-    case SND_CTL_ELEM_TYPE_ENUMERATED:
-        for (i = 0; i < count; i++)
-        *val = snd_ctl_elem_value_get_enumerated(control, i);
-        break;
-    default:
-        AUDIO_LOG_WARN("unsupported control element type\n");
-        goto close;
-    }
-
-    snd_ctl_close(handle);
-
-#ifdef AUDIO_DEBUG
-    AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
-#endif
-
-    pthread_mutex_unlock(&(ah->mixer.mutex));
-    return AUDIO_RET_OK;
-
-close:
-    AUDIO_LOG_ERROR("Error\n");
-    snd_ctl_close(handle);
-    pthread_mutex_unlock(&(ah->mixer.mutex));
-    return AUDIO_ERR_UNDEFINED;
-}
-
-audio_return_t _audio_mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val)
-{
-    snd_ctl_t *handle;
-    snd_ctl_elem_value_t *control;
-    snd_ctl_elem_id_t *id;
-    snd_ctl_elem_info_t *info;
-    snd_ctl_elem_type_t type;
-    int ret = 0, count = 0, i = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
-
-    pthread_mutex_lock(&(ah->mixer.mutex));
-
-    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
-    if (ret < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", ALSA_DEFAULT_CARD, snd_strerror(ret));
-        pthread_mutex_unlock(&(ah->mixer.mutex));
-        return AUDIO_ERR_IOCTL;
-    }
-
-    // Get Element Info
-
-    snd_ctl_elem_id_alloca(&id);
-    snd_ctl_elem_info_alloca(&info);
-    snd_ctl_elem_value_alloca(&control);
-
-    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
-    snd_ctl_elem_id_set_name(id, ctl_name);
-
-    snd_ctl_elem_info_set_id(info, id);
-    if (snd_ctl_elem_info(handle, info) < 0) {
-        AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
-        goto close;
-    }
-    snd_ctl_elem_info_get_id(info, id);
-
-    type = snd_ctl_elem_info_get_type(info);
-    count = snd_ctl_elem_info_get_count(info);
-
-    snd_ctl_elem_value_set_id(control, id);
-
-    snd_ctl_elem_read(handle, control);
-
-    switch (type) {
-    case SND_CTL_ELEM_TYPE_BOOLEAN:
-        for (i = 0; i < count; i++)
-            snd_ctl_elem_value_set_boolean(control, i, val);
-        break;
-    case SND_CTL_ELEM_TYPE_INTEGER:
-        for (i = 0; i < count; i++)
-            snd_ctl_elem_value_set_integer(control, i, val);
-        break;
-    case SND_CTL_ELEM_TYPE_ENUMERATED:
-        for (i = 0; i < count; i++)
-            snd_ctl_elem_value_set_enumerated(control, i, val);
-        break;
-
-    default:
-        AUDIO_LOG_WARN("unsupported control element type");
-        goto close;
-    }
-
-    snd_ctl_elem_write(handle, control);
-
-    snd_ctl_close(handle);
-
-    AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
-
-    pthread_mutex_unlock(&(ah->mixer.mutex));
-    return AUDIO_RET_OK;
-
-close:
-    AUDIO_LOG_ERROR("Error");
-    snd_ctl_close(handle);
-    pthread_mutex_unlock(&(ah->mixer.mutex));
-    return AUDIO_ERR_UNDEFINED;
-}
-
-audio_return_t _audio_mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
-
-    /* TODO. */
-    return AUDIO_RET_OK;
-}
-
-
-audio_return_t _audio_mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER);
-
-    /* TODO. */
-    return AUDIO_RET_OK;
-}
-
-#ifdef __USE_TINYALSA__
-/* Convert pcm format from pulse to alsa */
-static const uint32_t g_format_convert_table[] = {
-    [AUDIO_SAMPLE_U8]        = PCM_FORMAT_S8,
-    [AUDIO_SAMPLE_S16LE]     = PCM_FORMAT_S16_LE,
-    [AUDIO_SAMPLE_S32LE]     = PCM_FORMAT_S32_LE,
-    [AUDIO_SAMPLE_S24_32LE]  = PCM_FORMAT_S24_LE
-};
-#else  /* alsa-lib */
-/* Convert pcm format from pulse to alsa */
-static const uint32_t g_format_convert_table[] = {
-    [AUDIO_SAMPLE_U8]        = SND_PCM_FORMAT_U8,
-    [AUDIO_SAMPLE_ALAW]      = SND_PCM_FORMAT_A_LAW,
-    [AUDIO_SAMPLE_ULAW]      = SND_PCM_FORMAT_MU_LAW,
-    [AUDIO_SAMPLE_S16LE]     = SND_PCM_FORMAT_S16_LE,
-    [AUDIO_SAMPLE_S16BE]     = SND_PCM_FORMAT_S16_BE,
-    [AUDIO_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
-    [AUDIO_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
-    [AUDIO_SAMPLE_S32LE]     = SND_PCM_FORMAT_S32_LE,
-    [AUDIO_SAMPLE_S32BE]     = SND_PCM_FORMAT_S32_BE,
-    [AUDIO_SAMPLE_S24LE]     = SND_PCM_FORMAT_S24_3LE,
-    [AUDIO_SAMPLE_S24BE]     = SND_PCM_FORMAT_S24_3BE,
-    [AUDIO_SAMPLE_S24_32LE]  = SND_PCM_FORMAT_S24_LE,
-    [AUDIO_SAMPLE_S24_32BE]  = SND_PCM_FORMAT_S24_BE
-};
-#endif
-
-uint32_t _convert_format(audio_sample_format_t format)
-{
-    return g_format_convert_table[format];
-}
-
-/* Generic snd pcm interface APIs */
-audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size)
-{
-    audio_return_t ret = AUDIO_RET_OK;
-    snd_pcm_hw_params_t *hwparams;
-    int err = 0;
-    int dir;
-    unsigned int val = 0;
-    snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
-    snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
-    uint8_t _use_mmap = use_mmap && *use_mmap;
-    uint32_t channels = 0;
-
-    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
-
-    snd_pcm_hw_params_alloca(&hwparams);
-
-    /* Skip parameter setting to null device. */
-    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
-        return AUDIO_ERR_IOCTL;
-
-    /* Allocate a hardware parameters object. */
-    snd_pcm_hw_params_alloca(&hwparams);
-
-    /* Fill it in with default values. */
-    if (snd_pcm_hw_params_any(pcm, hwparams) < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
-        goto error;
-    }
-
-    /* Set the desired hardware parameters. */
-
-    if (_use_mmap) {
-
-        if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
-
-            /* mmap() didn't work, fall back to interleaved */
-
-            if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-                AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
-                goto error;
-            }
-
-            _use_mmap = 0;
-        }
-
-    } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-        AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
-        goto error;
-    }
-    AUDIO_LOG_DEBUG("setting rate - %d", sample_spec->rate);
-    err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
-    }
-
-    err = snd_pcm_hw_params(pcm, hwparams);
-    if (err < 0) {
-        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
-        goto error;
-    }
-
-    /* Dump current param */
-
-    if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
-        AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
-        goto error;
-    }
-
-    if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
-        (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
-        AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
-        goto error;
-    }
-
-    snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
-    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
-
-    snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
-    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
-                    snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
-                    snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
-
-    snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
-    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
-                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
-                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
-
-    snd_pcm_hw_params_get_channels(hwparams, &channels);
-    sample_spec->channels = (uint8_t)channels;
-    AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
-
-    if (buffer_size)
-        *buffer_size = _buffer_size;
-
-    if (period_size)
-        *period_size = _period_size;
-
-    if (use_mmap)
-        *use_mmap = _use_mmap;
-
-    return AUDIO_RET_OK;
-
-error:
-    return AUDIO_ERR_RESOURCE;
-}
-
-audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event)
-{
-    snd_pcm_sw_params_t *swparams;
-    snd_pcm_uframes_t boundary;
-    int err;
-
-    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
-
-    snd_pcm_sw_params_alloca(&swparams);
-
-    if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
-        AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
-        AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
-        AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
-        AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
-        AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) {
-        AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
-        AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err));
-        goto error;
-    }
-    if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
-        AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err));
-        goto error;
-    }
-    return AUDIO_RET_OK;
-error:
-    return err;
-}
-
 /* ------ dump helper --------  */
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 
-dump_data_t* dump_new(int length)
+dump_data_t* _audio_dump_new(int length)
 {
     dump_data_t* dump = NULL;
 
@@ -459,7 +48,7 @@ dump_data_t* dump_new(int length)
     return dump;
 }
 
-void dump_add_str(dump_data_t *dump, const char *fmt, ...)
+void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...)
 {
     int len;
     va_list ap;
@@ -475,12 +64,12 @@ void dump_add_str(dump_data_t *dump, const char *fmt, ...)
     dump->left -= MAX(0, len);
 }
 
-char* dump_get_str(dump_data_t *dump)
+char* _audio_dump_get_str(dump_data_t *dump)
 {
     return (dump) ? dump->strbuf : NULL;
 }
 
-void dump_free(dump_data_t *dump)
+void _audio_dump_free(dump_data_t *dump)
 {
     if (dump) {
         if (dump->strbuf)
index a81c160..6d83d29 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
index 3e628c2..c7a3098 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include "tizen-audio-internal.h"
 
-/* audio latency */
-static const char* AUDIO_LATENCY_LOW  = "low";
-static const char* AUDIO_LATENCY_MID  = "mid";
-static const char* AUDIO_LATENCY_HIGH = "high";
-static const char* AUDIO_LATENCY_VOIP = "voip";
-
-audio_return_t audio_add_message_cb(void *audio_handle, message_cb callback, void *user_data)
-{
-    audio_return_t ret = AUDIO_RET_OK;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
-
-    /* NOTE: Management of several callbacks could be implemented.
-             But we do not care of it for now.*/
-    ret = _audio_comm_set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
-
-    return ret;
-}
-
-audio_return_t audio_remove_message_cb(void *audio_handle, message_cb callback)
-{
-    audio_return_t ret = AUDIO_RET_OK;
-
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
-
-    ret = _audio_comm_unset_message_callback((audio_hal_t *)audio_handle);
-
-    return ret;
-}
-
 audio_return_t audio_init(void **audio_handle)
 {
     audio_hal_t *ah;
@@ -63,31 +31,31 @@ audio_return_t audio_init(void **audio_handle)
     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
 
     if (!(ah = malloc(sizeof(audio_hal_t)))) {
-        AUDIO_LOG_ERROR("am malloc failed");
+        AUDIO_LOG_ERROR("failed to malloc()");
         return AUDIO_ERR_RESOURCE;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_device_init(ah)))) {
-        AUDIO_LOG_ERROR("device init failed");
+    if ((ret = _audio_volume_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_volume_init(), ret(0x%x)", ret);
         goto error_exit;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_volume_init(ah)))) {
-        AUDIO_LOG_ERROR("stream init failed");
+    if ((ret = _audio_routing_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_routing_init(), ret(0x%x)", ret);
         goto error_exit;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_ucm_init(ah)))) {
-        AUDIO_LOG_ERROR("ucm init failed");
+    if ((ret = _audio_stream_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_stream_init(), ret(0x%x)", ret);
         goto error_exit;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_util_init(ah)))) {
-        AUDIO_LOG_ERROR("mixer init failed");
+    if ((ret = _audio_pcm_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_pcm_init(), ret(0x%x)", ret);
         goto error_exit;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_modem_init(ah)))) {
-        AUDIO_LOG_ERROR("modem init failed");
+    if ((ret = _audio_modem_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_modem_init(), ret(0x%x)", ret);
         goto error_exit;
     }
-    if (AUDIO_IS_ERROR((ret = _audio_comm_init(ah)))) {
-        AUDIO_LOG_ERROR("comm init failed");
+    if ((ret = _audio_comm_init(ah))) {
+        AUDIO_LOG_ERROR("failed to _audio_comm_init(), ret(0x%x)", ret);
         goto error_exit;
     }
 
@@ -107,181 +75,14 @@ audio_return_t audio_deinit(void *audio_handle)
 
     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
 
-    _audio_device_deinit(ah);
     _audio_volume_deinit(ah);
-    _audio_ucm_deinit(ah);
-    _audio_util_deinit(ah);
+    _audio_routing_deinit(ah);
+    _audio_stream_deinit(ah);
+    _audio_pcm_deinit(ah);
     _audio_modem_deinit(ah);
     _audio_comm_deinit(ah);
     free(ah);
     ah = NULL;
 
     return AUDIO_RET_OK;
-}
-
-/* Latency msec */
-static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC  = 20;
-static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC   = 25;
-static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC   = 50;
-static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC  = 75;
-static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
-static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC  = 20;
-
-static const uint32_t g_size_table[] = {
-    [AUDIO_SAMPLE_U8]        = 1,
-    [AUDIO_SAMPLE_ULAW]      = 1,
-    [AUDIO_SAMPLE_ALAW]      = 1,
-    [AUDIO_SAMPLE_S16LE]     = 2,
-    [AUDIO_SAMPLE_S16BE]     = 2,
-    [AUDIO_SAMPLE_FLOAT32LE] = 4,
-    [AUDIO_SAMPLE_FLOAT32BE] = 4,
-    [AUDIO_SAMPLE_S32LE]     = 4,
-    [AUDIO_SAMPLE_S32BE]     = 4,
-    [AUDIO_SAMPLE_S24LE]     = 3,
-    [AUDIO_SAMPLE_S24BE]     = 3,
-    [AUDIO_SAMPLE_S24_32LE]  = 4,
-    [AUDIO_SAMPLE_S24_32BE]  = 4
-};
-
-int _sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
-{
-    if ((rate <= 0                 ||
-        rate > (48000U*4U)         ||
-        channels <= 0              ||
-        channels > 32U             ||
-        format >= AUDIO_SAMPLE_MAX ||
-        format <  AUDIO_SAMPLE_U8))
-        return 0;
-
-    AUDIO_LOG_ERROR("hal-latency - _sample_spec_valid() -> return true");
-
-    return 1;
-}
-
-uint32_t _audio_usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
-{
-    uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
-    AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
-    return ret;
-}
-
-uint32_t _audio_sample_size(audio_sample_format_t format)
-{
-    return g_size_table[format];
-}
-audio_return_t audio_get_buffer_attr(void                  *audio_handle,
-                                     uint32_t              direction,
-                                     const char            *latency,
-                                     uint32_t              samplerate,
-                                     audio_sample_format_t format,
-                                     uint32_t              channels,
-                                     uint32_t              *maxlength,
-                                     uint32_t              *tlength,
-                                     uint32_t              *prebuf,
-                                     uint32_t              *minreq,
-                                     uint32_t              *fragsize)
-{
-    AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
-
-    AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
-
-    uint32_t period_time        = 0,
-             sample_per_period  = 0;
-
-    if (_sample_spec_valid(samplerate, format, channels) == 0) {
-        return AUDIO_ERR_PARAMETER;
-    }
-
-    if (direction == AUDIO_DIRECTION_IN) {
-        if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
-            period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = -1;
-            *maxlength         = -1;
-            *fragsize          = sample_per_period * _audio_sample_size(format);
-        } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
-            period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = -1;
-            *maxlength         = -1;
-            *fragsize          = sample_per_period * _audio_sample_size(format);
-        } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
-            period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = -1;
-            *maxlength         = -1;
-            *fragsize          = sample_per_period * _audio_sample_size(format);
-        } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
-            period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = -1;
-            *maxlength         = -1;
-            *fragsize          = sample_per_period * _audio_sample_size(format);
-        } else {
-            AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
-            return AUDIO_ERR_UNDEFINED;
-        }
-    } else {  /* AUDIO_DIRECTION_OUT */
-        if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
-            period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = (samplerate / 10) * _audio_sample_size(format) * channels;  /* 100ms */
-            *maxlength         = -1;
-            *fragsize          = 0;
-        } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
-            period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = (uint32_t) _audio_usec_to_bytes(200000, samplerate, format, channels);
-            *maxlength         = -1;
-            *fragsize          = -1;
-        } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
-            period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = -1;
-            *tlength           = (uint32_t) _audio_usec_to_bytes(400000, samplerate, format, channels);
-            *maxlength         = -1;
-            *fragsize          = -1;
-        } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
-            AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
-            period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
-            sample_per_period  = (samplerate * period_time) / 1000;
-            *prebuf            = 0;
-            *minreq            = _audio_usec_to_bytes(20000, samplerate, format, channels);
-            *tlength           = _audio_usec_to_bytes(100000, samplerate, format, channels);
-            *maxlength         = -1;
-            *fragsize          = 0;
-        } else {
-            AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
-            return AUDIO_ERR_UNDEFINED;
-        }
-    }
-
-    AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
-    return AUDIO_RET_OK;
-}
+}
\ No newline at end of file
index fcaf018..0bfac13 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * audio-hal
  *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
 #include <stdint.h>
 
 /* Error code */
-#define AUDIO_IS_ERROR(ret)             (ret < 0)
 typedef enum audio_return {
     AUDIO_RET_OK                        = 0,
     AUDIO_ERR_UNDEFINED                 = (int32_t)0x80001000,
@@ -90,10 +89,9 @@ typedef struct audio_interface {
     audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option);
     /* Stream */
     audio_return_t (*notify_stream_connection_changed)(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected);
-    /* Buffer attribute */
     audio_return_t (*get_buffer_attr)(void *audio_handle, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels,
                                       uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
-    /* PCM device */
+    /* PCM */
     audio_return_t (*pcm_open)(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
     audio_return_t (*pcm_start)(void *audio_handle, void *pcm_handle);
     audio_return_t (*pcm_stop)(void *audio_handle, void *pcm_handle);