1f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//
2f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  Copyright (C) 2015 Google, Inc.
3f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//
4f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  Licensed under the Apache License, Version 2.0 (the "License");
5f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  you may not use this file except in compliance with the License.
6f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  You may obtain a copy of the License at:
7f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//
8f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  http://www.apache.org/licenses/LICENSE-2.0
9f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//
10f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  Unless required by applicable law or agreed to in writing, software
11f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  distributed under the License is distributed on an "AS IS" BASIS,
12f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  See the License for the specific language governing permissions and
14f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//  limitations under the License.
15f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray//
16f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
17f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#define LOG_TAG "hal_util"
18f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
19f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <hardware/bluetooth.h>
20f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <hardware/hardware.h>
21f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
22f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <dlfcn.h>
23f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <errno.h>
24f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <string.h>
25f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
26f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include "btcore/include/hal_util.h"
27f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include "osi/include/log.h"
28f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
29f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#if defined(OS_GENERIC)
30f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
31f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray// TODO(armansito): All logging macros should include __func__ by default (see
32f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray// Bug: 22671731)
33911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define HULOGERR(fmt, args...)                                          \
34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  LOG_ERROR(LOG_TAG, "[%s] failed to load the Bluetooth library: " fmt, \
35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            __func__, ##args)
36f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
37f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray// TODO(armansito): It might be better to pass the library name in a more
38f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray// generic manner as opposed to hard-coding it here.
39f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguraystatic const char kBluetoothLibraryName[] = "libbluetooth.default.so";
40f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
41911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic int load_bt_library(const struct hw_module_t** module) {
42911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  const char* id = BT_STACK_MODULE_ID;
43911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
44911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  struct hw_module_t* hmi = nullptr;
45f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
46f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  // Always try to load the default Bluetooth stack on GN builds.
47911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  void* handle = dlopen(kBluetoothLibraryName, RTLD_NOW);
48f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  if (!handle) {
49911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    char const* err_str = dlerror();
50f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    HULOGERR("%s", err_str ? err_str : "error unknown");
51f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    goto error;
52f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  }
53f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
54f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  // Get the address of the struct hal_module_info.
55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  hmi = (struct hw_module_t*)dlsym(handle, sym);
56f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  if (!hmi) {
57f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    HULOGERR("%s", sym);
58f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    goto error;
59f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  }
60f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
61f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  // Check that the id matches.
62f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  if (strcmp(id, hmi->id) != 0) {
63f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    HULOGERR("id=%s does not match HAL module ID: %s", id, hmi->id);
64f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    goto error;
65f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  }
66f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
67f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  hmi->dso = handle;
68f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
69f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  // Success.
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  LOG_INFO(LOG_TAG, "[%s] loaded HAL id=%s path=%s hmi=%p handle=%p", __func__,
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           id, kBluetoothLibraryName, hmi, handle);
72f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
73f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  *module = hmi;
74f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  return 0;
75f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
76f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Ugurayerror:
77f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  *module = NULL;
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (handle) dlclose(handle);
79f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
80f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  return -EINVAL;
81f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray}
82f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
83f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#endif  // defined(OS_GENERIC)
84f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonint hal_util_load_bt_library(const struct hw_module_t** module) {
86f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#if defined(OS_GENERIC)
87f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  return load_bt_library(module);
88f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#else  // !defined(OS_GENERIC)
89f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray  return hw_get_module(BT_STACK_MODULE_ID, module);
90f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#endif  // defined(OS_GENERIC)
91f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray}
92