【Android驱动07】Sensor传感器框架以及驱动移植和调试方法(Hal层部分)

avatar
作者
筋斗云
阅读量:0

一,Android sensor 系统架构

Hal 就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。
在这里插入图片描述
二,HAL 层Sensor 框架实现
Sensor HAL层相对来说比较简单,它的意图就是为framework层提供接口API的实现,如open_sensors,poll等,一旦实现完毕,framewoerk 里面的SensorManager,SensorService 里面的native(本地)方法可以直接被调用。
在这里插入图片描述

2.1 HAL 客制化
在alps\device\mediatek$(proj)\ProjectConfig.mk中 配置对应的传感器为y
等效路径(kernel3.18\arch\arm64\configs$(proj).deconfig)

CONFIG_MTK_SENSOR_SUPPORT=y CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y CONFIG_MTK_ICM20645G=y CONFIG_CUSTOM_KERNEL_ALSPS=y CONFIG_MTK_CM36558=y CONFIG_CUSTOM_KERNEL_GYROSCOPE=y CONFIG_MTK_ICM20645GY=y 

2.2 获取module函数
Hal层的库文件是怎么被上层调用的?上层调用时的入口(相当于main)又是什么呢?它就是HAL_MODULE_INFO_SYM。
路径: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) {    ALOGD("%s: name: %s! fwq debug\r\n", __func__, name);        return init_nusensors(module, device); }  static struct hw_module_methods_t sensors_module_methods = {     .open = open_sensors };  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, }; 

路径: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; } 

2.3 创建 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; } 

2.4 创建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] = '\0';             sscanf(buf, "%d", &mDataDiv);             ALOGD("read div buf(%s), mdiv %d", datapath,mDataDiv);         }         close(fd);     }     else     {     ALOGE("open acc misc path %s fail ", datapath);     } } 

2.5 通用sensor 的使能函数

static int poll__activate(struct sensors_poll_device_t *dev,         int handle, int enabled) {     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;     return ctx->activate(handle-ID_OFFSET, enabled); } 
int sensors_poll_context_t::activate(int handle, int enabled) {     ....     int index = handleToDriver(handle);     .....     if(NULL != mSensors[index])     {        ALOGD( "use new sensor index=%d, mSensors[index](%x)", index, mSensors[index]);        if(this->device.common.version  >= SENSORS_DEVICE_API_VERSION_1_1)        {                ALOGD("support batch active \n" );                mSensors[batchsensor]->enable(handle, enabled);        }        err =  mSensors[index]->enable(handle, enabled);     }          return err; } 

2.6 封装poll 函数
poll 函数对应framework中poll操作,这里只需了解它的功能实现,调用逻辑需要查看framework层代码
poll 是一个非常重要的接口,它的实现基于linux 内核中IO多路复用策略(一种效率非常高的机制)

static int poll__poll(struct sensors_poll_device_t *dev,         sensors_event_t* data, int count) {     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;     return ctx->pollEvents(data, count); } 

轮询事件方法,这是一个构造方法,该对象创建,会启动轮询机制,监听sensorlist[]中文件描述符,等待事件上报 (使用IO多路复用策略)

int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) {     .....     do {         for (int i=0 ; count && i<numSensorDrivers ; i++) {             SensorBase* const sensor(mSensors[i]);             if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {                 int nb = sensor->readEvents(data, count);     .....           }             if (count) {             // we still have some room, so try to see if we can get             // some events immediately or just wait if we don't have             // anything to return                 n = poll(mPollFds, numFds, nbEvents ? 0 : -1);             if (n<0) {                 int err;         err = errno;                 ALOGE("poll() failed (%s)", strerror(errno));                 return -err;             }             if (mPollFds[wake].revents & POLLIN) {                 char msg;                 int result = read(mPollFds[wake].fd, &msg, 1);                 ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));                 ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));                 mPollFds[wake].revents = 0;             }         }         // if we have events and space, go read them     } while (n && count);         return nbEvents; } 

2.7 读取事件函数

int ProximitySensor::readEvents(sensors_event_t* data, int count) {     ....         ssize_t n = mInputReader.fill(mdata_fd);     if (n < 0)         return n;     int numEventReceived = 0;     input_event const* event;         while (count && mInputReader.readEvent(&event)) {         int type = event->type;         //ALOGE("fwq1....\r\n");        if (type == EV_REL)         {             processEvent(event->code, event->value);             //ALOGE("fwq2....\r\n");         }          .....           mInputReader.next();     }     //ALOGE("fwq read Event 2\r\n");     return numEventReceived; } 
void ProximitySensor::processEvent(int code, int value) {     ALOGD("processEvent code=%d,value=%d\r\n",code, value);     switch (code) {     case EVENT_TYPE_PS_VALUE:         mPendingEvent.distance= value-1;         break;     } } 

2.8 获得sensor 列表函数
路径:vendor/mediatek/proprietary/hardware/sensor/sensors.c
这一步非常重要,HAL_MODULE_INFO_SYM 映射了hal 层XXX.so 库的入口,上层hw_get_module 将获得该入口,使得上层可以和底层.so库进行交互

static int sensors__get_sensors_list(struct sensors_module_t* module,         struct sensor_t const** list) {     ALOGD(" sSensorList addr =%p, module addr =%p\r\n",sSensorList,module);     ALOGD(" ARRAY_SIZE(sSensorList) =%d SENSORS_NUM=%d MAX_NUM_SENSOR=%d \r\n",ARRAY_SIZE(sSensorList), SENSORS_NUM, MAX_NUM_SENSOR);     *list = sSensorList;     return ARRAY_SIZE(sSensorList); } 
struct sensor_t sSensorList[] = { #ifdef CUSTOM_KERNEL_ACCELEROMETER     {         .name       = ACCELEROMETER,         .vendor     = ACCELEROMETER_VENDER,         .version    = 3,         .handle     = ID_ACCELEROMETER+ID_OFFSET,         .type       = SENSOR_TYPE_ACCELEROMETER,         .maxRange   = ACCELEROMETER_RANGE,//32.0f,         .resolution = ACCELEROMETER_RESOLUTION,//4.0f/1024.0f,         .power      = ACCELEROMETER_POWER,//130.0f/1000.0f,         .minDelay   = 10000,         .maxDelay   = 1000000,         .reserved   = {}     }, #endif     #if defined(CUSTOM_KERNEL_ALSPS) || defined(CUSTOM_KERNEL_ALS)      {         .name       = LIGHT,         .vendor     = LIGHT_VENDER,         .version    = 1,         .handle     = ID_LIGHT+ID_OFFSET,         .type       = SENSOR_TYPE_LIGHT,         .maxRange   = LIGHT_RANGE,//10240.0f,         .resolution = LIGHT_RESOLUTION,//1.0f,         .power      = LIGHT_POWER,//0.13f,         .reserved   = {}     }, #endif }; 

三,Selinux权限问题
在这里插入图片描述
四,HAL 层log分析

psensor 手机中常见的使用就是拨号时贴脸灭屏,拨号后遮挡psensor,使用Adb抓取android log ,过滤的的psensor log部分如下:
在这里插入图片描述驱动部分后续再介绍

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!