/*
 * Copyright (C) 2008-2014 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 <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <poll.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/select.h>
#include <unistd.h>

#define LOG_TAG "CrosECSensor"
#include <cutils/log.h>
#include <cutils/properties.h>
#include <utils/Timers.h>

#include "cros_ec_sensors.h"


/*****************************************************************************/
static int min(int a, int b) {
    return (a < b) ? a : b;
}

/*
 * Constructor.
 *
 * Setup and open the ring buffer.
 */
CrosECSensor::CrosECSensor(
        struct cros_ec_sensor_info *sensor_info,
        size_t sensor_nb,
        struct cros_ec_gesture_info *gesture_info,
        size_t gesture_nb,
        const char *ring_device_name,
        const char *trigger_name)
    : mSensorInfo(sensor_info),
      mSensorNb(sensor_nb),
      mGestureInfo(gesture_info),
      mGestureNb(gesture_nb)
{
    char ring_buffer_name[IIO_MAX_NAME_LENGTH] = "/dev/";

    strcat(ring_buffer_name, ring_device_name);
    mDataFd = open(ring_buffer_name, O_RDONLY);
    if (mDataFd < 0) {
        ALOGE("open file '%s' failed: %s\n",
                ring_buffer_name, strerror(errno));
    }

    strcpy(mRingPath, ring_device_name);

    /* Be sure the buffer is disbabled before altering parameters */
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 0) < 0) {
        ALOGE("disable IIO buffer failed: %s\n", strerror(errno));
        return;
    }
    if (cros_ec_sysfs_set_input_attr(mRingPath, "trigger/current_trigger",
                trigger_name, strlen(trigger_name))) {
        ALOGE("Unable to set trigger name: %s\n", strerror(errno));
        return;
    }
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/length",
                IIO_MAX_BUFF_SIZE) < 0) {
        ALOGE("set IIO buffer length (%d) failed: %s\n",
                IIO_MAX_BUFF_SIZE, strerror(errno));
    }
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 1) < 0) {
        ALOGE("enable IIO buffer failed: %s\n",
                strerror(errno));
        return;
    }
}

CrosECSensor::~CrosECSensor() {
    /* Silence all the sensors, so that we can stop the buffer */
    for (size_t i = 0 ; i < mSensorNb ; i++) {
        if (mSensorInfo[i].device_name == NULL)
            continue;
        activate(i, 0);
    }
    for (size_t i = 0 ; i < mGestureNb ; i++) {
        if (mGestureInfo[i].device_name == NULL)
            continue;
        activate(i + CROS_EC_MAX_PHYSICAL_SENSOR, 0);
    }
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 0) < 0) {
        ALOGE("disable IIO buffer failed: %s\n", strerror(errno));
        return;
    }
    close(mDataFd);
}

/*
 * getFd: retrieve the ring file descriptor.
 *
 * Needed for CrosECSensor creator to listen to the buffer.
 */
int CrosECSensor::getFd(void)
{
    return mDataFd;
}

/*
 * flush: Flush entry point.
 *
 * Issue the flush for a particular sensor to the EC via iio.
 */
int CrosECSensor::flush(int handle)
{
    if (handle >= CROS_EC_MAX_PHYSICAL_SENSOR) {
        struct cros_ec_gesture_info* info = &mGestureInfo[handle - CROS_EC_MAX_PHYSICAL_SENSOR];
        if (info->sensor_data.flags & SENSOR_FLAG_ONE_SHOT_MODE)
            return -EINVAL;
        /* not expected, current gestures are all one-shot. */
        return -EINVAL;
    } else {
        struct cros_ec_sensor_info *info = &mSensorInfo[handle];

        if (!info->enabled)
            return -EINVAL;

        return cros_ec_sysfs_set_input_attr_by_int(info->device_name, "flush", 1);
    }
}

/*
 * activate: Activate entry point.
 *
 * When enabled set the sensor frequency. If not enabled, set
 * the sensor in suspend mode by setting the frequency to 0.
 */
