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 
43 static int s_poll_time = -1;
44 static int min_poll_time = 50;
45 static struct timespec t_pre;
46 
47 /*****************************************************************************/
48 
PressureSensor(const char * sysfs_path)49 PressureSensor::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 
~PressureSensor()65 PressureSensor::~PressureSensor()
66 {
67     VFUNC_LOG;
68 
69     if( pressure_fd > 0)
70         close(pressure_fd);
71 }
72 
getFd() const73 int 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  */
enable(int32_t handle,int en)88 int 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 
setDelay(int32_t handle,int64_t ns)101 int 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 **/
getEnable(int32_t handle)130 int 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  */
getDelay(int32_t handle)140 int64_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 
fillList(struct sensor_t * list)154 void 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 
inv_init_sysfs_attributes(void)181 int PressureSensor::inv_init_sysfs_attributes(void)
182 {
183     VFUNC_LOG;
184 
185     pathP = (char*)calloc(PRESSURE_MAX_SYSFS_ATTRB,
186                           sizeof(char[MAX_SYSFS_NAME_LEN]));
187     if (pathP == NULL)
188         return -1;
189 
190     char *sptr = pathP;
191     char **dptr = reinterpret_cast<char **>(&pressureSysFs);
192     for (size_t i = 0; i < PRESSURE_MAX_SYSFS_ATTRB; i++) {
193       *dptr++ = sptr;
194       sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
195     }
196 
197     sprintf(pressureSysFs.pressure_enable, "%s%s", mSysfsPath, "/pressure_enable");
198     sprintf(pressureSysFs.pressure_rate, "%s%s", mSysfsPath, "/pressure_rate");
199 
200     // Supported by driver ?
201     FILE  *sysfsfp;
202     sysfsfp = fopen(pressureSysFs.pressure_rate, "r");
203     if (sysfsfp == NULL) {
204         LOGE("HAL: HAL configured to support Pressure sensor but not by driver");
205     } else {
206         fclose(sysfsfp);
207     }
208     return 0;
209 }
210