blob: ffc9a2598ede55db570a8385a4102003195fd52e [file] [log] [blame]
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <hardware/hardware.h>
18
19#include <cutils/properties.h>
20
21#include <dlfcn.h>
22#include <string.h>
23#include <pthread.h>
24#include <errno.h>
25#include <limits.h>
26
27#define LOG_TAG "HAL"
28#include <utils/Log.h>
29
30/** Base path of the hal modules */
31#define HAL_LIBRARY_PATH "/system/lib/hw"
32
33/**
34 * There are a set of variant filename for modules. The form of the filename
35 * is "<MODULE_ID>.variant.so" so for the led module the Dream variants
36 * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
37 *
38 * led.trout.so
39 * led.msm7k.so
40 * led.ARMV6.so
41 * led.default.so
42 */
43
44#define HAL_DEFAULT_VARIANT "default"
The Android Open Source Project8232b502009-03-13 13:04:23 -070045static const char *variant_keys[] = {
46 "ro.hardware", /* This goes first so that it can pick up a different
47 file on the emulator. */
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080048 "ro.product.board",
49 "ro.board.platform",
The Android Open Source Project8232b502009-03-13 13:04:23 -070050 "ro.arch"
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080051};
The Android Open Source Project8232b502009-03-13 13:04:23 -070052#define HAL_VARIANT_KEYS_COUNT (sizeof(variant_keys)/sizeof(variant_keys[0]))
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080053
54/**
The Android Open Source Project8232b502009-03-13 13:04:23 -070055 * Load the file defined by the variant and if succesfull
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080056 * return the dlopen handle and the hmi.
57 * @return 0 = success, !0 = failure.
58 */
59static int load(const char *id,
The Android Open Source Project8232b502009-03-13 13:04:23 -070060 const char *variant,
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080061 const struct hw_module_t **pHmi)
62{
63 int status;
64 void *handle;
Mathias Agopiana8a75162009-04-10 14:24:31 -070065 struct hw_module_t *hmi;
The Android Open Source Project8232b502009-03-13 13:04:23 -070066 char path[PATH_MAX];
67
68 /* Construct the path. */
69 snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, variant);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080070
71 LOGV("load: E id=%s path=%s", id, path);
72
73 /*
74 * load the symbols resolving undefined symbols before
75 * dlopen returns. Since RTLD_GLOBAL is not or'd in with
76 * RTLD_NOW the external symbols will not be global
77 */
78 handle = dlopen(path, RTLD_NOW);
79 if (handle == NULL) {
80 char const *err_str = dlerror();
Mathias Agopiana8a75162009-04-10 14:24:31 -070081 //LOGW("load: module=%s error=%s", path, err_str);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080082 status = -EINVAL;
83 goto done;
84 }
85
86 /* Get the address of the struct hal_module_info. */
87 const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
Mathias Agopiana8a75162009-04-10 14:24:31 -070088 hmi = (struct hw_module_t *)dlsym(handle, sym);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -080089 if (hmi == NULL) {
90 char const *err_str = dlerror();
91 LOGE("load: couldn't find symbol %s", sym);
92 status = -EINVAL;
93 goto done;
94 }
95
96 /* Check that the id matches */
97 if (strcmp(id, hmi->id) != 0) {
98 LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
99 status = -EINVAL;
100 goto done;
101 }
Mathias Agopiana8a75162009-04-10 14:24:31 -0700102
103 hmi->dso = handle;
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800104
105 /* success */
106 status = 0;
107
108done:
109 if (status != 0) {
110 hmi = NULL;
111 if (handle != NULL) {
112 dlclose(handle);
113 handle = NULL;
114 }
115 }
116
117 *pHmi = hmi;
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800118
The Android Open Source Project8232b502009-03-13 13:04:23 -0700119 LOGV("load: X id=%s path=%s hmi=%p handle=%p status=%d",
120 id, path, *pHmi, handle, status);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800121 return status;
122}
123
124int hw_get_module(const char *id, const struct hw_module_t **module)
125{
126 int status;
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800127 int i;
The Android Open Source Project8232b502009-03-13 13:04:23 -0700128 const struct hw_module_t *hmi = NULL;
129 char prop[PATH_MAX];
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800130
131 /*
132 * Here we rely on the fact that calling dlopen multiple times on
133 * the same .so will simply increment a refcount (and not load
134 * a new copy of the library).
135 * We also assume that dlopen() is thread-safe.
136 */
137
138 LOGV("hal_module_info_get: Load module id=%s", id);
139
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800140 status = -EINVAL;
The Android Open Source Project8232b502009-03-13 13:04:23 -0700141
142 /* Loop through the configuration variants looking for a module */
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800143 for (i = 0; (status != 0) && (i < HAL_VARIANT_KEYS_COUNT); i++) {
The Android Open Source Project8232b502009-03-13 13:04:23 -0700144 if (property_get(variant_keys[i], prop, NULL) == 0) {
145 continue;
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800146 }
The Android Open Source Project8232b502009-03-13 13:04:23 -0700147 status = load(id, prop, &hmi);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800148 }
The Android Open Source Project8232b502009-03-13 13:04:23 -0700149
150 /* Try default */
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800151 if (status != 0) {
The Android Open Source Project8232b502009-03-13 13:04:23 -0700152 status = load(id, HAL_DEFAULT_VARIANT, &hmi);
The Android Open Source Projectf53ebec2009-03-03 19:32:14 -0800153 }
154
155 *module = hmi;
156 LOGV("hal_module_info_get: X id=%s hmi=%p status=%d", id, hmi, status);
157
158 return status;
159}