int CrosECSensor::activate(int handle, int enabled)
{
    int err;
    if (handle < CROS_EC_MAX_PHYSICAL_SENSOR) {
        struct cros_ec_sensor_info *info = &mSensorInfo[handle];
        /*
         * Frequency is in mHz, sampling period in ns, use 10^(9 + 3)
         * coefficient.
         */
        long frequency = enabled ? 1e12 / info->sampling_period_ns : 0;

        err = cros_ec_sysfs_set_input_attr_by_int(info->device_name,
                "frequency", frequency);
        if (err)
            return err;

        long ec_period = nanoseconds_to_milliseconds(info->max_report_latency_ns);

        if (enabled)
            ec_period = min(CROS_EC_MAX_SAMPLING_PERIOD, ec_period);
        else
            ec_period = 0;

        /* Sampling is encoded on a 16bit so, so the maximal period is ~65s. */
        err = cros_ec_sysfs_set_input_attr_by_int(
                info->device_name, "sampling_frequency", ec_period);
        if (!err)
            info->enabled = enabled;
    } else {
        struct cros_ec_gesture_info* info = &mGestureInfo[handle - CROS_EC_MAX_PHYSICAL_SENSOR];
        char attr[PATH_MAX] = "events/";
        strcat(attr, info->enable_entry);
        err = cros_ec_sysfs_set_input_attr_by_int(info->device_name, attr, enabled);
        if (!err)
            info->enabled = enabled;
    }

    return err;
}

/*
 * batch: Batch entry point.
 *
 * Set the EC sampling frequency. Check boundaries to prevent polling too fast.
 */
int CrosECSensor::batch(int handle,
        int64_t sampling_period_ns,
        int64_t max_report_latency_ns)
{
    if (handle < CROS_EC_MAX_PHYSICAL_SENSOR) {
        struct cros_ec_sensor_info *info = &mSensorInfo[handle];

        info->max_report_latency_ns = max_report_latency_ns;

        if (nanoseconds_to_microseconds(sampling_period_ns) >
                info->sensor_data.maxDelay)
            info->sampling_period_ns = microseconds_to_nanoseconds(info->sensor_data.maxDelay);
        else if (nanoseconds_to_microseconds(sampling_period_ns) <
                info->sensor_data.minDelay)
            info->sampling_period_ns = microseconds_to_nanoseconds(info->sensor_data.minDelay);
        else
            info->sampling_period_ns = sampling_period_ns;

        /*
         * Note that the sensor hub limit minimal sampling frequency at few ms.
         * Which is good, because HAL shold not ask for polling sensor at
         * more than the sampling period, set in sensor_t.
         */
        if (info->max_report_latency_ns < info->sampling_period_ns) {
            /*
             * We have to report an event as soon as available.
             * Set polling frequency as low as sampling frequency
             */
            info->max_report_latency_ns = info->sampling_period_ns;
        }
        /* Call activate to change the paramters if necessary */
        return activate(handle, info->enabled);
    } else {
        return 0;
    }
}

/*
 * readEvents: Read events from the iio ring buffer.
 *
 * data: where to put the events.
 * count: maximal number of events to read from iio.
 * If iio indicates no more events are available, return.
 */
int CrosECSensor::readEvents(sensors_event_t* data, int count)
{
    int rc;

    if (count < 1) {
        return -EINVAL;
    }

    /*
     * Do a single read to collects all pending events.
     * up to what poll caller can handle.
     */
    rc = read(mDataFd, mEvents, sizeof(cros_ec_event) * count);
    if (rc < 0) {
        ALOGE("rc %d while reading ring\n", rc);
        return rc;
    }
    if (rc % sizeof(cros_ec_event) != 0) {
        ALOGE("Incomplete event while reading ring: %d\n", rc);
        return -EINVAL;
    }

    int nb_events = rc / sizeof(cros_ec_event);
    int data_events = 0;
    for (int i = 0; i < nb_events; i++) {
        rc = processEvent(data, &mEvents[i]);
        if (rc == 0) {
            data++;
            data_events++;
        }
    }

    return data_events;
}

/*
 * processEvent:
 *
 * Internal function to translate an event from the iio ring
 * buffer into a sensors_event_t.
 *
 * Support flush meta event and regular events.
 */
