一 背景
1.需求
陀螺儀硬件并非接在android cpu上,所以不存在陀螺儀驅(qū)動(dòng),而陀螺儀數(shù)據(jù)是通過(guò)用戶(hù)空間的一個(gè)c程序傳過(guò)來(lái)。
2.思路
修改陀螺儀hal層,在hal層構(gòu)建socket客戶(hù)端,在數(shù)據(jù)源的c程序上構(gòu)建socket服務(wù)端。一旦有數(shù)據(jù),c程序通過(guò)socket發(fā)送數(shù)據(jù)到陀螺儀hal層,并上報(bào)。
二 步驟
1.把device/samsung/crespo/libsensors目錄拷貝到hardware/libhardware/modules目錄下
2.修改sensors.cpp文件下的傳感器數(shù)組定義。
因只用到陀螺儀傳感器,把其他傳感器定義刪掉
- static const struct sensor_t sSensorList[] = {
- /*
- { "KR3DM 3-axis Accelerometer",
- "STMicroelectronics",
- 1, SENSORS_ACCELERATION_HANDLE,
- SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.23f, 20000, { } },
- { "AK8973 3-axis Magnetic field sensor",
- "Asahi Kasei Microdevices",
- 1, SENSORS_MAGNETIC_FIELD_HANDLE,
- SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 16667, { } },
- { "AK8973 Orientation sensor",
- "Asahi Kasei Microdevices",
- 1, SENSORS_ORIENTATION_HANDLE,
- SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 16667, { } },
- { "GP2A Light sensor",
- "Sharp",
- 1, SENSORS_LIGHT_HANDLE,
- SENSOR_TYPE_LIGHT, 3000.0f, 1.0f, 0.75f, 0, { } },
- { "GP2A Proximity sensor",
- "Sharp",
- 1, SENSORS_PROXIMITY_HANDLE,
- SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } },
- */
- { "K3G Gyroscope sensor",
- "STMicroelectronics",
- 1, SENSORS_GYROSCOPE_HANDLE,
- SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },
- };
3.修改sensors.cpp的sensors_poll_context_t結(jié)構(gòu)體,刪除其他的傳感器定義
- struct sensors_poll_context_t {
- struct sensors_poll_device_t device; // must be first
-
- sensors_poll_context_t();
- ~sensors_poll_context_t();
- int activate(int handle, int enabled);
- int setDelay(int handle, int64_t ns);
- int pollEvents(sensors_event_t* data, int count);
-
- private:
- enum {
- //light = 0,
- //proximity = 1,
- //akm = 2,
- //gyro = 3,
- gyro = 0,
- numSensorDrivers,
- numFds,
- };
-
- static const size_t wake = numFds - 1; //wake = 1
- static const char WAKE_MESSAGE = 'W';
- struct pollfd mPollFds[numFds];//2
- int mWritePipeFd;
- SensorBase* mSensors[numSensorDrivers];// 2
-
- int handleToDriver(int handle) const {
- switch (handle) {
- /*
- case ID_A:
- case ID_M:
- case ID_O:
- return akm;
- case ID_P:
- return proximity;
- case ID_L:
- return light;
- */
- case ID_GY:
- return gyro;
- }
- return -EINVAL;
- }
- };
包括構(gòu)造函數(shù):
- sensors_poll_context_t::sensors_poll_context_t()
- {
- /*
- mSensors[light] = new LightSensor();
- mPollFds[light].fd = mSensors[light]->getFd();
- mPollFds[light].events = POLLIN;
- mPollFds[light].revents = 0;
-
- mSensors[proximity] = new ProximitySensor();
- mPollFds[proximity].fd = mSensors[proximity]->getFd();
- mPollFds[proximity].events = POLLIN;
- mPollFds[proximity].revents = 0;
-
- mSensors[akm] = new AkmSensor();
- mPollFds[akm].fd = mSensors[akm]->getFd();
- mPollFds[akm].events = POLLIN;
- mPollFds[akm].revents = 0;
-
- */
- //LOGD("sensors_poll_context_t");
- mSensors[gyro] = new GyroSensor();
- mPollFds[gyro].fd = mSensors[gyro]->getFd();
- mPollFds[gyro].events = POLLIN;
- mPollFds[gyro].revents = 0;
-
- int wakeFds[2];
- int result = pipe(wakeFds);
- LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
- fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
- fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
- mWritePipeFd = wakeFds[1];
-
- //wake equals 1
- mPollFds[wake].fd = wakeFds[0];//store the reading fd of the pipe
- mPollFds[wake].events = POLLIN;
- mPollFds[wake].revents = 0;
- }
3.修改GyroSensor.cpp的getFd()函數(shù),把原來(lái)的返回gyro設(shè)備驅(qū)動(dòng)的文件描述符,改為返回socket的文件描述符。
- int GyroSensor::getFd()
- {
- if(mSocketFd == -1){
- socket_connect();
- }
-
- return mSocketFd;
- }
其中,mSocketFd是在GyroSensor.h中新定義的socket文件描述符,socket_connect()函數(shù)實(shí)現(xiàn)連接socket服務(wù)端。
我們回過(guò)頭看sensors.cpp文件的sensors_poll_context_t構(gòu)造函數(shù):
- mSensors[gyro] = new GyroSensor();
- mPollFds[gyro].fd = mSensors[gyro]->getFd();
- mPollFds[gyro].events = POLLIN;
- mPollFds[gyro].revents = 0;
這里初始化gyro類(lèi)后,通過(guò)getFd()獲取socket文件描述符,然后就可以通過(guò)poll函數(shù)對(duì)文件描述符進(jìn)行讀取數(shù)據(jù),poll的讀取在sensors_poll_context_t::pollEvents函數(shù)中,代碼都不用改變,像這樣:
- int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
- {
- //what does parameter count mean ? fuck
- int nbEvents = 0;
- int n = 0;
- //LOGD("sensors_poll_context_t::pollEvents");
- //LOGD("count=%d",count);
-
- do {
- // see if we have some leftover from the last poll()
- 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 (nb < count) {
- // no more data for this sensor
- mPollFds[i].revents = 0;
- }
- count -= nb;
- nbEvents += nb;
- data += nb;
- }
- }
-
- 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) {
- LOGE("poll() failed (%s)", strerror(errno));
- return -errno;
- }
- //read data from pipe
- if (mPollFds[wake].revents & POLLIN) {
- char msg;
- int result = read(mPollFds[wake].fd, &msg, 1);
- LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
- LOGE_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;
- }
4.修改gyro類(lèi)的構(gòu)造函數(shù),把與設(shè)備驅(qū)動(dòng)相關(guān)的那一段代碼刪除:
- GyroSensor::GyroSensor()
- : SensorBase(NULL, "gyro"),
- mEnabled(0),
- mInputReader(4),
- mHasPendingEvent(false),
- mEnabledTime(0),
- mSocketFd(-1)
- {
- //LOGD("GyroSensor::GyroSensor");
- mPendingEvent.version = sizeof(sensors_event_t);
- mPendingEvent.sensor = ID_GY;
- mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;
- memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
-
-
- /*
- if (data_fd) {
- strcpy(input_sysfs_path, "/sys/class/input/");
- strcat(input_sysfs_path, input_name);
- strcat(input_sysfs_path, "/device/");
- input_sysfs_path_len = strlen(input_sysfs_path);
- enable(0, 1);
- }
-
- */
- }
5.修改gyro類(lèi)的其他成員函數(shù),包括setDelay,enable,setInitialState等函數(shù)里面的代碼去全部刪除:
- int GyroSensor::setInitialState() {
-
- /*
- struct input_absinfo absinfo_x;
- struct input_absinfo absinfo_y;
- struct input_absinfo absinfo_z;
- float value;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) &&
- !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) &&
- !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) {
- value = absinfo_x.value;
- mPendingEvent.data[0] = value * CONVERT_GYRO_X;
- value = absinfo_x.value;
- mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
- value = absinfo_x.value;
- mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
- mHasPendingEvent = true;
- }
-
-
- */
-
- //LOGD("GyroSensor::setInitialState");
- return 0;
- }
- int GyroSensor::enable(int32_t, int en) {
- /*
- int flags = en ? 1 : 0;
- if (flags != mEnabled) {
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[2];
- int err;
- buf[1] = 0;
- if (flags) {
- buf[0] = '1';
- mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
- } else {
- buf[0] = '0';
- }
- err = write(fd, buf, sizeof(buf));
- close(fd);
- mEnabled = flags;
- setInitialState();
- return 0;
- }
- return -1;
- }
- */
-
- //LOGD("GyroSensor::enable");
- return 0;
- }
- int GyroSensor::setDelay(int32_t handle, int64_t delay_ns)
- {
- /*
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[80];
- sprintf(buf, "%lld", delay_ns);
- write(fd, buf, strlen(buf)+1);
- close(fd);
- return 0;
- }
- return -1;
- */
- //LOGD("GyroSensor::setDelay");
- return 0;
-
- }
6.修改gyro類(lèi)的readEvents函數(shù),這個(gè)函數(shù)是最重要的函數(shù),要從socket中讀取gyro數(shù)據(jù):
- float value = 0;
- char buf[2];
- int nread = 0;
-
- nread = read(mSocketFd, buf, 2);
- if(nread <= 0){
- LOGE("GyroSensor::readEvents read error.");
- return 0;
- }
-
- float value = (float)((buf[0] << 8) + buf[1]);
- //LOGD("gyro_msg_handle, value=%f",value);
- value *= CONVERT_GYRO_X;
-
-
- mPendingEvent.data[0] = value;
- mPendingEvent.data[1] = value;
- mPendingEvent.data[2] = value;
-
- *data = *mPendingEvent;
-
- return 1;
sokcet服務(wù)端每次發(fā)送2個(gè)字節(jié)數(shù)據(jù),因是單軸陀螺儀,所以只有1個(gè)數(shù)據(jù),把mPendingEvent的data數(shù)據(jù)3個(gè)字節(jié)都填充同一數(shù)據(jù),然后賦值給*data,最后返回1,表述讀到1個(gè)數(shù)據(jù)。
7.修改libsensors下的Android.mk文件的:
- LOCAL_MODULE := sensors.default
8.編譯后,生成sensors.default.so文件到lib/hw目錄,把hw目錄下其他有sensors文字的so文件刪除,只留sensors.default.so文件,然后就可以在模擬器或設(shè)備上進(jìn)行測(cè)試了,App層的Java測(cè)試程序如下:
- package com.hase.ng102.sensors;
-
- import android.R.string;
- import android.app.Activity;
- import android.content.Context;
- import android.hardware.Sensor;
- import android.hardware.SensorEvent;
- import android.hardware.SensorEventListener;
- import android.hardware.SensorManager;
- import android.os.Bundle;
- import android.util.Log;
- import android.widget.TextView;
-
- public class SensorDemoActivity extends Activity {
- //設(shè)置LOG標(biāo)簽
- private static final String TAG = "sensors";
- private SensorManager sm;
- private TextView tv1;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- tv1 = (TextView)this.findViewById(R.id.tv1);
- sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
- Log.d(String.format("getSystemService %s", sm == null ? "sucess":"fail"), TAG);
- int sensorType = Sensor.TYPE_GYROSCOPE;
- sm.registerListener(myAccelerometerListener,sm.getDefaultSensor(sensorType),SensorManager.SENSOR_DELAY_NORMAL);
- }
-
- /*
- * SensorEventListener接口的實(shí)現(xiàn),需要實(shí)現(xiàn)兩個(gè)方法
- * 方法1 onSensorChanged 當(dāng)數(shù)據(jù)變化的時(shí)候被觸發(fā)調(diào)用
- * 方法2 onAccuracyChanged 當(dāng)獲得數(shù)據(jù)的精度發(fā)生變化的時(shí)候被調(diào)用,比如突然無(wú)法獲得數(shù)據(jù)時(shí)
- * */
- final SensorEventListener myAccelerometerListener = new SensorEventListener(){
-
- //復(fù)寫(xiě)onSensorChanged方法//
- public void onSensorChanged(SensorEvent sensorEvent){
- if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){
- Log.i(TAG,"onSensorChanged");
-
- //圖解中已經(jīng)解釋三個(gè)值的含義
- float x = sensorEvent.values[0];
- float y = sensorEvent.values[1];
- float z = sensorEvent.values[2];
-
- String msg = String.format("x=%f\n y=%f\n z=%f\n",x,y,z);
- tv1.setText(msg);
- Log.i(TAG, msg);
- }
- else {
- String msg = "other sensors data changed";
- tv1.setText(msg);
- Log.i(TAG, msg);
- }
- }
- //復(fù)寫(xiě)onAccuracyChanged方法
- public void onAccuracyChanged(Sensor sensor , int accuracy){
- Log.i(TAG, "onAccuracyChanged");
- }
- };
-
- public void onPause(){
- /*
- * 很關(guān)鍵的部分:注意,說(shuō)明文檔中提到,即使activity不可見(jiàn)的時(shí)候,感應(yīng)器依然會(huì)繼續(xù)的工作,測(cè)試的時(shí)候可以發(fā)現(xiàn),沒(méi)有正常的刷新頻率
- * 也會(huì)非常高,所以一定要在onPause方法中關(guān)閉觸發(fā)器,否則講耗費(fèi)用戶(hù)大量電量,很不負(fù)責(zé)。
- * */
- sm.unregisterListener(myAccelerometerListener);
- super.onPause();
- }
-
-
-
- }
|