/*
 * 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;
}

static int max(int a, int b) {
    return (a < b) ? b : a;
}

/*
 * 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);
            ec_period = max(CROS_EC_MIN_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);
}
