blob: 01db93f12835c643374f82beffe6e0521d470c84 [file] [log] [blame]
/******************************************************************************
*
* 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;
}