int CrosECSensor::processEvent(sensors_event_t* data, const cros_ec_event *event)
{
    if (event->flags & CROS_EC_EVENT_FLUSH_FLAG) {
        data->version = META_DATA_VERSION;
        data->sensor = 0;
        data->type = SENSOR_TYPE_META_DATA;
        data->reserved0 = 0;
        data->timestamp = 0;
        data->meta_data.what = META_DATA_FLUSH_COMPLETE;
        data->meta_data.sensor = event->sensor_id;
        return 0;
    }

    if (event->sensor_id >= mSensorNb) {
        return -EINVAL;
    }
    struct cros_ec_sensor_info *info = &mSensorInfo[event->sensor_id];

    if (info->type == CROS_EC_ACTIVITY) {
        ALOGI("Activity: %d - state: %d\n", event->activity, event->state);
        if (event->activity >= mGestureNb)
            return -ENOKEY;

        struct cros_ec_gesture_info *gesture = &mGestureInfo[event->activity];
        if (!gesture->enabled)
            return -ENOKEY;

        data->version = sizeof(sensors_event_t);
        data->sensor = CROS_EC_MAX_PHYSICAL_SENSOR + event->activity;
        data->type = gesture->sensor_data.type;

        /*
         * bootime Timestamp coming from the kernel are not reliable when
         * the system resume: very early, the sleep delay has not yet been added.
         * Use the current time, not the kernel timestamp.
         * chrome-os-partner:46724
         */
        data->timestamp = systemTime(SYSTEM_TIME_BOOTTIME);
        data->data[0] = (float)event->state;

        if (gesture->sensor_data.flags & SENSOR_FLAG_ONE_SHOT_MODE)
            gesture->enabled = 0;
    } else {

        /*
         * The sensor hub can send data even if the sensor is not set up.
         * workaround it unitl b/23238991 is fixed.
         */
        if (!info->enabled)
            return -ENOKEY;

        data->version = sizeof(sensors_event_t);
        data->sensor = event->sensor_id;
        data->type = info->sensor_data.type;
        data->timestamp = event->timestamp;
        data->acceleration.status = SENSOR_STATUS_ACCURACY_LOW;

        /*
         * Even for sensor with one axis (light, proxmity), be sure to write
         * the other vectors. EC 0s them out.
         */
        float d;
        for (int i = X ; i < MAX_AXIS; i++) {
            switch (info->sensor_data.type) {
                case SENSOR_TYPE_ACCELEROMETER:
                case SENSOR_TYPE_GYROSCOPE:
                case SENSOR_TYPE_MAGNETIC_FIELD:
                    d = event->vector[i];
                    break;
                case SENSOR_TYPE_LIGHT:
                case SENSOR_TYPE_PROXIMITY:
                    d = (uint16_t)event->vector[i];
                    break;
                default:
                    return -EINVAL;
            }
            data->acceleration.v[i] =
                d * mSensorInfo[event->sensor_id].sensor_data.resolution;
        }
    }
    return 0;
}


/*
 * cros_ec_sysfs_get_attr: Helper function to read sysfs attributes.
 *
 * path: the path of the device.
 * attr: attribute to read (path/attr)
 * output: where to put the string read.
 */
int cros_ec_sysfs_get_attr(const char *path, const char *attr, char *output)
{
    char name[IIO_MAX_DEVICE_NAME_LENGTH + 10];
    strcpy(name, path);
    strcat(name, "/");
    strcat(name, attr);
    int fd = open(name, O_RDONLY);
    if (fd < 0) {
        ALOGE("Unable to read %s\n", name);
        return -errno;
    }
    int size = read(fd, output, IIO_MAX_NAME_LENGTH);
    close(fd);
    if (size == 0)
        return -EINVAL;
    if (output[size - 1] == '\n')
        output[size - 1] = 0;
    else
        output[size] = 0;
    return 0;
}

/*
 * cros_ec_sysfs_set_input_attr: Helper function to write a sysfs attribute.
 */
int cros_ec_sysfs_set_input_attr(const char *path, const char *attr,
                                 const char *value, size_t len)
{
    char fname[PATH_MAX];
    int fd;
    int rc;

    snprintf(fname, sizeof(fname), "%s%s/%s", IIO_DIR, path, attr);
    fname[sizeof(fname) - 1] = '\0';

    fd = open(fname, O_WRONLY);
    if (fd < 0) {
        ALOGE("%s: fname = %s, fd = %d, failed: %s\n", __func__,
              fname, fd, strerror(errno));
        return -EACCES;
    }

    rc = write(fd, value, (size_t)len);
    if (rc < 0) {
        ALOGE("%s: write failed: fd = %d, rc = %d, strerr = %s\n", __func__,
              fd, rc, strerror(errno));
        ALOGE("fname = %s, value = %s\n", fname, value);
    }

    close(fd);

    return rc < 0 ? rc : 0;
}

int cros_ec_sysfs_set_input_attr_by_int(const char *path,
                                        const char *attr, int value)
{
    char buf[INT32_CHAR_LEN];

    size_t n = snprintf(buf, sizeof(buf), "%d", value);
    if (n > sizeof(buf)) {
        return -1;
    }

    return cros_ec_sysfs_set_input_attr(path, attr, buf, n);
}
