這幾天深入學習了Android sensor框架,以此博客記錄和分享分析過程,其中難免會有錯誤的地方,歡迎指出! 這裡主要分析KERNEL->HAL->JNI這3層的流程。主要從以下幾方面開始著手:(A) 驅動層向上提供了那些文件節點給系統層讀寫?(B) 系統層通過什麼方式訪問驅動層?(C) 如何統 ...
這幾天深入學習了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庫就行了