204 lines
6.4 KiB
C
204 lines
6.4 KiB
C
|
/******************************************************************************
|
||
|
* GPS HAL wrapper
|
||
|
* wrapps around Samsung GPS Libary and replaces a faulty pointer to
|
||
|
* a faulty function from Samsung that will cause the system_server
|
||
|
* to crash.
|
||
|
*
|
||
|
* Copyright 2010 - Kolja Dummann
|
||
|
*
|
||
|
* 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 <hardware/hardware.h>
|
||
|
#include <hardware/gps.h>
|
||
|
#include <errno.h>
|
||
|
#include <dlfcn.h>
|
||
|
|
||
|
//#define ALOG_NDEBUG 0
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#define ALOG_TAG "gps-wrapper"
|
||
|
#include <utils/Log.h>
|
||
|
|
||
|
#define ORIGINAL_HAL_PATH "/system/lib/hw/vendor-gps.exynos4.so"
|
||
|
|
||
|
static const AGpsRilInterface* oldAGPSRIL = NULL;
|
||
|
static AGpsRilInterface newAGPSRIL;
|
||
|
|
||
|
static const GpsInterface* originalGpsInterface = NULL;
|
||
|
static GpsInterface newGpsInterface;
|
||
|
|
||
|
/**
|
||
|
* Load the file defined by the variant and if successful
|
||
|
* return the dlopen handle and the hmi.
|
||
|
* @return 0 = success, !0 = failure.
|
||
|
*/
|
||
|
static int load(const char *id,
|
||
|
const char *path,
|
||
|
const struct hw_module_t **pHmi)
|
||
|
{
|
||
|
int status;
|
||
|
void *handle;
|
||
|
struct hw_module_t *hmi;
|
||
|
|
||
|
/*
|
||
|
* load the symbols resolving undefined symbols before
|
||
|
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
|
||
|
* RTLD_NOW the external symbols will not be global
|
||
|
*/
|
||
|
handle = dlopen(path, RTLD_NOW);
|
||
|
if (handle == NULL) {
|
||
|
char const *err_str = dlerror();
|
||
|
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
|
||
|
status = -EINVAL;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/* Get the address of the struct hal_module_info. */
|
||
|
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
|
||
|
hmi = (struct hw_module_t *)dlsym(handle, sym);
|
||
|
if (hmi == NULL) {
|
||
|
ALOGE("load: couldn't find symbol %s", sym);
|
||
|
status = -EINVAL;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/* Check that the id matches */
|
||
|
if (strcmp(id, hmi->id) != 0) {
|
||
|
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
|
||
|
status = -EINVAL;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
hmi->dso = handle;
|
||
|
|
||
|
/* success */
|
||
|
status = 0;
|
||
|
|
||
|
done:
|
||
|
if (status != 0) {
|
||
|
hmi = NULL;
|
||
|
if (handle != NULL) {
|
||
|
dlclose(handle);
|
||
|
handle = NULL;
|
||
|
}
|
||
|
} else {
|
||
|
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
|
||
|
id, path, *pHmi, handle);
|
||
|
}
|
||
|
|
||
|
*pHmi = hmi;
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static void update_network_state_wrapper(int connected, int type, int roaming, const char* extra_info)
|
||
|
{
|
||
|
ALOGI("%s was called and saved your from a faulty implementation ;-)", __func__);
|
||
|
}
|
||
|
|
||
|
static const void* wrapper_get_extension(const char* name)
|
||
|
{
|
||
|
ALOGV("%s was called", __func__);
|
||
|
|
||
|
if (!strcmp(name, AGPS_RIL_INTERFACE) && (oldAGPSRIL = originalGpsInterface->get_extension(name)))
|
||
|
{
|
||
|
ALOGV("%s AGPS_RIL_INTERFACE extension requested", __func__);
|
||
|
/* use a wrapper to avoid calling samsungs faulty implemetation */
|
||
|
newAGPSRIL.size = sizeof(AGpsRilInterface);
|
||
|
newAGPSRIL.init = oldAGPSRIL->init;
|
||
|
newAGPSRIL.set_ref_location = oldAGPSRIL->set_ref_location;
|
||
|
newAGPSRIL.set_set_id = oldAGPSRIL->set_set_id;
|
||
|
newAGPSRIL.ni_message = oldAGPSRIL->ni_message;
|
||
|
ALOGV("%s setting update_network_state_wrapper", __func__);
|
||
|
newAGPSRIL.update_network_state = update_network_state_wrapper;
|
||
|
return &newAGPSRIL;
|
||
|
}
|
||
|
return originalGpsInterface->get_extension(name);
|
||
|
}
|
||
|
|
||
|
/* HAL Methods */
|
||
|
const GpsInterface* gps_get_gps_interface(struct gps_device_t* dev)
|
||
|
{
|
||
|
hw_module_t* module;
|
||
|
int err;
|
||
|
|
||
|
ALOGV("%s was called", __func__);
|
||
|
|
||
|
err = load(GPS_HARDWARE_MODULE_ID, ORIGINAL_HAL_PATH, (hw_module_t const**)&module);
|
||
|
|
||
|
if (err == 0) {
|
||
|
ALOGV("%s vendor lib loaded", __func__);
|
||
|
hw_device_t* device;
|
||
|
struct gps_device_t *gps_device;
|
||
|
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
|
||
|
if (err == 0) {
|
||
|
ALOGV("%s got gps device", __func__);
|
||
|
gps_device = (struct gps_device_t *)device;
|
||
|
originalGpsInterface = gps_device->get_gps_interface(gps_device);
|
||
|
ALOGV("%s device set", __func__);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(originalGpsInterface)
|
||
|
{
|
||
|
ALOGV("%s exposing callbacks", __func__);
|
||
|
newGpsInterface.size = sizeof(GpsInterface);
|
||
|
newGpsInterface.init = originalGpsInterface->init;
|
||
|
newGpsInterface.start = originalGpsInterface->start;
|
||
|
newGpsInterface.stop = originalGpsInterface->stop;
|
||
|
newGpsInterface.cleanup = originalGpsInterface->cleanup;
|
||
|
newGpsInterface.inject_time = originalGpsInterface->inject_time;
|
||
|
newGpsInterface.inject_location = originalGpsInterface->inject_location;
|
||
|
newGpsInterface.delete_aiding_data = originalGpsInterface->delete_aiding_data;
|
||
|
newGpsInterface.set_position_mode = originalGpsInterface->set_position_mode;
|
||
|
ALOGV("%s setting extension wrapper", __func__);
|
||
|
newGpsInterface.get_extension = wrapper_get_extension;
|
||
|
|
||
|
}
|
||
|
ALOGV("%s done", __func__);
|
||
|
return &newGpsInterface;
|
||
|
}
|
||
|
|
||
|
static int open_gps(const struct hw_module_t* module, char const* name,
|
||
|
struct hw_device_t** device)
|
||
|
{
|
||
|
struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
|
||
|
memset(dev, 0, sizeof(*dev));
|
||
|
|
||
|
ALOGV("%s was called", __func__);
|
||
|
|
||
|
dev->common.tag = HARDWARE_DEVICE_TAG;
|
||
|
dev->common.version = 0;
|
||
|
dev->common.module = (struct hw_module_t*)module;
|
||
|
dev->get_gps_interface = gps_get_gps_interface;
|
||
|
|
||
|
*device = (struct hw_device_t*)dev;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static struct hw_module_methods_t gps_module_methods = {
|
||
|
.open = open_gps
|
||
|
};
|
||
|
|
||
|
const struct hw_module_t HAL_MODULE_INFO_SYM = {
|
||
|
.tag = HARDWARE_MODULE_TAG,
|
||
|
.version_major = 1,
|
||
|
.version_minor = 0,
|
||
|
.id = GPS_HARDWARE_MODULE_ID,
|
||
|
.name = "GPS HAL Wrapper Module",
|
||
|
.author = "Kolja Dummann",
|
||
|
.methods = &gps_module_methods,
|
||
|
};
|