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