Home | History | Annotate | Download | only in libsensors
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <fcntl.h>
     18 #include <errno.h>
     19 #include <math.h>
     20 #include <poll.h>
     21 #include <unistd.h>
     22 #include <dirent.h>
     23 #include <sys/select.h>
     24 #include <cutils/log.h>
     25 #include <linux/kxtf9.h>
     26 
     27 #include "KionixSensor.h"
     28 
     29 #define KIONIX_IOCTL_ENABLE_OUTPUT	KXTF9_IOCTL_ENABLE_OUTPUT
     30 #define KIONIX_IOCTL_DISABLE_OUTPUT	KXTF9_IOCTL_DISABLE_OUTPUT
     31 #define KIONIX_IOCTL_GET_ENABLE		KXTF9_IOCTL_GET_ENABLE
     32 #define KIONIX_IOCTL_UPDATE_ODR		KXTF9_IOCTL_UPDATE_ODR
     33 
     34 #define KIONIX_UNIT_CONVERSION(value) ((value) * GRAVITY_EARTH / (1024.0f))
     35 
     36 /*****************************************************************************/
     37 
     38 KionixSensor::KionixSensor()
     39     : SensorBase(DIR_DEV, INPUT_NAME_ACC),
     40       mEnabled(0),
     41       mDelay(-1),
     42       mInputReader(32),
     43       mHasPendingEvent(false)
     44 {
     45     mPendingEvent.version = sizeof(sensors_event_t);
     46     mPendingEvent.sensor = ID_A;
     47     mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
     48     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
     49 
     50 	open_device();
     51 }
     52 
     53 KionixSensor::~KionixSensor() {
     54     if (mEnabled) {
     55         setEnable(0, 0);
     56     }
     57 
     58 	close_device();
     59 }
     60 
     61 int KionixSensor::setInitialState() {
     62     struct input_absinfo absinfo;
     63 
     64 	if (mEnabled) {
     65     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
     66 			mPendingEvent.acceleration.x = KIONIX_UNIT_CONVERSION(absinfo.value);
     67 		}
     68     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
     69 			mPendingEvent.acceleration.y = KIONIX_UNIT_CONVERSION(absinfo.value);
     70 		}
     71 		if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
     72 			mPendingEvent.acceleration.z = KIONIX_UNIT_CONVERSION(absinfo.value);
     73 		}
     74 	}
     75     return 0;
     76 }
     77 
     78 bool KionixSensor::hasPendingEvents() const {
     79     return mHasPendingEvent;
     80 }
     81 
     82 int KionixSensor::setEnable(int32_t handle, int enabled) {
     83     int err = 0;
     84 	int opDone = 0;
     85 
     86 	/* handle check */
     87 	if (handle != ID_A) {
     88 		ALOGE("KionixSensor: Invalid handle (%d)", handle);
     89 		return -EINVAL;
     90 	}
     91 
     92 	if (mEnabled <= 0) {
     93 		if (enabled) {
     94 			err = ioctl(dev_fd, KIONIX_IOCTL_ENABLE_OUTPUT);
     95 			opDone = 1;
     96 		}
     97 	} else if (mEnabled == 1) {
     98 		if (!enabled) {
     99 			err = ioctl(dev_fd, KIONIX_IOCTL_DISABLE_OUTPUT);
    100 			opDone = 1;
    101 		}
    102 	}
    103 	if (err != 0) {
    104 		ALOGE("KionixSensor: IOCTL failed (%s)", strerror(errno));
    105 		return err;
    106 	}
    107 	if (opDone) {
    108 		ALOGD("KionixSensor: Control set %d", enabled);
    109 		setInitialState();
    110 	}
    111 
    112 	if (enabled) {
    113 		mEnabled++;
    114 		if (mEnabled > 32767) mEnabled = 32767;
    115 	} else {
    116 		mEnabled--;
    117 		if (mEnabled < 0) mEnabled = 0;
    118 	}
    119 	ALOGD("KionixSensor: mEnabled = %d", mEnabled);
    120 
    121     return err;
    122 }
    123 
    124 int KionixSensor::setDelay(int32_t handle, int64_t delay_ns)
    125 {
    126 	int err = 0;
    127 	int ms;
    128 
    129 	/* handle check */
    130 	if (handle != ID_A) {
    131 		ALOGE("KionixSensor: Invalid handle (%d)", handle);
    132 		return -EINVAL;
    133 	}
    134 
    135 	if (mDelay != delay_ns) {
    136 		ms = delay_ns / 1000000;
    137         if (ioctl(dev_fd, KIONIX_IOCTL_UPDATE_ODR, &ms)) {
    138 			return -errno;
    139 		}
    140 		mDelay = delay_ns;
    141 	}
    142 
    143 	return err;
    144 }
    145 
    146 int64_t KionixSensor::getDelay(int32_t handle)
    147 {
    148 	return (handle == ID_A) ? mDelay : 0;
    149 }
    150 
    151 int KionixSensor::getEnable(int32_t handle)
    152 {
    153 	return (handle == ID_A) ? mEnabled : 0;
    154 }
    155 
    156 int KionixSensor::readEvents(sensors_event_t* data, int count)
    157 {
    158     if (count < 1)
    159         return -EINVAL;
    160 
    161     if (mHasPendingEvent) {
    162         mHasPendingEvent = false;
    163         mPendingEvent.timestamp = getTimestamp();
    164         *data = mPendingEvent;
    165         return mEnabled ? 1 : 0;
    166     }
    167 
    168     ssize_t n = mInputReader.fill(data_fd);
    169     if (n < 0)
    170         return n;
    171 
    172     int numEventReceived = 0;
    173     input_event const* event;
    174 
    175     while (count && mInputReader.readEvent(&event)) {
    176         int type = event->type;
    177         if (type == EV_ABS) {
    178             float value = event->value;
    179             if (event->code == EVENT_TYPE_ACCEL_X) {
    180                 mPendingEvent.acceleration.x = KIONIX_UNIT_CONVERSION(value);
    181             } else if (event->code == EVENT_TYPE_ACCEL_Y) {
    182                 mPendingEvent.acceleration.y = KIONIX_UNIT_CONVERSION(value);
    183             } else if (event->code == EVENT_TYPE_ACCEL_Z) {
    184                 mPendingEvent.acceleration.z = KIONIX_UNIT_CONVERSION(value);
    185             }
    186         } else if (type == EV_SYN) {
    187             mPendingEvent.timestamp = timevalToNano(event->time);
    188             if (mEnabled) {
    189                 *data++ = mPendingEvent;
    190                 count--;
    191                 numEventReceived++;
    192             }
    193         } else {
    194             ALOGE("KionixSensor: unknown event (type=%d, code=%d)",
    195                     type, event->code);
    196         }
    197         mInputReader.next();
    198     }
    199 
    200     return numEventReceived;
    201 }
    202 
    203