1/*
2* Copyright (C) 2012 Invensense, Inc.
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 <MPLSupport.h>
20#include <string.h>
21#include <stdio.h>
22#include <fcntl.h>
23
24#include "log.h"
25#include "SensorBase.h"
26
27#include "ml_sysfs_helper.h"
28#include "local_log_def.h"
29
30int64_t getTimestamp()
31{
32    struct timespec t;
33    t.tv_sec = t.tv_nsec = 0;
34    clock_gettime(CLOCK_MONOTONIC, &t);
35    return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
36}
37
38int64_t timevalToNano(timeval const& t) {
39    return t.tv_sec * 1000000000LL + t.tv_usec * 1000;
40}
41
42int inv_read_data(char *fname, long *data)
43{
44    VFUNC_LOG;
45
46    char buf[sizeof(long) * 4];
47    int count, fd;
48
49    fd = open(fname, O_RDONLY);
50    if(fd < 0) {
51        LOGE("HAL:Error opening %s", fname);
52        return -1;
53    }
54    memset(buf, 0, sizeof(buf));
55    count = read_attribute_sensor(fd, buf, sizeof(buf));
56    if(count < 1) {
57        close(fd);
58        return -1;
59    } else {
60        count = sscanf(buf, "%ld", data);
61        if(count)
62            LOGV_IF(EXTRA_VERBOSE, "HAL:Data= %ld", *data);
63    }
64    close(fd);
65
66    return 0;
67}
68
69/* This one DOES NOT close FDs for you */
70int read_attribute_sensor(int fd, char* data, unsigned int size)
71{
72    VFUNC_LOG;
73
74    int count = 0;
75    if (fd > 0) {
76        count = pread(fd, data, size, 0);
77        if(count < 1) {
78            LOGE("HAL:read fails with error code=%d", count);
79        }
80    }
81    return count;
82}
83
84/**
85 *  @brief  Enable a sensor through the sysfs file descriptor
86 *          provided.
87 *  @note   this function one closes FD after the write
88 *  @param  fd
89 *              the file descriptor to write into
90 *  @param  en
91 *              the value to write, typically 1 or 0
92 *  @return the errno whenever applicable.
93 */
94int enable_sysfs_sensor(int fd, int en)
95{
96    VFUNC_LOG;
97
98    int nb;
99    int err = 0;
100
101    char c = en ? '1' : '0';
102    nb = write(fd, &c, 1);
103
104    if (nb <= 0) {
105        err = errno;
106        LOGE("HAL:enable_sysfs_sensor - write %c returned %d (%s / %d)",
107             c, nb, strerror(err), err);
108    }
109    close(fd);
110
111
112    return err;
113}
114
115/* This one closes FDs for you */
116int write_attribute_sensor(int fd, long data)
117{
118    VFUNC_LOG;
119
120    int num_b = 0;
121
122    if (fd >= 0) {
123        char buf[80];
124        sprintf(buf, "%ld", data);
125        num_b = write(fd, buf, strlen(buf) + 1);
126        if (num_b <= 0) {
127            int err = errno;
128            LOGE("HAL:write fd %d returned '%s' (%d)", fd, strerror(err), err);
129        } else {
130            LOGV_IF(EXTRA_VERBOSE, "HAL:fd=%d write attribute to %ld", fd, data);
131        }
132        close(fd);
133    }
134
135    return num_b;
136}
137
138int read_sysfs_int(char *filename, int *var)
139{
140    int res=0;
141    FILE  *sysfsfp;
142
143    sysfsfp = fopen(filename, "r");
144    if (sysfsfp != NULL) {
145        if (fscanf(sysfsfp, "%d\n", var) < 1) {
146           LOGE("HAL:ERR failed to read an int from %s.", filename);
147           res = -EINVAL;
148        }
149        fclose(sysfsfp);
150    } else {
151        res = -errno;
152        LOGE("HAL:ERR open file %s to read with error %d", filename, res);
153    }
154    return res;
155}
156
157int write_sysfs_int(char *filename, int var)
158{
159    int res = 0;
160    FILE  *sysfsfp;
161
162    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
163            var, filename, getTimestamp());
164    sysfsfp = fopen(filename, "w");
165    if (sysfsfp == NULL) {
166        res = -errno;
167        LOGE("HAL:ERR open file %s to write with error %d", filename, res);
168        return res;
169    }
170    int fpres, fcres = 0;
171    fpres = fprintf(sysfsfp, "%d\n", var);
172    /* fprintf() can succeed because it never actually writes to the
173     * underlying sysfs node.
174     */
175    if (fpres < 0) {
176       res = -errno;
177       fclose(sysfsfp);
178    } else {
179        fcres = fclose(sysfsfp);
180        /* Check for errors from: fflush(), write(), and close() */
181        if (fcres < 0) {
182            res = -errno;
183        }
184    }
185    if (fpres < 0 || fcres < 0) {
186        LOGE("HAL:ERR failed to write %d to %s (err=%d) print/close=%d/%d",
187            var, filename, res, fpres, fcres);
188    }
189    return res;
190}
191