You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
5.1 KiB
202 lines
5.1 KiB
/* |
|
* Copyright (C) 2008 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. |
|
*/ |
|
|
|
#include <fcntl.h> |
|
#include <errno.h> |
|
#include <math.h> |
|
#include <poll.h> |
|
#include <unistd.h> |
|
#include <dirent.h> |
|
#include <sys/select.h> |
|
#include <cutils/log.h> |
|
#include <linux/kxtf9.h> |
|
|
|
#include "KionixSensor.h" |
|
|
|
#define KIONIX_IOCTL_ENABLE_OUTPUT KXTF9_IOCTL_ENABLE_OUTPUT |
|
#define KIONIX_IOCTL_DISABLE_OUTPUT KXTF9_IOCTL_DISABLE_OUTPUT |
|
#define KIONIX_IOCTL_GET_ENABLE KXTF9_IOCTL_GET_ENABLE |
|
#define KIONIX_IOCTL_UPDATE_ODR KXTF9_IOCTL_UPDATE_ODR |
|
|
|
#define KIONIX_UNIT_CONVERSION(value) ((value) * GRAVITY_EARTH / (1024.0f)) |
|
|
|
/*****************************************************************************/ |
|
|
|
KionixSensor::KionixSensor() |
|
: SensorBase(DIR_DEV, INPUT_NAME_ACC), |
|
mEnabled(0), |
|
mDelay(-1), |
|
mInputReader(32), |
|
mHasPendingEvent(false) |
|
{ |
|
mPendingEvent.version = sizeof(sensors_event_t); |
|
mPendingEvent.sensor = ID_A; |
|
mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER; |
|
memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); |
|
|
|
open_device(); |
|
} |
|
|
|
KionixSensor::~KionixSensor() { |
|
if (mEnabled) { |
|
setEnable(0, 0); |
|
} |
|
|
|
close_device(); |
|
} |
|
|
|
int KionixSensor::setInitialState() { |
|
struct input_absinfo absinfo; |
|
|
|
if (mEnabled) { |
|
if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { |
|
mPendingEvent.acceleration.x = KIONIX_UNIT_CONVERSION(absinfo.value); |
|
} |
|
if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { |
|
mPendingEvent.acceleration.y = KIONIX_UNIT_CONVERSION(absinfo.value); |
|
} |
|
if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { |
|
mPendingEvent.acceleration.z = KIONIX_UNIT_CONVERSION(absinfo.value); |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
bool KionixSensor::hasPendingEvents() const { |
|
return mHasPendingEvent; |
|
} |
|
|
|
int KionixSensor::setEnable(int32_t handle, int enabled) { |
|
int err = 0; |
|
int opDone = 0; |
|
|
|
/* handle check */ |
|
if (handle != ID_A) { |
|
ALOGE("KionixSensor: Invalid handle (%d)", handle); |
|
return -EINVAL; |
|
} |
|
|
|
if (mEnabled <= 0) { |
|
if (enabled) { |
|
err = ioctl(dev_fd, KIONIX_IOCTL_ENABLE_OUTPUT); |
|
opDone = 1; |
|
} |
|
} else if (mEnabled == 1) { |
|
if (!enabled) { |
|
err = ioctl(dev_fd, KIONIX_IOCTL_DISABLE_OUTPUT); |
|
opDone = 1; |
|
} |
|
} |
|
if (err != 0) { |
|
ALOGE("KionixSensor: IOCTL failed (%s)", strerror(errno)); |
|
return err; |
|
} |
|
if (opDone) { |
|
ALOGD("KionixSensor: Control set %d", enabled); |
|
setInitialState(); |
|
} |
|
|
|
if (enabled) { |
|
mEnabled++; |
|
if (mEnabled > 32767) mEnabled = 32767; |
|
} else { |
|
mEnabled--; |
|
if (mEnabled < 0) mEnabled = 0; |
|
} |
|
ALOGD("KionixSensor: mEnabled = %d", mEnabled); |
|
|
|
return err; |
|
} |
|
|
|
int KionixSensor::setDelay(int32_t handle, int64_t delay_ns) |
|
{ |
|
int err = 0; |
|
int ms; |
|
|
|
/* handle check */ |
|
if (handle != ID_A) { |
|
ALOGE("KionixSensor: Invalid handle (%d)", handle); |
|
return -EINVAL; |
|
} |
|
|
|
if (mDelay != delay_ns) { |
|
ms = delay_ns / 1000000; |
|
if (ioctl(dev_fd, KIONIX_IOCTL_UPDATE_ODR, &ms)) { |
|
return -errno; |
|
} |
|
mDelay = delay_ns; |
|
} |
|
|
|
return err; |
|
} |
|
|
|
int64_t KionixSensor::getDelay(int32_t handle) |
|
{ |
|
return (handle == ID_A) ? mDelay : 0; |
|
} |
|
|
|
int KionixSensor::getEnable(int32_t handle) |
|
{ |
|
return (handle == ID_A) ? mEnabled : 0; |
|
} |
|
|
|
int KionixSensor::readEvents(sensors_event_t* data, int count) |
|
{ |
|
if (count < 1) |
|
return -EINVAL; |
|
|
|
if (mHasPendingEvent) { |
|
mHasPendingEvent = false; |
|
mPendingEvent.timestamp = getTimestamp(); |
|
*data = mPendingEvent; |
|
return mEnabled ? 1 : 0; |
|
} |
|
|
|
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) { |
|
float value = event->value; |
|
if (event->code == EVENT_TYPE_ACCEL_X) { |
|
mPendingEvent.acceleration.x = KIONIX_UNIT_CONVERSION(value); |
|
} else if (event->code == EVENT_TYPE_ACCEL_Y) { |
|
mPendingEvent.acceleration.y = KIONIX_UNIT_CONVERSION(value); |
|
} else if (event->code == EVENT_TYPE_ACCEL_Z) { |
|
mPendingEvent.acceleration.z = KIONIX_UNIT_CONVERSION(value); |
|
} |
|
} else if (type == EV_SYN) { |
|
mPendingEvent.timestamp = timevalToNano(event->time); |
|
if (mEnabled) { |
|
*data++ = mPendingEvent; |
|
count--; |
|
numEventReceived++; |
|
} |
|
} else { |
|
ALOGE("KionixSensor: unknown event (type=%d, code=%d)", |
|
type, event->code); |
|
} |
|
mInputReader.next(); |
|
} |
|
|
|
return numEventReceived; |
|
} |
|
|
|
|