| /****************************************************************************** |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| |
| #include <dlfcn.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <time.h> |
| |
| #include "base.h" |
| #include "btcore/include/hal_util.h" |
| #include "support/hal.h" |
| #include "osi/include/hash_functions.h" |
| #include "osi/include/hash_map.h" |
| #include "osi/include/log.h" |
| |
| #define TIMER_BUCKET_COUNT 4 |
| |
| static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data); |
| static int acquire_wake_lock(const char *lock_name); |
| static int release_wake_lock(const char *lock_name); |
| |
| static const bluetooth_device_t *bt_device; |
| |
| static bt_os_callouts_t callouts = { |
| sizeof(bt_os_callouts_t), |
| set_wake_alarm, |
| acquire_wake_lock, |
| release_wake_lock, |
| }; |
| |
| bool hal_open(bt_callbacks_t *callbacks) { |
| hw_module_t *module; |
| if (hal_util_load_bt_library((const struct hw_module_t **)&module)) { |
| return false; |
| } |
| |
| hw_device_t *device; |
| if (module->methods->open(module, BT_STACK_MODULE_ID, &device)) { |
| return false; |
| } |
| |
| bt_device = (bluetooth_device_t *)device; |
| bt_interface = bt_device->get_bluetooth_interface(); |
| if (!bt_interface) { |
| bt_device->common.close((hw_device_t *)&bt_device->common); |
| bt_device = NULL; |
| return false; |
| } |
| |
| bool success = (bt_interface->init(callbacks) == BT_STATUS_SUCCESS); |
| success = success && (bt_interface->set_os_callouts(&callouts) == BT_STATUS_SUCCESS); |
| return success; |
| } |
| |
| void hal_close() { |
| if (bt_interface) { |
| bt_interface->cleanup(); |
| bt_interface = NULL; |
| } |
| |
| if (bt_device) { |
| bt_device->common.close((hw_device_t *)&bt_device->common); |
| bt_device = NULL; |
| } |
| } |
| |
| static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) { |
| static hash_map_t *timers; |
| |
| if (!timers) { |
| timers = hash_map_new(TIMER_BUCKET_COUNT, hash_function_pointer, NULL, NULL, NULL); |
| } |
| |
| timer_t *timer = hash_map_get(timers, cb); |
| if (!timer) { |
| timer = malloc(sizeof(timer_t)); |
| hash_map_set(timers, cb, timer); |
| |
| struct sigevent sigevent; |
| memset(&sigevent, 0, sizeof(sigevent)); |
| sigevent.sigev_notify = SIGEV_THREAD; |
| sigevent.sigev_notify_function = (void (*)(union sigval))cb; |
| sigevent.sigev_value.sival_ptr = data; |
| timer_create(CLOCK_MONOTONIC, &sigevent, timer); |
| } |
| |
| struct itimerspec new_value; |
| new_value.it_value.tv_sec = delay_millis / 1000; |
| new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000; |
| new_value.it_interval.tv_sec = 0; |
| new_value.it_interval.tv_nsec = 0; |
| timer_settime(*timer, 0, &new_value, NULL); |
| |
| return true; |
| } |
| |
| static int acquire_wake_lock(const char *lock_name) { |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int release_wake_lock(const char *lock_name) { |
| return BT_STATUS_SUCCESS; |
| } |