OSDN Git Service

am 525178d5: am e6b5c05a: Add a helper for dumping layers into the log
[android-x86/hardware-libhardware.git] / hardware.c
1 /*
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 static const char *variant_keys[] = {
45     "ro.hardware",  /* This goes first so that it can pick up a different
46                        file on the emulator. */
47     "ro.product.board",
48     "ro.board.platform",
49     "ro.arch"
50 };
51
52 static const int HAL_VARIANT_KEYS_COUNT =
53     (sizeof(variant_keys)/sizeof(variant_keys[0]));
54
55 /**
56  * Load the file defined by the variant and if successful
57  * return the dlopen handle and the hmi.
58  * @return 0 = success, !0 = failure.
59  */
60 static int load(const char *id,
61         const char *path,
62         const struct hw_module_t **pHmi)
63 {
64     int status;
65     void *handle;
66     struct hw_module_t *hmi;
67
68     /*
69      * load the symbols resolving undefined symbols before
70      * dlopen returns. Since RTLD_GLOBAL is not or'd in with
71      * RTLD_NOW the external symbols will not be global
72      */
73     handle = dlopen(path, RTLD_NOW);
74     if (handle == NULL) {
75         char const *err_str = dlerror();
76         LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
77         status = -EINVAL;
78         goto done;
79     }
80
81     /* Get the address of the struct hal_module_info. */
82     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
83     hmi = (struct hw_module_t *)dlsym(handle, sym);
84     if (hmi == NULL) {
85         LOGE("load: couldn't find symbol %s", sym);
86         status = -EINVAL;
87         goto done;
88     }
89
90     /* Check that the id matches */
91     if (strcmp(id, hmi->id) != 0) {
92         LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
93         status = -EINVAL;
94         goto done;
95     }
96
97     hmi->dso = handle;
98
99     /* success */
100     status = 0;
101
102     done:
103     if (status != 0) {
104         hmi = NULL;
105         if (handle != NULL) {
106             dlclose(handle);
107             handle = NULL;
108         }
109     } else {
110         LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
111                 id, path, *pHmi, handle);
112     }
113
114     *pHmi = hmi;
115
116     return status;
117 }
118
119 int hw_get_module(const char *id, const struct hw_module_t **module) 
120 {
121     int status;
122     int i;
123     const struct hw_module_t *hmi = NULL;
124     char prop[PATH_MAX];
125     char path[PATH_MAX];
126
127     /*
128      * Here we rely on the fact that calling dlopen multiple times on
129      * the same .so will simply increment a refcount (and not load
130      * a new copy of the library).
131      * We also assume that dlopen() is thread-safe.
132      */
133
134     /* Loop through the configuration variants looking for a module */
135     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
136         if (i < HAL_VARIANT_KEYS_COUNT) {
137             if (property_get(variant_keys[i], prop, NULL) == 0) {
138                 continue;
139             }
140             snprintf(path, sizeof(path), "%s/%s.%s.so",
141                     HAL_LIBRARY_PATH, id, prop);
142         } else {
143             snprintf(path, sizeof(path), "%s/%s.default.so",
144                     HAL_LIBRARY_PATH, id);
145         }
146         if (access(path, R_OK)) {
147             continue;
148         }
149         /* we found a library matching this id/variant */
150         break;
151     }
152
153     status = -ENOENT;
154     if (i < HAL_VARIANT_KEYS_COUNT+1) {
155         /* load the module, if this fails, we're doomed, and we should not try
156          * to load a different variant. */
157         status = load(id, path, module);
158     }
159
160     return status;
161 }