Android sensor 系统框架 (一)
这几天深入学习了Android sensor框架,以此博客记录和分享分析过程,其中难免会有错误的地方,欢迎指出!
这里主要分析KERNEL->HAL->JNI这3层的流程。主要从以下几方面开始着手:
(A) 驱动层向上提供了那些文件节点给系统层读写?
(B) 系统层通过什么方式访问驱动层?
(C) 如何统一各种sensors的接口,生成.so库?
(D) 如何加载访问.so库
(E) 实现sensor service (未写,待续)
(F) JNI接口 (未写,待续)
(A) 驱动层向上提供了那些文件节点给系统层读写?
关于linux基本驱动框架,不在本文范围,这里不再分析。学习过Linux驱动的都知道应用层要访问内核驱动,都是通过open、
read、write等系统函数操作驱动注册的文件节点进行的。这里以n2dm g-sensor的驱动为例,找出这些文件节点。文件路径:
./kernel/drivers/input/misc/n2dm.c
1 static int n2dm_acc_probe(struct i2c_client *client,const struct i2c_device_id *id) 2 { 3 ...... 4 acc->input_dev->name = "accelerometer"; 5 err = input_register_device(acc->input_dev); /* 生成 /dev/input/event2 */ 6 ...... 7 err = misc_register(&n2dm_acc_misc_device); /* 生成 /sys/class/n2dm_acc */ 8 ...... 9 gsensor_class = class_create(THIS_MODULE,"xr-gsensor"); 10 gsensor_cmd_dev = device_create(gsensor_class, NULL, 0, NULL, "device"); 11 device_create_file(gsensor_cmd_dev, &dev_attr_gsensor); /* 生成 /sys/class/xr-gsensor/device/gsensor */ 12 device_create_file(gsensor_cmd_dev, &dev_attr_delay_acc); /* 生成 /sys/class/xr-gsensor/device/delay_acc */ 13 14 ...... 15 }
由以上代码可知,这个驱动生成了/dev/input/event2、/sys/class/n2dm_acc、/sys/class/xr-gsensor/device/gsensor、
/sys/class/xr-gsensor/device/delay_acc这4个文件节点,其中/sys/class/n2dm_acc文件节点用不到,可以不用理会。其余3
个文件节点的作用分别是:
1. /dev/input/event2:驱动通过这个文件节点上报输入事件,如这个是g-sensor传感器,会上报x,y,z三轴事件,数据格式:
input_report_abs(acc->input_dev, ABS_X, xyz[0]); input_report_abs(acc->input_dev, ABS_Y, xyz[1]); input_report_abs(acc->input_dev, ABS_Z, xyz[2]); input_sync(acc->input_dev);
2. /sys/class/xr-gsensor/device/gsensor数据格式:
"1" /* 使能g-sensor */ "0" /* 禁止g-sensor */
3. /sys/class/xr-gsensor/device/delay_acc数据格式:
十进制数值 /* g-sensor 数据刷新频率,时间ms */
(B) 系统层通过什么方式访问驱动层?
系统层肯定是通过open、read、write、ioctl等函数读写文件节点的方式访问驱动层,读写这些文件节点的代码路径在:
vendor/sprd/open-source/libs/libsensors_sprd/
这个目录下是各种传感器,如:g-sensor、光感、陀螺仪等的系统访问驱动的接口文件,这里以g-sensor为例来分析,
文件路径:
vendor/sprd/open-source/libs/libsensors_sprd/Acc_Xr.cpp vendor/sprd/open-source/libs/libsensors_sprd/AccSensor.h vendor/sprd/open-source/libs/libsensors_sprd/InputEventReader.cpp vendor/sprd/open-source/libs/libsensors_sprd/InputEventReader.h vendor/sprd/open-source/libs/libsensors_sprd/sensors.cpp vendor/sprd/open-source/libs/libsensors_sprd/sensors.h
其中,vendor/sprd/open-source/libs/libsensors_sprd/InputEventReader.cpp文件的作用是为事件读取提供一个环形
缓冲区,vendor/sprd/open-source/libs/libsensors_sprd/sensors.cpp的作用是抽象所有的sensor为一个sensor hal。
AccSensor.h
1 class AccSensor : public SensorBase { 2 public: 3 AccSensor(); 4 virtual ~AccSensor(); 5 6 #ifndef ACC_NULL 7 enum { 8 Accelerometer = 0, 9 numSensors 10 }; 11 #else 12 static const int numSensors = 0; 13 #endif 14 15 virtual int readEvents(sensors_event_t* data, int count); 16 virtual bool hasPendingEvents() const; 17 virtual int setDelay(int32_t handle, int64_t ns); 18 virtual int setEnable(int32_t handle, int enabled); 19 virtual int64_t getDelay(int32_t handle); 20 virtual int getEnable(int32_t handle); 21 virtual int populateSensorList(struct sensor_t *list); 22 private: 23 int mEnabled; 24 int64_t mDelay; 25 int mLayout; 26 InputEventCircularReader mInputReader; 27 sensors_event_t mPendingEvent; 28 bool mHasPendingEvent; 29 char input_sysfs_path[PATH_MAX]; 30 int input_sysfs_path_len; 31 32 int setInitialState(); 33 SensorCoordinate mSensorCoordinate; 34 };
AccSensor.h 文件定义了一个AccSensor类,派生于SensorBase,而Acc_Xr.cpp就是实现了这个类里面的方法
Acc_Xr.cpp
1 AccSensor::AccSensor() : 2 SensorBase(NULL, XR_ACC_INPUT_NAME), 3 mEnabled(0), mDelay(-1), mInputReader(32), mHasPendingEvent(false), 4 mSensorCoordinate() 5 { 6 ...... 7 mPendingEvent.sensor = ID_A; 8 ...... 9 10 strcpy(input_sysfs_path, XR_GSENSOR_DEVICE_NAME); 11 input_sysfs_path_len = strlen(input_sysfs_path); 12 ...... 13 14 /* AccSensor的构造函数主要做了: 15 * 1. 构造SensorBase,扫描所有的/dev/input/event*,并判断该文件节点下是否存在一个名为XR_ACC_INPUT_NAME 16 * (accelerometer)的输入设备,我的设备是/dev/input/event2,如果存在,则返回该文件节点的fd 17 * 2. 获得input_sysfs_path文件节点为XR_GSENSOR_DEVICE_NAME(/sys/class/xr-gsensor/device/) 18 * 3. 初始化一个环形缓冲区 19 * 4. 设置sensor类型ID_A 20 */ 21 } 22 23 int AccSensor::setEnable(int32_t handle, int enabled) 24 { 25 ...... 26 if(enabled==1) 27 strcpy(enable,"1"); 28 else if(enabled==0) 29 strcpy(enable,"0"); 30 else 31 strcpy(enable,"2"); 32 ...... 33 34 /* 设置sensor状态,1:使能,0:禁止 35 * 把状态值写到文件节点:/sys/class/xr-gsensor/device/gsensor 36 */ 37 strcpy(&input_sysfs_path[input_sysfs_path_len], "gsensor"); 38 err = write_sys_attribute(input_sysfs_path, enable, 1); 39 ...... 40 mEnabled &= ~(1); 41 mEnabled |= uint32_t(newState); 42 43 ...... 44 } 45 46 47 int AccSensor::setDelay(int32_t handle, int64_t delay_ns) 48 { 49 ...... 50 ms = delay_ns / 1000000; 51 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_acc"); 52 bytes = sprintf(buffer, "%d", ms); 53 write_sys_attribute(input_sysfs_path, buffer, bytes); 54 ...... 55 } 56 57 58 int AccSensor::readEvents(sensors_event_t * data, int count) 59 { 60 ...... 61 /* 从文件节点/dev/input/event2中读取驱动层提交的事件, 62 * 并写入环形队列 63 */ 64 ssize_t n = mInputReader.fill(data_fd); 65 ...... 66 /* 从队列中取出一个事件 */ 67 while (count && mInputReader.readEvent(&event)) { 68 ...... 69 /* 写入到sensors_event_t缓冲区 */ 70 *data++ = mPendingEvent; 71 count--; 72 numEventReceived++; 73 ...... 74 /* 指向下一个事件 */ 75 mInputReader.next(); 76 } 77 78 return numEventReceived; 79 } 80 81 82 int AccSensor::populateSensorList(struct sensor_t *list) 83 { 84 /* 把该sensor加入list链表 85 * 所有的sensor都要加入到这个链表,以便统一管理 86 */ 87 memcpy(list, sSensorList, sizeof(struct sensor_t) * numSensors); 88 return numSensors; 89 }
(C) 如何统一各种sensors的接口,生成.so库?
通过vendor/sprd/open-source/libs/libsensors_sprd/sensors.cpp 和
vendor/sprd/open-source/libs/libsensors_sprd/sensors.h 统一管理所有
sensor,抽象所有接口
sensors.cpp
1 static int sensors__get_sensors_list(struct sensors_module_t *module, 2 struct sensor_t const **list) 3 { 4 /* 获取sensor链表首指针 */ 5 *list = sSensorList; 6 /* 返回该sensor总数 */ 7 return numSensors; 8 } 9 10 static struct hw_module_methods_t sensors_module_methods = { 11 open: open_sensors 12 }; 13 14 /* sensors.cpp最终的目的就是要构造这个结构体 */ 15 struct sensors_module_t HAL_MODULE_INFO_SYM = { 16 common:{ 17 tag: HARDWARE_MODULE_TAG, 18 version_major: 1, 19 version_minor: 0, 20 /* 加载so库时,是通过SENSORS_HARDWARE_MODULE_ID 21 * 找到这个结构体 22 */ 23 id: SENSORS_HARDWARE_MODULE_ID, 24 name: "SPRD Sensor module", 25 author: "Spreadtrum", 26 methods: &sensors_module_methods, 27 dso: 0, 28 reserved:{}, 29 }, 30 get_sensors_list:sensors__get_sensors_list, 31 }; 32 33 34 sensors_poll_context_t::sensors_poll_context_t() 35 { 36 /* 实例化一个AccSensor类的对象 37 * 这个对象代表一个g-sensor 38 */ 39 mSensors[acc] = new AccSensor(); 40 /* 获得sensor索引 */ 41 numSensors += 42 mSensors[acc]->populateSensorList(sSensorList + numSensors); 43 /* 读取/dev/input/event2节点的fd */ 44 mPollFds[acc].fd = mSensors[acc]->getFd(); 45 /* 有数据输入就产生POLLIN事件 */ 46 mPollFds[acc].events = POLLIN; 47 mPollFds[acc].revents = 0; 48 ...... 49 50 /* 实例化一个磁力计对象 */ 51 mSensors[ori] = new OriSensor(); 52 numSensors += 53 mSensors[ori]->populateSensorList(sSensorList + numSensors); 54 mPollFds[ori].fd = mSensors[ori]->getFd(); 55 mPollFds[ori].events = POLLIN; 56 mPollFds[ori].revents = 0; 57 58 /* 实例化一个光感对象 */ 59 ...... 60 61 /* 以下创建的管道,感觉没啥用,多余的 62 * 因为在activate中写管道,在pollEvent中度管道, 63 * 读到消息后并没有做什么相关处理,有知道的兄弟 64 * 麻烦指教一下,非常感谢! 65 */ 66 int wakeFds[2]; 67 /* 创建一个管道 */ 68 int result = pipe(wakeFds); 69 ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno)); 70 fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); 71 fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); 72 /* 写管道的fd */ 73 mWritePipeFd = wakeFds[1]; 74 75 /* 读管道的fd */ 76 mPollFds[wake].fd = wakeFds[0]; 77 mPollFds[wake].events = POLLIN; 78 mPollFds[wake].revents = 0; 79 } 80 81 82 int sensors_poll_context_t::activate(int handle, int enabled) 83 { 84 /* 获得sensor类型 */ 85 int drv = handleToDriver(handle); 86 ...... 87 /* 使能该sensor,如:如果这是g-sensor,则调用的是 88 * AccSensor::setEnable(int32_t handle, int enabled) 89 */ 90 err = mSensors[drv]->setEnable(handle, enabled); 91 /* 往管道写一个WAKE_MESSAGE消息 */ 92 const char wakeMessage(WAKE_MESSAGE); 93 int result = write(mWritePipeFd, &wakeMessage, 1); 94 } 95 96 97 int sensors_poll_context_t::setDelay(int handle, int64_t ns) 98 { 99 ...... 100 return setDelay_sub(handle, ns); 101 } 102 103 int sensors_poll_context_t::setDelay_sub(int handle, int64_t ns) 104 { 105 /* 获得sensor类型 */ 106 int drv = handleToDriver(handle); 107 108 /* 获取sensor的状态,使能还是禁止 109 * 如:如果这是g-sensor,则调用的是 110 * AccSensor::getEnable(int32_t handle) 111 */ 112 int en = mSensors[drv]->getEnable(handle); 113 /* 获取sensor的输入事件频率 114 * 如:如果这是g-sensor,则调用的是 115 * AccSensor::getDelay(int32_t handle) 116 */ 117 int64_t cur = mSensors[drv]->getDelay(handle); 118 ...... 119 120 /* 设置sensor的输入事件频率 121 * 如:如果这是g-sensor,则调用的是 122 * AccSensor::setDelay(int32_t handle, int64_t delay_ns) 123 */ 124 err = mSensors[drv]->setDelay(handle, ns); 125 ...... 126 } 127 128 129 int sensors_poll_context_t::pollEvents(sensors_event_t * data, int count) 130 { 131 ...... 132 do { 133 /* 轮询读各个sensor的输入事件 */ 134 for (int i = 0; count && i < numSensorDrivers; i++) { 135 SensorBase *const sensor(mSensors[i]); 136 ...... 137 /* 读事件 */ 138 int nb = sensor->readEvents(data, count); 139 .... 140 count -= nb; 141 nbEvents += nb; 142 data += nb; 143 } 144 /* 还有事件没读完 */ 145 if (count) { 146 do { 147 /* 休眠等待事件输入,如果超时则退出 */ 148 n = poll(mPollFds, numFds, 149 nbEvents ? 0 : polltime); 150 } while (n < 0 && errno == EINTR); 151 152 if (mPollFds[wake].revents & POLLIN) { 153 ...... 154 /* 从管道读出msg,然而什么都没干,why? */ 155 int result = read(mPollFds[wake].fd, &msg, 1); 156 ...... 157 } 158 } 159 } while (n && count); 160 161 return nbEvents; 162 } 163 164 static int poll__activate(struct sensors_poll_device_t *dev, 165 int handle, int enabled) 166 { 167 sensors_poll_context_t *ctx = (sensors_poll_context_t *) dev; 168 return ctx->activate(handle, enabled); 169 } 170 171 static int poll__setDelay(struct sensors_poll_device_t *dev, 172 int handle, int64_t ns) 173 { 174 sensors_poll_context_t *ctx = (sensors_poll_context_t *) dev; 175 return ctx->setDelay(handle, ns); 176 } 177 178 static int poll__poll(struct sensors_poll_device_t *dev, 179 sensors_event_t * data, int count) 180 { 181 sensors_poll_context_t *ctx = (sensors_poll_context_t *) dev; 182 return ctx->pollEvents(data, count); 183 } 184 185 186 /** Open a new instance of a sensor device using name */ 187 static int open_sensors(const struct hw_module_t *module, const char *id, 188 struct hw_device_t **device) 189 { 190 int status = -EINVAL; 191 sensors_poll_context_t *dev = new sensors_poll_context_t(); 192 193 memset(&dev->device, 0, sizeof(sensors_poll_device_t)); 194 195 /* 构造sensors_poll_context_t结构体 */ 196 dev->device.common.tag = HARDWARE_DEVICE_TAG; 197 dev->device.common.version = 0; 198 dev->device.common.module = const_cast < hw_module_t * >(module); 199 dev->device.common.close = poll__close; 200 dev->device.activate = poll__activate; 201 dev->device.setDelay = poll__setDelay; 202 dev->device.poll = poll__poll; 203 204 *device = &dev->device.common; 205 status = 0; 206 207 return status; 208 }
Android.mk
...... LOCAL_MODULE := sensors.$(TARGET_BOARD_PLATFORM) #这里的TARGET_BOARD_PLATFORM是sc8830 ......
mmm ./vendor/sprd/open-source/libs/libsensors_sprd -B
生成sensors.sc8830.so
这样就实现了硬件和应用的分离,应用要访问硬件是只要加载这个so库就行了