blob: 4ff9b394764a60bcb8356b0179aa78f30c9b9787 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2012-2015 Freescale Semiconductor, Inc.
*
* 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.
*/
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <dlfcn.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include "FSLSensorsHub.h"
#define FSL_SENS_CTRL_NAME "FSL_SENS_HUB"
#define FSL_SENS_DATA_NAME "FSL_SENS_HUB"
#define FSL_SENS_SYSFS_PATH "/sys/class/misc"
#define FSL_SENS_SYSFS_DELAY "poll_delay"
#define FSL_SENS_SYSFS_ENABLE "enable"
#define FSL_ACC_DEVICE_NAME "FreescaleAccelerometer"
#define FSL_MAG_DEVICE_NAME "FreescaleMagnetometer"
#define FSL_GYRO_DEVICE_NAME "FreescaleGyroscope"
#define EVENT_ACC_X REL_X
#define EVENT_ACC_Y REL_Y
#define EVENT_ACC_Z REL_Z
#define EVENT_MAG_X REL_RX
#define EVENT_MAG_Y REL_RY
#define EVENT_MAG_Z REL_RZ
#define EVENT_MAG_STATUS REL_MISC
#define EVENT_GYRO_X (REL_MISC + 1) /*0x0A*/
#define EVENT_GYRO_Y (REL_MISC + 2) /*0x0B*/
#define EVENT_GYRO_Z (REL_MISC + 3) /*0x0C*/
#define EVENT_STEP_DETECTED REL_DIAL
#define EVENT_STEP_COUNT_HIGH REL_HWHEEL
#define EVENT_STEP_COUNT_LOW REL_WHEEL
#define EVENT_ORNT_X ABS_X
#define EVENT_ORNT_Y ABS_Y
#define EVENT_ORNT_Z ABS_Z
#define EVENT_ORNT_STATUS EVENT_MAG_STATUS /*0x0A*/
#define EVENT_LINEAR_ACC_X ABS_RX
#define EVENT_LINEAR_ACC_Y ABS_RY
#define EVENT_LINEAR_ACC_Z ABS_RZ
#define EVENT_GRAVITY_X ABS_HAT0X
#define EVENT_GRAVITY_Y ABS_HAT1X
#define EVENT_GRAVITY_Z ABS_HAT2X
#define EVENT_ROTATION_VECTOR_W ABS_MISC
#define EVENT_ROTATION_VECTOR_A ABS_HAT0Y
#define EVENT_ROTATION_VECTOR_B ABS_HAT1Y
#define EVENT_ROTATION_VECTOR_C ABS_HAT2Y
#define ACC_DATA_CONVERSION(value) ((float)value * GRAVITY_EARTH/0x4000 )
#define MAG_DATA_CONVERSION(value) ((float)value/10.0f)
#define ORNT_DATA_CONVERSION(value) ((float)value/10.0f)
#define GYRO_DATA_CONVERSION(value) ((float)value/1000.0f /180.0f * M_PI )
#define RV_DATA_CONVERSION(value) ((float)value /10000.0f)
#define LA_DATA_CONVERSION(value) ((float)value /10.0f)
#define GRAVT_DATA_CONVERSION(value)((float)value /10.0f)
FSLSensorsHub::FSLSensorsHub()
: SensorBase(FSL_SENS_CTRL_NAME, FSL_SENS_DATA_NAME),
mPendingMask(0),
mInputReader(16)
{
memset(&mPendingEvent[0], 0, sensors *sizeof(sensors_event_t));
mEnabled[accel] = 0;
mDelay[accel] = 0;
mPendingEvent[accel].version = sizeof(sensors_event_t);
mPendingEvent[accel].sensor = ID_A;
mPendingEvent[accel].type = SENSOR_TYPE_ACCELEROMETER;
mPendingEvent[accel].magnetic.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[accel].version = sizeof(sensors_event_t);
mEnabled[mag] = 0;
mDelay[mag] = 0;
mPendingEvent[mag].version = sizeof(sensors_event_t);
mPendingEvent[mag].sensor = ID_M;
mPendingEvent[mag].type = SENSOR_TYPE_MAGNETIC_FIELD;
mPendingEvent[mag].magnetic.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[mag].version = sizeof(sensors_event_t);
mEnabled[orn] = 0;
mDelay[orn] = 0;
mPendingEvent[orn].sensor = ID_O;
mPendingEvent[orn].type = SENSOR_TYPE_ORIENTATION;
mPendingEvent[orn].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[orn].version = sizeof(sensors_event_t);
mEnabled[gyro] = 0;
mDelay[gyro] = 0;
mPendingEvent[gyro].sensor = ID_GY;
mPendingEvent[gyro].type = SENSOR_TYPE_GYROSCOPE;
mPendingEvent[gyro].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[gyro].version = sizeof(sensors_event_t);
mEnabled[rv] = 0;
mDelay[rv] = 0;
mPendingEvent[rv].sensor = ID_RV;
mPendingEvent[rv].type = SENSOR_TYPE_ROTATION_VECTOR;
mPendingEvent[rv].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[rv].version = sizeof(sensors_event_t);
mEnabled[la] = 0;
mDelay[la] = 0;
mPendingEvent[la].sensor = ID_LA;
mPendingEvent[la].type = SENSOR_TYPE_LINEAR_ACCELERATION;
mPendingEvent[la].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[la].version = sizeof(sensors_event_t);
mEnabled[gravt] = 0;
mDelay[gravt] = 0;
mPendingEvent[gravt].sensor = ID_GR;
mPendingEvent[gravt].type = SENSOR_TYPE_GRAVITY;
mPendingEvent[gravt].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[gravt].version = sizeof(sensors_event_t);
mEnabled[sd] = 0;
mDelay[sd] = 0;
mPendingEvent[sd].sensor = ID_SD;
mPendingEvent[sd].type = SENSOR_TYPE_STEP_DETECTOR;
mPendingEvent[sd].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
mPendingEvent[sd].version = sizeof(sensors_event_t);
mEnabled[sc] = 0;
mDelay[sc] = 0;
mPendingEvent[sc].sensor = ID_SC;
mPendingEvent[sc].type = SENSOR_TYPE_STEP_COUNTER;
mPendingEvent[sc].orientation.status = SENSOR_STATUS_ACCURACY_LOW;
mPendingEvent[sc].version = sizeof(sensors_event_t);
sprintf(mClassPath[accel],"%s/%s",FSL_SENS_SYSFS_PATH,FSL_ACC_DEVICE_NAME);
sprintf(mClassPath[mag],"%s/%s",FSL_SENS_SYSFS_PATH,FSL_MAG_DEVICE_NAME);
sprintf(mClassPath[gyro],"%s/%s",FSL_SENS_SYSFS_PATH,FSL_GYRO_DEVICE_NAME);
}
FSLSensorsHub::~FSLSensorsHub()
{
}
int FSLSensorsHub::setEnable(int32_t handle, int en)
{
int err = 0;
int what = accel;
bool isHaveSensorRun = 0;
switch(handle){
case ID_A : what = accel; break;
case ID_M : what = mag; break;
case ID_O : what = orn; break;
case ID_GY: what = gyro; break;
case ID_RV: what = rv; break;
case ID_LA: what = la; break;
case ID_GR: what = gravt; break;
case ID_SD: what = sd; break;
case ID_SC: what = sc; break;
}
if(en)
mEnabled[what]++;
else
mEnabled[what]--;
if(mEnabled[what] < 0)
mEnabled[what] = 0;
for(int i = 0; i < sensors; i++ ){
if(mEnabled[i] > 0)
{
isHaveSensorRun = 1;
break;
}
}
if(isHaveSensorRun){
if(mEnabled[rv] > 0 || mEnabled[gravt] > 0 ||mEnabled[la] > 0 || mEnabled[mag]> 0 || mEnabled[orn] > 0 || mEnabled[gyro]> 0) //need fusion run
{
enable_sensor(accel);
enable_sensor(mag);
enable_sensor(gyro);
} else if(mEnabled[accel] > 0) { //only accel enable
enable_sensor(accel);
disable_sensor(mag);
disable_sensor(gyro);
}
}else
{
disable_sensor(accel);
disable_sensor(mag);
disable_sensor(gyro);
}
ALOGD("FSLSensorsHub sensor waht = %d , enable = %d",what,mEnabled[what]);
return err;
}
int FSLSensorsHub::setDelay(int32_t handle, int64_t ns)
{
if (ns < 0)
return -EINVAL;
int what = accel;
switch(handle){
case ID_A : what = accel; break;
case ID_M : what = mag; break;
case ID_O : what = orn; break;
case ID_GY: what = gyro; break;
case ID_RV: what = rv; break;
case ID_LA: what = la; break;
case ID_GR: what = gravt; break;
case ID_SD: what = sd; break;
case ID_SC: what = sc; break;
}
mDelay[what] = ns;
if(what == accel)
update_delay(accel,mDelay[accel]);
else if(what == mag || what == orn)
update_delay(mag,mDelay[mag]);
else if(what == gyro)
update_delay(gyro,mDelay[gyro]);
else{
update_delay(accel,mDelay[accel]);
update_delay(mag,mDelay[mag]);
update_delay(gyro,mDelay[gyro]);
}
return 0;
}
int FSLSensorsHub::update_delay(int sensor_type , int64_t ns)
{
return writeDelay(sensor_type,ns);
}
int FSLSensorsHub::readEvents(sensors_event_t* data, int count)
{
int i;
if (count < 1)
return -EINVAL;
ssize_t n = mInputReader.fill(data_fd);
if (n < 0)
return n;
int numEventReceived = 0;
input_event const* event;
while (count && mInputReader.readEvent(&event)) {
int type = event->type;
if ((type == EV_ABS) || (type == EV_REL) || (type == EV_KEY)) {
processEvent(type,event->code, event->value);
mInputReader.next();
} else if (type == EV_SYN) {
int64_t time = timevalToNano(event->time);
for(i = 0 ; i< sensors && mPendingMask && count ;i++){
if(mPendingMask & (1 << i)){
mPendingMask &= ~(1 << i);
mPendingEvent[i].timestamp = time;
if (mEnabled[i]) {
*data++ = mPendingEvent[i];
count--;
numEventReceived++;
}
}
}
if (!mPendingMask) {
mInputReader.next();
}
} else {
mInputReader.next();
}
}
return numEventReceived;
}
void FSLSensorsHub::processEvent(__attribute__((unused)) int code, __attribute__((unused)) int value)
{
}
void FSLSensorsHub::processEvent(int type ,int code, int value){
static uint64_t steps_high = 0,steps_low = 0;
if(type == EV_REL){
switch (code) {
case EVENT_ACC_X :
mPendingMask |= 1 << accel;
mPendingEvent[accel].acceleration.x = ACC_DATA_CONVERSION(value);
break;
case EVENT_ACC_Y:
mPendingMask |= 1 << accel;
mPendingEvent[accel].acceleration.y = ACC_DATA_CONVERSION(value);
break;
case EVENT_ACC_Z:
mPendingMask |= 1 << accel;
mPendingEvent[accel].acceleration.z = ACC_DATA_CONVERSION(value);
break;
case EVENT_MAG_X :
mPendingMask |= 1 << mag;
mPendingEvent[mag].magnetic.x = MAG_DATA_CONVERSION(value);
break;
case EVENT_MAG_Y:
mPendingMask |= 1 << mag;
mPendingEvent[mag].magnetic.y = MAG_DATA_CONVERSION(value);
break;
case EVENT_MAG_Z:
mPendingMask |= 1 << mag;
mPendingEvent[mag].magnetic.z = MAG_DATA_CONVERSION(value);
break;
case EVENT_MAG_STATUS:
mPendingMask |= 1 << mag;
mPendingEvent[mag].magnetic.status = value;
mPendingEvent[orn].orientation.status = value;
break;
case EVENT_GYRO_X :
mPendingMask |= 1 << gyro;
mPendingEvent[gyro].gyro.x= GYRO_DATA_CONVERSION(value);
break;
case EVENT_GYRO_Y :
mPendingMask |= 1 << gyro;
mPendingEvent[gyro].gyro.y = GYRO_DATA_CONVERSION(value);
break;
case EVENT_GYRO_Z :
mPendingMask |= 1 << gyro;
mPendingEvent[gyro].gyro.z = GYRO_DATA_CONVERSION(value);
break;
case EVENT_STEP_DETECTED:
mPendingMask |= 1 << sd;
mPendingEvent[sd].data[0] = 1.0f;
break;
case EVENT_STEP_COUNT_HIGH:
steps_high = (uint64_t)(value & 0xffffffff);
break;
case EVENT_STEP_COUNT_LOW:
mPendingMask |= 1 << sc;
steps_low = (uint64_t)(value & 0xffffffff);
mPendingEvent[sc].u64.step_counter = ((steps_high << 32) | steps_low);
break;
}
} else if (type == EV_ABS) {
switch(code){
case EVENT_ORNT_X :
mPendingMask |= 1 << orn;
mPendingEvent[orn].orientation.azimuth = ORNT_DATA_CONVERSION(value);
break;
case EVENT_ORNT_Y :
mPendingMask |= 1 << orn;
mPendingEvent[orn].orientation.pitch = ORNT_DATA_CONVERSION(value);
break;
case EVENT_ORNT_Z :
mPendingMask |= 1 << orn;
mPendingEvent[orn].orientation.roll = ORNT_DATA_CONVERSION(value);
break;
case EVENT_LINEAR_ACC_X :
mPendingMask |= 1 << la;
mPendingEvent[la].data[0] = LA_DATA_CONVERSION(value);
break;
case EVENT_LINEAR_ACC_Y:
mPendingMask |= 1 << la;
mPendingEvent[la].data[1] = LA_DATA_CONVERSION(value);
break;
case EVENT_LINEAR_ACC_Z:
mPendingMask |= 1 << la;
mPendingEvent[la].data[2] = LA_DATA_CONVERSION(value);
break;
case EVENT_GRAVITY_X :
mPendingMask |= 1 << gravt;
mPendingEvent[gravt].data[0] = GRAVT_DATA_CONVERSION(value);
break;
case EVENT_GRAVITY_Y:
mPendingMask |= 1 << gravt;
mPendingEvent[gravt].data[1] = GRAVT_DATA_CONVERSION(value);
break;
case EVENT_GRAVITY_Z:
mPendingMask |= 1 << gravt;
mPendingEvent[gravt].data[2] = GRAVT_DATA_CONVERSION(value);
break;
case EVENT_ROTATION_VECTOR_W :
mPendingMask |= 1 << rv;
mPendingEvent[rv].data[3] = RV_DATA_CONVERSION(value);
break;
case EVENT_ROTATION_VECTOR_A:
mPendingMask |= 1 << rv;
mPendingEvent[rv].data[0] = RV_DATA_CONVERSION(value);
break;
case EVENT_ROTATION_VECTOR_B:
mPendingMask |= 1 << rv;
mPendingEvent[rv].data[1] = RV_DATA_CONVERSION(value);
break;
case EVENT_ROTATION_VECTOR_C:
mPendingMask |= 1 << rv;
mPendingEvent[rv].data[2] = RV_DATA_CONVERSION(value);
break;
}
}
}
int FSLSensorsHub::writeEnable(int what ,int isEnable) {
char attr[PATH_MAX] = {'\0'};
int err = 0;
if(mClassPath[what][0] == '\0')
return -1;
strcpy(attr, mClassPath[what]);
strcat(attr,"/");
strcat(attr,FSL_SENS_SYSFS_ENABLE);
int fd = open(attr, O_RDWR);
if (0 > fd) {
ALOGE("Could not open (write-only) SysFs attribute \"%s\" (%s).", attr, strerror(errno));
return -errno;
}
char buf[16];
sprintf(buf,"%d",isEnable);
err = write(fd, buf, sizeof(buf));
if (0 > err) {
err = -errno;
ALOGE("Could not write SysFs attribute \"%s\" (%s).", attr, strerror(errno));
} else {
err = 0;
}
close(fd);
return err;
}
int FSLSensorsHub::writeDelay(int what,int64_t ns) {
char attr[PATH_MAX] = {'\0'};
int delay;
if(mClassPath[what][0] == '\0')
return -1;
strcpy(attr, mClassPath[what]);
strcat(attr,"/");
strcat(attr,FSL_SENS_SYSFS_DELAY);
int fd = open(attr, O_RDWR);
if (0 > fd) {
ALOGE("Could not open (write-only) SysFs attribute \"%s\" (%s).", attr, strerror(errno));
return -errno;
}
if (ns > 10240000000LL) {
ns = 10240000000LL; /* maximum delay in nano second. */
}
if (ns < 312500LL) {
ns = 312500LL; /* minimum delay in nano second. */
}
char buf[80];
delay = ns/1000/1000;
sprintf(buf, "%d",delay);
ALOGD("FSL_SENS write delay %s\n",buf);
write(fd, buf, strlen(buf)+1);
close(fd);
return 0;
}
int FSLSensorsHub::enable_sensor(int what) {
return writeEnable(what,1);
}
int FSLSensorsHub::disable_sensor(int what) {
return writeEnable(what,0);
}
int FSLSensorsHub::getEnable(int32_t handle) {
int what = accel;
switch(handle){
case ID_A : what = accel; break;
case ID_M : what = mag; break;
case ID_O : what = orn; break;
case ID_GY: what = gyro; break;
case ID_RV: what = rv; break;
case ID_LA: what = la; break;
case ID_GR: what = gravt; break;
case ID_SD: what = sd; break;
case ID_SC: what = sc; break;
}
return mEnabled[what];
}
/*****************************************************************************/