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 <dlfcn.h>
     26 
     27 #include <cutils/log.h>
     28 
     29 #include "AkmSensor.h"
     30 
     31 #define AKMD_DEFAULT_INTERVAL	200000000
     32 
     33 /*****************************************************************************/
     34 
     35 AkmSensor::AkmSensor()
     36 : SensorBase(NULL, "compass"),
     37       mPendingMask(0),
     38       mInputReader(32)
     39 {
     40 	for (int i=0; i<numSensors; i++) {
     41 		mEnabled[i] = 0;
     42 		mDelay[i] = -1;
     43 	}
     44     memset(mPendingEvents, 0, sizeof(mPendingEvents));
     45 
     46     mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
     47     mPendingEvents[Accelerometer].sensor = ID_A;
     48     mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
     49     mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
     50 
     51     mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
     52     mPendingEvents[MagneticField].sensor = ID_M;
     53     mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
     54     mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
     55 
     56     mPendingEvents[Orientation  ].version = sizeof(sensors_event_t);
     57     mPendingEvents[Orientation  ].sensor = ID_O;
     58     mPendingEvents[Orientation  ].type = SENSOR_TYPE_ORIENTATION;
     59     mPendingEvents[Orientation  ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
     60 
     61     if (data_fd) {
     62 		strcpy(input_sysfs_path, "/sys/class/compass/akm8975/");
     63 		input_sysfs_path_len = strlen(input_sysfs_path);
     64 	} else {
     65 		input_sysfs_path[0] = '\0';
     66 		input_sysfs_path_len = 0;
     67 	}
     68 }
     69 
     70 AkmSensor::~AkmSensor()
     71 {
     72 	for (int i=0; i<numSensors; i++) {
     73 		setEnable(i, 0);
     74 	}
     75 }
     76 
     77 int AkmSensor::setEnable(int32_t handle, int enabled)
     78 {
     79 	int id = handle2id(handle);
     80 	int err = 0;
     81 	char buffer[2];
     82 
     83 	switch (id) {
     84 	case Accelerometer:
     85 		strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_acc");
     86 		break;
     87 	case MagneticField:
     88 		strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_mag");
     89 		break;
     90 	case Orientation:
     91 		strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_ori");
     92 		break;
     93 	default:
     94 		ALOGE("AkmSensor: unknown handle (%d)", handle);
     95 		return -EINVAL;
     96 	}
     97 
     98 	buffer[0] = '\0';
     99 	buffer[1] = '\0';
    100 
    101 	if (mEnabled[id] <= 0) {
    102 		if(enabled) buffer[0] = '1';
    103 	} else if (mEnabled[id] == 1) {
    104 		if(!enabled) buffer[0] = '0';
    105 	}
    106 
    107     if (buffer[0] != '\0') {
    108 		err = write_sys_attribute(input_sysfs_path, buffer, 1);
    109 		if (err != 0) {
    110 			return err;
    111 		}
    112 		ALOGD("AkmSensor: set %s to %s",
    113 			&input_sysfs_path[input_sysfs_path_len], buffer);
    114 
    115 		/* for AKMD specification */
    116 		if (buffer[0] == '1') {
    117 			setDelay(handle, AKMD_DEFAULT_INTERVAL);
    118 		} else {
    119 			setDelay(handle, -1);
    120 		}
    121     }
    122 
    123 	if (enabled) {
    124 		(mEnabled[id])++;
    125 		if (mEnabled[id] > 32767) mEnabled[id] = 32767;
    126 	} else {
    127 		(mEnabled[id])--;
    128 		if (mEnabled[id] < 0) mEnabled[id] = 0;
    129 	}
    130 	ALOGD("AkmSensor: mEnabled[%d] = %d", id, mEnabled[id]);
    131 
    132     return err;
    133 }
    134 
    135 int AkmSensor::setDelay(int32_t handle, int64_t ns)
    136 {
    137 	int id = handle2id(handle);
    138 	int err = 0;
    139 	char buffer[32];
    140 	int bytes;
    141 
    142     if (ns < -1 || 2147483647 < ns) {
    143 		ALOGE("AkmSensor: invalid delay (%lld)", ns);
    144         return -EINVAL;
    145 	}
    146 
    147     switch (id) {
    148         case Accelerometer:
    149 			strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_acc");
    150 			break;
    151         case MagneticField:
    152 			strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_mag");
    153 			break;
    154         case Orientation:
    155 			strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_ori");
    156 			break;
    157 		default:
    158 			ALOGE("AkmSensor: unknown handle (%d)", handle);
    159 			return -EINVAL;
    160     }
    161 
    162 	if (ns != mDelay[id]) {
    163    		bytes = sprintf(buffer, "%lld", ns);
    164 		err = write_sys_attribute(input_sysfs_path, buffer, bytes);
    165 		if (err == 0) {
    166 			mDelay[id] = ns;
    167 			ALOGD("AkmSensor: set %s to %f ms.",
    168 				&input_sysfs_path[input_sysfs_path_len], ns/1000000.0f);
    169 		}
    170 	}
    171 
    172     return err;
    173 }
    174 
    175 int64_t AkmSensor::getDelay(int32_t handle)
    176 {
    177 	int id = handle2id(handle);
    178 	if (id > 0) {
    179 		return mDelay[id];
    180 	} else {
    181 		return 0;
    182 	}
    183 }
    184 
    185 int AkmSensor::getEnable(int32_t handle)
    186 {
    187 	int id = handle2id(handle);
    188 	if (id >= 0) {
    189 		return mEnabled[id];
    190 	} else {
    191 		return 0;
    192 	}
    193 }
    194 
    195 int AkmSensor::readEvents(sensors_event_t* data, int count)
    196 {
    197     if (count < 1)
    198         return -EINVAL;
    199 
    200     ssize_t n = mInputReader.fill(data_fd);
    201     if (n < 0)
    202         return n;
    203 
    204     int numEventReceived = 0;
    205     input_event const* event;
    206 
    207     while (count && mInputReader.readEvent(&event)) {
    208         int type = event->type;
    209         if (type == EV_ABS) {
    210             processEvent(event->code, event->value);
    211             mInputReader.next();
    212         } else if (type == EV_SYN) {
    213             int64_t time = timevalToNano(event->time);
    214             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
    215                 if (mPendingMask & (1<<j)) {
    216                     mPendingMask &= ~(1<<j);
    217                     mPendingEvents[j].timestamp = time;
    218 					//ALOGD("data=%8.5f,%8.5f,%8.5f",
    219 						//mPendingEvents[j].data[0],
    220 						//mPendingEvents[j].data[1],
    221 						//mPendingEvents[j].data[2]);
    222                     if (mEnabled[j]) {
    223                         *data++ = mPendingEvents[j];
    224                         count--;
    225                         numEventReceived++;
    226                     }
    227                 }
    228             }
    229             if (!mPendingMask) {
    230                 mInputReader.next();
    231             }
    232         } else {
    233             ALOGE("AkmSensor: unknown event (type=%d, code=%d)",
    234                     type, event->code);
    235             mInputReader.next();
    236         }
    237     }
    238     return numEventReceived;
    239 }
    240 
    241 int AkmSensor::setAccel(sensors_event_t* data)
    242 {
    243 	int err;
    244 	int16_t acc[3];
    245 
    246 	acc[0] = (int16_t)(data->acceleration.x / GRAVITY_EARTH * AKSC_LSG);
    247 	acc[1] = (int16_t)(data->acceleration.y / GRAVITY_EARTH * AKSC_LSG);
    248 	acc[2] = (int16_t)(data->acceleration.z / GRAVITY_EARTH * AKSC_LSG);
    249 
    250 	strcpy(&input_sysfs_path[input_sysfs_path_len], "accel");
    251 	err = write_sys_attribute(input_sysfs_path, (char*)acc, 6);
    252 	if (err < 0) {
    253 		ALOGD("AkmSensor: %s write failed.",
    254 			&input_sysfs_path[input_sysfs_path_len]);
    255 	}
    256 	return err;
    257 }
    258 
    259 int AkmSensor::handle2id(int32_t handle)
    260 {
    261     switch (handle) {
    262         case ID_A:
    263 			return Accelerometer;
    264         case ID_M:
    265 			return MagneticField;
    266         case ID_O:
    267 			return Orientation;
    268 		default:
    269 			ALOGE("AkmSensor: unknown handle (%d)", handle);
    270 			return -EINVAL;
    271     }
    272 }
    273 
    274 void AkmSensor::processEvent(int code, int value)
    275 {
    276     switch (code) {
    277         case EVENT_TYPE_ACCEL_X:
    278             mPendingMask |= 1<<Accelerometer;
    279             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A;
    280             break;
    281         case EVENT_TYPE_ACCEL_Y:
    282             mPendingMask |= 1<<Accelerometer;
    283             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A;
    284             break;
    285         case EVENT_TYPE_ACCEL_Z:
    286             mPendingMask |= 1<<Accelerometer;
    287             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A;
    288             break;
    289 
    290         case EVENT_TYPE_MAGV_X:
    291             mPendingMask |= 1<<MagneticField;
    292             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M;
    293             break;
    294         case EVENT_TYPE_MAGV_Y:
    295             mPendingMask |= 1<<MagneticField;
    296             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M;
    297             break;
    298         case EVENT_TYPE_MAGV_Z:
    299             mPendingMask |= 1<<MagneticField;
    300             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M;
    301             break;
    302         case EVENT_TYPE_MAGV_STATUS:
    303             mPendingMask |= 1<<MagneticField;
    304             mPendingEvents[MagneticField].magnetic.status = value;
    305             break;
    306 
    307         case EVENT_TYPE_YAW:
    308             mPendingMask |= 1<<Orientation;
    309             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O;
    310             break;
    311         case EVENT_TYPE_PITCH:
    312             mPendingMask |= 1<<Orientation;
    313             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O;
    314             break;
    315         case EVENT_TYPE_ROLL:
    316             mPendingMask |= 1<<Orientation;
    317             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O;
    318             break;
    319         case EVENT_TYPE_ORIENT_STATUS:
    320             mPendingMask |= 1<<Orientation;
    321             mPendingEvents[Orientation].orientation.status = value;
    322             break;
    323     }
    324 }
    325