diff --git a/audio/Android.mk b/audio/Android.mk index 0a54b69..20b50f7 100755 --- a/audio/Android.mk +++ b/audio/Android.mk @@ -14,25 +14,16 @@ $(warning $(TARGET_BOARD_PLATFORM)) -LOCAL_PATH := $(call my-dir) +MY_LOCAL_PATH := $(call my-dir) -ifneq ($(filter astar,$(TARGET_BOARD_PLATFORM)),) - include $(call all-named-subdir-makefiles,astar) -else -ifneq ($(filter kylin,$(TARGET_BOARD_PLATFORM)),) - include $(call all-named-subdir-makefiles,kylin) -else -ifneq ($(filter octopus,$(TARGET_BOARD_PLATFORM)),) - include $(call all-named-subdir-makefiles,octopus) -else -ifneq ($(filter tulip,$(TARGET_BOARD_PLATFORM)),) - include $(call all-named-subdir-makefiles,tulip) -else - $(warning $(TARGET_BOARD_PLATFORM)) -endif -endif -endif -endif +# audio effects lib +include $(MY_LOCAL_PATH)/effects/Android.mk + +# audio primary module +include $(MY_LOCAL_PATH)/$(TARGET_BOARD_PLATFORM)/Android.mk + +# audio a2dp module +include $(MY_LOCAL_PATH)/audio_a2dp_hw/Android.mk include $(CLEAR_VARS) diff --git a/audio/astar/audio_policy.conf b/audio/astar/audio_policy.conf index c1ce9e7..f67c58f 100755 --- a/audio/astar/audio_policy.conf +++ b/audio/astar/audio_policy.conf @@ -39,8 +39,8 @@ audio_hw_modules { } inputs { primary { - sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000 - channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_VOICE_UPLINK|AUDIO_CHANNEL_IN_VOICE_DNLINK|AUDIO_CHANNEL_IN_VOICE + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_IN_STEREO formats AUDIO_FORMAT_PCM_16_BIT devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_AF|AUDIO_DEVICE_IN_VOICE_CALL|AUDIO_DEVICE_IN_FM } diff --git a/audio/audio_a2dp_hw/Android.mk b/audio/audio_a2dp_hw/Android.mk new file mode 100755 index 0000000..ca6685b --- /dev/null +++ b/audio/audio_a2dp_hw/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/../effects/audio_3d_surround + +LOCAL_SRC_FILES := \ + audio_a2dp_hw.c \ + ../effects/audio_3d_surround/audio_3d_surround.c + + +LOCAL_CFLAGS += -std=c99 $(bdroid_CFLAGS) + +LOCAL_MODULE := audio.a2dp.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_STATIC_LIBRARIES += libaw_audio3dsur + +LOCAL_SHARED_LIBRARIES := libcutils liblog + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/audio/audio_a2dp_hw/audio_a2dp_hw.c b/audio/audio_a2dp_hw/audio_a2dp_hw.c new file mode 100755 index 0000000..1f7e1b6 --- /dev/null +++ b/audio/audio_a2dp_hw/audio_a2dp_hw.c @@ -0,0 +1,1464 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: audio_a2dp_hw.c + * + * Description: Implements hal for bluedroid a2dp audio device + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "audio_a2dp_hw.h" +#include "bt_utils.h" +#include "audio_3d_surround.h" +#define USE_3D_SURROUND 1 + +#define LOG_TAG "bt_a2dp_hw" +#include "log.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define CTRL_CHAN_RETRY_COUNT 3 +#define USEC_PER_SEC 1000000L + +#define CASE_RETURN_STR(const) case const: return #const; + +#define FNLOG() LOG_VERBOSE("%s", __FUNCTION__); +#define DEBUG(fmt, ...) LOG_VERBOSE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define INFO(fmt, ...) LOG_INFO("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define ERROR(fmt, ...) LOG_ERROR("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) + +#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);} + +/***************************************************************************** +** Local type definitions +******************************************************************************/ + +typedef enum { + AUDIO_A2DP_STATE_STARTING, + AUDIO_A2DP_STATE_STARTED, + AUDIO_A2DP_STATE_STOPPING, + AUDIO_A2DP_STATE_STOPPED, + AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */ + AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */ +} a2dp_state_t; + +struct a2dp_stream_in; +struct a2dp_stream_out; + +#if USE_3D_SURROUND +struct audio_3d_surround sur; +#endif + +struct a2dp_audio_device { + struct audio_hw_device device; + struct a2dp_stream_in *input; + struct a2dp_stream_out *output; +}; + +struct a2dp_config { + uint32_t rate; + uint32_t channel_flags; + int format; +}; + +/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */ + +struct a2dp_stream_common { + pthread_mutex_t lock; + int ctrl_fd; + int audio_fd; + size_t buffer_sz; + struct a2dp_config cfg; + a2dp_state_t state; +}; + +struct a2dp_stream_out { + struct audio_stream_out stream; + struct a2dp_stream_common common; + uint64_t frames_presented; // frames written, never reset + uint64_t frames_rendered; // frames written, reset on standby + +#if USE_3D_SURROUND + audio_devices_t devices; +#endif + +}; + +struct a2dp_stream_in { + struct audio_stream_in stream; + struct a2dp_stream_common common; +}; + +/***************************************************************************** +** Static variables +******************************************************************************/ + +/***************************************************************************** +** Static functions +******************************************************************************/ + +static size_t out_get_buffer_size(const struct audio_stream *stream); + +/***************************************************************************** +** Externs +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + +/***************************************************************************** +** Miscellaneous helper functions +******************************************************************************/ + +static const char* dump_a2dp_ctrl_event(char event) +{ + switch(event) + { + CASE_RETURN_STR(A2DP_CTRL_CMD_NONE) + CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY) + CASE_RETURN_STR(A2DP_CTRL_CMD_START) + CASE_RETURN_STR(A2DP_CTRL_CMD_STOP) + CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND) + default: + return "UNKNOWN MSG ID"; + } +} + +/* logs timestamp with microsec precision + pprev is optional in case a dedicated diff is required */ +static void ts_log(char *tag, int val, struct timespec *pprev_opt) +{ + struct timespec now; + static struct timespec prev = {0,0}; + unsigned long long now_us; + unsigned long long diff_us; + UNUSED(tag); + UNUSED(val); + + clock_gettime(CLOCK_MONOTONIC, &now); + + now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000; + + if (pprev_opt) + { + diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; + *pprev_opt = now; + DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val); + } + else + { + diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; + prev = now; + DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val); + } +} + +static int calc_audiotime(struct a2dp_config cfg, int bytes) +{ + int chan_count = popcount(cfg.channel_flags); + + ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT, + "unsupported sample sz", cfg.format); + + return bytes*(1000000/(chan_count*2))/cfg.rate; +} + +/***************************************************************************** +** +** bluedroid stack adaptation +** +*****************************************************************************/ + +static int skt_connect(char *path, size_t buffer_sz) +{ + int ret; + int skt_fd; + struct sockaddr_un remote; + int len; + + INFO("connect to %s (sz %zu)", path, buffer_sz); + + skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + + if(socket_local_client_connect(skt_fd, path, + ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0) + { + ERROR("failed to connect (%s)", strerror(errno)); + close(skt_fd); + return -1; + } + + len = buffer_sz; + ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len)); + + /* only issue warning if failed */ + if (ret < 0) + ERROR("setsockopt failed (%s)", strerror(errno)); + + ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len)); + + /* only issue warning if failed */ + if (ret < 0) + ERROR("setsockopt failed (%s)", strerror(errno)); + + INFO("connected to stack fd = %d", skt_fd); + + return skt_fd; +} + +static int skt_read(int fd, void *p, size_t len) +{ + int read; + struct pollfd pfd; + struct timespec ts; + + FNLOG(); + + ts_log("skt_read recv", len, NULL); + + if ((read = recv(fd, p, len, MSG_NOSIGNAL)) == -1) + { + ERROR("write failed with errno=%d\n", errno); + return -1; + } + + return read; +} + +static int skt_write(int fd, const void *p, size_t len) +{ + int sent; + struct pollfd pfd; + + FNLOG(); + + pfd.fd = fd; + pfd.events = POLLOUT; + + /* poll for 500 ms */ + + /* send time out */ + if (poll(&pfd, 1, 500) == 0) + return 0; + + ts_log("skt_write", len, NULL); + + if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1) + { + ERROR("write failed with errno=%d\n", errno); + return -1; + } + + return sent; +} + +static int skt_disconnect(int fd) +{ + INFO("fd %d", fd); + + if (fd != AUDIO_SKT_DISCONNECTED) + { + shutdown(fd, SHUT_RDWR); + close(fd); + } + return 0; +} + + + +/***************************************************************************** +** +** AUDIO CONTROL PATH +** +*****************************************************************************/ + +static int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length) +{ + int ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL); + if (ret < 0) + { + ERROR("ack failed (%s)", strerror(errno)); + if (errno == EINTR) + { + /* retry again */ + ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL); + if (ret < 0) + { + ERROR("ack failed (%s)", strerror(errno)); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + } + } + else + { + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + + } + } + return ret; +} + +static int a2dp_command(struct a2dp_stream_common *common, char cmd) +{ + char ack; + + DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd)); + + /* send command */ + if (send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1) + { + ERROR("cmd failed (%s)", strerror(errno)); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + } + + /* wait for ack byte */ + if (a2dp_ctrl_receive(common, &ack, 1) < 0) + return -1; + + DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack); + + if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) + return ack; + if (ack != A2DP_CTRL_ACK_SUCCESS) + return -1; + + return 0; +} + +static int check_a2dp_ready(struct a2dp_stream_common *common) +{ + if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0) + { + ERROR("check a2dp ready failed"); + return -1; + } + return 0; +} + +static int a2dp_read_audio_config(struct a2dp_stream_common *common) +{ + char cmd = A2DP_CTRL_GET_AUDIO_CONFIG; + uint32_t sample_rate; + uint8_t channel_count; + + if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0) + { + ERROR("check a2dp ready failed"); + return -1; + } + + if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0) + return -1; + if (a2dp_ctrl_receive(common, &channel_count, 1) < 0) + return -1; + + common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO); + common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; + common->cfg.rate = sample_rate; + + INFO("got config %d %d", common->cfg.format, common->cfg.rate); + + return 0; +} + +static void a2dp_open_ctrl_path(struct a2dp_stream_common *common) +{ + int i; + + /* retry logic to catch any timing variations on control channel */ + for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++) + { + /* connect control channel if not already connected */ + if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0) + { + /* success, now check if stack is ready */ + if (check_a2dp_ready(common) == 0) + break; + + ERROR("error : a2dp not ready, wait 250 ms and retry"); + usleep(250000); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + } + + /* ctrl channel not ready, wait a bit */ + usleep(250000); + } +} + +/***************************************************************************** +** +** AUDIO DATA PATH +** +*****************************************************************************/ + +static void a2dp_stream_common_init(struct a2dp_stream_common *common) +{ + pthread_mutexattr_t lock_attr; + + FNLOG(); + + pthread_mutexattr_init(&lock_attr); + pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&common->lock, &lock_attr); + + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + common->audio_fd = AUDIO_SKT_DISCONNECTED; + common->state = AUDIO_A2DP_STATE_STOPPED; + + /* manages max capacity of socket pipe */ + common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; +} + +static int start_audio_datapath(struct a2dp_stream_common *common) +{ + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) { + INFO("%s AUDIO_SKT_DISCONNECTED", __func__); + return -1; + } + + int oldstate = common->state; + common->state = AUDIO_A2DP_STATE_STARTING; + + int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START); + if (a2dp_status < 0) + { + ERROR("%s Audiopath start failed (status %d)", __func__, a2dp_status); + + common->state = oldstate; + return -1; + } + else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE) + { + ERROR("%s Audiopath start failed - in call, move to suspended", __func__); + common->state = oldstate; + return -1; + } + + /* connect socket if not yet connected */ + if (common->audio_fd == AUDIO_SKT_DISCONNECTED) + { + common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz); + if (common->audio_fd < 0) + { + common->state = oldstate; + return -1; + } + + common->state = AUDIO_A2DP_STATE_STARTED; + } + + return 0; +} + +static int stop_audio_datapath(struct a2dp_stream_common *common) +{ + int oldstate = common->state; + + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) + return -1; + + /* prevent any stray output writes from autostarting the stream + while stopping audiopath */ + common->state = AUDIO_A2DP_STATE_STOPPING; + + if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0) + { + ERROR("audiopath stop failed"); + common->state = oldstate; + return -1; + } + + common->state = AUDIO_A2DP_STATE_STOPPED; + + /* disconnect audio path */ + skt_disconnect(common->audio_fd); + common->audio_fd = AUDIO_SKT_DISCONNECTED; + + return 0; +} + +static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby) +{ + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) + return -1; + + if (common->state == AUDIO_A2DP_STATE_STOPPING) + return -1; + + if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0) + return -1; + + if (standby) + common->state = AUDIO_A2DP_STATE_STANDBY; + else + common->state = AUDIO_A2DP_STATE_SUSPENDED; + + /* disconnect audio path */ + skt_disconnect(common->audio_fd); + + common->audio_fd = AUDIO_SKT_DISCONNECTED; + + return 0; +} + + +/***************************************************************************** +** +** audio output callbacks +** +*****************************************************************************/ + +static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, + size_t bytes) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + int sent; + + DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd); + + pthread_mutex_lock(&out->common.lock); + + if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED) + { + DEBUG("stream suspended"); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + + /* only allow autostarting if we are in stopped or standby */ + if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) || + (out->common.state == AUDIO_A2DP_STATE_STANDBY)) + { + if (start_audio_datapath(&out->common) < 0) + { + /* emulate time this write represents to avoid very fast write + failures during transition periods or remote suspend */ + + int us_delay = calc_audiotime(out->common.cfg, bytes); + + DEBUG("emulate a2dp write delay (%d us)", us_delay); + + usleep(us_delay); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + } + else if (out->common.state != AUDIO_A2DP_STATE_STARTED) + { + ERROR("stream not in stopped or standby"); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + + pthread_mutex_unlock(&out->common.lock); +#if USE_3D_SURROUND + if (sur_enable(&sur)) { + if (sur_prepare(&sur, out->devices, 1, out->common.cfg.rate, + 2, bytes / audio_stream_out_frame_size(stream))) { + sur_process(&sur, (short*)buffer, bytes / audio_stream_out_frame_size(stream), 2); + } + } +#endif + sent = skt_write(out->common.audio_fd, buffer, bytes); + + if (sent == -1) { + skt_disconnect(out->common.audio_fd); + out->common.audio_fd = AUDIO_SKT_DISCONNECTED; + if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED) + out->common.state = AUDIO_A2DP_STATE_STOPPED; + else + ERROR("write failed : stream suspended, avoid resetting state"); + } else { + const size_t frames = bytes / audio_stream_out_frame_size(stream); + out->frames_rendered += frames; + out->frames_presented += frames; + } + + DEBUG("wrote %d bytes out of %zu bytes", sent, bytes); + return sent; +} + + +static uint32_t out_get_sample_rate(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("rate %" PRIu32,out->common.cfg.rate); + + return out->common.cfg.rate; +} + +static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("out_set_sample_rate : %" PRIu32, rate); + + if (rate != AUDIO_STREAM_DEFAULT_RATE) + { + ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE); + return -1; + } + + out->common.cfg.rate = rate; + + return 0; +} + +static size_t out_get_buffer_size(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("buffer_size : %zu", out->common.buffer_sz); + + return out->common.buffer_sz; +} + +static uint32_t out_get_channels(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags); + + return out->common.cfg.channel_flags; +} + +static audio_format_t out_get_format(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + DEBUG("format 0x%x", out->common.cfg.format); + return out->common.cfg.format; +} + +static int out_set_format(struct audio_stream *stream, audio_format_t format) +{ + UNUSED(format); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + DEBUG("setting format not yet supported (0x%x)", format); + return -ENOSYS; +} + +static int out_standby(struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + int retVal = 0; + + FNLOG(); + + pthread_mutex_lock(&out->common.lock); + // Do nothing in SUSPENDED state. + if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED) + retVal = suspend_audio_datapath(&out->common, true); + out->frames_rendered = 0; // rendered is reset, presented is not + pthread_mutex_unlock (&out->common.lock); + + return retVal; +} + +static int out_dump(const struct audio_stream *stream, int fd) +{ + UNUSED(fd); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + FNLOG(); + return 0; +} + +static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + struct str_parms *parms; + char keyval[16]; + int retval; + int status = 0; + + INFO("state %d", out->common.state); + + parms = str_parms_create_str(kvpairs); + + /* dump params */ + str_parms_dump(parms); + + retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval)); + + if (retval >= 0) + { + if (strcmp(keyval, "true") == 0) + { + DEBUG("stream closing, disallow any writes"); + pthread_mutex_lock(&out->common.lock); + out->common.state = AUDIO_A2DP_STATE_STOPPING; + pthread_mutex_unlock(&out->common.lock); + } + } + + retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval)); + + if (retval >= 0) + { + pthread_mutex_lock(&out->common.lock); + if (strcmp(keyval, "true") == 0) + { + if (out->common.state == AUDIO_A2DP_STATE_STARTED) + status = suspend_audio_datapath(&out->common, false); + } + else + { + /* Do not start the streaming automatically. If the phone was streaming + * prior to being suspended, the next out_write shall trigger the + * AVDTP start procedure */ + if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED) + out->common.state = AUDIO_A2DP_STATE_STANDBY; + /* Irrespective of the state, return 0 */ + } + pthread_mutex_unlock(&out->common.lock); + } + + str_parms_destroy(parms); + + return status; +} + +static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +{ + UNUSED(keys); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + + /* add populating param here */ + + return strdup(""); +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + int latency_us; + + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + + latency_us = ((out->common.buffer_sz * 1000 ) / + audio_stream_out_frame_size(&out->stream) / + out->common.cfg.rate) * 1000; + + + return (latency_us / 1000) + 200; +} + +static int out_set_volume(struct audio_stream_out *stream, float left, + float right) +{ + UNUSED(stream); + UNUSED(left); + UNUSED(right); + + FNLOG(); + + /* volume controlled in audioflinger mixer (digital) */ + + return -ENOSYS; +} + +static int out_get_presentation_position(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + if (stream == NULL || frames == NULL || timestamp == NULL) + return -EINVAL; + + int ret = -EWOULDBLOCK; + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_presented >= latency_frames) { + *frames = out->frames_presented - latency_frames; + clock_gettime(CLOCK_MONOTONIC, timestamp); // could also be associated with out_write(). + ret = 0; + } + pthread_mutex_unlock(&out->common.lock); + return ret; +} + +static int out_get_render_position(const struct audio_stream_out *stream, + uint32_t *dsp_frames) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + if (stream == NULL || dsp_frames == NULL) + return -EINVAL; + + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_rendered >= latency_frames) { + *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames); + } else { + *dsp_frames = 0; + } + pthread_mutex_unlock(&out->common.lock); + return 0; +} + +static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +/* + * AUDIO INPUT STREAM + */ + +static uint32_t in_get_sample_rate(const struct audio_stream *stream) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + return in->common.cfg.rate; +} + +static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + + if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate) + return 0; + else + return -1; +} + +static size_t in_get_buffer_size(const struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return 320; +} + +static uint32_t in_get_channels(const struct audio_stream *stream) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + return in->common.cfg.channel_flags; +} + +static audio_format_t in_get_format(const struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return AUDIO_FORMAT_PCM_16_BIT; +} + +static int in_set_format(struct audio_stream *stream, audio_format_t format) +{ + UNUSED(stream); + UNUSED(format); + + FNLOG(); + if (format == AUDIO_FORMAT_PCM_16_BIT) + return 0; + else + return -1; +} + +static int in_standby(struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return 0; +} + +static int in_dump(const struct audio_stream *stream, int fd) +{ + UNUSED(stream); + UNUSED(fd); + + FNLOG(); + return 0; +} + +static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + UNUSED(stream); + UNUSED(kvpairs); + + FNLOG(); + return 0; +} + +static char * in_get_parameters(const struct audio_stream *stream, + const char *keys) +{ + UNUSED(stream); + UNUSED(keys); + + FNLOG(); + return strdup(""); +} + +static int in_set_gain(struct audio_stream_in *stream, float gain) +{ + UNUSED(stream); + UNUSED(gain); + + FNLOG(); + return 0; +} + +static ssize_t in_read(struct audio_stream_in *stream, void* buffer, + size_t bytes) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + int read; + + DEBUG("read %zu bytes, state: %d", bytes, in->common.state); + + if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED) + { + DEBUG("stream suspended"); + return -1; + } + + /* only allow autostarting if we are in stopped or standby */ + if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) || + (in->common.state == AUDIO_A2DP_STATE_STANDBY)) + { + pthread_mutex_lock(&in->common.lock); + + if (start_audio_datapath(&in->common) < 0) + { + /* emulate time this write represents to avoid very fast write + failures during transition periods or remote suspend */ + + int us_delay = calc_audiotime(in->common.cfg, bytes); + + DEBUG("emulate a2dp read delay (%d us)", us_delay); + + usleep(us_delay); + pthread_mutex_unlock(&in->common.lock); + return -1; + } + + pthread_mutex_unlock(&in->common.lock); + } + else if (in->common.state != AUDIO_A2DP_STATE_STARTED) + { + ERROR("stream not in stopped or standby"); + return -1; + } + + read = skt_read(in->common.audio_fd, buffer, bytes); + + if (read == -1) + { + skt_disconnect(in->common.audio_fd); + in->common.audio_fd = AUDIO_SKT_DISCONNECTED; + in->common.state = AUDIO_A2DP_STATE_STOPPED; + } else if (read == 0) { + DEBUG("read time out - return zeros"); + memset(buffer, 0, bytes); + read = bytes; + } + + DEBUG("read %d bytes out of %zu bytes", read, bytes); + return read; +} + +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +{ + UNUSED(stream); + + FNLOG(); + return 0; +} + +static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + + return 0; +} + +static int adev_open_output_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address) + +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out; + int ret = 0; + int i; + UNUSED(address); + UNUSED(handle); + +#if USE_3D_SURROUND + //UNUSED(devices); +#else + UNUSED(devices); +#endif + + UNUSED(flags); + + INFO("opening output"); + + out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out)); + + if (!out) + return -ENOMEM; + + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + out->stream.get_presentation_position = out_get_presentation_position; + + + /* initialize a2dp specifics */ + a2dp_stream_common_init(&out->common); + + out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG; + out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; + out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE; + +#if USE_3D_SURROUND + out->devices = devices; +#endif + + /* set output config values */ + if (config) + { + config->format = out_get_format((const struct audio_stream *)&out->stream); + config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream); + config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream); + } + *stream_out = &out->stream; + a2dp_dev->output = out; + + a2dp_open_ctrl_path(&out->common); + if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED) + { + ERROR("ctrl socket failed to connect (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + DEBUG("success"); + /* Delay to ensure Headset is in proper state when START is initiated + from DUT immediately after the connection due to ongoing music playback. */ + usleep(250000); + return 0; + +err_open: + free(out); + *stream_out = NULL; + a2dp_dev->output = NULL; + ERROR("failed"); + return ret; +} + +static void adev_close_output_stream(struct audio_hw_device *dev, + struct audio_stream_out *stream) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + INFO("closing output (state %d)", out->common.state); + + pthread_mutex_lock(&out->common.lock); + if ((out->common.state == AUDIO_A2DP_STATE_STARTED) || (out->common.state == AUDIO_A2DP_STATE_STOPPING)) + stop_audio_datapath(&out->common); + + skt_disconnect(out->common.ctrl_fd); + free(stream); + a2dp_dev->output = NULL; + pthread_mutex_unlock(&out->common.lock); + + DEBUG("done"); +} + +static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out = a2dp_dev->output; + int retval = 0; + + if (out == NULL) + return retval; + + INFO("state %d", out->common.state); + + retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs); + + return retval; +} + +static char * adev_get_parameters(const struct audio_hw_device *dev, + const char *keys) +{ + struct str_parms *parms; + UNUSED(dev); + + FNLOG(); + + parms = str_parms_create_str(keys); + + str_parms_dump(parms); + + str_parms_destroy(parms); + + return strdup(""); +} + +static int adev_init_check(const struct audio_hw_device *dev) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev; + + FNLOG(); + + return 0; +} + +static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +{ + UNUSED(dev); + UNUSED(volume); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +{ + UNUSED(dev); + UNUSED(volume); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_set_mode(struct audio_hw_device *dev, int mode) +{ + UNUSED(dev); + UNUSED(mode); + + FNLOG(); + + return 0; +} + +static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) +{ + UNUSED(dev); + UNUSED(state); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) +{ + UNUSED(dev); + UNUSED(state); + + FNLOG(); + + return -ENOSYS; +} + +static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, + const struct audio_config *config) +{ + UNUSED(dev); + UNUSED(config); + + FNLOG(); + + return 320; +} + +static int adev_open_input_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags, + const char *address, + audio_source_t source) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_in *in; + int ret; + UNUSED(address); + UNUSED(config); + UNUSED(devices); + UNUSED(flags); + UNUSED(handle); + UNUSED(source); + + FNLOG(); + + in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in)); + + if (!in) + return -ENOMEM; + + in->stream.common.get_sample_rate = in_get_sample_rate; + in->stream.common.set_sample_rate = in_set_sample_rate; + in->stream.common.get_buffer_size = in_get_buffer_size; + in->stream.common.get_channels = in_get_channels; + in->stream.common.get_format = in_get_format; + in->stream.common.set_format = in_set_format; + in->stream.common.standby = in_standby; + in->stream.common.dump = in_dump; + in->stream.common.set_parameters = in_set_parameters; + in->stream.common.get_parameters = in_get_parameters; + in->stream.common.add_audio_effect = in_add_audio_effect; + in->stream.common.remove_audio_effect = in_remove_audio_effect; + in->stream.set_gain = in_set_gain; + in->stream.read = in_read; + in->stream.get_input_frames_lost = in_get_input_frames_lost; + + /* initialize a2dp specifics */ + a2dp_stream_common_init(&in->common); + + *stream_in = &in->stream; + a2dp_dev->input = in; + + a2dp_open_ctrl_path(&in->common); + if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED) + { + ERROR("ctrl socket failed to connect (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + if (a2dp_read_audio_config(&in->common) < 0) { + ERROR("a2dp_read_audio_config failed (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + DEBUG("success"); + return 0; + +err_open: + free(in); + *stream_in = NULL; + a2dp_dev->input = NULL; + ERROR("failed"); + return ret; +} + +static void adev_close_input_stream(struct audio_hw_device *dev, + struct audio_stream_in *stream) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream; + a2dp_state_t state = in->common.state; + + INFO("closing input (state %d)", state); + + if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING)) + stop_audio_datapath(&in->common); + + skt_disconnect(in->common.ctrl_fd); + free(stream); + a2dp_dev->input = NULL; + + DEBUG("done"); +} + +static int adev_dump(const audio_hw_device_t *device, int fd) +{ + UNUSED(device); + UNUSED(fd); + + FNLOG(); + + return 0; +} + +static int adev_close(hw_device_t *device) +{ + FNLOG(); + +#if 1 +#if USE_3D_SURROUND + sur_exit(&sur); +#endif +#endif + + free(device); + return 0; +} + +static int adev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct a2dp_audio_device *adev; + int ret; + + INFO(" adev_open in A2dp_hw module"); + FNLOG(); + + if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) + { + ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE); + return -EINVAL; + } + + adev = calloc(1, sizeof(struct a2dp_audio_device)); + + if (!adev) + return -ENOMEM; + + adev->device.common.tag = HARDWARE_DEVICE_TAG; + adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; + adev->device.common.module = (struct hw_module_t *) module; + adev->device.common.close = adev_close; + + adev->device.init_check = adev_init_check; + adev->device.set_voice_volume = adev_set_voice_volume; + adev->device.set_master_volume = adev_set_master_volume; + adev->device.set_mode = adev_set_mode; + adev->device.set_mic_mute = adev_set_mic_mute; + adev->device.get_mic_mute = adev_get_mic_mute; + adev->device.set_parameters = adev_set_parameters; + adev->device.get_parameters = adev_get_parameters; + adev->device.get_input_buffer_size = adev_get_input_buffer_size; + adev->device.open_output_stream = adev_open_output_stream; + adev->device.close_output_stream = adev_close_output_stream; + adev->device.open_input_stream = adev_open_input_stream; + adev->device.close_input_stream = adev_close_input_stream; + adev->device.dump = adev_dump; + + adev->output = NULL; + + + *device = &adev->device.common; + +#if 1 +#if USE_3D_SURROUND + sur_init(&sur, AUDIO_STREAM_DEFAULT_RATE, 2, AUDIO_STREAM_OUTPUT_BUFFER_SZ/4); +#endif +#endif + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = adev_open, +}; + +struct audio_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = AUDIO_HARDWARE_MODULE_ID, + .name = "A2DP Audio HW HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +}; diff --git a/audio/audio_a2dp_hw/audio_a2dp_hw.h b/audio/audio_a2dp_hw/audio_a2dp_hw.h new file mode 100755 index 0000000..1e9464c --- /dev/null +++ b/audio/audio_a2dp_hw/audio_a2dp_hw.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: audio_a2dp_hw.h + * + * Description: + * + *****************************************************************************/ + +#ifndef AUDIO_A2DP_HW_H +#define AUDIO_A2DP_HW_H + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define A2DP_AUDIO_HARDWARE_INTERFACE "audio.a2dp" +#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl" +#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data" + +#define AUDIO_STREAM_DEFAULT_RATE 44100 +#define AUDIO_STREAM_DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT +#define AUDIO_STREAM_DEFAULT_CHANNEL_FLAG AUDIO_CHANNEL_OUT_STEREO +#define AUDIO_STREAM_OUTPUT_BUFFER_SZ (20*512) +#define AUDIO_SKT_DISCONNECTED (-1) + +typedef enum { + A2DP_CTRL_CMD_NONE, + A2DP_CTRL_CMD_CHECK_READY, + A2DP_CTRL_CMD_START, + A2DP_CTRL_CMD_STOP, + A2DP_CTRL_CMD_SUSPEND, + A2DP_CTRL_GET_AUDIO_CONFIG, +} tA2DP_CTRL_CMD; + +typedef enum { + A2DP_CTRL_ACK_SUCCESS, + A2DP_CTRL_ACK_FAILURE, + A2DP_CTRL_ACK_INCALL_FAILURE /* Failure when in Call*/ +} tA2DP_CTRL_ACK; + + +/***************************************************************************** +** Type definitions for callback functions +******************************************************************************/ + +/***************************************************************************** +** Type definitions and return values +******************************************************************************/ + +/***************************************************************************** +** Extern variables and functions +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + + +/***************************************************************************** +** +** Function +** +** Description +** +** Returns +** +******************************************************************************/ + +#endif /* A2DP_AUDIO_HW_H */ + diff --git a/audio/audio_a2dp_hw/bt_utils.h b/audio/audio_a2dp_hw/bt_utils.h new file mode 100755 index 0000000..fa397f9 --- /dev/null +++ b/audio/audio_a2dp_hw/bt_utils.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ + +#ifndef BT_UTILS_H +#define BT_UTILS_H + +static const char BT_UTILS_MODULE[] = "bt_utils_module"; + +/******************************************************************************* +** Type definitions +********************************************************************************/ + +typedef enum { + TASK_HIGH_MEDIA = 0, + TASK_HIGH_GKI_TIMER, + TASK_HIGH_BTU, + TASK_HIGH_HCI_WORKER, + TASK_HIGH_USERIAL_READ, + TASK_UIPC_READ, + TASK_JAVA_ALARM, + TASK_HIGH_MAX +} tHIGH_PRIORITY_TASK; + +/******************************************************************************* +** Functions +********************************************************************************/ + +void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task); +void adjust_priority_a2dp(int start); +#define UNUSED(x) (void)(x) +#endif /* BT_UTILS_H */ diff --git a/audio/audio_a2dp_hw/log.h b/audio/audio_a2dp_hw/log.h new file mode 100755 index 0000000..a5de1cf --- /dev/null +++ b/audio/audio_a2dp_hw/log.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * 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. + * + ******************************************************************************/ + +#pragma once + +#include + +#define LOG_VERBOSE(...) ALOGV(__VA_ARGS__) +#define LOG_DEBUG(...) ALOGD(__VA_ARGS__) +#define LOG_INFO(...) ALOGI(__VA_ARGS__) +#define LOG_WARN(...) ALOGW(__VA_ARGS__) +#define LOG_ERROR(...) ALOGE(__VA_ARGS__) diff --git a/audio/effects/Android.mk b/audio/effects/Android.mk new file mode 100755 index 0000000..bbca55c --- /dev/null +++ b/audio/effects/Android.mk @@ -0,0 +1,18 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# 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. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/audio/effects/audio_3d_surround/Android.mk b/audio/effects/audio_3d_surround/Android.mk new file mode 100755 index 0000000..8ac5653 --- /dev/null +++ b/audio/effects/audio_3d_surround/Android.mk @@ -0,0 +1,34 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# 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. + +LOCAL_PATH := $(call my-dir) + +# libAwSurround.so +include $(CLEAR_VARS) +LOCAL_MODULE := libAwSurround +LOCAL_SRC_FILES := libAwSurround.so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := .so +LOCAL_MULTILIB := 32 +include $(BUILD_PREBUILT) + +# libaw_audio3dsur.a +include $(CLEAR_VARS) +LOCAL_SRC_FILES:= audio_3d_surround.c +LOCAL_MODULE:= libaw_audio3dsur +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) diff --git a/audio/effects/audio_3d_surround/audio_3d_surround.c b/audio/effects/audio_3d_surround/audio_3d_surround.c new file mode 100755 index 0000000..7e0da8e --- /dev/null +++ b/audio/effects/audio_3d_surround/audio_3d_surround.c @@ -0,0 +1,165 @@ +#define LOG_TAG "audio_3d_surround" +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include +#include + +#include "audio_3d_surround.h" + +/* debug 3d surround parameters*/ +//#define DEBUG_3D_SURROUND + +#define SUR_LIB_PATH "libAwSurround.so" + +#define SPACE_GAIN (0.50) +#define BASS_GAIN (0.33) +#define DEFINTION_GAIN (0.80) + +static int sur_load_lib(struct audio_3d_surround *sur) +{ + memset(sur, 0, sizeof(*sur)); + + /* open lib */ + sur->lib = dlopen(SUR_LIB_PATH, RTLD_LAZY); + if (NULL == sur->lib) { + ALOGW("%s,line:%d, can't open surround lib.", __func__, __LINE__); + return -1; + } + + /* get 3d srround function */ + sur->process_init = dlsym(sur->lib, "process_init"); + sur->process_exit = dlsym(sur->lib, "process_exit"); + sur->surround_pro_in_out = dlsym(sur->lib, "surround_pro_in_out"); + sur->set_bass = dlsym(sur->lib, "set_bass"); + sur->set_defintion = dlsym(sur->lib, "set_defintion"); + sur->set_space = dlsym(sur->lib, "set_space"); + + return 0; +} + +static int sur_init_parameter(struct audio_3d_surround *sur, int samp_rate, + int chn, int num_frame, int headp_use) +{ + ALOGV("%s: rate:%d, ch:%d, num_frame:%d, headp_use:%d", + __func__, samp_rate, chn, num_frame, headp_use); + sur->headp_use = headp_use; + sur->sur_handle = sur->process_init(sur->sur_handle, samp_rate, chn, num_frame, headp_use); + sur->set_bass(sur->sur_handle, BASS_GAIN); + sur->set_defintion(sur->sur_handle, DEFINTION_GAIN); + sur->set_space(sur->sur_handle, SPACE_GAIN); + + return 0; +} + +int sur_init(struct audio_3d_surround *sur, + int samp_rate, int chn, int num_frame) +{ + sur_load_lib(sur); + + sur_init_parameter(sur, samp_rate, chn, num_frame, 1); + + return 0; +} + + +bool sur_enable(struct audio_3d_surround *sur) +{ + int use; + char value[PROPERTY_VALUE_MAX]; + + if ( (NULL == sur->lib) || (NULL == sur->sur_handle) ) + return false; + + /* get the current switch state. Default value is close. */ + property_get("persist.sys.audio_3d_surround", value, "0"); + use = atoi(value); + + return use; +} + +static int sur_headp_use(int out_device, int dul_spk_use) +{ + int headp_dev; + int spk_dev; + + headp_dev = + AUDIO_DEVICE_OUT_WIRED_HEADSET | + AUDIO_DEVICE_OUT_WIRED_HEADPHONE | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; + + spk_dev = + (dul_spk_use ? AUDIO_DEVICE_OUT_SPEAKER : 0) | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; + + if (out_device & headp_dev) { + return 1; + } else if (out_device & spk_dev) { + return 0; + } + + return -1; +} + +bool sur_prepare(struct audio_3d_surround *sur, int out_device, int dul_spk_use, + int samp_rate, int chn, int num_frame) +{ + int headp_use; + + headp_use = sur_headp_use(out_device, dul_spk_use); + if (headp_use < 0) + return false; + + /* reinitialization */ + if (headp_use != sur->headp_use) { + sur->process_exit(sur->sur_handle); + sur_init_parameter(sur, samp_rate, chn, num_frame, headp_use); + } + + return true; +} + +int sur_process(struct audio_3d_surround *sur, short *buf, int frames, int channels) +{ + +#ifdef DEBUG_3D_SURROUND + int bass, defintion, space; + char value[PROPERTY_VALUE_MAX]; + + property_get("persist.sys.gain1", value, "33"); + bass = atoi(value); + + property_get("persist.sys.gain2", value, "80"); + defintion = atoi(value); + + property_get("persist.sys.gain3", value, "50"); + space = atoi(value); + + /*set parameter for debug */ + sur->set_bass(sur->sur_handle, bass/100.0); + sur->set_defintion(sur->sur_handle, defintion/100.0); + sur->set_space(sur->sur_handle, space/100.0); +#endif + + sur->surround_pro_in_out(sur->sur_handle, buf, buf, frames * channels); + + return 0; +} + +void sur_exit(struct audio_3d_surround *sur) +{ + if (sur->sur_handle != NULL) { + sur->process_exit(sur->sur_handle); + sur->sur_handle = NULL; + } + + if (sur->lib != NULL) { + dlclose(sur->lib); + sur->lib = NULL; + } +} + diff --git a/audio/effects/audio_3d_surround/audio_3d_surround.h b/audio/effects/audio_3d_surround/audio_3d_surround.h new file mode 100755 index 0000000..83411bd --- /dev/null +++ b/audio/effects/audio_3d_surround/audio_3d_surround.h @@ -0,0 +1,32 @@ +#ifndef __AUDIO_3D_SURROUND_H_ +#define __AUDIO_3D_SURROUND_H_ + +/* + * the 3d surround struct + * + */ +struct audio_3d_surround { + void *lib; + + void *sur_handle; + int headp_use; + void *(*process_init)(void *handle, int samp_rate, int chn, int num_frame, int headp_use); + void (*surround_pro_in_out)(void *handle, short *buf, short *new_sp, int data_num); + void (*process_exit)(void *handle); + void (*set_space)(void *handle, double space_gain); + void (*set_bass)(void *handle, double sub_gain); + void (*set_defintion)(void *handle, double defintion_gain); +}; + +/* + * interface for user + * + */ +int sur_init(struct audio_3d_surround *sur, int samp_rate, int chn, int num_frame); +bool sur_enable(struct audio_3d_surround *sur); +bool sur_prepare(struct audio_3d_surround *sur, int out_device, int dul_spk_use, + int samp_rate, int chn, int num_frame); +int sur_process(struct audio_3d_surround *sur, short *buf, int frames, int channels); +void sur_exit(struct audio_3d_surround *sur); + +#endif diff --git a/audio/effects/audio_3d_surround/libAwSurround.so b/audio/effects/audio_3d_surround/libAwSurround.so new file mode 100755 index 0000000..bcacd36 Binary files /dev/null and b/audio/effects/audio_3d_surround/libAwSurround.so differ diff --git a/audio/octopus/Android.mk b/audio/octopus/Android.mk index e4e6e48..fe243e2 100755 --- a/audio/octopus/Android.mk +++ b/audio/octopus/Android.mk @@ -18,10 +18,12 @@ include $(CLEAR_VARS) LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM) -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := audio_hw.c audio_iface.c sunxi_volume.c +LOCAL_STATIC_LIBRARIES += libaw_audio3dsur + #ifneq ($(SW_BOARD_HAVE_3G), true) #LOCAL_SRC_FILES += audio_ril_stub.c #else @@ -32,8 +34,9 @@ LOCAL_C_INCLUDES += \ external/tinyalsa/include \ system/media/audio_utils/include \ system/media/audio_effects/include \ + $(LOCAL_PATH)/../effects/audio_3d_surround \ system/media/audio_route/include - + LOCAL_SHARED_LIBRARIES += liblog libcutils libtinyalsa libaudioutils libdl libcodec_audio libril_audio libaudioroute LOCAL_MODULE_TAGS := optional diff --git a/audio/octopus/audio_hw.c b/audio/octopus/audio_hw.c index 9da68d4..5648dc1 100755 --- a/audio/octopus/audio_hw.c +++ b/audio/octopus/audio_hw.c @@ -41,8 +41,8 @@ #include "audio_iface.h" #include "volume.h" - -#include // for property_get +#include "audio_3d_surround.h" +#define USE_3D_SURROUND 1 #define F_LOG ALOGV("%s, line: %d", __FUNCTION__, __LINE__); @@ -107,6 +107,7 @@ static bool NO_EARPIECE = 1; static bool last_call_path_is_bt = 0; static bool dmic_used = 0; +static bool spk_dul_used = 1; static bool last_communication_is_bt = 0; /*VOLUME CTL*/ @@ -326,6 +327,10 @@ struct sunxi_audio_device { struct volume_array *vol_array; }; +#if USE_3D_SURROUND +struct audio_3d_surround sur; +#endif + struct sunxi_stream_out { struct audio_stream_out stream; @@ -1736,6 +1741,15 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, memset(buf, 0, out_frames * frame_size); //mute } +#if USE_3D_SURROUND + if (sur_enable(&sur)) { + if (sur_prepare(&sur, adev->out_device, spk_dul_used, out->config.rate, + out->config.channels, out_frames)) { + sur_process(&sur, (short*)buf, out_frames, out->config.channels); + } + } +#endif + ret = pcm_write(out->pcm, (void *)buf, out_frames * frame_size); if(ret!=0) { @@ -2973,7 +2987,9 @@ static int adev_close(hw_device_t *device) audio_route_free(adev->ar); free(adev->vol_array); free(device); - +#if USE_3D_SURROUND + sur_exit(&sur); +#endif return 0; } @@ -3005,6 +3021,17 @@ static int case_init(void) }else{ dmic_used = false; } + + ret = property_get("ro.spk_dul.used", prop_value, "0"); + if (ret <= 0) { + ALOGE("wrn: ro.spk_dul.used"); + } + if (!strcmp(prop_value, "true")) { + spk_dul_used = true; + } else { + spk_dul_used = false; + } + ret = property_get("ro.sw.audio.codec_plan_name", device_name, "0"); if(ret <= 0){ ALOGE("wrn: get ro.sw.audio.codec_plan_name failed"); @@ -3092,7 +3119,9 @@ static int adev_open(const hw_module_t* module, const char* name, ALOGE("err: ril_dev_init ****LINE:%d,FUNC:%s",__LINE__,__FUNCTION__); } case_init(); - +#if USE_3D_SURROUND + sur_init(&sur, MM_SAMPLING_RATE, 2, SHORT_PERIOD_SIZE); +#endif return 0; error_out: diff --git a/audio/tulip/Android.mk b/audio/tulip/Android.mk index 851d50b..d5b29aa 100755 --- a/audio/tulip/Android.mk +++ b/audio/tulip/Android.mk @@ -33,8 +33,10 @@ LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := audio_hw.c audio_iface.c sunxi_volume.c audio_3d_surround/audio_3d_surround.c +LOCAL_STATIC_LIBRARIES += libaw_audio3dsur + #ifneq ($(SW_BOARD_HAVE_3G), true) -#LOCAL_SRC_FILES += audio_ril_stub.c +#LOCAL_SRC_FILES += audio_ril_stub.c #else #LOCAL_SHARED_LIBRARIES := libaudio_ril #endif @@ -43,15 +45,11 @@ LOCAL_C_INCLUDES += \ external/tinyalsa/include \ system/media/audio_utils/include \ system/media/audio_effects/include \ + $(LOCAL_PATH)/../effects/audio_3d_surround \ system/media/audio_route/include - LOCAL_SHARED_LIBRARIES += liblog libcutils libtinyalsa libaudioutils libdl libcodec_audio libril_audio libaudioroute -LOCAL_SHARED_LIBRARIES_32 += libAwHeadpSurround LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under, $(LOCAL_PATH)) - - - diff --git a/audio/tulip/a64_paths.xml b/audio/tulip/a64_paths.xml index a826935..ec7cbdd 100755 --- a/audio/tulip/a64_paths.xml +++ b/audio/tulip/a64_paths.xml @@ -89,6 +89,7 @@ + @@ -110,6 +111,7 @@ + diff --git a/audio/tulip/audio_hw.c b/audio/tulip/audio_hw.c index 68020a7..785a41b 100755 --- a/audio/tulip/audio_hw.c +++ b/audio/tulip/audio_hw.c @@ -48,7 +48,7 @@ #include #include -#include "audio_3d_surround/audio_3d_surround.h" +#include "audio_3d_surround.h" #define USE_3D_SURROUND 1 #define F_LOG ALOGV("%s, line: %d", __FUNCTION__, __LINE__); @@ -341,6 +341,7 @@ struct sunxi_audio_device { struct pcm_buf_manager PcmManager; struct audio_route *ar; struct volume_array *vol_array; + struct audio_patch audiopatch; }; @@ -525,6 +526,7 @@ static int set_route_by_array(struct mixer *mixer, struct route_setting *route, { struct mixer_ctl *ctl; unsigned int i, j; +<<<<<<< HEAD /* Go through the route array and set each value */ i = 0; @@ -550,6 +552,33 @@ static int set_route_by_array(struct mixer *mixer, struct route_setting *route, i++; } +======= + + /* Go through the route array and set each value */ + i = 0; + while (route[i].ctl_name) { + ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name); + if (!ctl) + return -EINVAL; + + if (route[i].strval) { + if (enable) + mixer_ctl_set_enum_by_string(ctl, route[i].strval); + else + mixer_ctl_set_enum_by_string(ctl, "Off"); + } else { + /* This ensures multiple (i.e. stereo) values are set jointly */ + for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) { + if (enable) + mixer_ctl_set_value(ctl, j, route[i].intval); + else + mixer_ctl_set_value(ctl, j, 0); + } + } + i++; + } + +>>>>>>> de1e5bc... Update to Android 7.0 of AW return 0; } @@ -1584,6 +1613,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) ((val & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ^ (adev->out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET))) do_output_standby(out); +<<<<<<< HEAD } adev->out_device = val; F_LOG; @@ -1591,6 +1621,15 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_MODE_FACTORY_TEST || adev->mode == AUDIO_MODE_FM){ adev_set_voice_volume(&adev->hw_device, adev->voice_volume); } +======= + } + adev->out_device = val; + F_LOG; + select_device(adev); + if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_MODE_FACTORY_TEST || adev->mode == AUDIO_MODE_FM){ + adev_set_voice_volume(&adev->hw_device, adev->voice_volume); + } +>>>>>>> de1e5bc... Update to Android 7.0 of AW } pthread_mutex_unlock(&out->lock); @@ -1732,8 +1771,17 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } #if USE_3D_SURROUND +<<<<<<< HEAD if (surround_ready(sur) && surround_use(adev->out_device)) surround_process(sur, (short*)buf, out_frames, out->config.channels); +======= + if (sur_enable(&sur)) { + if (sur_prepare(&sur, adev->out_device, spk_dul_used, out->config.rate, + out->config.channels, out_frames)) { + sur_process(&sur, (short*)buf, out_frames, out->config.channels); + } + } +>>>>>>> de1e5bc... Update to Android 7.0 of AW #endif ret = pcm_write(out->pcm, (void *)buf, out_frames * frame_size); @@ -1744,12 +1792,21 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, exit: pthread_mutex_unlock(&out->lock); +<<<<<<< HEAD if (ret != 0) { usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / out_get_sample_rate(&stream->common)); } +======= + + if (ret != 0) { + usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / + out_get_sample_rate(&stream->common)); + } + +>>>>>>> de1e5bc... Update to Android 7.0 of AW if (force_input_standby) { pthread_mutex_lock(&adev->lock); if (adev->active_input) { @@ -2273,12 +2330,21 @@ static ssize_t read_frames(struct sunxi_stream_in *in, void *buffer, ssize_t fra } release_buffer(&in->buf_provider, &buf); } +<<<<<<< HEAD /* in->read_status is updated by getNextBuffer() also called by * in->resampler->resample_from_provider() */ if (in->read_status != 0) return in->read_status; +======= + + /* in->read_status is updated by getNextBuffer() also called by + * in->resampler->resample_from_provider() */ + if (in->read_status != 0) + return in->read_status; + +>>>>>>> de1e5bc... Update to Android 7.0 of AW frames_wr += frames_rd; } return frames_wr; @@ -2508,10 +2574,17 @@ static int in_remove_audio_effect(const struct audio_stream *stream, found = true; } } +<<<<<<< HEAD if (status != 0) goto exit; +======= + + if (status != 0) + goto exit; + +>>>>>>> de1e5bc... Update to Android 7.0 of AW in->num_preprocessors--; status = (*effect)->get_descriptor(effect, &desc); @@ -2898,6 +2971,7 @@ static void adev_close_input_stream(struct audio_hw_device *dev, struct sunxi_audio_device *ladev = (struct sunxi_audio_device *)dev; in_standby(&stream->common); +<<<<<<< HEAD if (in->buffer) { free(in->buffer); @@ -2917,11 +2991,63 @@ static void adev_close_input_stream(struct audio_hw_device *dev, } free(stream); +======= + + if (in->buffer) { + free(in->buffer); + in->buffer = 0; + } + if (in->resampler) { + release_resampler(in->resampler); + in->resampler = 0; + } + if (ladev->af_capture_flag) { + ladev->af_capture_flag = false; + } + if (ladev->PcmManager.BufStart) { + ladev->PcmManager.BufExist = false; + free(ladev->PcmManager.BufStart); + ladev->PcmManager.BufStart = 0; + } + free(stream); + +>>>>>>> de1e5bc... Update to Android 7.0 of AW normal_record_enable(false); fm_record_enable(false); phone_record_enable(false); ALOGD("adev_close_input_stream set voice record status"); return; +<<<<<<< HEAD +======= +} + +int adev_create_audio_patch(struct audio_hw_device *dev, + unsigned int num_sources, + const struct audio_port_config *sources, + unsigned int num_sinks, + const struct audio_port_config *sinks, + audio_patch_handle_t *handle) +{ + return 0; +} + +int adev_release_audio_patch(struct audio_hw_device *dev, + audio_patch_handle_t handle) +{ + return 0; +} + +int adev_get_audio_port(struct audio_hw_device *dev, + struct audio_port *port) +{ + return 0; +} + +int adev_set_audio_port_config(struct audio_hw_device *dev, + const struct audio_port_config *config) +{ + return 0; +>>>>>>> de1e5bc... Update to Android 7.0 of AW } static int adev_dump(const audio_hw_device_t *device, int fd) @@ -2934,7 +3060,11 @@ static int adev_close(hw_device_t *device) struct sunxi_audio_device *adev = (struct sunxi_audio_device *)device; #if USE_3D_SURROUND +<<<<<<< HEAD surround_exit(&sur); +======= + sur_exit(&sur); +>>>>>>> de1e5bc... Update to Android 7.0 of AW #endif audio_route_free(adev->ar); @@ -3030,6 +3160,10 @@ static int adev_open(const hw_module_t* module, const char* name, adev->hw_device.close_output_stream = adev_close_output_stream; adev->hw_device.open_input_stream = adev_open_input_stream; adev->hw_device.close_input_stream = adev_close_input_stream; + adev->hw_device.create_audio_patch = adev_create_audio_patch; + adev->hw_device.release_audio_patch = adev_release_audio_patch; + adev->hw_device.get_audio_port = adev_get_audio_port; + adev->hw_device.set_audio_port_config = adev_set_audio_port_config; adev->hw_device.dump = adev_dump; adev->raw_flag = false; /* Set the default route before the PCM stream is opened */ @@ -3070,7 +3204,11 @@ static int adev_open(const hw_module_t* module, const char* name, case_init(); #if USE_3D_SURROUND +<<<<<<< HEAD surround_init(&sur, MM_SAMPLING_RATE, 2, SHORT_PERIOD_SIZE); +======= + sur_init(&sur, MM_SAMPLING_RATE, 2, SHORT_PERIOD_SIZE); +>>>>>>> de1e5bc... Update to Android 7.0 of AW #endif return 0; diff --git a/audio/tulip/audio_policy.conf b/audio/tulip/audio_policy.conf index f20d248..06b48e7 100755 --- a/audio/tulip/audio_policy.conf +++ b/audio/tulip/audio_policy.conf @@ -83,7 +83,7 @@ audio_hw_modules { r_submix { outputs { submix { - sampling_rates 48000 + sampling_rates 44100|48000 channel_masks AUDIO_CHANNEL_OUT_STEREO formats AUDIO_FORMAT_PCM_16_BIT devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX @@ -91,7 +91,7 @@ audio_hw_modules { } inputs { submix { - sampling_rates 48000 + sampling_rates 44100|48000 channel_masks AUDIO_CHANNEL_IN_STEREO formats AUDIO_FORMAT_PCM_16_BIT devices AUDIO_DEVICE_IN_REMOTE_SUBMIX diff --git a/audio/tulip/libcodec_audio/pcm.c b/audio/tulip/libcodec_audio/pcm.c index 262f329..e5b28e2 100755 --- a/audio/tulip/libcodec_audio/pcm.c +++ b/audio/tulip/libcodec_audio/pcm.c @@ -724,7 +724,6 @@ int pcm_wait(struct pcm *pcm, int timeout) } -/* ͨ¹ýÇý¶¯µÄÃû³ÆÀ´É豸½Úµã±àºÅ */ int pcm_get_node_number(char *name) { char card[32]; @@ -764,7 +763,7 @@ int pcm_get_node_number(char *name) continue; } - /* È¥µô»»Ðзû */ + for(j = 0; j < 32; j++){ if(id[j] == 0x0a){ id[j] = 0; diff --git a/client-api/Android.mk b/client-api/Android.mk deleted file mode 100755 index 44fd01b..0000000 --- a/client-api/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -ifeq ($(SECURE_OS_OPTEE), no) - -LOCAL_SRC_FILES:= \ - sunxi_tee_api.c - -LOCAL_SHARED_LIBRARIES:=\ - libcutils \ - libutils - -LOCAL_MODULE_TAGS := optional - -LOCAL_MODULE:= libtee_client - -include $(BUILD_SHARED_LIBRARY) -################################ -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - test_api.c - -LOCAL_SHARED_LIBRARIES:=\ - libtee_client \ - libcutils \ - libutils - -LOCAL_MODULE_TAGS := optional - -LOCAL_MODULE:= test_api - -#include $(BUILD_EXECUTABLE) - -endif diff --git a/client-api/Makefile b/client-api/Makefile deleted file mode 100755 index e93ccf9..0000000 --- a/client-api/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -CC=arm-linux-gnueabihf-gcc -AR=arm-linux-gnueabihf-ar - -CFLAGS:=-Werror -O2 -D__OS_LINUX - -TARGET_DIR=. - -LOCAL_SRC_FILES:= \ - sunxi_tee_api.c - -BUILD_STATIC_LIB:=1 - -ifeq ($(BUILD_STATIC_LIB),1) -LIB= $(TARGET_DIR)/libtee_client.a -else -LIB= $(TARGET_DIR)/libtee_client.so -CFLAGS+=-fPIC -endif - - -OBJS=$(addsuffix .o, $(basename $(LOCAL_SRC_FILES))) -all:$(LIB) - -obj:$(OBJS) - -%.o:%.c - $(CC) $(CFLAGS) -o $@ -c $< - -%.o:%.S - $(CC) $(CFLAGS) -o $@ -c $< - -ifeq ($(BUILD_STATIC_LIB),1) -$(LIB):$(OBJS) - $(AR) $(ARFLAGS) $@ $^ -else -$(LIB):$(OBJS) - $(CC) -shared -o $@ $^ -endif - -test: - $(CC) -static test_api.c $(CFLAGS) -ltee_client -lpthread -L./ -o test_api - -clean: - rm -rf $(OBJS) $(LIB) - rm -rf test_api.o diff --git a/client-api/sunxi_tee_api.c b/client-api/sunxi_tee_api.c deleted file mode 100755 index 2520628..0000000 --- a/client-api/sunxi_tee_api.c +++ /dev/null @@ -1,502 +0,0 @@ -//#define LOG_NDEBUG 0 -#define LOG_TAG "sunxi_tee_api" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tee_protocol.h" -#include "tee_types.h" -#include "sunxi_tee_api.h" -#include "sw_list.h" - -#ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#endif -#define OTZ_CLIENT_FULL_PATH_DEV_NAME "/dev/te_device" - -TEEC_Result TEEC_InitializeContext(const char* name, TEEC_Context* context) { - int ret = 0; - char temp_name[256]; - - if (context == NULL) { - ALOGE("TEEC_InitializeContext : Context is null"); - return TEEC_ERROR_BAD_PARAMETERS; - } - if (name == NULL) { - //ALOGE("%s is assigned as default context", OTZ_CLIENT_FULL_PATH_DEV_NAME ); - strcpy(temp_name, OTZ_CLIENT_FULL_PATH_DEV_NAME); - } else { - strcpy(temp_name, name); - } - ret = open(temp_name, O_RDWR); - - if (ret == -1) { - ALOGE("TEEC_InitializeContext : device open failed %s", - strerror(errno)); - context->s_errno = errno; - return TEEC_ERROR_GENERIC; - } else { - context->fd = ret; - context->session_count = 0; - context->shared_mem_cnt = 0; - context->nSessionNum = 0; - INIT_LIST_HEAD(&context->shared_mem_list); - } - return TEEC_SUCCESS; - -} - -void TEEC_FinalizeContext(TEEC_Context* context) { - if (!context) { - ALOGE("context is NULL"); - return; - } - if (context->session_count != 0) { - ALOGW("warning: pending open sessions %d", context->session_count); - } - - if (context->shared_mem_cnt != 0) { - ALOGW("warning: unreleased shared memory blocks %d", - context->shared_mem_cnt); - } - if ((context->session_count == 0) && (context->shared_mem_cnt == 0)) { - ALOGV("device closed "); - close(context->fd); - context->fd = 0; - } - return; -} - -TEEC_Result TEEC_AllocateSharedMemory( - TEEC_Context* context, - TEEC_SharedMemory* sharedMem) -{ - int mmap_flags; - if (context == NULL || sharedMem == NULL) { - ALOGE("TEEC_AllocateSharedMemory : Error Illegal argument"); - return TEEC_ERROR_BAD_PARAMETERS; - } - if((sharedMem->size == 0) || - ((sharedMem->flags != TEEC_MEM_INPUT) && - (sharedMem->flags != TEEC_MEM_OUTPUT) && - (sharedMem->flags != (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)))) { - - ALOGE("TEEC_AllocateSharedMemory : Error Illegal argument"); - return TEEC_ERROR_BAD_PARAMETERS; - } - - sharedMem->buffer = NULL; - mmap_flags = PROT_READ | PROT_WRITE; - sharedMem->buffer = mmap(0, sharedMem->size, mmap_flags, MAP_SHARED, - context->fd, 0); - - if (sharedMem->buffer == MAP_FAILED) { - ALOGE("TEEC_AllocateSharedMemory - mmap failed"); - sharedMem->s_errno = errno; - sharedMem->buffer = NULL; - return TEEC_ERROR_OUT_OF_MEMORY; - } - - sharedMem->allocated = 1; - sharedMem->context = context; - sharedMem->operation_count = 0; - return TEEC_SUCCESS; - -} -void TEEC_ReleaseSharedMemory(TEEC_SharedMemory* sharedMem) { - - struct list *l; - TEEC_SharedMemory* tempSharedMem; - int found = 0; - unsigned int ret; - - if (sharedMem == NULL) { - return; - } - if (sharedMem->operation_count != 0) { - ALOGE("TEEC_ReleaseSharedMemory - pending operations count %d", - sharedMem->operation_count); - return; - } - - if(sharedMem->allocated) { - ret = ioctl(sharedMem->context->fd, TE_IOCTL_SHARED_MEM_FREE_REQUEST, sharedMem->buffer); - if(ret != 0){ - ALOGE("TEEC_ReleaseShaarddMemory - release kernel sharedmemory list failed! return value: %x", ret); - } - munmap(sharedMem->buffer, sharedMem->size); - } - - sharedMem->buffer = NULL; - sharedMem->size = 0; - sharedMem->context = NULL; -} - -TEEC_Result TEEC_OpenSession ( - TEEC_Context* context, - TEEC_Session* session, - const TEEC_UUID* destination, - uint32_t connectionMethod, - const void* connectionData, - TEEC_Operation* operation ATTRIBUTE_UNUSED, - uint32_t* returnOrigin) -{ - int ret,i=0; - union te_cmd *cmd; - struct te_answer answer; - struct te_oper_param *te_param; - - cmd = (union te_cmd *) malloc(sizeof(union te_cmd)); - memset(cmd, 0, sizeof(union te_cmd)); - - if ((context == NULL) || (session == NULL) || (destination == NULL)) { - ALOGE("TEEC_OpenSession : Error Illegal argument"); - return TEEC_ERROR_BAD_PARAMETERS; - } - - switch (connectionMethod) { - case TEEC_LOGIN_PUBLIC: { - if (connectionData != NULL) { - ALOGE("TEEC_OpenSession : connection method requires empty connection data"); - return TEEC_ERROR_BAD_PARAMETERS; - } - break; - } - case TEEC_LOGIN_USER: - case TEEC_LOGIN_APPLICATION: - case TEEC_LOGIN_USER_APPLICATION: { - if (connectionData != NULL) { - ALOGE("TEEC_OpenSession : connection method requires empty connection data"); - return TEEC_ERROR_BAD_PARAMETERS; - } - ALOGV("TEEC_OpenSession : connection method is not implemented "); - return TEEC_ERROR_NOT_IMPLEMENTED; - break; - } - case TEEC_LOGIN_GROUP: - case TEEC_LOGIN_GROUP_APPLICATION: { - if (connectionData == NULL) { - ALOGE("TEEC_OpenSession : connection method requires valid connection data"); - return TEEC_ERROR_BAD_PARAMETERS; - } - return TEEC_ERROR_NOT_IMPLEMENTED; - break; - } - } - - /*encode te_cmd*/ - memcpy(&cmd->opensession.dest_uuid, destination, sizeof(cmd->opensession.dest_uuid)); - ret = ioctl(context->fd, TE_IOCTL_OPEN_CLIENT_SESSION, cmd); - if (ret < 0) { - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_API; - } - context->s_errno = errno; - - ALOGE("TEEC_OpenSession: Session client open request failed"); - if (ret == -ENOMEM) { - return TEEC_ERROR_OUT_OF_MEMORY; - } - if (ret == -EFAULT) { - return TEEC_ERROR_ACCESS_DENIED; - } - if (ret == -EINVAL) { - return TEEC_ERROR_BAD_PARAMETERS; - } - - return TEEC_ERROR_GENERIC; - } else if (ret > 0) { - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_TRUSTED_APP; - } - ALOGE("TEEC_OpenSession: service return error"); - return ret; - } - answer.session_id = cmd->opensession.answer.session_id; - context->session_count++; - session->operation_cnt = 0; - session->session_id = answer.session_id; - memcpy(&session->service_id, destination, sizeof(cmd->opensession.dest_uuid)); - session->device = context; - free(cmd); - return TEEC_SUCCESS; -} - -void TEEC_CloseSession(TEEC_Session* session) { - - int ret = 0; - union te_cmd *cmd; - cmd = (union te_cmd *) malloc(sizeof(union te_cmd)); - memset(cmd, 0, sizeof(union te_cmd)); - - if (session == NULL) { - ALOGE("TEEC_CloseSession: Warning: Session pointer is NULL"); - return; - } - if (session->operation_cnt) { - ALOGE("TEEC_CloseSession: Warning: Pending operations %d", - session->operation_cnt); - return; - } - cmd->closesession.session_id = session->session_id; - memcpy(&cmd->closesession.service_id, &session->service_id, sizeof(session->service_id)); - ret = ioctl(session->device->fd, TE_IOCTL_CLOSE_CLIENT_SESSION, cmd); - - if (ret == 0) { - session->device->session_count--; - session->device = NULL; - session->session_id = -1; - } else { - ALOGE("TEEC_CloseSession: Session client close request failed"); - } - free(cmd); -} -TEEC_Result TEEC_InvokeCommand( - TEEC_Session* session, - uint32_t commandID, - TEEC_Operation* operation, - uint32_t* returnOrigin) -{ - int ret = TEEC_SUCCESS; - int rel_ret; - int i; - unsigned char inout = 0; - uint32_t param_types[4], param_count; - union te_cmd *cmd; - struct te_oper_param *sunxi_tee_param; - struct te_oper_param *decode_param, *temp_param; - - cmd = (union te_cmd *) malloc(sizeof(union te_cmd)); - memset(cmd, 0, sizeof(union te_cmd)); - - sunxi_tee_param = (struct te_oper_param *)malloc(4 * sizeof(struct te_oper_param)); - memset(sunxi_tee_param,0,4*sizeof(struct te_oper_param)); - - if (session == NULL) { - ALOGE("TEEC_InvokeCommand : Illegal argument"); - return TEEC_ERROR_BAD_PARAMETERS; - } - - cmd->launchop.session_id = session->session_id ; - memcpy(&cmd->closesession.service_id, &session->service_id, sizeof(session->service_id)); - cmd->launchop.operation.command = commandID; - /* Need to support cancellation in future releases */ - if (operation && !operation->started) { - ALOGE("TEEC_InvokeCommand : cancellation support not yet implemented"); - return TEEC_ERROR_NOT_IMPLEMENTED; - } - - session->operation_cnt++; - if (operation->paramTypes != 0) { - param_types[0] = operation->paramTypes & 0xf; - param_types[1] = (operation->paramTypes >> 4) & 0xf; - param_types[2] = (operation->paramTypes >> 8) & 0xf; - param_types[3] = (operation->paramTypes >> 12) & 0xf; - - for(param_count = 0; param_count < 4; param_count++){ - if((param_types[param_count] == TEEC_VALUE_INPUT) || - (param_types[param_count] == TEEC_VALUE_OUTPUT) || - (param_types[param_count] == TEEC_VALUE_INOUT)){ - - if( (param_types[param_count] == TEEC_VALUE_INPUT)){ - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_INT_RO; - - sunxi_tee_param[param_count].u.Int.val_a = operation->params[param_count].value.a; - sunxi_tee_param[param_count].u.Int.val_b = operation->params[param_count].value.b; - sunxi_tee_param[param_count].index = 0xffffffff; - } - if((param_types[param_count] == TEEC_VALUE_OUTPUT) || - (param_types[param_count] == TEEC_VALUE_INOUT)){ - - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_INT_RW; - sunxi_tee_param[param_count].u.Int.val_a = operation->params[param_count].value.a; - sunxi_tee_param[param_count].u.Int.val_b = operation->params[param_count].value.b; - sunxi_tee_param[param_count].index = 0xffffffff; - } - }else if( (param_types[param_count] == TEEC_MEMREF_WHOLE) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_INPUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_INOUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_OUTPUT)) { - //* check the info - if(!operation->params[param_count].memref.parent) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_NO_DATA; - ALOGE("TEEC_InvokeCommand: memory reference parent is NULL"); - break; - } - if (!operation->params[param_count].memref.parent->buffer) { - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_NO_DATA; - ALOGE("TEEC_InvokeCommand: memory reference parent data is NULL"); - break; - } - if(param_types[param_count] == TEEC_MEMREF_PARTIAL_INPUT) { - if(!(operation->params[param_count].memref.parent->flags & TEEC_MEM_INPUT)) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_BAD_FORMAT; - ALOGE("TEEC_InvokeCommand: memory reference direction is invalid"); - break; - } - } - if(param_types[param_count] == TEEC_MEMREF_PARTIAL_OUTPUT) { - if(!(operation->params[param_count].memref.parent->flags & TEEC_MEM_OUTPUT)) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_BAD_FORMAT; - ALOGE("TEEC_InvokeCommand: memory reference direction is invalid"); - break; - } - } - if(param_types[param_count] == TEEC_MEMREF_PARTIAL_INOUT) { - if(!(operation->params[param_count].memref.parent->flags & TEEC_MEM_INPUT)) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_BAD_FORMAT; - ALOGE("TEEC_InvokeCommand: memory reference direction is invalid"); - break; - } - if(!(operation->params[param_count].memref.parent->flags & TEEC_MEM_OUTPUT)) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_BAD_FORMAT; - ALOGE("TEEC_InvokeCommand: memory reference direction is invalid"); - break; - } - } - if((param_types[param_count] == TEEC_MEMREF_PARTIAL_INPUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_INOUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_OUTPUT)) { - if((operation->params[param_count].memref.offset + operation->params[param_count].memref.size > - operation->params[param_count].memref.parent->size) ) { - if(returnOrigin){ - *returnOrigin = TEEC_ORIGIN_API; - } - ret = TEEC_ERROR_EXCESS_DATA; - ALOGE("TEEC_InvokeCommand:memory reference offset + size is greater than the actual memory size"); - break; - } - } - //* assign sunxi_tee_param from operation->param - if (param_types[param_count] == TEEC_MEMREF_PARTIAL_INPUT) { - - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_MEM_RO; - sunxi_tee_param[param_count].u.Mem.base = (void*) ((uintptr_t)operation->params[param_count].memref.parent->buffer + - (uint32_t)operation->params[param_count].memref.offset); - sunxi_tee_param[param_count].u.Mem.len = operation->params[param_count].memref.parent->size; - sunxi_tee_param[param_count].index = (uintptr_t)operation->params[param_count].memref.parent->buffer; - }else if((param_types[param_count] == TEEC_MEMREF_PARTIAL_OUTPUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_INOUT)){ - - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_MEM_RW; - sunxi_tee_param[param_count].u.Mem.base = (void*) ((uintptr_t)operation->params[param_count].memref.parent->buffer + - (uint32_t)operation->params[param_count].memref.offset); - sunxi_tee_param[param_count].u.Mem.len = operation->params[param_count].memref.parent->size; - sunxi_tee_param[param_count].index = (uintptr_t)operation->params[param_count].memref.parent->buffer; - - }else if((param_types[param_count] == TEEC_MEMREF_WHOLE)){ - if(operation->params[param_count].memref.parent->flags == TEEC_MEM_INPUT){ - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_MEM_RO; - sunxi_tee_param[param_count].u.Mem.base = (void*) ((uintptr_t)operation->params[param_count].memref.parent->buffer); - sunxi_tee_param[param_count].u.Mem.len = operation->params[param_count].memref.parent->size; - sunxi_tee_param[param_count].index = (uintptr_t)operation->params[param_count].memref.parent->buffer; - } - if((operation->params[param_count].memref.parent->flags == TEEC_MEM_OUTPUT) || - (operation->params[param_count].memref.parent->flags == (TEEC_MEM_INPUT|TEEC_MEM_OUTPUT ))){ - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_MEM_RW; - sunxi_tee_param[param_count].u.Mem.base = (void*) ((uintptr_t)operation->params[param_count].memref.parent->buffer); - sunxi_tee_param[param_count].u.Mem.len = operation->params[param_count].memref.parent->size; - sunxi_tee_param[param_count].index = (uintptr_t)operation->params[param_count].memref.parent->buffer; - } - } - }else if(param_types[param_count] == TEEC_NONE){ - sunxi_tee_param[param_count].type = TE_PARAM_TYPE_NONE; - } - } - - //* set sunxi_tee_param to cmd - for (param_count = 0; param_count < 4; param_count++) { - if (cmd->launchop.operation.list_count == 0) { - cmd->launchop.operation.list_head = sunxi_tee_param + param_count; - ALOGV("list_head:%p", sunxi_tee_param + param_count); - cmd->launchop.operation.list_tail = sunxi_tee_param + param_count; - cmd->launchop.operation.list_count++; - sunxi_tee_param[param_count].next_ptr_user = NULL; - } else { - temp_param = cmd->launchop.operation.list_tail; - temp_param->next_ptr_user = sunxi_tee_param + param_count; - cmd->launchop.operation.list_tail = sunxi_tee_param + param_count; - cmd->launchop.operation.list_count++; - sunxi_tee_param[param_count].next_ptr_user = NULL; - } - } - } - if (ret) { - ALOGE("error in encoding the data"); - goto operation_release; - } - - /* Invoke the command */ - ret = ioctl(session->device->fd, TE_IOCTL_LAUNCH_OPERATION, cmd); - if (ret < 0) { - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_API; - } - session->s_errno = errno; - if (ret == -EFAULT) { - ret = TEEC_ERROR_ACCESS_DENIED; - } - if (ret == -EINVAL) { - ret = TEEC_ERROR_BAD_PARAMETERS; - } - ALOGV("TEEC_InvokeCommand:command submission in client driver failed"); - } else if (ret > 0) { - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_TRUSTED_APP; - } - ALOGV("TEEC_InvokeCommand:command submission failed in trusted application"); - //TEEC_GetError(ret, TEEC_ORIGIN_TRUSTED_APP)); - } - //if (ret != 0) { - // goto operation_release; - //} - - /*decode cmd*/ - if (operation->paramTypes != 0) { - for (param_count = 0; param_count < 4; param_count++) { - if((param_types[param_count] == TEEC_VALUE_INOUT) ||(param_types[param_count] == TEEC_VALUE_OUTPUT)) { - decode_param = cmd->launchop.operation.list_head; - operation->params[param_count].value.a = (decode_param + param_count)->u.Int.val_a; - operation->params[param_count].value.b = (decode_param + param_count)->u.Int.val_b; - - }else if( (param_types[param_count] == TEEC_MEMREF_WHOLE) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_INOUT) || - (param_types[param_count] == TEEC_MEMREF_PARTIAL_OUTPUT)){ - decode_param = cmd->launchop.operation.list_head; - operation->params[param_count].memref.size = (decode_param + param_count)->u.Mem.len; - } - } - } -operation_release: - session->operation_cnt--; - free(sunxi_tee_param); - free(cmd); - return ret; -} diff --git a/client-api/sunxi_tee_api.h b/client-api/sunxi_tee_api.h deleted file mode 100755 index d4f5c2a..0000000 --- a/client-api/sunxi_tee_api.h +++ /dev/null @@ -1,1046 +0,0 @@ - - -/* - * OpenVirtualization: - * For additional details and support contact developer@sierraware.com. - * Additional documentation can be found at www.openvirtualization.org - * - * Copyright (C) 2011 SierraWare - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Header file for global platform TEE client API - */ - -#ifndef __SUNXI_TEE_CLIENT_API_H_ -#define __SUNXI_TEE_CLIENT_API_H_ - -#define MAX_SESSIONS_PER_DEVICE 16 -#define MAX_OPERATIONS_PER_SESSION 16 -#define MAX_MEMBLOCKS_PER_SESSION 16 -#define MAX_MEMBLOCKS_PER_OPERATION 4 - - -#define TEEC_PARAM_TYPES( param0Type, param1Type, param2Type, param3Type) \ - (param3Type << 12 | param2Type << 8 | param1Type << 4 | param0Type) - -#define TEEC_VALUE_UNDEF 0xffffffff -#include "sw_list.h" -#include "tee_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** -* @brief Return code origin -* -* -*/ -enum TEEC_return_code_origin { -/*! The return code is an error that originated within the TEE Client API -* implementation. */ - TEEC_ORIGIN_API = 0x1, -/*! The return code is an error that originated within the underlying -* communications stack linking the rich OS with the TEE. */ - TEEC_ORIGIN_COMMS = 0x2, -/*! The return code is an error that originated within the common TEE code. */ - TEEC_ORIGIN_TEE = 0x3, -/*! The return code is an error that originated within the Trusted application -* code. This includes the case where the return code is a success. */ - TEEC_ORIGIN_TRUSTED_APP = 0x4, -}; - - -/** -* @brief Login flag constants -* -* -*/ -enum TEEC_login_flags { -/*! No login is to be used.*/ - TEEC_LOGIN_PUBLIC = 0x0, -/*! The user executing the application is provided.*/ - TEEC_LOGIN_USER , -/*! The user group executing the application is provided.*/ - TEEC_LOGIN_GROUP , -/*! Login data about the running Client Application itself is provided. */ - TEEC_LOGIN_APPLICATION = 0x4 , -/*! Login data about the user running the Client Application and about the -* Client Application itself is provided. */ - TEEC_LOGIN_USER_APPLICATION = 0x5 , -/*! Login data about the group running the Client Application and about the -* Client Application itself is provided. */ - TEEC_LOGIN_GROUP_APPLICATION = 0x6 , -}; - -/** -* @brief Shared memory flag constants -* -* -*/ -enum TEEC_shared_mem_flags { -/*! The Shared Memory can carry data from the Client Application -* to the Trusted Application. */ - TEEC_MEM_INPUT = 0x1, -/*! The Shared Memory can carry data from the Trusted Application -* to the Client Application. */ - TEEC_MEM_OUTPUT = 0x2, -}; - -/** -* @brief Param type constants -* -*/ -enum TEEC_param_type { -/*! The Parameter is not used. */ - TEEC_NONE = 0x1, -/*! The Parameter is a TEEC_Value tagged as input. */ - TEEC_VALUE_INPUT, -/*! The Parameter is a TEEC_Value tagged as output. */ - TEEC_VALUE_OUTPUT, -/*! The Parameter is a TEEC_Value tagged as both as input and output, -* i.e., for which both the behaviors of TEEC_VALUE_INPUT and -* TEEC_VALUE_OUTPUT apply. */ - TEEC_VALUE_INOUT, -/*! The Parameter is a TEEC_TempMemoryReference describing a region of memory -* which needs to be temporarily registered for the duration of the Operation -and is tagged as input. */ - TEEC_MEMREF_TEMP_INPUT, -/*! Same as TEEC_MEMREF_TEMP_INPUT, but the Memory Reference is tagged as -* output. The Implementation may update the size field to reflect the -* required output size in some use cases. */ - TEEC_MEMREF_TEMP_OUTPUT, -/*! A Temporary Memory Reference tagged as both input and output, -* i.e., for which both the behaviors of TEEC_MEMREF_TEMP_INPUT and -* TEEC_MEMREF_TEMP_OUTPUT apply. */ - TEEC_MEMREF_TEMP_INOUT, -/*! The Parameter is a Registered Memory Reference that refers to the -* entirety of its parent Shared Memory block. The parameter structure is a -* TEEC_MemoryReference. In this structure, the Implementation MUST read -* only the parent field and MAY update the size field when the -* operation completes. */ - TEEC_MEMREF_WHOLE = 0xc, - -/*! A Registered Memory Reference structure that refers to a partial region -* of its parent Shared Memory block and is tagged as input. -*/ - TEEC_MEMREF_PARTIAL_INPUT = 0xd, - -/*! A Registered Memory Reference structure that refers to a partial region -* of its parent Shared Memory block and is tagged as output. -*/ - TEEC_MEMREF_PARTIAL_OUTPUT = 0xe, - -/*! A Registered Memory Reference structure that refers to a partial region -* of its parent Shared Memory block and is tagged as both input and output. -*/ - TEEC_MEMREF_PARTIAL_INOUT = 0xf -}; - -/** - * @brief - */ -typedef struct TEEC_Operation TEEC_Operation; -/** - * @brief - */ -typedef struct TEEC_Session TEEC_Session; -/** - * @brief - */ -typedef struct TEEC_Context TEEC_Context; -/** - * @brief - */ -typedef struct TEEC_SharedMemory TEEC_SharedMemory; -/** - * @brief - */ -typedef struct TEEC_TempMemoryReference TEEC_TempMemoryReference; -/** - * @brief - */ -typedef struct TEEC_RegisteredMemoryReference TEEC_RegisteredMemoryReference; -/** - * @brief - */ -typedef struct TEEC_Value TEEC_Value; - - - -/** -* @brief Universally Unique IDentifier (UUID) type as defined in -* [RFC4122].A -* -* UUID is the mechanism by which a service is identified. -*/ -typedef struct -{ - uint32_t timeLow; - uint16_t timeMid; - uint16_t timeHiAndVersion; - uint8_t clockSeqAndNode[8]; -} TEEC_UUID; - -#if 0 -typedef uint32_t TEEC_UUID; -#endif -/** -* @brief The TEEC_Session structure is used to contain control information -* related to a session between a client and a service. -* -*/ -struct TEEC_Session -{ -/*! Implementation-defined variables */ -/*! Reference count of operations*/ - int operation_cnt; -/*! Session id obtained for the service*/ - int session_id; -/*! Unique service id */ - TEEC_UUID service_id; -/*! Device context */ - TEEC_Context* device; -/*! Service error number */ - int s_errno; -}; - - -/** -* @brief The TEEC_Context structure is used to contain control information -* related to the TEE -* -*/ -struct TEEC_Context -{ -/*! Implementation-defined variables */ -/*! Device identifier */ - uint32_t fd; -/*! Sessions count of the device */ - int session_count; -/*! Shared memory counter which got created for this context */ - uint32_t shared_mem_cnt; -/*! Shared memory list */ - struct list shared_mem_list; -/*! Error number from the client driver */ - int s_errno; - - int nSessionNum; -}; - - -/** -* @brief The TEEC_SharedMemory structure is used to contain control information -* related to a block of shared memory that is mapped between the client and the -* service. -* -*/ - -struct TEEC_SharedMemory -{ -/*! The pointer to the block of shared memory. */ - void* buffer; - -/*! The length of the shared memory block in bytes. Should not be zero */ - size_t size; - -/*! flags is a bit-vector which can contain the following flags:\n -* TEEC_MEM_INPUT: the memory can be used to transfer data from the -* Client Application to the TEE. \n -* TEEC_MEM_OUTPUT: The memory can be used to transfer data from the -* TEE to the Client Application. \n -* All other bits in this field SHOULD be set to zero, and are reserved for -* future use. -*/ - uint32_t flags; - -/*! Implementation defined fields. */ - -/*! Device context */ - TEEC_Context* context; -/*! Operation count */ - int operation_count; -/*! Shared memory type */ - uint32_t allocated; -/*! List head used by Context */ - struct list head_ref; -/*! Service error number */ - int s_errno; -}; - - -/** -* @brief Small raw data value type -* -* This type defines a parameter that is not referencing shared memory, -* but carries instead small raw data passed by value. -* It is used as a TEEC_Operation parameter when the corresponding -* parameter type is one of -* TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, or TEEC_VALUE_INOUT. -*/ -struct TEEC_Value -{ -/*! The two fields of this structure do not have a particular meaning. -* It is up to the protocol between the Client Application and -* the Trusted Application to assign a semantic to those two integers. -*/ - uint32_t a; - uint32_t b; -}; - - -/** -* @brief Temporary shared memory reference -* -*/ -struct TEEC_TempMemoryReference -{ -/*! "buffer" is a pointer to the first byte of a region of memory which needs \n -* to be temporarily registered for the duration of the Operation. \n -* This field can be NULL to specify a null Memory Reference. */ - void *buffer; -/*! Size of the referenced memory region. When the operation completes, and \n -* unless the parameter type is TEEC_MEMREF_TEMP_INPUT, \n -* the Implementation must update this field to reflect the actual or \n -* required size of the output: \n -* If the Trusted Application has actually written some data in the -* output buffer, then the Implementation MUST update the size field with -* the actual number of bytes written.\n\n -* If the output buffer was not large enough to contain the whole output, -* or if it is null, the Implementation MUST update the size field with -* the size of the output buffer requested by the Trusted Application. -* In this case, no data has been written into the output buffer -*/ - size_t size; -}; - -/** -* @brief Registered memory reference -* -* A pre-registered or pre-allocated Shared Memory block. -* It is used as a TEEC_Operation parameter when the corresponding -* parameter type is one of TEEC_MEMREF_WHOLE, -* TEEC_MEMREF_PARTIAL_INPUT, TEEC_MEMREF_PARTIAL_OUTPUT, or -* TEEC_MEMREF_PARTIAL_INOUT. -*/ -struct TEEC_RegisteredMemoryReference -{ -/*! Pointer to the shared memory structure. \n -* The memory reference refers either to the whole Shared Memory or -* to a partial region within the Shared Memory block, depending of the -* parameter type. The data flow direction of the memory reference -* must be consistent with the flags defined in the parent Shared Memory Block. -* Note that the parent field MUST NOT be NULL. To encode a null -* Memory Reference, the Client Application must use a Temporary Memory -* Reference with the buffer field set to NULL. */ - TEEC_SharedMemory* parent; - -/*! Size of the referenced memory region, in bytes. \n -* The Implementation MUST only interpret this field if the Memory Reference -* type in the operation structure is not TEEC_MEMREF_WHOLE. Otherwise, -* the size is read from the parent Shared Memory structure.\n -* When an operation completes, and if the Memory Reference is -* tagged as ¡°output¡±, the Implementation must update this field to reflect -* the actual or required size of the output. This applies even if the -* parameter type is TEEC_MEMREF_WHOLE:\n -* If the Trusted Application has actually written some data in the -* output buffer, then the Implementation MUST update the size field with the -* actual number of bytes written.\n -* If the output buffer was not large enough to contain the -* whole output, the Implementation MUST update the size field with the size of -* the output buffer requested by the Trusted Application. In this case, -* no data has been written into the output buffer. -*/ - size_t size; - -/*! Offset from the allocated Shared memory for reference \n -* The Implementation MUST only interpret this field if the -* Memory Reference type in the operation structure is not TEEC_MEMREF_WHOLE. -* Otherwise, the Implementation MUST use the base address of the -* Shared Memory block. -*/ - size_t offset; -}; - -/** -* @brief Parameter of a TEEC_Operation -* -* It can be a Temporary Memory Reference, a Registered Memory Reference, -* or a Value Parameter. -*/ -typedef union -{ -/*! For parameter type:\n -* TEEC_MEMREF_TEMP_INPUT \n -* TEEC_MEMREF_TEMP_OUTPUT \n -* TEEC_MEMREF_TEMP_INOUT \n -*/ - TEEC_TempMemoryReference tmpref; - -/*! For parameter type:\n -* TEEC_MEMREF_WHOLE \n -* TEEC_MEMREF_PARTIAL_INPUT \n -* TEEC_MEMREF_PARTIAL_OUTPUT \n -* TEEC_MEMREF_PARTIAL_INOUT \n -*/ - TEEC_RegisteredMemoryReference memref; - -/*! For parameter type:\n -* TEEC_VALUE_INPUT \n -* TEEC_VALUE_OUTPUT \n -* TEEC_VALUE_INOUT \n -*/ - TEEC_Value value; -} TEEC_Parameter; - -/** -* @brief The TEEC_Operation structure is used to contain control information -* related to an operation that is to be invoked with the security environment. -* -* This type defines the payload of either an open Session operation or -* an invoke Command operation. It is also used for cancellation of operations, -* which may be desirable even if no payload is passed. -*/ -struct TEEC_Operation -{ -/*! -* This field which MUST be initialized to zero by the Client Application -* before each use in an operation if the Client Application may need to -* cancel the operation about to be performed. -*/ - uint32_t started; - -/*! paramTypes field encodes the type of each of the Parameters in the -* operation. The layout of these types within a 32-bit integer is -* implementation-defined and the Client Application MUST use the -* macro TEEC_PARAMS_TYPE to construct a constant value for this field. -* As a special case, if the Client Application sets paramTypes to 0, -* then the Implementation MUST interpret it as meaning that the type for each -* Parameter is set to TEEC_NONE.\n -* The type of each Parameter can take one of the following values\n -* TEEC_NONE\n -* TEEC_VALUE_INPUT\n -* TEEC_VALUE_OUTPUT\n -* TEEC_VALUE_INOUT\n -* TEEC_MEMREF_TEMP_INPUT\n -* TEEC_MEMREF_TEMP_OUTPUT\n -* TEEC_MEMREF_TEMP_INOUT\n -* TEEC_MEMREF_WHOLE\n -* TEEC_MEMREF_PARTIAL_INPUT\n -* TEEC_MEMREF_PARTIAL_OUTPUT\n -* TEEC_MEMREF_PARTIAL_INOUT\n -*/ - uint32_t paramTypes; - -/*! params is an array of four Parameters. For each parameter, one of the -* memref, tmpref, or value fields must be used depending on the corresponding -* parameter type passed in paramTypes as described in the specification -* of TEEC_Parameter -*/ - TEEC_Parameter params[4]; -}; - - -/** -* @brief Shared memory flag constants -* -* -*/ -enum otz_shared_mem_flags { -/*! Service can only read from the memory block.*/ - OTZ_MEM_SERVICE_RO = 0x0, -/*! Service can only write from the memory block.*/ - OTZ_MEM_SERVICE_WO , -/*! Service can read and write from the memory block.*/ - OTZ_MEM_SERVICE_RW, -/*! Invalid flag */ - OTZ_MEM_SERVICE_UNDEFINED -}; - - -/** -* @brief Initialize Context -* -* This function initializes a new TEE Context, forming a connection between -* this Client Application and the TEE identified by the string identifier -* name.\n -* The Client Application MAY pass a NULL name, which means that the -* Implementation MUST select a default TEE to connect to. -* The supported name strings, the mapping of these names to a specific TEE, -* and the nature of the default TEE are implementation-defined.\n -* The caller MUST pass a pointer to a valid TEEC Context in context. -* The Implementation MUST assume that all fields of the TEEC_Context structure -* are in an undefined state.\n -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error: \n -* Attempting to initialize the same TEE Context structure concurrently -* from multiple threads. Multi-threaded Client Applications must use -* platform-provided locking mechanisms to ensure that this case -* does not occur. \n \n -* \b Implementers¡¯ \b Notes \n -* It is valid Client Application behavior to concurrently initialize -* different TEE Contexts, so the Implementation MUST support this. -* -* @param name: A zero-terminated string that describes the TEE to connect to. -* If this parameter is set to NULL the Implementation MUST select a default TEE. -* -* @param context: A TEEC_Context structure that MUST be initialized by the -* Implementation. -* -* @return TEEC_Result: -* TEEC_SUCCESS: The initialization was successful. \n -* TEEC_ERROR_*: An implementation-defined error code for any other error. -* -* -*/ -TEEC_Result TEEC_InitializeContext( - const char* name, - TEEC_Context* context); - - - -/** -* @brief Finalizes an initialized TEE context. -* -* This function finalizes an initialized TEE Context, -* closing the connection between the Client Application and the TEE. -* The Client Application MUST only call this function when all Sessions -* inside this TEE Context have been closed and all -* Shared Memory blocks have been released. \n -* The implementation of this function MUST NOT be able to fail: -* after this function returns the Client Application must be able to -* consider that the Context has been closed.\n -* The function implementation MUST do nothing if context is NULL. -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Calling with a context which still has sessions opened.\n -* Calling with a context which contains unreleased Shared Memory blocks.\n -* Attempting to finalize the same TEE Context structure concurrently -* from multiple threads.\n -* Attempting to finalize the same TEE Context structure more than once, -* without an intervening call to TEEC_InitalizeContext. -* -* @param context: An initialized TEEC_Context structure which is to be -* finalized. -* -*/ -void TEEC_FinalizeContext( - TEEC_Context* context); - -/** -* @brief Register a allocated shared memory block. -* -* This function registers a block of existing Client Application memory as a -* block of Shared Memory within the scope of the specified TEE Context, -* in accordance with the parameters which have been set by the -* Client Application inside the \a sharedMem structure. -* -* The parameter \a context MUST point to an initialized TEE Context. -* -* The parameter \a sharedMem MUST point to the Shared Memory structure -* defining the memory region to register. -* The Client Application MUST have populated the following fields of the -* Shared Memory structure before calling this function: \n -* The \a buffer field MUST point to the memory region to be shared, -* and MUST not be NULL.\n -* The \a size field MUST contain the size of the buffer, in bytes. -* Zero is a valid length for a buffer. \n -* The \a flags field indicates the intended directions of data flow -* between the Client Application and the TEE. \n -* The Implementation MUST assume that all other fields in the Shared Memory -* structure have undefined content. -* -* An Implementation MAY put a hard limit on the size of a single -* Shared Memory block, defined by the constant TEEC_CONFIG_SHAREDMEM_MAX_SIZE. -* However note that this function may fail to register a -* block smaller than this limit due to a low resource condition -* encountered at run-time. -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Calling with a \a context which is not initialized.\n -* Calling with a \a sharedMem which has not be correctly populated -* in accordance with the specification.\n -* Attempting to initialize the same Shared Memory structure concurrently -* from multiple threads.Multi-threaded Client Applications must use -* platform-provided locking mechanisms to ensure that -* this case does not occur. -* -* \b Implementor's \b Notes \n -* This design allows a non-NULL buffer with a size of 0 bytes to allow -* trivial integration with any implementations of the C library malloc, -* in which is valid to allocate a zero byte buffer and receive a non- -* NULL pointer which may not be de-referenced in return. -* Once successfully registered, the Shared Memory block can be used for -* efficient data transfers between the Client Application and the -* Trusted Application. The TEE Client API implementation and the underlying -* communications infrastructure SHOULD attempt to transfer data in to the -* TEE without using copies, if this is possible on the underlying -* implementation, but MUST fall back on data copies if zero-copy cannot be -* achieved. Client Application developers should be aware that, -* if the Implementation requires data copies, -* then Shared Memory registration may allocate a block of memory of the -* same size as the block being registered. -* -* @param context: A pointer to an initialized TEE Context -* @param sharedMem: A pointer to a Shared Memory structure to register: \n -* the \a buffer, \a size, and \a flags fields of the sharedMem structure -* MUST be set in accordance with the specification described above -* -* @return TEEC_Result: -* TEEC_SUCCESS: The device was successfully opened. \n -* TEEC_ERROR_*: An implementation-defined error code for any other error. -* -*/ -TEEC_Result TEEC_RegisterSharedMemory( - TEEC_Context* context, - TEEC_SharedMemory* sharedMem); - - -/** -* @brief Allocate a shared memory block. -* -* This function allocates a new block of memory as a block of Shared Memory -* within the scope of the specified TEE Context, in accordance with the -* parameters which have been set by the Client Application inside the -* \a sharedMem structure. -* -* The parameter \a context MUST point to an initialized TEE Context. -* -* The \a sharedMem parameter MUST point to the Shared Memory structure -* defining the region to allocate. -* Client Application MUST have populated the following fields of the -* Shared Memory structure: \n -* The \a size field MUST contain the desired size of the buffer, in bytes. -* The size is allowed to be zero. In this case memory is allocated and -* the pointer written in to the buffer field on return MUST not be NULL -* but MUST never be de-referenced by the Client Application. In this case -* however, the Shared Memory block can be used in -* Registered Memory References. \n -* The \a flags field indicates the allowed directions of data flow -* between the Client Application and the TEE. \n -* The Implementation MUST assume that all other fields in the Shared Memory -* structure have undefined content. -* -* An Implementation MAY put a hard limit on the size of a single -* Shared Memory block, defined by the constant -* \a TEEC_CONFIG_SHAREDMEM_MAX_SIZE. -* However note that this function may fail to allocate a -* block smaller than this limit due to a low resource condition -* encountered at run-time. -* -* If this function returns any code other than \a TEEC_SUCCESS -* the Implementation MUST have set the \a buffer field of \a sharedMem to NULL. -* -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Calling with a \a context which is not initialized.\n -* Calling with a \a sharedMem which has not be correctly populated -* in accordance with the specification.\n -* Attempting to initialize the same Shared Memory structure concurrently -* from multiple threads.Multi-threaded Client Applications must use -* platform-provided locking mechanisms to ensure that -* this case does not occur. -* -* \b Implementor's \b Notes \n -* Once successfully allocated the Shared Memory block can be used for -* efficient data transfers between the Client Application and the -* Trusted Application. The TEE Client API and the underlying communications -* infrastructure should attempt to transfer data in to the TEE -* without using copies, if this is possible on the underlying implementation, -* but may have to fall back on data copies if zero-copy cannot be achieved. -* The memory buffer allocated by this function must have sufficient -* alignment to store any fundamental C data type at a natural alignment. -* For most platforms this will require the memory buffer to have 8-byte -* alignment, but refer to the Application Binary Interface (ABI) of the -* target platform for details. -* -* @param context: A pointer to an initialized TEE Context -* @param sharedMem: A pointer to a Shared Memory structure to allocate: \n -* Before calling this function, the Client Application MUST have set -* the \a size, and \a flags fields. \n -* On return, for a successful allocation the Implementation -* MUST have set the pointer buffer to the address of the allocated block, -* otherwise it MUST set buffer to NULL. -* -* @return TEEC_Result: -* TEEC_SUCCESS: The allocation was successful. \n -* TEEC_ERROR_*: An implementation-defined error code for any other error. -* -*/ -TEEC_Result TEEC_AllocateSharedMemory( - TEEC_Context* context, - TEEC_SharedMemory* sharedMem); - - -/** -* @brief Release a shared memory block. -* -* This function deregisters or deallocates a previously initialized block of -* Shared Memory. -* For a memory buffer allocated using \a TEEC_AllocateSharedMemory the -* Implementation MUST free the underlying memory and the Client Application -* MUST NOT access this region after this function has been called. -* In this case the Implementation MUST set the \a buffer and \a size fields -* of the \a sharedMem structure to NULL and 0 respectively before returning. -* -* For memory registered using \a TEEC_RegisterSharedMemory -* the Implementation MUST deregister the underlying memory from the TEE, -* but the memory region will stay available to the Client Application for -* other purposes as the memory is owned by it. -* -* The Implementation MUST do nothing if the \a sharedMem parameter is \a NULL. -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Attempting to release Shared Memory which is used by a -* pending operation. \n -* Attempting to release the same Shared Memory structure concurrently -* from multiple threads. Multi-threaded Client Applications -* must use platform-provided locking mechanisms to ensure that -* this case does not occur. -* -* @param sharedMem: A pointer to a valid Shared Memory structure \n -* -*/ -void TEEC_ReleaseSharedMemory( - TEEC_SharedMemory* sharedMem); - - -/** -* @brief Opens a new session between client and trusted application -* -* -* This function opens a new Session between the Client Application and -* the specified Trusted Application. -* -* The Implementation MUST assume that all fields of this \a session structure -* are in an \a undefined state. When this function returns \a TEEC_SUCCESS -* the Implementation MUST have populated this structure with any information -* necessary for subsequent operations within the Session. -* -* The target Trusted Application is identified by a UUID passed in the -* parameter destination. -* -* The Session MAY be opened using a specific connection method that can carry -* additional connection data, such as data about the user or user-group running -* the Client Application, or about the Client Application itself. -* This allows the Trusted Application to implement access control methods -* which separate functionality or data accesses for different actors -* in the rich environment outside of the TEE. The additional data associated -* with each connection method is passed in via the pointer \a connectionData. -* For the core login types the following connection data is required: -* -* \a TEEC_LOGIN_PUBLIC - \a connectionData SHOULD be \a NULL.\n -* \a TEEC_LOGIN_USER - \a connectionData SHOULD be \a NULL.\n -* \a TEEC_LOGIN_GROUP - \a connectionData MUST point to a uint32_t -* which contains the group which this Client Application wants to connect as. -* The Implementation is responsible for securely ensuring that the -* Client Application instance is actually a member of this group.\n -* \a TEEC_LOGIN_APPLICATION - \a connectionData SHOULD be \a NULL.\n -* \a TEEC_LOGIN_USER_APPLICATION - \a connectionData SHOULD be \a NULL.\n -* \a TEEC_LOGIN_GROUP_APPLICATION - \a connectionData MUST point to a uint32_t -* which contains the group which this Client Application wants to connect as. -* The Implementation is responsible for securely ensuring that the -* Client Application instance is actually a member of this group.\n -* -* An open-session operation MAY optionally carry an Operation Payload, -* and MAY also be cancellable. When the payload is present the parameter -* \a operation MUST point to a \a TEEC_Operation structure populated by the -* Client Application. If \a operation is NULL then no data buffers are -* exchanged with the Trusted Application, and the operation cannot be -* cancelled by the Client Application. -* -* The result of this function is returned both in the function -* \a TEEC_Result return code and the return origin, stored in the variable -* pointed to by \a returnOrigin: \n -* If the return origin is different from \a TEEC_ORIGIN_TRUSTED_APP, -* then the return code MUST be one of the defined error codes . -* If the return code is \a TEEC_ERROR_CANCEL then it means that the -* operation was cancelled before it reached the Trusted Application.\n -* If the return origin is \a TEEC_ORIGIN_TRUSTED_APP, the meaning of the -* return code depends on the protocol between the Client Application -* and the Trusted Application. However, if \a TEEC_SUCCESS is returned, -* it always means that the session was successfully opened and if the -* function returns a code different from \a TEEC_SUCCESS, -* it means that the session opening failed. -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Calling with a \a context which is not yet initialized. \n -* Calling with a connectionData set to NULL if connection data is -* required by the specified connection method. \n -* Calling with an operation containing an invalid paramTypes field, -* i.e., containing a reserved parameter type or where a parameter type -* that conflicts with the parent Shared Memory. \n -* Encoding Registered Memory References which refer to -* Shared Memory blocks allocated within the scope of a different TEE Context. \n -* Attempting to open a Session using the same Session structure -* concurrently from multiple threads. Multi-threaded Client Applications -* must use platform-provided locking mechanisms, to ensure that this -* case does not occur.\n -* Using the same Operation structure for multiple concurrent operations. \n -* -* @param context: A pointer to an initialized TEE Context. -* @param session: A pointer to a Session structure to open. -* @param destination: A pointer to a structure containing the UUID of the -* destination Trusted Application -* @param connectionMethod: The method of connection to use -* @param connectionData: Any necessary data required to support the -* connection method chosen. -* @param operation: A pointer to an Operation containing a set of Parameters -* to exchange with the Trusted Application, or \a NULL if no Parameters -* are to be exchanged or if the operation cannot be cancelled -* @param returnOrigin: A pointer to a variable which will contain the -* return origin. This field may be \a NULL if the return origin is not needed. -* -* @return TEEC_Result: -* TEEC_SUCCESS: The session was successfully opened. \n -* TEEC_ERROR_*: An implementation-defined error code for any other error. -*/ -TEEC_Result TEEC_OpenSession ( - TEEC_Context* context, - TEEC_Session* session, - const TEEC_UUID* destination, - uint32_t connectionMethod, - const void* connectionData, - TEEC_Operation* operation, - uint32_t* returnOrigin); - - -/** -* @brief Close a opened session between client and trusted application -* -* -* This function closes a Session which has been opened with a -* Trusted Application. -* -* All Commands within the Session MUST have completed before -* calling this function. -* -* The Implementation MUST do nothing if the session parameter is NULL. -* -* The implementation of this function MUST NOT be able to fail: -* after this function returns the Client Application must be able to -* consider that the Session has been closed. -* -* \b Programmer \b Error \n -* The following usage of the API is a programmer error:\n -* Calling with a session which still has commands running.\n -* Attempting to close the same Session concurrently from multiple -* threads. \n -* Attempting to close the same Session more than once. -* -* @param session: Session to close -*/ -void TEEC_CloseSession ( - TEEC_Session* session); - - -/** -* @brief Invokes a command within the session -* -* -* This function invokes a Command within the specified Session. -* -* The parameter \a session MUST point to a valid open Session. -* -* The parameter \a commandID is an identifier that is used to indicate -* which of the exposed Trusted Application functions should be invoked. -* The supported command identifiers are defined by the Trusted Application?s -* protocol. -* -* \b Operation \b Handling \n -* A Command MAY optionally carry an Operation Payload. -* When the payload is present the parameter \a operation MUST point to a -* \a TEEC_Operation structure populated by the Client Application. -* If \a operation is NULL then no parameters are exchanged with the -* Trusted Application, and only the Command ID is exchanged. -* -* The \a operation structure is also used to manage cancellation of the -* Command. If cancellation is required then \a the operation pointer MUST be -* \a non-NULL and the Client Application MUST have zeroed the \a started -* field of the \a operation structure before calling this function. -* The \a operation structure MAY contain no Parameters if no data payload -* is to be exchanged. -* -* The Operation Payload is handled as described by the following steps, -* which are executed sequentially: \n -* 1. Each Parameter in the Operation Payload is examined. -* If the parameter is a Temporary Memory Reference, then it is registered -* for the duration of the Operation in accordance with the fields set in -* the \a TEEC_TempMemoryReference structure and the data flow direction -* specified in the parameter type. Refer to the \a TEEC_RegisterSharedMemory -* function for error conditions which can be triggered during -* temporary registration of a memory region. \n -* 2. The contents of all the Memory Regions which are exchanged -* with the TEE are synchronized \n -* 3. The fields of all Value Parameters tagged as input are read by the -* Implementation. This applies to Parameters of type \a TEEC_VALUE_INPUT or -* \a TEEC_VALUE_INOUT. \n -* 4. The Operation is issued to the Trusted Application. -* During the execution of the Command, the Trusted Application may read -* the data held within the memory referred to by input Memory References. -* It may also write data in to the memory referred to by -* output Memory References, but these modifications are not guaranteed -* to be observable by the Client Application until the command completes. \n -* 5. After the Command has completed, the Implementation MUST update the -* \a size field of the Memory Reference structures flagged as output: \n -* -* a. For Memory References that are non-null and marked as output, -* the updated size field MAY be less than or equal to original size field. -* In this case this indicates the number of bytes actually written by the -* Trusted Application, and the Implementation MUST synchronize this region -* with the Client Application memory space. \n -* b. For all Memory References marked as output, the updated size -* field MAY be larger than the original size field. -* For null Memory References, a required buffer size MAY be specified by -* the Trusted Application. In these cases the passed output buffer was -* too small or absent, and the returned size indicates the size of the -* output buffer which is necessary for the operation to succeed. -* In these cases the Implementation SHOULD NOT synchronize any -* shared data with the Client Application.\n\n -* -* 6. When the Command completes, the Implementation MUST update the fields -* of all Value Parameters tagged as output, -* i.e., of type \a TEEC_VALUE_OUTPUT or \a TEEC_VALUE_INOUT. \n -* 7. All memory regions that were temporarily registered at the -* beginning of the function are deregistered as if the function -* \a TEEC_ReleaseSharedMemory was called on each of them. -* 8. Control is passed back to the calling Client Application code. \n -* \b Programmer \b Error \n. -* -* The result of this function is returned both in the function -* \a TEEC_Result return code and the return origin, stored in the -* variable pointed to by \a returnOrigin: \n -* If the return origin is different from \a TEEC_ORIGIN_TRUSTED_APP, -* then the return code MUST be one of the error codes. -* If the return code is TEEC_ERROR_CANCEL then it means that the operation -* was cancelled before it reached the Trusted Application.\n -* If the return origin is \a TEEC_ORIGIN_TRUSTED_APP, then the -* meaning of the return code is determined by the protocol exposed by the -* Trusted Application. It is recommended that the Trusted Application -* developer chooses TEEC_SUCCESS (0) to indicate success in their protocol, -* as this means that it is possible for the Client Application developer -* to determine success or failure without looking at the return origin. -* -* \b Programmer \n Error \n -* The following usage of the API is a programmer error:\n -* Calling with a \a session which is not an open session. \n -* Calling with invalid content in the \a paramTypes field of the -* \a operation structure. This invalid behavior includes types which are -* \a Reserved for future use or which conflict with the \a flags -* of the parent Shared Memory block. \n -* Encoding Registered Memory References which refer to -* Shared Memory blocks allocated or registered within the scope of a -* different TEE Context. \n -* Using the same operation structure concurrently for -* multiple operations, whether open Session operations or Command invocations. -* -* @param session: The open Session in which the command will be invoked. -* @param commandID: The identifier of the Command within the -* Trusted Application to invoke. The meaning of each Command Identifier -* must be defined in the protocol exposed by the Trusted Application -* @param operation: A pointer to a Client Application initialized -* \a TEEC_Operation structure, or NULL if there is no payload to send or -* if the Command does not need to support cancellation. -* @param returnOrigin: A pointer to a variable which will contain the -* return origin. This field may be \a NULL if the return origin is not needed. -* -* @return TEEC_Result: -* TEEC_SUCCESS: The command was successfully invoked. \n -* TEEC_ERROR_*: An implementation-defined error code for any other error. -*/ -TEEC_Result TEEC_InvokeCommand( - TEEC_Session* session, - uint32_t commandID, - TEEC_Operation* operation, - uint32_t* returnOrigin); - - -/** -* @brief Request cancellation of pending open session or command invocation. -* -* This function requests the cancellation of a pending open Session operation -* or a Command invocation operation. As this is a synchronous API, -* this function must be called from a thread other than the one executing the -* \a TEEC_OpenSession or \a TEEC_InvokeCommand function. -* -* This function just sends a cancellation signal to the TEE and returns -* immediately; the operation is not guaranteed to have been cancelled -* when this function returns. In addition, the cancellation request is just -* a hint; the TEE or the Trusted Application MAY ignore the -* cancellation request. -* -* It is valid to call this function using a \a TEEC_Operation structure -* any time after the Client Application has set the \a started field of an -* Operation structure to zero. In particular, an operation can be -* cancelled before it is actually invoked, during invocation, and -* after invocation. Note that the Client Application MUST reset -* the started field to zero each time an Operation structure is used -* or re-used to open a Session or invoke a Command if the new operation -* is to be cancellable. -* -* Client Applications MUST NOT reuse the Operation structure for another -* Operation until the cancelled command has actually returned in the thread -* executing the \a TEEC_OpenSession or \a TEEC_InvokeCommand function. -* -* \b Detecting \b cancellation \n -* In many use cases it will be necessary for the Client Application -* to detect whether the operation was actually cancelled, or whether it -* completed normally. \n -* In some implementations it MAY be possible for part of the infrastructure -* to cancel the operation before it reaches the Trusted Application. -* In these cases the return origin returned by \a TEEC_OpenSession or -* \a TEEC_InvokeCommand MUST be either or \a TEEC_ORIGIN_API, -* \a TEEC_ORIGIN_COMMS, \a TEEC_ORIGIN_TEE, and the return code MUST be -* \a TEEC_ERROR_CANCEL. \n -* If the cancellation request is handled by the Trusted Application itself -* then the return origin returned by \a TEEC_OpenSession or -* \a TEEC_InvokeCommand MUST be \a TEE_ORIGIN_TRUSTED_APP, -* and the return code is defined by the Trusted Application?s protocol. -* If possible, Trusted Applications SHOULD use \a TEEC_ERROR_CANCEL -* for their return code, but it is accepted that this is not always -* possible due to conflicts with existing return code definitions in -* other standards. -* -* @param operation: A pointer to a Client Application instantiated -* Operation structure. -*/ -void TEEC_RequestCancellation( - TEEC_Operation* operation); - -/** -* @brief Returns error string. -* -* This function returns the error string value based on error number and -* return origin. -* -* @param error: Error number. -* @param returnOrigin: Origin of the return. -* -* @return char*: Error string value. -* -*/ -char* TEEC_GetError(int error, int returnOrigin); -#ifdef __cplusplus -} -#endif -#endif - diff --git a/client-api/sw_list.h b/client-api/sw_list.h deleted file mode 100755 index 554ebc9..0000000 --- a/client-api/sw_list.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * OpenVirtualization: - * For additional details and support contact developer@sierraware.com. - * Additional documentation can be found at www.openvirtualization.org - * - * Copyright (C) 2011 SierraWare - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * list declrations - */ - -#ifndef __LIB_LIST_H__ -#define __LIB_LIST_H__ - -#define LIST_POISON_PREV 0xDEADBEEF -#define LIST_POISON_NEXT 0xFADEBABE - -/** - * @brief - */ -struct list { - struct list *next, *prev; -}; - -#define INIT_HEAD(__lname) { &(__lname), &(__lname) } -#define LIST_HEAD(_lname) struct list _lname = INIT_HEAD(_lname) -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = ptr; (ptr)->prev = ptr; \ - }while (0); - -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -#define list_for_each(curr, head) \ - for (curr = (head)->next; curr != head; curr = (curr)->next) - -#define list_for_each_entry(ptr, head ,member) \ - for(ptr = list_entry((head)->next, typeof(*ptr), member); \ - &ptr->member != (head); \ - ptr = list_entry(ptr->member.next , typeof(*ptr), member))\ - - -/** - * list_for_each_entry_safe - iterate over list of given type - * safe against removal of list entry - * @param pos: the type * to use as a loop cursor. - * @param n: another type * to use as temporary storage - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * @brief - * - * @param prev - * @param next - * @param new - */ -static inline void __list_add(struct list *prev, - struct list *next, struct list *n) -{ - n->prev = prev; - n->next = next; - prev->next = n; - next->prev = n; -} - -/** - * @brief - * Adds the new node after the given head. - * @param head: List head after which the "new" node should be added. - * @param new: New node that needs to be added to list. - * @note Please note that new node is added after the head. - */ -static inline void list_add(struct list *head, struct list *n) -{ - __list_add(head, head->next, n); -} - -/** - * Adds a node at the tail where tnode points to tail node. - * @param tnode: The current tail node. - * @param new: The new node to be added before tail. - * @note: Please note that new node is added before tail node. - */ -static inline void list_add_tail(struct list *tnode, struct list *n) -{ - __list_add(tnode->prev, tnode, n); -} - -/** - * @brief - * - * @param node - * @param prev - * @param next - */ -static inline void __list_del(struct list *node, - struct list *prev, struct list *next) -{ - prev->next = node->next; - next->prev = node->prev; - node->next = (struct list *)LIST_POISON_NEXT; - node->prev = (struct list *)LIST_POISON_PREV; -} - -/** - * @brief - * Deletes a given node from list. - * @param node: Node to be deleted. - * - * @param node - */ -static inline void list_del(struct list *node) -{ - __list_del(node, node->prev, node->next); -} - -/** - * @brief - * - * @param head - * - * @return - */ -static inline struct list *list_pop_tail(struct list *head) -{ - struct list *dnode = head->prev; - list_del(head->prev); - return dnode; -} - -/** - * @brief - * - * @param head - * - * @return - */ -static inline struct list *list_pop(struct list *head) -{ - struct list *dnode = head->next; - list_del(head->next); - return dnode; -} - -/** - * @brief - * - * @param head - * - * @return - */ -static inline int list_empty(struct list *head) -{ - return (head->next == head); -} - -#endif /* __LIB_LIST_H__ */ diff --git a/client-api/tee_protocol.h b/client-api/tee_protocol.h deleted file mode 100755 index c450b9e..0000000 --- a/client-api/tee_protocol.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __TEE_PROTOCOL_H__ -#define __TEE_PROTOCOL_H__ - -#include "tee_types.h" - - -#define TE_IOCTL_MAGIC_NUMBER ('t') -#define TE_IOCTL_OPEN_CLIENT_SESSION \ - _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x10, union te_cmd) -#define TE_IOCTL_CLOSE_CLIENT_SESSION \ - _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x11, union te_cmd) -#define TE_IOCTL_LAUNCH_OPERATION \ - _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd) -#define TE_IOCTL_SHARED_MEM_FREE_REQUEST \ - _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x15, union te_cmd) - -#define TE_IOCTL_MIN_NR _IOC_NR(TE_IOCTL_OPEN_CLIENT_SESSION) -#define TE_IOCTL_MAX_NR _IOC_NR(TE_IOCTL_FILE_REQ_COMPLETE) - -/* shared buffer is 2 pages: 1st are requests, 2nd are params */ -#define TE_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct te_request)) -#define TE_PARAM_MAX (PAGE_SIZE / sizeof(struct te_oper_param)) - -#define MAX_EXT_SMC_ARGS 12 - - - -enum { - TE_PARAM_TYPE_NONE = 0, - TE_PARAM_TYPE_INT_RO = 1, - TE_PARAM_TYPE_INT_RW = 2, - TE_PARAM_TYPE_MEM_RO = 3, - TE_PARAM_TYPE_MEM_RW = 4, -}; - -struct te_oper_param { - uint32_t index; - uint32_t type; - union { - struct { - uint32_t val_a; - uint32_t val_b; - } Int; - struct { - void *base; - void *phys; - uint32_t len; - } Mem; - } u; - void *next_ptr_user; -}; - -struct te_operation { - uint32_t command; - struct te_oper_param *list_head; - /* Maintain a pointer to tail of list to easily add new param node */ - struct te_oper_param *list_tail; - uint32_t list_count; - uint32_t status; - uint32_t iterface_side; -}; - -struct te_service_id { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_and_node[8]; -}; -struct te_answer { - uint32_t result; - uint32_t session_id; - uint32_t result_origin; -}; - -/* - * OpenSession - */ -struct te_opensession { - struct te_service_id dest_uuid; - struct te_operation operation; - struct te_answer answer; -}; - -/* - * CloseSession - */ -struct te_closesession { - struct te_service_id service_id; - uint32_t session_id; - struct te_answer answer; -}; - -/* - * LaunchOperation - */ -struct te_launchop { - struct te_service_id service_id; - uint32_t session_id; - struct te_operation operation; - struct te_answer answer; -}; - -union te_cmd { - struct te_opensession opensession; - struct te_closesession closesession; - struct te_launchop launchop; -}; - -struct te_request { - uint32_t type; - uint32_t session_id; - uint32_t command_id; - struct te_oper_param *params; - uint32_t params_size; - uint32_t dest_uuid[4]; - uint32_t result; - uint32_t result_origin; -}; - -#endif diff --git a/client-api/tee_types.h b/client-api/tee_types.h deleted file mode 100755 index 7712687..0000000 --- a/client-api/tee_types.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __TEE_TYPES_H__ -#define __TEE_TYPES_H__ -#include -/* - * Return Codes - */ -typedef enum TEEC_Result{ -/*!The operation succeeded. \n*/ - TEEC_SUCCESS = 0x0, -/*!Non-specific cause.*/ - TEEC_ERROR_GENERIC = 0xFFFF0000, -/*!Access privileges are not sufficient.*/ - TEEC_ERROR_ACCESS_DENIED = 0xFFFF0001 , -/*!The operation was cancelled.*/ - TEEC_ERROR_CANCEL = 0xFFFF0002 , -/*!Concurrent accesses caused conflict.*/ - TEEC_ERROR_ACCESS_CONFLICT = 0xFFFF0003 , -/*!Too much data for the requested operation was passed.*/ - TEEC_ERROR_EXCESS_DATA = 0xFFFF0004 , -/*!Input data was of invalid format.*/ - TEEC_ERROR_BAD_FORMAT = 0xFFFF0005 , -/*!Input parameters were invalid.*/ - TEEC_ERROR_BAD_PARAMETERS = 0xFFFF0006 , -/*!Operation is not valid in the current state.*/ - TEEC_ERROR_BAD_STATE = 0xFFFF0007, -/*!The requested data item is not found.*/ - TEEC_ERROR_ITEM_NOT_FOUND = 0xFFFF0008, -/*!The requested operation should exist but is not yet implemented.*/ - TEEC_ERROR_NOT_IMPLEMENTED = 0xFFFF0009, -/*!The requested operation is valid but is not supported in this -* Implementation.*/ - TEEC_ERROR_NOT_SUPPORTED = 0xFFFF000A, -/*!Expected data was missing.*/ - TEEC_ERROR_NO_DATA = 0xFFFF000B, -/*!System ran out of resources.*/ - TEEC_ERROR_OUT_OF_MEMORY = 0xFFFF000C, -/*!The system is busy working on something else. */ - TEEC_ERROR_BUSY = 0xFFFF000D, -/*!Communication with a remote party failed.*/ - TEEC_ERROR_COMMUNICATION = 0xFFFF000E, -/*!A security fault was detected.*/ - TEEC_ERROR_SECURITY = 0xFFFF000F, -/*!The supplied buffer is too short for the generated output.*/ - TEEC_ERROR_SHORT_BUFFER = 0xFFFF0010, -/*! The MAC value supplied is different from the one calculated */ - TEEC_ERROR_MAC_INVALID = 0xFFFF3071, -}TEEC_Result; - - -#ifdef __OS_LINUX -#ifndef LOG_NDEBUG -#define LOG_NDEBUG 1 -#endif - -#if LOG_NDEBUG -#define ALOGV(...) ((void)0) -#else -#ifndef ALOGV -#define ALOGV(...) ((void)printf("V/" LOG_TAG ": ")); \ - ((void)printf("(%d) ",__LINE__)); \ - ((void)printf(__VA_ARGS__)); \ - ((void)printf("\n")) - -#endif -#endif - -#ifndef ALOGD -#define ALOGD(...) ((void)printf("D/" LOG_TAG ": ")); \ - ((void)printf("(%d) ",__LINE__)); \ - ((void)printf(__VA_ARGS__)); \ - ((void)printf("\n")) -#endif - -#ifndef ALOGI -#define ALOGI(...) ((void)printf("I/" LOG_TAG ": ")); \ - ((void)printf("(%d) ",__LINE__)); \ - ((void)printf(__VA_ARGS__)); \ - ((void)printf("\n")) -#endif - -#ifndef ALOGW -#define ALOGW(...) ((void)printf("W/" LOG_TAG ": ")); \ - ((void)printf("(%d) ",__LINE__)); \ - ((void)printf(__VA_ARGS__)); \ - ((void)printf("\n")) -#endif - -#ifndef ALOGE -#define ALOGE(...) ((void)printf("E/" LOG_TAG ": ")); \ - ((void)printf("(%d) ",__LINE__)); \ - ((void)printf(__VA_ARGS__)); \ - ((void)printf("\n")) -#endif -#else -#endif - -typedef uint32_t TEE_Result; - -#endif diff --git a/client-api/test_api.c b/client-api/test_api.c deleted file mode 100755 index 7be5a40..0000000 --- a/client-api/test_api.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * OpenVirtualization: - * For additional details and support contact developer@sierraware.com. - * Additional documentation can be found at www.openvirtualization.org - * - * Copyright (C) 2011 SierraWare - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linux trustzone example application. - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sunxi_tee_api.h" -#include "tee_types.h" -#include - - -/*------------------------------------------------------------------------------ - * - * testcase:1 - * test for request sharedmem - * - * - *------------------------------------------------------------------------------*/ - -int test_repreat_request_sharedmem(void) -{ - int cpu = 0; - int i=0; - TEEC_Context context; - TEEC_Session session; - TEEC_Operation operation; - TEEC_SharedMemory sharedMem, sharedMem1, sharedMem2; - TEEC_SharedMemory nonZeroCopysharedMem; - - TEEC_Result result; - static const TEEC_UUID svc_id = - { - 0xF0F0F0F0, 0, 0, - { 0, 0, 0, 0, 0, 0, 0, 0} - }; - uint32_t len; - char testData[256]; - int check_output; - - printf("init context\n"); - result = TEEC_InitializeContext( - NULL, - &context); - - if(result != TEEC_SUCCESS) { - printf("init context failed\n"); - } - for(i=0;i<100;i++){ - printf("loop---%d\n", i); - sharedMem.size = 1024 * 2; - sharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem1.size = 200 * 2; - sharedMem1.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem2.size = 512 * 2; - sharedMem2.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - - result = TEEC_AllocateSharedMemory( - &context, - &sharedMem); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory( - &context, - &sharedMem1); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory( - &context, - &sharedMem2); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - strcpy(sharedMem.buffer, "test 0"); - strcpy(sharedMem1.buffer, "test 1"); - strcpy(sharedMem2.buffer, "test 2"); - - TEEC_ReleaseSharedMemory(&sharedMem); - TEEC_ReleaseSharedMemory(&sharedMem1); - TEEC_ReleaseSharedMemory(&sharedMem2); -} - - TEEC_FinalizeContext(&context); - printf("final context\n"); - - return 0; -} - -/*------------------------------------------------------------------------------ - * - * testcase:1 - * test for communication - * - * - *------------------------------------------------------------------------------*/ -int test_communication(void) -{ - int cpu = 0; - TEEC_Context context; - TEEC_Session session; - TEEC_Operation operation; - TEEC_SharedMemory sharedMem, sharedMem1, sharedMem2; - TEEC_SharedMemory nonZeroCopysharedMem; - - TEEC_Result result; - static const TEEC_UUID svc_id = - { - 0xF0F0F0F0, 0, 0, - { 0, 0, 0, 0, 0, 0, 0, 0} - }; - - uint32_t len; - char testData[256]; - int check_output; - - printf("init context\n"); - result = TEEC_InitializeContext(NULL, &context); - - if(result != TEEC_SUCCESS) { - printf("init context failed\n"); - } - - printf("open session\n"); - result = TEEC_OpenSession( - &context, - &session, - &svc_id, - TEEC_LOGIN_PUBLIC, - NULL, - NULL, - NULL); - - if(result != TEEC_SUCCESS) { - printf("open session failed\n"); - } - sharedMem.size = 1024 * 2; - sharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem1.size = 200 * 2; - sharedMem1.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem2.size = 512 * 2; - sharedMem2.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - - result = TEEC_AllocateSharedMemory(&context, &sharedMem); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory(&context, &sharedMem1); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory(&context, &sharedMem2); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - strcpy(sharedMem.buffer, "test 0"); - strcpy(sharedMem1.buffer, "test 1"); - strcpy(sharedMem2.buffer, "test 2"); - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_NONE); - - operation.started = 1; - operation.params[0].memref.parent = &sharedMem; - operation.params[0].memref.offset = 0; - operation.params[0].memref.size = 0; - - operation.params[1].memref.parent = &sharedMem1; - operation.params[1].memref.offset = 0; - operation.params[1].memref.size = 0; - - operation.params[2].memref.parent = &sharedMem2; - operation.params[2].memref.offset = 0; - operation.params[2].memref.size = 0; - - result = TEEC_InvokeCommand(&session, 0x00001111, &operation, NULL); - if (result != TEEC_SUCCESS) - { - printf("call invoke command error\n"); - } - printf("TEEC output buffer-0: %s [size]:%d\n", (char*)(sharedMem.buffer), operation.params[0].memref.size); - printf("TEEC output buffer-1: %s [size]:%d\n", (char*)(sharedMem1.buffer), operation.params[1].memref.size); - printf("TEEC output buffer-2: %s [size]:%d\n", (char*)(sharedMem2.buffer), operation.params[2].memref.size); - - TEEC_ReleaseSharedMemory(&sharedMem); - TEEC_ReleaseSharedMemory(&sharedMem1); - TEEC_ReleaseSharedMemory(&sharedMem2); - - /*repeat again*/ - sharedMem.size = 100 * 2; - sharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem1.size = 300 * 2; - sharedMem1.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem2.size = 440 * 2; - sharedMem2.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - result = TEEC_AllocateSharedMemory(&context, &sharedMem); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory(&context, &sharedMem1); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory(&context, &sharedMem2); - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - strcpy(sharedMem.buffer, "1--test 0"); - strcpy(sharedMem1.buffer, "1--test 1"); - strcpy(sharedMem2.buffer, "1--test 2"); - printf("TEEC output buffer-0: %s [size]:%d\n", (char*)(sharedMem.buffer), operation.params[0].memref.size); - printf("TEEC output buffer-1: %s [size]:%d\n", (char*)(sharedMem1.buffer), operation.params[1].memref.size); - printf("TEEC output buffer-2: %s [size]:%d\n", (char*)(sharedMem2.buffer), operation.params[2].memref.size); - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_NONE); - - operation.started = 1; - operation.params[0].memref.parent = &sharedMem; - operation.params[0].memref.offset = 0; - operation.params[0].memref.size = 0; - - operation.params[1].memref.parent = &sharedMem1; - operation.params[1].memref.offset = 0; - operation.params[1].memref.size = 0; - - operation.params[2].memref.parent = &sharedMem2; - operation.params[2].memref.offset = 0; - operation.params[2].memref.size = 0; - - result = TEEC_InvokeCommand(&session, 0x00001111, &operation, NULL); - if (result != TEEC_SUCCESS) - { - printf("call invoke command error\n"); - } - printf("TEEC output buffer-1-0: %s [size]:%d\n", (char*)(sharedMem.buffer), operation.params[0].memref.size); - printf("TEEC output buffer-1-1: %s [size]:%d\n", (char*)(sharedMem1.buffer), operation.params[1].memref.size); - printf("TEEC output buffer-1-2: %s [size]:%d\n", (char*)(sharedMem2.buffer), operation.params[2].memref.size); - - TEEC_ReleaseSharedMemory(&sharedMem); - TEEC_ReleaseSharedMemory(&sharedMem1); - TEEC_ReleaseSharedMemory(&sharedMem2); - - sharedMem.size = 5000 * 2; - sharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem1.size = 10000 * 2; - sharedMem1.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - sharedMem2.size = 440 * 2; - sharedMem2.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT ; - - - result = TEEC_AllocateSharedMemory(&context, &sharedMem); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory( - &context, - &sharedMem1); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - result = TEEC_AllocateSharedMemory( - &context, - &sharedMem2); - - if(result != TEEC_SUCCESS) { - printf("allocate share memory fail"); - } - - strcpy(sharedMem.buffer, "222222222--test 0"); - strcpy(sharedMem1.buffer, "122222222--test 1"); - strcpy(sharedMem2.buffer, "122222222--test 2"); - printf("TEEC output buffer-0: %s [size]:%d\n", (char*)(sharedMem.buffer), operation.params[0].memref.size); - printf("TEEC output buffer-1: %s [size]:%d\n", (char*)(sharedMem1.buffer), operation.params[1].memref.size); - printf("TEEC output buffer-2: %s [size]:%d\n", (char*)(sharedMem2.buffer), operation.params[2].memref.size); - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, - TEEC_NONE); - - operation.started = 1; - - operation.params[0].memref.parent = &sharedMem; - operation.params[0].memref.offset = 0; - operation.params[0].memref.size = 0; - - operation.params[1].memref.parent = &sharedMem1; - operation.params[1].memref.offset = 0; - operation.params[1].memref.size = 0; - - operation.params[2].memref.parent = &sharedMem2; - operation.params[2].memref.offset = 0; - operation.params[2].memref.size = 0; - - result = TEEC_InvokeCommand( - &session, - 0x00001111, - &operation, - NULL); - if (result != TEEC_SUCCESS) - { - printf("call invoke command error\n"); - } - printf("TEEC output buffer-2-0: %s [size]:%d\n", (char*)(sharedMem.buffer), operation.params[0].memref.size); - printf("TEEC output buffer-2-1: %s [size]:%d\n", (char*)(sharedMem1.buffer), operation.params[1].memref.size); - printf("TEEC output buffer-2-2: %s [size]:%d\n", (char*)(sharedMem2.buffer), operation.params[2].memref.size); - TEEC_ReleaseSharedMemory(&sharedMem); - TEEC_ReleaseSharedMemory(&sharedMem1); - TEEC_ReleaseSharedMemory(&sharedMem2); - - - TEEC_CloseSession(&session); - TEEC_FinalizeContext(&context); - printf("final context\n"); - - return 0; -} - -/*------------------------------------------------------------------------------ - * - * testcase:1 - * test for crypto - * - * - *------------------------------------------------------------------------------*/ -int test_crypto_api() -{ - int cpu = 0; - TEEC_Context context; - TEEC_Session session; - TEEC_Operation operation; - TEEC_Result result; - static const TEEC_UUID svc_id = - { - 0x12345678, 0, 0, - { 0, 0, 0, 0, 0, 0, 0, 0} - }; - - uint32_t len; - char testData[256]; - int check_output; - - - printf("init context\n"); - - result = TEEC_InitializeContext( - NULL, - &context); - - if(result != TEEC_SUCCESS) { - printf("init context failed\n"); - } - - printf("open session\n"); - result = TEEC_OpenSession( - &context, - &session, - &svc_id, - TEEC_LOGIN_PUBLIC, - NULL, - NULL, - NULL); - - if(result != TEEC_SUCCESS) { - printf("open session failed\n"); - } - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_NONE, - TEEC_NONE, - TEEC_NONE, - TEEC_NONE); - - operation.started = 1; - - result = TEEC_InvokeCommand(&session, 0x00001111, &operation, NULL); - if (result != TEEC_SUCCESS) - { - printf("call invoke command error\n"); - } - - TEEC_CloseSession(&session); - TEEC_FinalizeContext(&context); - printf("final context\n"); - - return 0; -} - - -/*------------------------------------------------------------------------------ - * - * testcase:1 - * test for multi communication - * - * - *------------------------------------------------------------------------------*/ - -typedef unsigned int u32; -typedef struct CEDARV_STREAM_DATA_INFORMATION -{ - u32 flags; - u32 lengh; - long long pts; - u32 type; -}cedarv_stream_data_info_t; - -static TEEC_Context context; -static TEEC_Session session; - -static unsigned int test_table[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, - 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, - 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, - 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, - 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, - 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, - 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, - 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, - 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, - 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, - 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, - 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, - 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, - 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, - 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, - 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, - 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, - 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, - 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, - 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, - 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, - 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, - 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, - 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, - 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, - 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, - 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, - 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, - 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, - 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, - 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, - 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, - 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, - 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, - 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, - 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, - 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, - 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, - 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - -void *thread_function_1(void *arg) { - //printf("thread %d start\n", (int)arg); - TEEC_Operation operation; - TEEC_SharedMemory sharedMem; - int thread_id = (int)arg; - int counter = 0; - int table_count = sizeof(test_table)/sizeof(unsigned int); - srand(time(NULL)); - while(1) { - cedarv_stream_data_info_t data_info; - data_info.flags = 26; - data_info.lengh = test_table[counter%table_count]; - data_info.pts = rand(); - data_info.type = rand()%2; - - sharedMem.size = sizeof(cedarv_stream_data_info_t); - sharedMem.flags = TEEC_MEM_INPUT; - TEEC_Result result = TEEC_AllocateSharedMemory(&context, &sharedMem); - if(result != TEEC_SUCCESS) { - //printf("allocate share memory fail\n"); - //printf("goto sleep\n"); - abort(); - } - - memcpy(sharedMem.buffer, &data_info, sizeof(cedarv_stream_data_info_t)); - printf("thread[%d]:%d vs 0x%x vs %d\n", thread_id, counter ++, data_info.lengh, data_info.type); - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_VALUE_INPUT, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE); - - operation.started = 1; - operation.params[0].value.a = thread_id; - - operation.params[1].memref.parent = &sharedMem; - operation.params[1].memref.offset = 0; - operation.params[1].memref.size = 0; - - //count times for each thread. - uint32_t commond = (thread_id == 1) ? 0x00002222 : 0x00003333; - - result = TEEC_InvokeCommand(&session, commond, &operation, NULL); - if(result != TEEC_SUCCESS) { - //printf("thread %d failed\n", thread_id); - abort(); - } - TEEC_ReleaseSharedMemory(&sharedMem); - } - pthread_exit(NULL); - return NULL; -} - -void *thread_function_2(void *arg) { - //printf("thread %d start\n", (int)arg); - TEEC_Operation operation; - TEEC_SharedMemory sharedMem; - int thread_id = (int)arg; - int counter = 0; - int table_count = sizeof(test_table)/sizeof(unsigned int); - srand(time(NULL)); - cedarv_stream_data_info_t data_info; - while(1) { - sharedMem.size = sizeof(cedarv_stream_data_info_t); - sharedMem.flags = TEEC_MEM_OUTPUT; - TEEC_Result result = TEEC_AllocateSharedMemory(&context, &sharedMem); - if(result != TEEC_SUCCESS) { - //printf("allocate share memory fail\n"); - //printf("goto sleep\n"); - abort(); - } - - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_VALUE_INPUT, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE); - - operation.started = 1; - operation.params[0].value.a = 3; - - operation.params[1].memref.parent = &sharedMem; - operation.params[1].memref.offset = 0; - operation.params[1].memref.size = 0; - - result = TEEC_InvokeCommand(&session, 0x00004444, &operation, NULL); - if(result != TEEC_SUCCESS) { - //printf("thread %d failed\n", thread_id); - } - - memcpy(&data_info, sharedMem.buffer, sizeof(cedarv_stream_data_info_t)); - - //printf("thread[%d]:%d vs 0x%x vs 0x%llx vs %d\n", thread_id, counter, data_info.lengh, data_info.pts, data_info.type); - if(data_info.lengh != test_table[counter%table_count]) { - //printf("thread 3 error\n"); - abort(); - } - counter ++; - TEEC_ReleaseSharedMemory(&sharedMem); - } - pthread_exit(NULL); - return NULL; -} - -int test_multi_communication(void) -{ - TEEC_Result result; - static const TEEC_UUID svc_id = - { - 0x000000F0, 0, 0, - { 0, 0, 0, 0, 0, 0, 0, 0} - }; - - //printf("init context\n"); - result = TEEC_InitializeContext(NULL, &context); - - if(result != TEEC_SUCCESS) { - //printf("init context failed\n"); - } - - //printf("open session\n"); - result = TEEC_OpenSession( - &context, - &session, - &svc_id, - TEEC_LOGIN_PUBLIC, - NULL, - NULL, - NULL); - - TEEC_Operation operation; - operation.paramTypes = TEEC_PARAM_TYPES( - TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); - - //printf("clear counter"); - operation.started = 1; - result = TEEC_InvokeCommand(&session, 0x00005555, &operation, NULL); - if(result != TEEC_SUCCESS) { - //printf("invoke failed\n"); - } - - pthread_t thread_1; - pthread_t thread_2; - pthread_t thread_3; - int err ; - //printf("to create thread 1\n"); - err = pthread_create(&thread_1, NULL, thread_function_1, (void*)1); - if(err) { - //printf("create thread 1 failed\n"); - return -1; - } - //printf("to create thread 2\n"); - err = pthread_create(&thread_2, NULL, thread_function_1, (void*)2); - if(err) { - //printf("create thread 2 failed\n"); - return -1; - } - -// //printf("to create thread 3\n"); -// err = pthread_create(&thread_3, NULL, thread_function_2, (void*)3); -// if(err) { -// //printf("create thread 3 failed\n"); -// return -1; -// } - - //printf("goto sleep\n"); - while(1) {sleep(1);} - pthread_join(thread_1, NULL); - pthread_join(thread_2, NULL); - pthread_join(thread_3, NULL); - TEEC_CloseSession(&session); - TEEC_FinalizeContext(&context); - return 0; - -} - - -/*------------------------------------------------------------------------------ - * - * main function - * - * - *------------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int a; - //printf("argc %d\n", argc); - //printf("argv %s\n", *++argv); - a = atoi(*++argv); - switch(a){ - case 1: - test_repreat_request_sharedmem(); - break; - case 2: - test_communication(); - break; - case 3: - test_crypto_api(); - break; - case 4: - test_multi_communication(); - break; - default: - break; - } - return 0; -} - - - - - - - - - - diff --git a/hwc/astar/hwc.cpp b/hwc/astar/hwc.cpp index ca1a1c4..b2ac603 100755 --- a/hwc/astar/hwc.cpp +++ b/hwc/astar/hwc.cpp @@ -188,6 +188,10 @@ int InitAddLayerTail(head_list_t* LayerHead,hwc_layer_1_t *psLayer, int Order,in while((i--)&&(LayerTmp == NULL)) { LayerTmp=(Layer_list_t* )calloc(1, sizeof(Layer_list_t)); + if(LayerTmp == NULL) { + ALOGE("InitAddLayerTail:calloc memory for LayerTmp fail !"); + return 0; + } memset(LayerTmp,0,sizeof(Layer_list_t)); } diff --git a/hwc/astar/hwc_sunxi.cpp b/hwc/astar/hwc_sunxi.cpp index 126e88c..1ba32e5 100755 --- a/hwc/astar/hwc_sunxi.cpp +++ b/hwc/astar/hwc_sunxi.cpp @@ -39,8 +39,8 @@ static int _hwcdev_is_valid_format(int format) case HAL_PIXEL_FORMAT_RGB_888: case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_sRGB_A_8888: - case HAL_PIXEL_FORMAT_sRGB_X_8888: + //case HAL_PIXEL_FORMAT_sRGB_A_8888: + //case HAL_PIXEL_FORMAT_sRGB_X_8888: case HAL_PIXEL_FORMAT_YV12: case HAL_PIXEL_FORMAT_YCrCb_420_SP: return 1; diff --git a/hwc/kylin/hwc.cpp b/hwc/kylin/hwc.cpp index 87eeb5b..4edeb87 100755 --- a/hwc/kylin/hwc.cpp +++ b/hwc/kylin/hwc.cpp @@ -269,7 +269,11 @@ int InitAddLayerTail(head_list_t* LayerHead,hwc_layer_1_t *psLayer, int Order,in Layer_list_t* LayerTmp = NULL; while((i--)&&(LayerTmp == NULL)) { - LayerTmp=(Layer_list_t* )calloc(1, sizeof(Layer_list_t)); + LayerTmp=(Layer_list_t* )calloc(1, sizeof(Layer_list_t)); + if(LayerTmp == NULL) { + ALOGE("InitAddLayerTail:calloc memory for LayerTmp fail !"); + return 0; + } } LayerTmp->pslayer = psLayer; LayerTmp->Order = Order; diff --git a/hwc/tulip/Android.mk b/hwc/tulip/Android.mk index 2b55ae5..0a28468 100755 --- a/hwc/tulip/Android.mk +++ b/hwc/tulip/Android.mk @@ -46,7 +46,7 @@ LOCAL_C_INCLUDES += $(TARGET_HARDWARE_INCLUDE) LOCAL_C_INCLUDES +=system/core/include/ \ system/core/libion/include/ \ system/core/libsync/include/ -LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE := hwcomposer.tulip LOCAL_CFLAGS:= -DLOG_TAG=\"hwcomposer\" LOCAL_MODULE_TAGS := optional TARGET_GLOBAL_CFLAGS += -DTARGET_BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) diff --git a/hwc/tulip/hwc.h b/hwc/tulip/hwc.h index 950c59c..4dd53e1 100755 --- a/hwc/tulip/hwc.h +++ b/hwc/tulip/hwc.h @@ -185,6 +185,7 @@ typedef struct { int share_fd;//ion_handle share_fd int size_buffer; bool valid; + bool is_secure; }hwc_cache_t; typedef struct { @@ -207,6 +208,7 @@ typedef struct { int share_fd; bool needsync;//for sw_write bool iscursor; + bool is_secure; disp_layer_config hwc_layer_info; }hwc_commit_layer_t; @@ -286,6 +288,7 @@ typedef struct layer_info { bool is3D; bool is_cursor; bool need_sync; + bool is_secure; int shared_fd; format_info form_info; AssignDUETO_T info; @@ -312,7 +315,6 @@ typedef struct{ bool VsyncEnable; bool issecure; bool active; - bool setblank; int HwChannelNum; int LayerNumofCH; @@ -460,6 +462,10 @@ typedef struct int fb_pre_mem; /* end mem limit */ int unblank_flag; + bool isFreeFB; + bool isNeedSecureBuffer; + unsigned char has_secure; + unsigned char has_3D; }SUNXI_hwcdev_context_t; @@ -603,6 +609,8 @@ static inline int check_valid_format(int format) //case HAL_PIXEL_FORMAT_RGB_888: case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_BGRA_8888: + //case HAL_PIXEL_FORMAT_sRGB_A_8888: + //case HAL_PIXEL_FORMAT_sRGB_X_8888: case HAL_PIXEL_FORMAT_YV12: case HAL_PIXEL_FORMAT_YCrCb_420_SP: case HAL_PIXEL_FORMAT_BGRX_8888: @@ -688,6 +696,8 @@ static inline bool check_support_blending(int format) case HAL_PIXEL_FORMAT_RGB_888: case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_BGRA_8888: + //case HAL_PIXEL_FORMAT_sRGB_A_8888: + //case HAL_PIXEL_FORMAT_sRGB_X_8888: case HAL_PIXEL_FORMAT_BGRX_8888: return 1; default: diff --git a/hwc/tulip/hwc_commit.cpp b/hwc/tulip/hwc_commit.cpp index 35b7eb0..1e07b4e 100755 --- a/hwc/tulip/hwc_commit.cpp +++ b/hwc/tulip/hwc_commit.cpp @@ -545,24 +545,31 @@ deal_fence: arg[1] = (unsigned long)(&hwc_cmd); ret = ioctl(Globctx->DisplayFd, DISP_HWC_COMMIT, (unsigned long)arg); } - if(Globctx->unblank_flag) + /* fixed when resume display error */ + if(Globctx->unblank_flag) + { + if(unblank_count == 1) + { + DisplayInfo *PsDisplayInfo = &Globctx->SunxiDisplay[DisplayData->first_disp]; + if(PsDisplayInfo->VirtualToHWDisplay != -EINVAL) + { + arg[0] = PsDisplayInfo->VirtualToHWDisplay; + arg[1] = 0; + if(ioctl(Globctx->DisplayFd, DISP_BLANK, (unsigned long)arg) != 0) + ALOGE("##########unblank error!"); + } + Globctx->unblank_flag = 0; + unblank_count = 0; + } + unblank_count++; + } + /* when the FB unused,free memory */ + if(!Globctx->isFreeFB) { - if(unblank_count == 1) - { - unsigned long arg[4]={0}; - DisplayInfo *PsDisplayInfo = &Globctx->SunxiDisplay[DisplayData->first_disp]; - if(PsDisplayInfo->VirtualToHWDisplay != -EINVAL) - { - arg[0] = PsDisplayInfo->VirtualToHWDisplay; - arg[1] = 0; - if(ioctl(Globctx->DisplayFd, DISP_BLANK, (unsigned long)arg) != 0) - ALOGE("##########unblank error!"); - } - Globctx->unblank_flag = 0; - unblank_count = 0; - } - unblank_count++; - } + if(ioctl(Globctx->FBFd, FBIO_FREE, (unsigned long)arg) == -1) + ALOGE("##########FBIO_FREE ioctl failed: %s", strerror(errno)); + Globctx->isFreeFB = true; + } /* check wb and display to HDMI or miracast */ /* update cursor disp data */ diff --git a/hwc/tulip/hwc_mem_ctrl.cpp b/hwc/tulip/hwc_mem_ctrl.cpp index 16e20b9..c4d0fed 100755 --- a/hwc/tulip/hwc_mem_ctrl.cpp +++ b/hwc/tulip/hwc_mem_ctrl.cpp @@ -144,6 +144,11 @@ void hwc_down_limit(SUNXI_hwcdev_context_t *Globctx, int local_mem[NUMBEROFDISPL { HWC_UNREFERENCED_PARAMETER(local_mem); int i = 0, tmp_mem_thruput0 = 0; + if((Globctx->has_secure != 0) || (Globctx->has_3D != 0)) + { + Globctx->memlimit = Globctx->max_mem_limit; + return; + } if(Globctx->ForceGPUComp[0] == 0 && Globctx->CanForceGPUCom && force_gpu) { if(Globctx->psHwcProcs != NULL diff --git a/hwc/tulip/hwc_others.cpp b/hwc/tulip/hwc_others.cpp index 6f0a792..7c7b178 100755 --- a/hwc/tulip/hwc_others.cpp +++ b/hwc/tulip/hwc_others.cpp @@ -129,8 +129,6 @@ int _hwc_device_set_enhancemode(int disp, bool on_off, bool half) int _hwc_device_set_output_mode(int disp, int out_type, int out_mode) { SUNXI_hwcdev_context_t *Globctx = &gSunxiHwcDevice; - if(Globctx->SunxiDisplay[0].DisplayType == DISP_OUTPUT_TYPE_HDMI) - disp = 0; DisplayInfo *PsDisplayInfo = &Globctx->SunxiDisplay[disp]; int disp_t; @@ -149,8 +147,6 @@ int _hwc_set_persent(int disp,int para0, int para1) { SUNXI_hwcdev_context_t *Globctx = &gSunxiHwcDevice; DisplayInfo *PsDisplayInfo = NULL; - if(Globctx->SunxiDisplay[0].DisplayType == DISP_OUTPUT_TYPE_HDMI) - disp = 0; PsDisplayInfo = &Globctx->SunxiDisplay[disp]; if(PsDisplayInfo->VirtualToHWDisplay != -1 && PsDisplayInfo->DisplayType == DISP_OUTPUT_TYPE_HDMI) diff --git a/hwc/tulip/hwc_rotate.cpp b/hwc/tulip/hwc_rotate.cpp index 5d341ae..b0a2d59 100755 --- a/hwc/tulip/hwc_rotate.cpp +++ b/hwc/tulip/hwc_rotate.cpp @@ -129,7 +129,7 @@ static rotate_cache_t *hwc_ratate_cache_manage(SUNXI_hwcdev_context_t *Globctx, return ratate_cache; } -static hwc_cache_t *hwc_tr_cache_get(rotate_cache_t *rotate_cache, int size, int fd, unsigned int sync_count) +static hwc_cache_t *hwc_tr_cache_get(rotate_cache_t *rotate_cache, int size, int fd, unsigned int sync_count, bool is_secure) { SUNXI_hwcdev_context_t *Globctx = &gSunxiHwcDevice; hwc_cache_t *tr_cache = NULL; @@ -163,7 +163,7 @@ static hwc_cache_t *hwc_tr_cache_get(rotate_cache_t *rotate_cache, int size, int close(tr_cache->fd); tr_cache->fd = -1; } - if(tr_cache->share_fd >= 0 && size <= tr_cache->size_buffer) + if(tr_cache->share_fd >= 0 && size <= tr_cache->size_buffer && tr_cache->is_secure == is_secure) { if(tr_cache->size_buffer - size > 4096) { @@ -181,22 +181,35 @@ static hwc_cache_t *hwc_tr_cache_get(rotate_cache_t *rotate_cache, int size, int } if(tr_cache->share_fd == -1 || tr_cache->size_buffer == 0) { - ret = ion_alloc_fd(Globctx->IonFd, size, - 4096, ION_HEAP_TYPE_DMA_MASK, 0, &tr_cache->share_fd); - if(ret < 0) - { - ALOGD("alloc err from ION_HEAP_TYPE_DMA_MASK"); - ret = ion_alloc_fd(Globctx->IonFd, size, - 4096, ION_HEAP_SYSTEM_CONTIG_MASK, 0, &tr_cache->share_fd); + if(is_secure){ + ret = ion_alloc_fd(Globctx->IonFd, size, + 4096, ION_HEAP_SECURE_MASK, 0, &tr_cache->share_fd); if(ret < 0) { - ALOGD("alloc err from ION_HEAP_SYSTEM_CONTIG_MASK"); - tr_cache->share_fd = -1; - tr_cache->size_buffer = 0; - return NULL; + ALOGD("alloc err from ION_HEAP_SECURE_MASK"); + return NULL; } - } - ion_sync_fd(Globctx->IonFd, tr_cache->share_fd); + tr_cache->is_secure = 1; + }else{ + ret = ion_alloc_fd(Globctx->IonFd, size, + 4096, ION_HEAP_TYPE_DMA_MASK, 0, &tr_cache->share_fd); + if(ret < 0) + { + ALOGD("alloc err from ION_HEAP_TYPE_DMA_MASK"); + ret = ion_alloc_fd(Globctx->IonFd, size, + 4096, ION_HEAP_SYSTEM_CONTIG_MASK, 0, &tr_cache->share_fd); + if(ret < 0) + { + ALOGD("alloc err from ION_HEAP_SYSTEM_CONTIG_MASK"); + tr_cache->share_fd = -1; + tr_cache->size_buffer = 0; + return NULL; + } + } + } + if(!is_secure){ + ion_sync_fd(Globctx->IonFd, tr_cache->share_fd); + } tr_cache->size_buffer = size; } tr_cache->sync_cnt = sync_count; @@ -645,7 +658,7 @@ bool hwc_rotate_layer_tr(hwc_dispc_data_t *hwc_layer, goto translat_err; } tr_cache = hwc_tr_cache_get(rotate_cache, size, - commit_data->releasefencefd[disp], hwc_layer->sync_count); + commit_data->releasefencefd[disp], hwc_layer->sync_count,commit_layer->is_secure); if(tr_cache != NULL) { memset(&tr_info, 0, sizeof(tr_info)); diff --git a/hwc/tulip/hwc_sunxi.cpp b/hwc/tulip/hwc_sunxi.cpp index d4cf169..0a1febb 100755 --- a/hwc/tulip/hwc_sunxi.cpp +++ b/hwc/tulip/hwc_sunxi.cpp @@ -178,6 +178,8 @@ static bool reset_globle(SUNXI_hwcdev_context_t *Globctx, Globctx->currentmem = 0; Globctx->has_tr_mem = 0; Globctx->has_tr_cnt = 0; + Globctx->has_secure = 0; + Globctx->has_3D = 0; int tmp_mem_thruput0 = 0; int all_mem_diff = 0, all_mem = 0, all_mem_fb = 0, ture_disp; for(i = 0; i < (int)NumofDisp && i < Globctx->NumberofDisp; i++) @@ -262,7 +264,7 @@ static bool reset_globle(SUNXI_hwcdev_context_t *Globctx, Globctx->stop_rotate_hw = 0; } Globctx->fb_pre_mem = all_mem_fb; - if(all_mem > (7 * Globctx->SunxiDisplay[0].InitDisplayHeight + if(all_mem > (9 * Globctx->SunxiDisplay[0].InitDisplayHeight * Globctx->SunxiDisplay[0].InitDisplayWidth * 4)) { @@ -924,24 +926,6 @@ static bool resize_layer(HwcDisContext_t *Localctx, layer_info->fb.crop.y = fb_crop->top + ((cut_top == 1) ? cut_mod:0); layer_info->fb.crop.height = srcdiff - cut_mod; } - -#if defined(HWC_DEBUG) - ALOGD("\nold:\n[%f,%f]#S[%lld,%lld,%lld,%lld] F[%lld,%lld,%lld,%lld]\n", - Localctx->WidthScaleFactor, Localctx->HighetScaleFactor, - layer_info->fb.crop.x, layer_info->fb.crop.y, layer_info->fb.crop.width, - layer_info->fb.crop.height, layer_info->screen_win.x, layer_info->screen_win.y, - layer_info->screen_win.width, layer_info->screen_win.height); -#endif - - if(gSunxiHwcDevice.SunxiDisplay[0].DisplayType == DISP_OUTPUT_TYPE_HDMI) { - layer_info->fb.crop.x = (long long)(((long long)(psLayer->sourceCrop.left)) << 32); - layer_info->fb.crop.width = (long long)(((long long)(psLayer->sourceCrop.right)) << 32); - layer_info->fb.crop.width -= layer_info->fb.crop.x; - layer_info->fb.crop.y = (long long)(((long long)(psLayer->sourceCrop.top)) << 32); - layer_info->fb.crop.height = (long long)(((long long)(psLayer->sourceCrop.bottom)) << 32); - layer_info->fb.crop.height -= layer_info->fb.crop.y; - } - if(layer_info->b_trd_out == 1) { switch(PsDisplayInfo->Current3DMode) @@ -1045,7 +1029,7 @@ ret_ok: HwcAssignStatus hwc_try_assign_layer(HwcDisContext_t *Localctx, size_t singcout, int zOrder) { - bool needchannel = 1, isvideo = 0, isalpha = 0, isFB = 0, has_tr = 0; + bool needchannel = 1, isvideo = 0, isalpha = 0, isFB = 0, has_tr = 0, issecure = 0; bool is3D = 0, need_sync = 0, is_cursor = 0; float WscalFac = 1.0, HscaleFac = 1.0; int CH= -1, tmCnt1 = 0, tmCnt2 = 0, addLayerCnt = 1; @@ -1095,11 +1079,16 @@ HwcAssignStatus hwc_try_assign_layer(HwcDisContext_t *Localctx, size_t singcout, goto assign_gpu; } - if(check_usage_protected(handle) && !PsDisplayInfo->issecure) + if(check_usage_protected(handle)) { - ALOGV("%s:Video Protected", __func__); - dueto = D_VIDEO_PD; - goto assign_gpu; + if(!PsDisplayInfo->issecure) + { + ALOGV("%s:Video Protected", __func__); + dueto = D_VIDEO_PD; + goto assign_gpu; + }else if(Globctx->isNeedSecureBuffer == 1){ + issecure = 1; + } } dueto = check_valid_layer(psLayer); @@ -1239,7 +1228,7 @@ needchannel: } } /*check the mem thruput*/ - if(!is_cursor) + if(!is_cursor && (Globctx->has_secure == 0) && (Globctx->has_3D == 0)) { dueto = calculate_memthruput(Localctx, &Localctx->psAllLayer[singcout], WscalFac, HscaleFac, Localctx->HwCHUsedCnt - CHdiff, isFB, isvideo); @@ -1274,7 +1263,7 @@ needchannel: if(!Localctx->force_gpu && (Localctx->UsedFB? isFB: ((int)singcout == Localctx->numberofLayer - 2))) { - if(mem_ctrl_power_policy(Globctx, Localctx)) + if(mem_ctrl_power_policy(Globctx, Localctx) && (Globctx->has_secure == 0) && (Globctx->has_3D == 0)) { Localctx->force_gpu = 1; goto assigned_need_resigne; @@ -1293,6 +1282,8 @@ assign_overlay: Globctx->has_tr_cnt += has_tr; Localctx->tr_mem += has_tr ? (handle->width * handle->height) : 0; Globctx->has_tr_mem += has_tr ? (handle->width * handle->height) : 0; + Globctx->has_secure += issecure; + Globctx->has_3D += is3D; psCH[Localctx->HwCHUsedCnt - CHdiff].hasVideo = isvideo; psCH[Localctx->HwCHUsedCnt - CHdiff].iCHFormat = @@ -1315,8 +1306,9 @@ assign_overlay: Localctx->psAllLayer[singcout].is3D = is3D; Localctx->psAllLayer[singcout].info = dueto; Localctx->psAllLayer[singcout].isvideo = isvideo; - Localctx->psAllLayer[singcout].need_sync = need_sync; + Localctx->psAllLayer[singcout].need_sync = issecure?0:need_sync; Localctx->psAllLayer[singcout].is_cursor = is_cursor; + Localctx->psAllLayer[singcout].is_secure = issecure; if(is_cursor) { return ASSIGN_CURSOR; @@ -1360,7 +1352,6 @@ int hwc_setup_layer(hwc_dispc_data_t *DisplayData, HwcDisContext_t *Localctx) const DisplayInfo *PsDisplayInfo = Localctx->psDisplayInfo; ChannelInfo_t *psChannelInfo = Localctx->ChannelInfo; struct private_handle_t *handle = NULL; - bool enableLayer = !(PsDisplayInfo->setblank); ture_disp = PsDisplayInfo->VirtualToHWDisplay; if(ture_disp < 0 || ture_disp >= NUMBEROFDISPLAY) @@ -1413,6 +1404,7 @@ int hwc_setup_layer(hwc_dispc_data_t *DisplayData, HwcDisContext_t *Localctx) } hw_layer_config->needsync = psHwlayer_info->need_sync; hw_layer_config->share_fd = dup(psHwlayer_info->shared_fd); + hw_layer_config->is_secure = psHwlayer_info->is_secure; if(check_is_blending(psLayer)) { layer_info->alpha_mode = 2; @@ -1430,7 +1422,7 @@ int hwc_setup_layer(hwc_dispc_data_t *DisplayData, HwcDisContext_t *Localctx) layer_info->zorder = zOrder; layer_info->alpha_value = psChannelInfo[CHCnt].planeAlpha; - psDisconfig->enable = enableLayer; + psDisconfig->enable = 1; psDisconfig->layer_id = LCnt; psDisconfig->channel = psChannelInfo[CHCnt].hasVideo ? VideoCnt : UiCnt; psHwlayer_info->hwchannel = psDisconfig->channel; @@ -1950,6 +1942,7 @@ static int hwc_init_display(void) SUNXI_hwcdev_context_t* hwc_create_device(void) { SUNXI_hwcdev_context_t *Globctx = &gSunxiHwcDevice; + char property[PROPERTY_VALUE_MAX]; unsigned long arg[4] = {0}; int outtype; int open_fd; @@ -2023,11 +2016,10 @@ SUNXI_hwcdev_context_t* hwc_create_device(void) && Globctx->SunxiDisplay[1].VirtualToHWDisplay == -EINVAL) { hwc_hotplug_switch(1, 1, DISP_TV_MODE_NUM); - ALOGD("### init hdmi_plug: IN ###"); } + ALOGD("### init hdmi_plug: IN ###"); }else{ - if(Globctx->SunxiDisplay[0].DisplayType != DISP_OUTPUT_TYPE_HDMI) - ALOGD("### init hdmi_plug: OUT ###"); + ALOGD("### init hdmi_plug: OUT ###"); } close(open_fd); }else{ @@ -2109,7 +2101,18 @@ SUNXI_hwcdev_context_t* hwc_create_device(void) Globctx->layer_st = -1; Globctx->fBeginTime = 0.0; Globctx->uiBeginFrame = 0; - Globctx->unblank_flag = 0; + Globctx->unblank_flag = 0; + Globctx->isFreeFB = false; + Globctx->has_secure = 0; + Globctx->has_3D = 0; + + if (property_get("ro.sys.widevine_oemcrypto_level", property, NULL) >= 0) + { + if (atoi(property) == 1) + Globctx->isNeedSecureBuffer = 1; + else + Globctx->isNeedSecureBuffer = 0; + } hwc_list_init(&Globctx->rotate_cache_list); Globctx->rotate_hold_cnt = 0; diff --git a/hwc/tulip/hwc_uevent.cpp b/hwc/tulip/hwc_uevent.cpp index b45d77a..f8bd940 100755 --- a/hwc/tulip/hwc_uevent.cpp +++ b/hwc/tulip/hwc_uevent.cpp @@ -151,7 +151,6 @@ disp_tv_mode get_suitable_hdmi_mode(int select, disp_tv_mode lastmode) arg[0] = select; int ret, i, j = -1; disp_tv_mode theMostMode = DISP_TV_MODE_NUM; - struct disp_output para; i = sizeof(g_tv_para) / sizeof(g_tv_para[0]); if(lastmode < DISP_TV_MODE_NUM) { @@ -163,42 +162,31 @@ disp_tv_mode get_suitable_hdmi_mode(int select, disp_tv_mode lastmode) return lastmode; } } - - if(Globctx->SunxiDisplay[0].DisplayType == DISP_OUTPUT_TYPE_HDMI) - { - arg[1] = (unsigned long)¶ - ret = ioctl(Globctx->DisplayFd, DISP_GET_OUTPUT, arg); - if(ret >= 0) - { - theMostMode = (disp_tv_mode)para.mode; - } - }else{ - while(i > 0) - { - i--; - if(g_tv_para[i].mode == DISP_TV_MOD_1080P_60HZ) + while(i > 0) + { + i--; + if(g_tv_para[i].mode == DISP_TV_MOD_1080P_60HZ) + { + j = i; + } + if(j != -1) + { + arg[1] = DISP_OUTPUT_TYPE_HDMI; + arg[2] = g_tv_para[i].mode; + ret = ioctl(Globctx->DisplayFd, DISP_DEVICE_SWITCH, arg); + if(ret >= 0) { - j = i; + if(theMostMode == DISP_TV_MODE_NUM) + { + g_tv_para[sizeof(g_tv_para) / sizeof(g_tv_para[0])-1].support = 1<DisplayFd, DISP_DEVICE_SWITCH, arg); - if(ret >= 0) - { - if(theMostMode == DISP_TV_MODE_NUM) - { - g_tv_para[sizeof(g_tv_para) / sizeof(g_tv_para[0])-1].support = 1<setblank = 1; PsDisplayInfo->VarDisplayWidth = get_info_mode(set_mode,WIDTH); PsDisplayInfo->VarDisplayHeight = get_info_mode(set_mode,HEIGHT); PsDisplayInfo->DisplayType = DISP_OUTPUT_TYPE_HDMI; @@ -252,17 +239,11 @@ int hwc_hotplug_switch(int DisplayNum, bool plug, disp_tv_mode set_mode) PsDisplayInfo->InitDisplayWidth = PsDisplayInfo->VarDisplayWidth; } Globctx->memlimit += PsDisplayInfo->InitDisplayHeight * PsDisplayInfo->InitDisplayWidth * 4; - if(Globctx->SunxiDisplay[0].DisplayType != DISP_OUTPUT_TYPE_HDMI) - { - Globctx->hot_plug = 1; - } + Globctx->hot_plug = 1; arg[0] = DisplayNum; arg[1] = DISP_OUTPUT_TYPE_HDMI; arg[2] = set_mode; ioctl(Globctx->DisplayFd, DISP_DEVICE_SWITCH, (unsigned long)arg); - PsDisplayInfo->setblank = 0; - if(Globctx->psHwcProcs && Globctx->psHwcProcs->invalidate) - Globctx->psHwcProcs->invalidate(Globctx->psHwcProcs); arg[0] = DisplayNum; arg[1] = 1; ioctl(Globctx->DisplayFd, DISP_VSYNC_EVENT_EN,(unsigned long)arg); @@ -273,9 +254,7 @@ int hwc_hotplug_switch(int DisplayNum, bool plug, disp_tv_mode set_mode) } ALOGD( "###hdmi plug in, Type:%d, Mode:0x%08x###", PsDisplayInfo->DisplayType, PsDisplayInfo->DisplayMode); - - } - else if(Globctx->SunxiDisplay[0].DisplayType != DISP_OUTPUT_TYPE_HDMI){ + }else{ Globctx->hot_plug = 0; hwc_manage_display(NULL, DisplayNum ,FREE_DISP); } @@ -290,7 +269,7 @@ int hwc_hotplug_switch(int DisplayNum, bool plug, disp_tv_mode set_mode) }else{ ALOGD("###psHwcProcs No register.###"); } - if(!plug && Globctx->SunxiDisplay[0].DisplayType != DISP_OUTPUT_TYPE_HDMI) + if(!plug) { arg[0] = DisplayNum; arg[1] = DISP_OUTPUT_TYPE_NONE; @@ -392,7 +371,7 @@ static int hwc_uevent(void) s = buf; if(count > 0) { - IsVsync = !strcmp(s, "change@/devices/platform/disp"); + IsVsync = !strcmp(s, "change@/devices/soc.0/1000000.disp");// "change@/devices/platform/disp" IsHdmi = !strcmp(s, "change@/devices/virtual/switch/hdmi"); s += strlen(s) + 1; if(IsVsync) @@ -425,7 +404,7 @@ static int hwc_uevent(void) } } - if(IsHdmi && Globctx->SunxiDisplay[0].DisplayType != DISP_OUTPUT_TYPE_HDMI) + if(IsHdmi) { while(s) { diff --git a/libkeymaster/Android.mk b/libkeymaster/Android.mk new file mode 100755 index 0000000..34a5f12 --- /dev/null +++ b/libkeymaster/Android.mk @@ -0,0 +1,53 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# 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. + + +LOCAL_PATH := $(call my-dir) + +######################### + +include $(CLEAR_VARS) +LOCAL_MODULE := libsunxi_crypto +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES_arm := arm/libsunxi_crypto.so +LOCAL_SRC_FILES_arm64 := arm64/libsunxi_crypto.so +LOCAL_MULTILIB := both +include $(BUILD_PREBUILT) + +################################ +include $(CLEAR_VARS) + +LOCAL_MODULE := keystore.exdroid +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MULTILIB := both +LOCAL_MODULE_PATH_32 := $(TARGET_OUT)/lib/hw +LOCAL_MODULE_PATH_64 := $(TARGET_OUT)/lib64/hw +LOCAL_SRC_FILES := module_sunxi.cpp +LOCAL_C_INCLUDES := \ + system/security/keystore \ + libnativehelper/include \ + $(LOCAL_PATH)/include/schw +LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libkeystore_binder \ + libdl \ + libc \ + libcutils \ + libsunxi_crypto +LOCAL_MODULE_TAGS := optional +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +include $(BUILD_SHARED_LIBRARY) diff --git a/libkeymaster/arm/libsunxi_crypto.so b/libkeymaster/arm/libsunxi_crypto.so new file mode 100755 index 0000000..3d70171 Binary files /dev/null and b/libkeymaster/arm/libsunxi_crypto.so differ diff --git a/libkeymaster/arm64/libsunxi_crypto.so b/libkeymaster/arm64/libsunxi_crypto.so new file mode 100755 index 0000000..c3ec95b Binary files /dev/null and b/libkeymaster/arm64/libsunxi_crypto.so differ diff --git a/libkeymaster/include/schw/keymaster_aw.h b/libkeymaster/include/schw/keymaster_aw.h new file mode 100755 index 0000000..62a8e20 --- /dev/null +++ b/libkeymaster/include/schw/keymaster_aw.h @@ -0,0 +1,62 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * 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. + */ +#ifndef __AWKEYMASTER_MODULEAPI_INCLUDE_H_ +#define __AWKEYMASTER_MODULEAPI_INCLUDE_H_ + +#include + +/** + * The id of this module + */ +#define AW_KEYSTORE_KEYMASTER "aw_keymaster" + +/** + * The API level of this version of the header. The allows the implementing + * module to recognize which API level of the client it is dealing with in + * the case of pre-compiled binary clients. + */ +#define AW_KEYMASTER_API_VERSION KEYMASTER_MODULE_API_VERSION_0_2 + +int aw_keymaster_req_libsym(void *handle); + +int aw_schw_generate_keypair(const keymaster0_device_t* dev, + const keymaster_keypair_t key_type, const void* key_params, + uint8_t** keyBlob, size_t* keyBlobLength); + +int aw_schw_import_keypair(const keymaster0_device_t* dev, + const uint8_t* key, const size_t key_length, + uint8_t** key_blob, size_t* key_blob_length); + +int aw_schw_get_keypair_public(const struct keymaster0_device* dev, + const uint8_t* key_blob, const size_t key_blob_length, + uint8_t** x509_data, size_t* x509_data_length); + +int aw_schw_sign_data(const keymaster0_device_t* dev, + const void* params, + const uint8_t* keyBlob, const size_t keyBlobLength, + const uint8_t* data, const size_t dataLength, + uint8_t** signedData, size_t* signedDataLength); + +int aw_schw_verify_data(const keymaster0_device_t* dev, + const void* params, + const uint8_t* keyBlob, const size_t keyBlobLength, + const uint8_t* signedData, const size_t signedDataLength, + const uint8_t* signature, const size_t signatureLength); + + + + +#endif /* AWKEYMASTER_INCLUDE_H */ diff --git a/libkeymaster/include/schw/log_aw.h b/libkeymaster/include/schw/log_aw.h new file mode 100755 index 0000000..4253b12 --- /dev/null +++ b/libkeymaster/include/schw/log_aw.h @@ -0,0 +1,160 @@ + +#ifndef __AWKEYMASTER_LOGAPI_INCLUDE_H_ +#define __AWKEYMASTER_LOGAPI_INCLUDE_H_ + +#include +#include "keymaster_aw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef AW_LOG_OFF +#define AW_LOG +#endif + +#ifndef AW_LOG_TAG +#define AW_LOG_TAG "AW_LOG" +#endif + +#ifdef AW_TRACE_ON +#define AW_TRACE +#endif + +typedef enum _LOG_LEVEL +{ + AW_LOG_TRACE = 0, + AW_LOG_INFO, + AW_LOG_WARNING, + AW_LOG_ERROR +} AW_LOG_LEVEL; + +static const char *log_msg[] = { + "AW_LOG_TRACE", + "AW_LOG_INFO", + "AW_LOG_WARNING", + "AW_LOG_ERROR", +}; + +void _Aw_SCHW_Log(AW_LOG_LEVEL logLevel, const char *msg, ...) +{ + va_list argptr; + va_start(argptr, msg); + ALOGE("%s:(%s:%d) %s",log_msg[logLevel],__FILE__, __LINE__, __FUNCTION__); + va_end(argptr); +} + + +#ifdef AW_LOG +#define Aw_SCHW_Log(a, ...) ((void)_Aw_SCHW_Log(a, AW_LOG_TAG, __VA_ARGS__)) +#else +#define Aw_SCHW_Log(a, ...) \ + do { \ + if (a == AW_LOG_ERROR) \ + ((void)_Aw_SCHW_Log(a, AW_LOG_TAG, __VA_ARGS__)); \ + } while (0) +#endif + +#ifdef AW_TRACE +#define Func_Entry() _Aw_SCHW_Log(AW_LOG_TRACE, AW_LOG_TAG, "%s Entry , Line: %d", __FUNCTION__, __LINE__) +#define Func_Exit() _Aw_SCHW_Log(AW_LOG_TRACE, AW_LOG_TAG, "%s Exit , Line: %d", __FUNCTION__, __LINE__) +#else +#define Func_Entry() ((void *)0) +#define Func_Exit() ((void *)0) +#endif + + +#ifdef __cplusplus +} +#endif + + +//#define AW_KEYMASTER_API_VERSION 0 +#define AW_KEYMASTER_CRYTPO_VERSION 1 + +enum keymaster_cmd_id { + /* + * List the commands by the hardware. + */ + KEYMASTER_SCHW_GENERATE_KEYPAIR = 0x00000001, + KEYMASTER_SCHW_IMPORT_KEYPAIR = 0x00000002, + KEYMASTER_SCHW_GET_KEYPAIR_PUBLIC = 0x00000003, + KEYMASTER_SCHW_SIGN_DATA = 0x00000004, + KEYMASTER_SCHW_VERIFY_DATA = 0x00000005, + +}; + + +struct aw_keymaster_cmd { + keymaster_cmd_id cid; + keymaster_keypair_t key_type; + void* key_params; + uint8_t* key_in; + size_t key_length; +}; +typedef struct aw_keymaster_cmd aw_keymaster_cmd_t; + + +struct aw_keymaster_resp { + keymaster_cmd_id cid; + int32_t status; + uint8_t** keyblob_bk; + size_t* keyblob_Length; +}; +typedef struct aw_keymaster_resp aw_keymaster_resp_t; + + +struct aw_sign_data_cmd { + keymaster_cmd_id cid; + void* sign_param; + uint8_t* key_blob; + size_t key_blen; + uint8_t* data; + size_t data_len; +}; +typedef struct aw_sign_data_cmd aw_sign_data_cmd_t; + + +struct aw_sign_data_resp { + keymaster_cmd_id cid; + int32_t status; + uint8_t** signed_data; + size_t* signed_dlen; +}; +typedef struct aw_sign_data_resp aw_sign_data_resp_t; + + + +struct aw_verify_data_cmd { + keymaster_cmd_id cid; + void* verify_param; + uint8_t* key_blob; + size_t key_blen; + uint8_t* signed_data; + size_t signed_dlen; + uint8_t* signature; + size_t signat_len; +}; +typedef struct aw_verify_data_cmd aw_verity_data_cmd_t; + +struct aw_verify_data_resp { + keymaster_cmd_id cid; + int32_t status; +}; +typedef struct aw_verify_data_resp aw_verity_data_resp_t; + +struct aw_keymaster_handle { + void *libreq; + int (*aw_schw_init)(const char* buf); + int (*aw_schw_close)(void * handle); + int (*aw_schw_send_cmd)(const void *cbuf, uint32_t clen, + const void *rbuf, uint32_t rlen); + int (*aw_schw_abort_err)(void * handle); +}; + +typedef struct aw_keymaster_handle aw_schw_handle_t; + + + + +#endif diff --git a/libkeymaster/module_sunxi.cpp b/libkeymaster/module_sunxi.cpp new file mode 100755 index 0000000..c303ca5 --- /dev/null +++ b/libkeymaster/module_sunxi.cpp @@ -0,0 +1,471 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +typedef UniquePtr Unique_keymaster_device_t; +static aw_schw_handle_t* aw_km_reqst = NULL; + + +int aw_schw_req_libsym(const void *handle) +{ + aw_schw_handle_t *schw_handle = NULL; + + if (handle == NULL) { + ALOGE("%s: handle is NULL ptr \n!",__func__); + return -1; + } + schw_handle = (aw_schw_handle_t *)handle; + + schw_handle->libreq = dlopen("libsunxi_crypto.so", RTLD_NOW); + if (schw_handle->libreq) { + + *(void **)(&schw_handle->aw_schw_init) = + dlsym(schw_handle->libreq,"AWSCHW_load_init"); + if (schw_handle->aw_schw_init == NULL) { + ALOGE("%s:dlsym: Error Loading aw_schw_init!:%s \n",__func__,dlerror()); + dlclose(schw_handle->libreq); + schw_handle->libreq = NULL; + return -1; + } + + + *(void **)(&schw_handle->aw_schw_send_cmd) = + dlsym(schw_handle->libreq,"AWSCHW_send_cmd"); + if (schw_handle->aw_schw_send_cmd == NULL) { + ALOGE("%s:dlsym: Error Loading aw_schw_send_cmd!:%s\n",__func__,dlerror()); + dlclose(schw_handle->libreq ); + schw_handle->libreq = NULL; + return -1; + } + } else { + ALOGE("%s:failed to load libaw_schw library!:%s\n",__func__,dlerror()); + return -1; + } + return 0; +} + + +static void aw_schw_malloc_free(void *ptr, void *pts) +{ + if (ptr != NULL) { + free(ptr); + } + if (pts != NULL) { + free(pts); + } +} + +int aw_schw_generate_keypair(const keymaster0_device_t* dev, + const keymaster_keypair_t key_type, const void* key_params, + uint8_t** keyBlob, size_t* keyBlobLength) +{ + aw_keymaster_cmd_t *send_cmd = NULL; + aw_keymaster_resp_t *resp = NULL; + aw_schw_handle_t *aw_req_handle = NULL; + int ret = 0; + + if (dev->context == NULL) { + ALOGE("aw_km_generate_keypair: Context NULL Ptr Err!"); + return -1; + } + + if (key_params == NULL) { + ALOGE("aw_km_generate_keypair: key_params NULL Ptr Err!"); + return -1; + } + + if (keyBlob == NULL || keyBlobLength == NULL) { + ALOGE("output key blob or length == NULL"); + return -1; + } + + if ((key_type != TYPE_RSA) && (key_type != TYPE_DSA) && (key_type != TYPE_EC)) { + ALOGE("Unsupported key type %d", key_type); + return -1; + } + + send_cmd = (aw_keymaster_cmd_t *)malloc(sizeof(aw_keymaster_cmd_t)); + if (!send_cmd ) { + ALOGE("send malloc fail!"); + return -1; + } + resp = (aw_keymaster_resp_t *)malloc(sizeof(aw_keymaster_resp_t)); + if (!resp) { + ALOGE("send or resp malloc fail!"); + free(send_cmd); + return -1; + } + aw_req_handle =(aw_schw_handle_t *)dev->context; + send_cmd->cid = KEYMASTER_SCHW_GENERATE_KEYPAIR; + send_cmd->key_type = key_type; + send_cmd->key_params = (void*) key_params; + resp->cid = KEYMASTER_SCHW_GENERATE_KEYPAIR; + resp->status = -1; + resp->keyblob_bk = keyBlob; + resp->keyblob_Length = keyBlobLength; + //ALOGE("send cmd!"); + ret = (*aw_req_handle->aw_schw_send_cmd)((void *)(send_cmd), sizeof(aw_keymaster_cmd_t), + (void *)(resp), sizeof(aw_keymaster_resp_t)); + if ( (ret < 0) || (resp->status < 0)) { + ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret); + goto err; + } + +err: + aw_schw_malloc_free(send_cmd, resp); + return ret; +} + + +int aw_schw_import_keypair(const keymaster0_device_t* dev, + const uint8_t* key, const size_t key_length, + uint8_t** key_blob, size_t* key_blob_length) +{ + aw_keymaster_cmd_t *send_cmd = NULL; + aw_keymaster_resp_t *resp = NULL; + aw_schw_handle_t *aw_req_handle = NULL; + int ret = 0; + + //ALOGE("%s:: Enter\n",__func__); + + if (dev->context == NULL) { + ALOGE("qcom_km_import_keypair: Context == NULL"); + return -1; + } + + if (key == NULL) { + ALOGE("Input key == NULL"); + return -1; + } + + if (key_blob == NULL || key_blob_length == NULL) { + ALOGE("Output key blob or length == NULL"); + return -1; + } + send_cmd = (aw_keymaster_cmd_t *)malloc(sizeof(aw_keymaster_cmd_t)); + if (!send_cmd) { + ALOGE("send malloc fail!"); + return -1; + } + resp = (aw_keymaster_resp_t *)malloc(sizeof(aw_keymaster_resp_t)); + if (!resp) { + ALOGE("resp malloc fail!"); + free(send_cmd); + return -1; + } + aw_req_handle =(aw_schw_handle_t *)dev->context; + + send_cmd->cid = KEYMASTER_SCHW_IMPORT_KEYPAIR; + send_cmd->key_in = (uint8_t *)key; + send_cmd->key_length = key_length; + + resp->cid = KEYMASTER_SCHW_IMPORT_KEYPAIR; + resp->status = -1; + resp->keyblob_bk = key_blob; + resp->keyblob_Length = key_blob_length; + ret = (*aw_req_handle->aw_schw_send_cmd)((void *)send_cmd ,sizeof(aw_keymaster_cmd_t), + (void *)resp ,sizeof(aw_keymaster_resp_t)); + if ((ret < 0) || (resp->status < 0)) { + ALOGE("import keypair command failed resp->status = %d ret =%d", resp->status, ret); + goto err; + } + + err: + aw_schw_malloc_free(send_cmd, resp); + return ret; +} + + + +int aw_schw_get_keypair_public(const struct keymaster0_device* dev, + const uint8_t* key_blob, const size_t key_blob_length, + uint8_t** x509_data, size_t* x509_data_length) +{ + aw_keymaster_cmd_t *send_cmd = NULL; + aw_keymaster_resp_t *resp = NULL; + aw_schw_handle_t *aw_req_handle = NULL; + int ret = 0; + + //ALOGE("%s:: Enter\n",__func__); + + if (x509_data == NULL || x509_data_length == NULL) { + ALOGE("Output public key buffer == NULL"); + return -1; + } + + if (x509_data == NULL) { + ALOGE("Supplied key blob was NULL"); + return -1; + } + send_cmd = (aw_keymaster_cmd_t *)malloc(sizeof(aw_keymaster_cmd_t)); + if (!send_cmd) { + ALOGE("send malloc fail!"); + return -1; + } + resp = (aw_keymaster_resp_t *)malloc(sizeof(aw_keymaster_resp_t)); + if (!resp) { + ALOGE("resp malloc fail!"); + free(send_cmd); + return -1; + } + + aw_req_handle =(aw_schw_handle_t *)dev->context; + + send_cmd->cid = KEYMASTER_SCHW_GET_KEYPAIR_PUBLIC; + send_cmd->key_in= (uint8_t *)key_blob; + send_cmd->key_length = key_blob_length; + + resp->cid = KEYMASTER_SCHW_GET_KEYPAIR_PUBLIC; + resp->status = -1; + resp->keyblob_bk = x509_data; + resp->keyblob_Length= x509_data_length; + ret = (*aw_req_handle->aw_schw_send_cmd)((void *)send_cmd ,sizeof(aw_keymaster_cmd_t), + (void *)resp ,sizeof(aw_keymaster_resp_t)); + if ((ret < 0) || (resp->status < 0)) { + ALOGE("get keypair public command failed resp->status = %d ret =%d", resp->status, ret); + goto err; + } + +err: + aw_schw_malloc_free(send_cmd, resp); + return ret; +} + + +int aw_schw_sign_data(const keymaster0_device_t* dev, + const void* params, + const uint8_t* keyBlob, const size_t keyBlobLength, + const uint8_t* data, const size_t dataLength, + uint8_t** signedData, size_t* signedDataLength) +{ + aw_sign_data_cmd_t *sign_cmd = NULL; + aw_sign_data_resp_t *sign_resp = NULL; + aw_schw_handle_t *aw_req_handle = NULL; + int ret = 0; + //ALOGE("%s:: Enter\n",__func__); + if (dev->context == NULL) { + ALOGE("qcom_km_sign_data: Context == NULL"); + return -1; + } + + if (data == NULL) { + ALOGE("input data to sign == NULL"); + return -1; + } + + if (signedData == NULL || signedDataLength == NULL) { + ALOGE("Output signature buffer == NULL"); + return -1; + } + + sign_cmd = (aw_sign_data_cmd_t *)malloc(sizeof(aw_sign_data_cmd_t)); + if (!sign_cmd) { + ALOGE("send malloc fail!"); + return -1; + } + sign_resp = (aw_sign_data_resp_t *)malloc(sizeof(aw_sign_data_resp_t)); + if (!sign_resp) { + ALOGE("resp malloc fail!"); + free(sign_cmd); + return -1; + } + + aw_req_handle =(aw_schw_handle_t *)dev->context; + sign_cmd->cid = KEYMASTER_SCHW_SIGN_DATA ; + sign_cmd->key_blob = (uint8_t *)keyBlob; + sign_cmd->key_blen = (size_t)keyBlobLength; + sign_cmd->sign_param = (void *)params; + sign_cmd->data = (uint8_t *)data; + sign_cmd->data_len = (size_t)dataLength; + sign_resp->status = -1; + sign_resp->cid = KEYMASTER_SCHW_SIGN_DATA; + sign_resp->signed_data = signedData; + sign_resp->signed_dlen = signedDataLength; + + ret = (*aw_req_handle->aw_schw_send_cmd)((void *)sign_cmd ,sizeof(aw_sign_data_cmd_t), + (void *)sign_resp ,sizeof(aw_sign_data_resp_t)); + + if ((ret < 0) || (sign_resp->status < 0)) { + ALOGE("Sign data command failed resp->status = %d ret =%d", sign_resp->status, ret); + goto err; + } + return 0; +err: + aw_schw_malloc_free(sign_cmd, sign_resp); + return -1; + +} + + + +int aw_schw_verify_data(const keymaster0_device_t* dev, + const void* params, + const uint8_t* keyBlob, const size_t keyBlobLength, + const uint8_t* signedData, const size_t signedDataLength, + const uint8_t* signature, const size_t signatureLength) +{ + aw_verity_data_cmd_t *verity_cmd = NULL; + aw_verity_data_resp_t *verity_resp = NULL; + aw_schw_handle_t *aw_req_handle = NULL; + int ret = 0; + //ALOGE("%s:: Enter\n",__func__); + if (dev->context == NULL) { + ALOGE("aw_km_verify_data: Context == NULL"); + return -1; + } + + if (signedData == NULL || signature == NULL) { + ALOGE("data or signature buffers == NULL"); + return -1; + } + + verity_cmd = (aw_verity_data_cmd_t *)malloc(sizeof(aw_verity_data_cmd_t)); + if (!verity_cmd) { + ALOGE("send malloc fail!"); + return -1; + } + verity_resp = (aw_verity_data_resp_t *)malloc(sizeof(aw_verity_data_resp_t)); + if (!verity_resp) { + ALOGE("resp malloc fail!"); + free(verity_cmd); + return -1; + } + aw_req_handle =(aw_schw_handle_t *)dev->context; + verity_cmd->cid = KEYMASTER_SCHW_VERIFY_DATA; + verity_cmd->verify_param = (void*)params; + verity_cmd->key_blob = (uint8_t *)keyBlob; + verity_cmd->key_blen = (size_t)keyBlobLength; + verity_cmd->signed_data = (uint8_t *)signedData; + verity_cmd->signed_dlen = (size_t)signedDataLength; + verity_cmd->signature = (uint8_t *)signature; + verity_cmd->signat_len = (size_t)signatureLength; + + verity_resp->cid = KEYMASTER_SCHW_VERIFY_DATA; + verity_resp->status = -1; + ret = (*aw_req_handle->aw_schw_send_cmd)((void *)verity_cmd ,sizeof(aw_verity_data_cmd_t), + (void *)verity_resp ,sizeof(aw_verity_data_resp_t)); + + if ( (ret < 0) || (verity_resp->status < 0)) { + ALOGE("Verify data command failed resp->status = %d ret =%d", verity_resp->status, ret); + goto err; + } + return 0; +err: + aw_schw_malloc_free(verity_cmd, verity_resp); + return -1; +} + + + +/* Close an opened aw schw instance */ +static int aw_device_close(hw_device_t *dev) { + if (aw_km_reqst) + free(aw_km_reqst); + delete dev; + return 0; +} + +/* + * Generic device handling + */ +static int aw_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) { + + const char *test_buf = {"Aw keymaster module get the app init!"}; + int ret = 0; + + if (strcmp(name, KEYSTORE_KEYMASTER) != 0) + return -EINVAL; + //ALOGE("%s:: Enter AW keymaster\n",__func__); + aw_km_reqst = (aw_schw_handle_t *)malloc(sizeof(aw_schw_handle_t)); + if (aw_km_reqst == NULL) { + ALOGE("Memalloc for aw keymaster handle failed"); + return -1; + } + aw_km_reqst->libreq= NULL; + ret = aw_schw_req_libsym((void*)aw_km_reqst); + if (ret < 0) { + free(aw_km_reqst); + return -1; + } + + (*aw_km_reqst->aw_schw_init)(test_buf); + + Unique_keymaster_device_t dev(new keymaster0_device_t); + if (dev.get() == NULL) + return -ENOMEM; + dev->context = (void *)aw_km_reqst; + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 1; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = aw_device_close; + + dev->flags = 0; + + dev->generate_keypair = aw_schw_generate_keypair; + dev->import_keypair = aw_schw_import_keypair; + dev->get_keypair_public = aw_schw_get_keypair_public; + dev->delete_keypair = NULL; + dev->delete_all = NULL; + dev->sign_data = aw_schw_sign_data; + dev->verify_data = aw_schw_verify_data; + + *device = reinterpret_cast(dev.release()); + + ALOGE("%s:AW keymaster open sucessfully!\n",__func__); + return 0; +} + +static struct hw_module_methods_t keystore_module_methods = { + .open = aw_device_open, +}; + +struct keystore_module HAL_MODULE_INFO_SYM +__attribute__ ((visibility ("default"))) = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = AW_KEYMASTER_API_VERSION, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = KEYSTORE_HARDWARE_MODULE_ID, + .name = "Keymaster AllSoftwinnertech HAL", + .author = "The Android Open Source Project", + .methods = &keystore_module_methods, + .dso = 0, + .reserved = {}, + }, +}; diff --git a/widevine/adapt_optee/widevine_L3/Android.mk b/widevine/adapt_optee/widevine_L3/Android.mk old mode 100644 new mode 100755 diff --git a/widevine/adapt_optee/widevine_L3/CleanSpec.mk b/widevine/adapt_optee/widevine_L3/CleanSpec.mk old mode 100644 new mode 100755 diff --git a/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.jar b/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.jar index ba8e2ce..0d091fd 100755 Binary files a/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.jar and b/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.jar differ diff --git a/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.xml b/widevine/adapt_optee/widevine_L3/com.google.widevine.software.drm.xml old mode 100644 new mode 100755 diff --git a/widevine/adapt_optee/widevine_L3/libdrmdecrypt.so b/widevine/adapt_optee/widevine_L3/libdrmdecrypt.so index be07cb3..c45e9bf 100755 Binary files a/widevine/adapt_optee/widevine_L3/libdrmdecrypt.so and b/widevine/adapt_optee/widevine_L3/libdrmdecrypt.so differ diff --git a/widevine/adapt_optee/widevine_L3/libdrmwvmplugin.so b/widevine/adapt_optee/widevine_L3/libdrmwvmplugin.so index 409cf4d..d79ff61 100755 Binary files a/widevine/adapt_optee/widevine_L3/libdrmwvmplugin.so and b/widevine/adapt_optee/widevine_L3/libdrmwvmplugin.so differ diff --git a/widevine/adapt_optee/widevine_L3/libwvdrmengine.so b/widevine/adapt_optee/widevine_L3/libwvdrmengine.so index 068c280..3b0fde0 100755 Binary files a/widevine/adapt_optee/widevine_L3/libwvdrmengine.so and b/widevine/adapt_optee/widevine_L3/libwvdrmengine.so differ diff --git a/widevine/adapt_optee/widevine_L3/libwvm.so b/widevine/adapt_optee/widevine_L3/libwvm.so index 5a52077..7d752eb 100755 Binary files a/widevine/adapt_optee/widevine_L3/libwvm.so and b/widevine/adapt_optee/widevine_L3/libwvm.so differ