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 <string.h>
     22 #include <unistd.h>
     23 #include <dirent.h>
     24 #include <sys/select.h>
     25 #include <cutils/log.h>
     26 
     27 #include "AdxlSensor.h"
     28 
     29 #define ADXL_DATA_NAME				"ADXL34x accelerometer"
     30 #define ADXL_MAX_SAMPLE_RATE_VAL	11 /* 200 Hz */
     31 
     32 #define ADXL_UNIT_CONVERSION(value) ((value) * GRAVITY_EARTH / (256.0f))
     33 
     34 /*****************************************************************************/
     35 
     36 AdxlSensor::AdxlSensor()
     37     : SensorBase(NULL, ADXL_DATA_NAME),
     38       mEnabled(0),
     39       mDelay(-1),
     40       mInputReader(4),
     41       mHasPendingEvent(false)
     42 {
     43     mPendingEvent.version = sizeof(sensors_event_t);
     44     mPendingEvent.sensor = ID_A;
     45     mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
     46     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
     47 
     48     if (data_fd >= 0) {
     49         strcpy(input_sysfs_path, "/sys/class/input/");
     50         strcat(input_sysfs_path, input_name);
     51         strcat(input_sysfs_path, "/device/device/");
     52         input_sysfs_path_len = strlen(input_sysfs_path);
     53 		ALOGD("AdxlSensor: sysfs_path=%s", input_sysfs_path);
     54     } else {
     55 		input_sysfs_path[0] = '\0';
     56 		input_sysfs_path_len = 0;
     57 	}
     58 }
     59 
     60 AdxlSensor::~AdxlSensor() {
     61     if (mEnabled) {
     62         setEnable(0, 0);
     63     }
     64 }
     65 
     66 int AdxlSensor::setInitialState() {
     67     struct input_absinfo absinfo;
     68 
     69 	if (mEnabled) {
     70     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
     71 			mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(absinfo.value);
     72 		}
     73     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
     74 			mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(absinfo.value);
     75 		}
     76 		if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
     77 			mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(absinfo.value);
     78 		}
     79 	}
     80     return 0;
     81 }
     82 
     83 bool AdxlSensor::hasPendingEvents() const {
     84     return mHasPendingEvent;
     85 }
     86 
     87 int AdxlSensor::setEnable(int32_t handle, int enabled) {
     88     int err = 0;
     89 	char buffer[2];
     90 
     91 	/* handle check */
     92 	if (handle != ID_A) {
     93 		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
     94 		return -EINVAL;
     95 	}
     96 
     97 	buffer[0] = '\0';
     98 	buffer[1] = '\0';
     99 
    100 	if (mEnabled <= 0) {
    101 		if(enabled) buffer[0] = '0';
    102 	} else if (mEnabled == 1) {
    103 		if(!enabled) buffer[0] = '1';
    104 	}
    105     if (buffer[0] != '\0') {
    106         strcpy(&input_sysfs_path[input_sysfs_path_len], "disable");
    107 		err = write_sys_attribute(input_sysfs_path, buffer, 1);
    108 		if (err != 0) {
    109 			return err;
    110 		}
    111 		ALOGD("AdxlSensor: Control set %s", buffer);
    112    		setInitialState();
    113     }
    114 
    115 	if (enabled) {
    116 		mEnabled++;
    117 		if (mEnabled > 32767) mEnabled = 32767;
    118 	} else {
    119 		mEnabled--;
    120 		if (mEnabled < 0) mEnabled = 0;
    121 	}
    122 	ALOGD("AdxlSensor: mEnabled = %d", mEnabled);
    123 
    124     return err;
    125 }
    126 
    127 int AdxlSensor::setDelay(int32_t handle, int64_t delay_ns)
    128 {
    129 	int err = 0;
    130 	int rate_val;
    131 	int32_t us;
    132 	char buffer[16];
    133 	int bytes;
    134 
    135 	/* handle check */
    136 	if (handle != ID_A) {
    137 		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
    138 		return -EINVAL;
    139 	}
    140 
    141 	if (mDelay != delay_ns) {
    142 		/*
    143 	 	* The ADXL34x Supports 16 sample rates ranging from 3200Hz-0.098Hz
    144 	 	* Calculate best fit and limit to max 200Hz (rate_val 11)
    145 	 	*/
    146 
    147 		us = (int32_t)(delay_ns / 1000);
    148 		for (rate_val = 0; rate_val < 16; rate_val++)
    149 			if (us  >= ((10000000) >> rate_val))
    150 				break;
    151 
    152 		if (rate_val > ADXL_MAX_SAMPLE_RATE_VAL) {
    153 			rate_val = ADXL_MAX_SAMPLE_RATE_VAL;
    154 		}
    155 
    156     	strcpy(&input_sysfs_path[input_sysfs_path_len], "rate");
    157    		bytes = sprintf(buffer, "%d", rate_val);
    158 		err = write_sys_attribute(input_sysfs_path, buffer, bytes);
    159 		if (err == 0) {
    160 			mDelay = delay_ns;
    161 			ALOGD("AdxlSensor: Control set delay %f ms requetsed, using %f ms",
    162 				delay_ns/1000000.0f, 1e6 / (3200000 >> (15 - rate_val)));
    163 		}
    164 	}
    165 
    166 	return err;
    167 }
    168 
    169 int64_t AdxlSensor::getDelay(int32_t handle)
    170 {
    171 	return (handle == ID_A) ? mDelay : 0;
    172 }
    173 
    174 int AdxlSensor::getEnable(int32_t handle)
    175 {
    176 	return (handle == ID_A) ? mEnabled : 0;
    177 }
    178 
    179 int AdxlSensor::readEvents(sensors_event_t* data, int count)
    180 {
    181     if (count < 1)
    182         return -EINVAL;
    183 
    184     if (mHasPendingEvent) {
    185         mHasPendingEvent = false;
    186         mPendingEvent.timestamp = getTimestamp();
    187         *data = mPendingEvent;
    188         return mEnabled ? 1 : 0;
    189     }
    190 
    191     ssize_t n = mInputReader.fill(data_fd);
    192     if (n < 0)
    193         return n;
    194 
    195     int numEventReceived = 0;
    196     input_event const* event;
    197 
    198     while (count && mInputReader.readEvent(&event)) {
    199         int type = event->type;
    200         if (type == EV_ABS) {
    201             float value = event->value;
    202             if (event->code == EVENT_TYPE_ACCEL_X) {
    203                 mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(value);
    204             } else if (event->code == EVENT_TYPE_ACCEL_Y) {
    205                 mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(value);
    206             } else if (event->code == EVENT_TYPE_ACCEL_Z) {
    207                 mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(value);
    208             }
    209         } else if (type == EV_SYN) {
    210             mPendingEvent.timestamp = timevalToNano(event->time);
    211             if (mEnabled) {
    212                 *data++ = mPendingEvent;
    213                 count--;
    214                 numEventReceived++;
    215             }
    216         } else {
    217             ALOGE("AdxlSensor: unknown event (type=%d, code=%d)",
    218                     type, event->code);
    219         }
    220         mInputReader.next();
    221     }
    222 
    223     return numEventReceived;
    224 }
    225 
    226