概述
一、HAL 层Sensor 流程
Hal 就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。
其中SensorDevice属于JNI层,与HAL进行通信的接口;在JNI层调用了HAL层的open_sensors()方法打开设备模块,再调用poll__activate()对设备使能,然后调用poll__poll读取数据。
二、HAL 层Sensor 框架实现
路径:frameworks/native/services/sensorservice/SensorDevice.cpp
1. Sensor设备对象
SensorDevice::SensorDevice()
: mSensorDevice(0),
mSensorModule(0)
{
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
.....
if (mSensorModule) {
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
Info model;
for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list[i].handle, model);
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
list[i].handle, 0);
}
}
}
.....
}
2. 获取module函数
路径:hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
3. 通过class 获取module
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
.....
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
.....
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
4. 模块加载函数,到此模块已经完成加载
/**
* 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)
{
/*
* 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);
/* 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);
return status;
}
5.打开sensor 函数路径:hardware/libhardware/include/hardware/sensors.h
static inline int sensors_open_1(const struct hw_module_t* module,
sensors_poll_device_1_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}
typedef struct hw_module_t {
.....
/** Modules methods */
struct hw_module_methods_t* methods;
.....
} hw_module_t;
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
路径:vendor/mediatek/proprietary/hardware/sensor/sensors.c
static int open_sensors(const struct hw_module_t* module, const char* name,
struct hw_device_t** device);
static struct hw_module_methods_t sensors_module_methods = {
.open = open_sensors
};
Hal层的库文件是怎么被上层调用的?上层调用时的入口(相当于main)又是什么呢?它就是HAL_MODULE_INFO_SYM。
struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "MTK SENSORS Module",
.author = "Mediatek",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list,
};
static int open_sensors(const struct hw_module_t* module, const char* name,
struct hw_device_t** device)
{
ALOGD("%s: name: %s! fwq debugrn", __func__, name);
return init_nusensors(module, device);
}
路径:vendor/mediatek/proprietary/hardware/sensor/nusensors.cpp
int init_nusensors(hw_module_t const* module, hw_device_t** device)
{
int status = -EINVAL;
dev = new sensors_poll_context_t();
memset(&dev->device, 0, sizeof(sensors_poll_device_1));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
#if defined(SENSOR_BATCH_SUPPORT) || defined(CUSTOM_KERNEL_SENSORHUB)
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_1;
#else
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_0;
#endif
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
dev->device.batch = poll__batch;
dev->device.flush = poll__flush;
*device = &dev->device.common;
status = 0;
return status;
}
6.创建 sensors_poll_context_t 对象
sensors_poll_context_t::sensors_poll_context_t()
{
memset(&device, 0, sizeof(device));
mSensors[accel] = new AccelerationSensor();
mPollFds[accel].fd = ((AccelerationSensor*)mSensors[accel])->mdata_fd;
mPollFds[accel].events = POLLIN;
mPollFds[accel].revents = 0;
mSensors[proximity] = new ProximitySensor();
mPollFds[proximity].fd = ((ProximitySensor*)mSensors[proximity])->mdata_fd;
mPollFds[proximity].events = POLLIN;
mPollFds[proximity].revents = 0;
int wakeFds[2];
int result = pipe(wakeFds);
if (result < 0) {
ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno));
mWritePipeFd = -1;
} else {
result = fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
ALOGE_IF(result < 0, "fcntl(wakeFds[0] fail (%s)", strerror(errno));
result = fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
ALOGE_IF(result < 0, "fcntl(wakeFds[1] fail (%s)", strerror(errno));
mWritePipeFd = wakeFds[1];
}
mPollFds[wake].fd = wakeFds[0];
mPollFds[wake].events = POLLIN;
mPollFds[wake].revents = 0;
}
7. 创建Sensor对象路径:vendor/mediatek/proprietary/hardware/sensor/Proximity.cpp
ProximitySensor::ProximitySensor()
: SensorBase(NULL, "m_alsps_input"),//PRO_INPUTDEV_NAME
mEnabled(0),
mInputReader(32)
{
char datapath[64]={"/sys/class/misc/m_alsps_misc/psactive"};
int fd = -1;
char buf[64]={0};
int len;
mdata_fd = FindDataFd();
if (mdata_fd >= 0) {
strcpy(input_sysfs_path, "/sys/class/misc/m_alsps_misc/");
input_sysfs_path_len = strlen(input_sysfs_path);
}
else
{
ALOGE("couldn't find input device ");
return;
}
ALOGD("prox misc path =%s", input_sysfs_path);
fd = open(datapath, O_RDWR);
if (fd >= 0)
{
len = read(fd,buf,sizeof(buf)-1);
if (len <= 0)
{
ALOGD("read div err, len = %d", len);
}
else
{
buf[len] = '