/*
 * 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 <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>

#include "AdxlSensor.h"

#define ADXL_DATA_NAME				"ADXL34x accelerometer"
#define ADXL_MAX_SAMPLE_RATE_VAL	11 /* 200 Hz */

#define ADXL_UNIT_CONVERSION(value) ((value) * GRAVITY_EARTH / (256.0f))

/*****************************************************************************/

AdxlSensor::AdxlSensor()
    : SensorBase(NULL, ADXL_DATA_NAME),
      mEnabled(0),
      mDelay(-1),
      mInputReader(4),
      mHasPendingEvent(false)
{
    mPendingEvent.version = sizeof(sensors_event_t);
    mPendingEvent.sensor = ID_A;
    mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
    memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

    if (data_fd >= 0) {
        strcpy(input_sysfs_path, "/sys/class/input/");
        strcat(input_sysfs_path, input_name);
        strcat(input_sysfs_path, "/device/device/");
        input_sysfs_path_len = strlen(input_sysfs_path);
		ALOGD("AdxlSensor: sysfs_path=%s", input_sysfs_path);
    } else {
		input_sysfs_path[0] = '\0';
		input_sysfs_path_len = 0;
	}
}

AdxlSensor::~AdxlSensor() {
    if (mEnabled) {
        setEnable(0, 0);
    }
}

int AdxlSensor::setInitialState() {
    struct input_absinfo absinfo;

	if (mEnabled) {
    	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
			mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(absinfo.value);
		}
    	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
			mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(absinfo.value);
		}
		if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
			mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(absinfo.value);
		}
	}
    return 0;
}

bool AdxlSensor::hasPendingEvents() const {
    return mHasPendingEvent;
}

int AdxlSensor::setEnable(int32_t handle, int enabled) {
    int err = 0;
	char buffer[2];

	/* handle check */
	if (handle != ID_A) {
		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
		return -EINVAL;
	}

	buffer[0] = '\0';
	buffer[1] = '\0';

	if (mEnabled <= 0) {
		if(enabled) buffer[0] = '0';
	} else if (mEnabled == 1) {
		if(!enabled) buffer[0] = '1';
	}
    if (buffer[0] != '\0') {
        strcpy(&input_sysfs_path[input_sysfs_path_len], "disable");
		err = write_sys_attribute(input_sysfs_path, buffer, 1);
		if (err != 0) {
			return err;
		}
		ALOGD("AdxlSensor: Control set %s", buffer);
   		setInitialState();
    }

	if (enabled) {
		mEnabled++;
		if (mEnabled > 32767) mEnabled = 32767;
	} else {
		mEnabled--;
		if (mEnabled < 0) mEnabled = 0;
	}
	ALOGD("AdxlSensor: mEnabled = %d", mEnabled);

    return err;
}

int AdxlSensor::setDelay(int32_t handle, int64_t delay_ns)
{
	int err = 0;
	int rate_val;
	int32_t us; 
	char buffer[16];
	int bytes;

	/* handle check */
	if (handle != ID_A) {
		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
		return -EINVAL;
	}

	if (mDelay != delay_ns) {
		/*  
	 	* The ADXL34x Supports 16 sample rates ranging from 3200Hz-0.098Hz
	 	* Calculate best fit and limit to max 200Hz (rate_val 11)
	 	*/

		us = (int32_t)(delay_ns / 1000);
		for (rate_val = 0; rate_val < 16; rate_val++)
			if (us  >= ((10000000) >> rate_val))
				break;

		if (rate_val > ADXL_MAX_SAMPLE_RATE_VAL) {
			rate_val = ADXL_MAX_SAMPLE_RATE_VAL;
		}

    	strcpy(&input_sysfs_path[input_sysfs_path_len], "rate");
   		bytes = sprintf(buffer, "%d", rate_val);
		err = write_sys_attribute(input_sysfs_path, buffer, bytes);
		if (err == 0) {
			mDelay = delay_ns;
			ALOGD("AdxlSensor: Control set delay %f ms requetsed, using %f ms",
				delay_ns/1000000.0f, 1e6 / (3200000 >> (15 - rate_val)));
		}
	}

	return err;
}

int64_t AdxlSensor::getDelay(int32_t handle)
{
	return (handle == ID_A) ? mDelay : 0;
}

int AdxlSensor::getEnable(int32_t handle)
{
	return (handle == ID_A) ? mEnabled : 0;
}

int AdxlSensor::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 = ADXL_UNIT_CONVERSION(value);
            } else if (event->code == EVENT_TYPE_ACCEL_Y) {
                mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(value);
            } else if (event->code == EVENT_TYPE_ACCEL_Z) {
                mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(value);
            }
        } else if (type == EV_SYN) {
            mPendingEvent.timestamp = timevalToNano(event->time);
            if (mEnabled) {
                *data++ = mPendingEvent;
                count--;
                numEventReceived++;
            }
        } else {
            ALOGE("AdxlSensor: unknown event (type=%d, code=%d)",
                    type, event->code);
        }
        mInputReader.next();
    }

    return numEventReceived;
}

