1/*
2 * Copyright (C) 2014 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#define LOG_NDEBUG 0
18
19#include <fcntl.h>
20#include <errno.h>
21#include <math.h>
22#include <unistd.h>
23#include <dirent.h>
24#include <sys/select.h>
25#include <cutils/log.h>
26#include <linux/input.h>
27#include <string.h>
28
29#include "PressureSensor.IIO.secondary.h"
30#include "sensors.h"
31#include "MPLSupport.h"
32#include "sensor_params.h"
33#include "ml_sysfs_helper.h"
34
35#pragma message("HAL:build pressure sensor on Invensense MPU secondary bus")
36/* dynamically get this when driver supports it */
37#define CHIP_ID "BMP280"
38
39//#define TIMER (1)
40#define DEFAULT_POLL_TIME 300
41#define PRESSURE_MAX_SYSFS_ATTRB sizeof(pressureSysFs) / sizeof(char*)
42
43static int s_poll_time = -1;
44static int min_poll_time = 50;
45static struct timespec t_pre;
46
47/*****************************************************************************/
48
49PressureSensor::PressureSensor(const char *sysfs_path)
50                  : SensorBase(NULL, NULL),
51                    pressure_fd(-1)
52{
53    VFUNC_LOG;
54
55    mSysfsPath = sysfs_path;
56    LOGV_IF(ENG_VERBOSE, "pressuresensor path: %s", mSysfsPath);
57    if(inv_init_sysfs_attributes()) {
58        LOGE("Error Instantiating Pressure Sensor\n");
59        return;
60    } else {
61        LOGI_IF(PROCESS_VERBOSE, "HAL:Secondary Chip Id: %s", CHIP_ID);
62    }
63}
64
65PressureSensor::~PressureSensor()
66{
67    VFUNC_LOG;
68
69    if( pressure_fd > 0)
70        close(pressure_fd);
71}
72
73int PressureSensor::getFd() const
74{
75    VHANDLER_LOG;
76    return pressure_fd;
77}
78
79/**
80 *  @brief        This function will enable/disable sensor.
81 *  @param[in]    handle
82 *                  which sensor to enable/disable.
83 *  @param[in]    en
84 *                  en=1, enable;
85 *                  en=0, disable
86 *  @return       if the operation is successful.
87 */
88int PressureSensor::enable(int32_t handle, int en)
89{
90    VFUNC_LOG;
91
92    int res = 0;
93
94    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
95            en, pressureSysFs.pressure_enable, getTimestamp());
96    res = write_sysfs_int(pressureSysFs.pressure_enable, en);
97
98    return res;
99}
100
101int PressureSensor::setDelay(int32_t handle, int64_t ns)
102{
103    VFUNC_LOG;
104
105    int res = 0;
106
107    mDelay = int(1000000000.f / ns);
108    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %lld > %s (%lld)",
109            mDelay, pressureSysFs.pressure_rate, getTimestamp());
110    res = write_sysfs_int(pressureSysFs.pressure_rate, mDelay);
111
112#ifdef TIMER
113    int t_poll_time = (int)(ns / 1000000LL);
114    if (t_poll_time > min_poll_time) {
115        s_poll_time = t_poll_time;
116    } else {
117        s_poll_time = min_poll_time;
118    }
119    LOGV_IF(PROCESS_VERBOSE,
120            "HAL:setDelay : %llu ns, (%.2f Hz)", ns, 1000000000.f/ns);
121#endif
122    return res;
123}
124
125
126/**
127    @brief      This function will return the state of the sensor.
128    @return     1=enabled; 0=disabled
129**/
130int PressureSensor::getEnable(int32_t handle)
131{
132    VFUNC_LOG;
133    return mEnable;
134}
135
136/**
137 *  @brief  This function will return the current delay for this sensor.
138 *  @return delay in nanoseconds.
139 */
140int64_t PressureSensor::getDelay(int32_t handle)
141{
142    VFUNC_LOG;
143
144#ifdef TIMER
145    if (mEnable) {
146        return s_poll_time;
147    } else {
148        return -1;
149    }
150#endif
151    return mDelay;
152}
153
154void PressureSensor::fillList(struct sensor_t *list)
155{
156    VFUNC_LOG;
157
158    const char *pressure = "BMP280";
159
160    if (pressure) {
161        if(!strcmp(pressure, "BMP280")) {
162            list->maxRange = PRESSURE_BMP280_RANGE;
163            list->resolution = PRESSURE_BMP280_RESOLUTION;
164            list->power = PRESSURE_BMP280_POWER;
165            list->minDelay = PRESSURE_BMP280_MINDELAY;
166            mMinDelay = list->minDelay;
167            return;
168        }
169    }
170    LOGE("HAL:unknown pressure id %s -- "
171         "params default to bmp280 and might be wrong.",
172         pressure);
173    list->maxRange = PRESSURE_BMP280_RANGE;
174    list->resolution = PRESSURE_BMP280_RESOLUTION;
175    list->power = PRESSURE_BMP280_POWER;
176    list->minDelay = PRESSURE_BMP280_MINDELAY;
177    mMinDelay = list->minDelay;
178    return;
179}
180
181int PressureSensor::inv_init_sysfs_attributes(void)
182{
183    VFUNC_LOG;
184
185    pathP = (char*)malloc(sizeof(char[PRESSURE_MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN]));
186    char *sptr = pathP;
187    char **dptr = (char**)&pressureSysFs;
188    if (sptr == NULL)
189        return -1;
190    unsigned char i = 0;
191    do {
192        *dptr++ = sptr;
193        memset(sptr, 0, sizeof(sptr));
194        sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
195    } while (++i < PRESSURE_MAX_SYSFS_ATTRB);
196
197    sprintf(pressureSysFs.pressure_enable, "%s%s", mSysfsPath, "/pressure_enable");
198    sprintf(pressureSysFs.pressure_rate, "%s%s", mSysfsPath, "/pressure_rate");
199    return 0;
200}
201