| /* |
| * Copyright (C) 2008-2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "Sensors" |
| |
| #include <dirent.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <linux/input.h> |
| #include <math.h> |
| #include <poll.h> |
| #include <pthread.h> |
| #include <stdlib.h> |
| |
| #include <utils/Atomic.h> |
| #include <utils/Log.h> |
| |
| #include <hardware/sensors.h> |
| |
| #include "sensors.h" |
| #include "CwMcuSensor.h" |
| |
| /*****************************************************************************/ |
| |
| #define DELAY_OUT_TIME 0x7FFFFFFF |
| |
| #define LIGHT_SENSOR_POLLTIME 2000000000 |
| |
| /*****************************************************************************/ |
| static const struct sensor_t sSensorList[] = { |
| {.name = "Accelerometer Sensor", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_A, |
| .type = SENSOR_TYPE_ACCELEROMETER, |
| .maxRange = RANGE_A, |
| .resolution = CONVERT_A, |
| .power = 0.17f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Magnetic field Sensor", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_M, |
| .type = SENSOR_TYPE_MAGNETIC_FIELD, |
| .maxRange = 200.0f, |
| .resolution = CONVERT_M, |
| .power = 5.0f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Gyroscope Sensor", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_GY, |
| .type = SENSOR_TYPE_GYROSCOPE, |
| .maxRange = 2000.0f, |
| .resolution = CONVERT_GYRO, |
| .power = 6.1f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "CM32181 Light sensor", |
| .vendor = "Capella Microsystems", |
| .version = 1, |
| .handle = ID_L, |
| .type = SENSOR_TYPE_LIGHT, |
| .maxRange = 10240.0f, |
| .resolution = 1.0f, |
| .power = 0.15f, |
| .minDelay = 0, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 0, |
| .stringType = NULL, |
| .requiredPermission = NULL, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_ON_CHANGE_MODE, |
| .reserved = {} |
| }, |
| {.name = "Pressure Sensor", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_PS, |
| .type = SENSOR_TYPE_PRESSURE, |
| .maxRange = 2000, |
| .resolution = 1.0f, |
| .power = 0.0027f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "CWGD Orientation Sensor", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_O, |
| .type = SENSOR_TYPE_ORIENTATION, |
| .maxRange = 360.0f, |
| .resolution = 0.1f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Rotation Vector", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_RV, |
| .type = SENSOR_TYPE_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Linear Acceleration", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_LA, |
| .type = SENSOR_TYPE_LINEAR_ACCELERATION, |
| .maxRange = RANGE_A, |
| .resolution = 0.01, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Gravity", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_G, |
| .type = SENSOR_TYPE_GRAVITY, |
| .maxRange = GRAVITY_EARTH, |
| .resolution = 0.01, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Magnetic Uncalibrated", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_MAGNETIC_UNCALIBRATED, |
| .type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, |
| .maxRange = 200.0f, |
| .resolution = CONVERT_M, |
| .power = 5.0f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 610, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Gyroscope Uncalibrated", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GYROSCOPE_UNCALIBRATED, |
| .type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, |
| .maxRange = 2000.0f, |
| .resolution = CONVERT_GYRO, |
| .power = 6.1f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 610, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Game Rotation Vector", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GAME_ROTATION_VECTOR, |
| .type = SENSOR_TYPE_GAME_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Geomagnetic Rotation Vector", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GEOMAGNETIC_ROTATION_VECTOR, |
| .type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE, |
| .reserved = {} |
| }, |
| {.name = "Significant Motion", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_SIGNIFICANT_MOTION, |
| .type = SENSOR_TYPE_SIGNIFICANT_MOTION, |
| .maxRange = 200.0f, |
| .resolution = 1.0f, |
| .power = 0.17f, |
| .minDelay = -1, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 0, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Step Detector", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_STEP_DETECTOR, |
| .type = SENSOR_TYPE_STEP_DETECTOR, |
| .maxRange = 200.0f, |
| .resolution = 1.0f, |
| .power = 0.17f, |
| .minDelay = 0, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_SPECIAL_REPORTING_MODE, |
| .reserved = {} |
| }, |
| {.name = "Step Counter", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_STEP_COUNTER, |
| .type = SENSOR_TYPE_STEP_COUNTER, |
| .maxRange = 200.0f, |
| .resolution = 1.0f, |
| .power = 0.17f, |
| .minDelay = 0, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_ON_CHANGE_MODE, |
| .reserved = {} |
| }, |
| |
| |
| {.name = "Accelerometer Sensor (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_A_W, |
| .type = SENSOR_TYPE_ACCELEROMETER, |
| .maxRange = RANGE_A, |
| .resolution = CONVERT_A, |
| .power = 0.17f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Magnetic field Sensor (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_M_W, |
| .type = SENSOR_TYPE_MAGNETIC_FIELD, |
| .maxRange = 200.0f, |
| .resolution = CONVERT_M, |
| .power = 5.0f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Gyroscope Sensor (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_GY_W, |
| .type = SENSOR_TYPE_GYROSCOPE, |
| .maxRange = 2000.0f, |
| .resolution = CONVERT_GYRO, |
| .power = 6.1f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Pressure Sensor (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_PS_W, |
| .type = SENSOR_TYPE_PRESSURE, |
| .maxRange = 2000, |
| .resolution = 1.0f, |
| .power = 0.0027f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "CWGD Orientation Sensor (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_O_W, |
| .type = SENSOR_TYPE_ORIENTATION, |
| .maxRange = 360.0f, |
| .resolution = 0.1f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Rotation Vector (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_RV_W, |
| .type = SENSOR_TYPE_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Linear Acceleration (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_LA_W, |
| .type = SENSOR_TYPE_LINEAR_ACCELERATION, |
| .maxRange = RANGE_A, |
| .resolution = 0.01, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Gravity (WAKE_UP)", |
| .vendor = "HTC Group Ltd.", |
| .version = 1, |
| .handle = ID_G_W, |
| .type = SENSOR_TYPE_GRAVITY, |
| .maxRange = GRAVITY_EARTH, |
| .resolution = 0.01, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Magnetic Uncalibrated (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_MAGNETIC_UNCALIBRATED_W, |
| .type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, |
| .maxRange = 200.0f, |
| .resolution = CONVERT_M, |
| .power = 5.0f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 610, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Gyroscope Uncalibrated (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GYROSCOPE_UNCALIBRATED_W, |
| .type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, |
| .maxRange = 2000.0f, |
| .resolution = CONVERT_GYRO, |
| .power = 6.1f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 610, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Game Rotation Vector (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GAME_ROTATION_VECTOR_W, |
| .type = SENSOR_TYPE_GAME_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Geomagnetic Rotation Vector (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_GEOMAGNETIC_ROTATION_VECTOR_W, |
| .type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR, |
| .maxRange = 1.0f, |
| .resolution = 0.0001f, |
| .power = 11.27f, |
| .minDelay = 10000, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 200000, |
| .flags = SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Step Detector (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_STEP_DETECTOR_W, |
| .type = SENSOR_TYPE_STEP_DETECTOR, |
| .maxRange = 200.0f, |
| .resolution = 1.0f, |
| .power = 0.17f, |
| .minDelay = 0, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| {.name = "Step Counter (WAKE_UP)", |
| .vendor = "hTC Corp.", |
| .version = 1, |
| .handle = ID_CW_STEP_COUNTER_W, |
| .type = SENSOR_TYPE_STEP_COUNTER, |
| .maxRange = 200.0f, |
| .resolution = 1.0f, |
| .power = 0.17f, |
| .minDelay = 0, |
| .fifoReservedEventCount = 0, |
| .fifoMaxEventCount = 1220, |
| .stringType = 0, |
| .requiredPermission = 0, |
| .maxDelay = 0, |
| .flags = SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP, |
| .reserved = {} |
| }, |
| }; |
| |
| static int open_sensors(const struct hw_module_t* module, const char* id, |
| struct hw_device_t** device); |
| |
| static int sensors__get_sensors_list(struct sensors_module_t*, |
| struct sensor_t const** list) |
| { |
| *list = sSensorList; |
| return ARRAY_SIZE(sSensorList); |
| } |
| |
| 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: "Sensor module", |
| author: "Electronic Company", |
| methods: &sensors_module_methods, |
| dso: NULL, |
| reserved: { }, |
| }, |
| get_sensors_list: sensors__get_sensors_list, |
| }; |
| |
| struct sensors_poll_context_t { |
| sensors_poll_device_1_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); |
| int batch(int handle, int flags, int64_t period_ns, int64_t timeout); |
| int flush(int handle); |
| |
| private: |
| enum { |
| cwmcu = 0, |
| numSensorDrivers, |
| numFds, |
| }; |
| |
| static const size_t wake = numFds - 1; |
| static const char WAKE_MESSAGE = 'W'; |
| struct pollfd mPollFds[numFds]; |
| int mWritePipeFd; |
| SensorBase* mSensors[numSensorDrivers]; |
| |
| int handleToDriver(int handle) const { |
| switch (handle) { |
| case ID_A: |
| case ID_M: |
| case ID_GY: |
| case ID_L: |
| case ID_PS: |
| case ID_O: |
| case ID_RV: |
| case ID_LA: |
| case ID_G: |
| case ID_CW_MAGNETIC_UNCALIBRATED: |
| case ID_CW_GYROSCOPE_UNCALIBRATED: |
| case ID_CW_GAME_ROTATION_VECTOR: |
| case ID_CW_GEOMAGNETIC_ROTATION_VECTOR: |
| case ID_CW_SIGNIFICANT_MOTION: |
| case ID_CW_STEP_DETECTOR: |
| case ID_CW_STEP_COUNTER: |
| case ID_A_W: |
| case ID_M_W: |
| case ID_GY_W: |
| case ID_PS_W: |
| case ID_O_W: |
| case ID_RV_W: |
| case ID_LA_W: |
| case ID_G_W: |
| case ID_CW_MAGNETIC_UNCALIBRATED_W: |
| case ID_CW_GYROSCOPE_UNCALIBRATED_W: |
| case ID_CW_GAME_ROTATION_VECTOR_W: |
| case ID_CW_GEOMAGNETIC_ROTATION_VECTOR_W: |
| case ID_CW_STEP_DETECTOR_W: |
| case ID_CW_STEP_COUNTER_W: |
| return cwmcu; |
| } |
| return -EINVAL; |
| } |
| }; |
| |
| /*****************************************************************************/ |
| |
| sensors_poll_context_t::sensors_poll_context_t() |
| { |
| mSensors[cwmcu] = new CwMcuSensor(); |
| mPollFds[cwmcu].fd = mSensors[cwmcu]->getFd(); |
| mPollFds[cwmcu].events = POLLIN; |
| mPollFds[cwmcu].revents = 0; |
| |
| int wakeFds[2]; |
| int result = pipe(wakeFds); |
| ALOGE_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]; |
| |
| mPollFds[wake].fd = wakeFds[0]; |
| mPollFds[wake].events = POLLIN; |
| mPollFds[wake].revents = 0; |
| } |
| |
| sensors_poll_context_t::~sensors_poll_context_t() { |
| for (int i=0 ; i<numSensorDrivers ; i++) { |
| delete mSensors[i]; |
| } |
| close(mPollFds[wake].fd); |
| close(mWritePipeFd); |
| } |
| |
| int sensors_poll_context_t::activate(int handle, int enabled) { |
| int index = handleToDriver(handle); |
| if (index < 0) return index; |
| int err = mSensors[index]->setEnable(handle, enabled); |
| if (enabled && !err) { |
| const char wakeMessage(WAKE_MESSAGE); |
| int result = write(mWritePipeFd, &wakeMessage, 1); |
| ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno)); |
| } |
| return err; |
| } |
| |
| int sensors_poll_context_t::setDelay(int handle, int64_t ns) { |
| |
| int index = handleToDriver(handle); |
| if (index < 0) return index; |
| return mSensors[index]->setDelay(handle, ns); |
| } |
| |
| int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) |
| { |
| int nbEvents = 0; |
| int n = 0; |
| 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 |
| do { |
| TEMP_FAILURE_RETRY(n = poll(mPollFds, numFds, nbEvents ? 0 : -1)); |
| } while (n < 0 && errno == EINTR); |
| if (n<0) { |
| ALOGE("poll() failed (%s)", strerror(errno)); |
| return -errno; |
| } |
| if (mPollFds[wake].revents & POLLIN) { |
| char msg(WAKE_MESSAGE); |
| 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; |
| } |
| |
| int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout) |
| { |
| int index = handleToDriver(handle); |
| |
| if (index < 0) |
| return index; |
| |
| int err = mSensors[index]->batch(handle, flags, period_ns, timeout); |
| |
| return err; |
| } |
| |
| int sensors_poll_context_t::flush(int handle) |
| { |
| int index = handleToDriver(handle); |
| |
| if (index < 0) |
| return index; |
| |
| int err = mSensors[index]->flush(handle); |
| |
| return err; |
| } |
| |
| |
| /*****************************************************************************/ |
| |
| static int poll__close(struct hw_device_t *dev) |
| { |
| sensors_poll_context_t *ctx = reinterpret_cast<sensors_poll_context_t *>(dev); |
| if (ctx) { |
| delete ctx; |
| } |
| return 0; |
| } |
| |
| static int poll__activate(struct sensors_poll_device_t *dev, |
| int handle, int enabled) { |
| sensors_poll_context_t *ctx = reinterpret_cast<sensors_poll_context_t *>(dev); |
| return ctx->activate(handle, enabled); |
| } |
| |
| static int poll__setDelay(struct sensors_poll_device_t *dev, |
| int handle, int64_t ns) { |
| sensors_poll_context_t *ctx = reinterpret_cast<sensors_poll_context_t *>(dev); |
| return ctx->setDelay(handle, ns); |
| } |
| |
| static int poll__poll(struct sensors_poll_device_t *dev, |
| sensors_event_t* data, int count) { |
| sensors_poll_context_t *ctx = reinterpret_cast<sensors_poll_context_t *>(dev); |
| return ctx->pollEvents(data, count); |
| } |
| |
| static int poll__batch(struct sensors_poll_device_1 *dev, |
| int handle, int flags, int64_t period_ns, int64_t timeout) |
| { |
| sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; |
| return ctx->batch(handle, flags, period_ns, timeout); |
| } |
| |
| static int poll__flush(struct sensors_poll_device_1 *dev, |
| int handle) |
| { |
| sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; |
| return ctx->flush(handle); |
| } |
| /*****************************************************************************/ |
| |
| // Open a new instance of a sensor device using name |
| static int open_sensors(const struct hw_module_t* module, const char*, |
| struct hw_device_t** device) |
| { |
| sensors_poll_context_t *dev = new sensors_poll_context_t(); |
| |
| memset(&dev->device, 0, sizeof(sensors_poll_device_1_t)); |
| |
| dev->device.common.tag = HARDWARE_DEVICE_TAG; |
| dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3; |
| 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; |
| |
| // Batch processing |
| dev->device.batch = poll__batch; |
| dev->device.flush = poll__flush; |
| |
| *device = &dev->device.common; |
| |
| return 0; |
| } |
| |