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 #include <MPLSupport.h>
18 #include <dirent.h>
19 #include <string.h>
20 #include <stdio.h>
21 #include "log.h"
22 #include "SensorBase.h"
23 #include <fcntl.h>
24 
25 #include "ml_sysfs_helper.h"
26 #include "ml_load_dmp.h"
27 
28 int inv_read_data(char *fname, long *data)
29 {
30     VFUNC_LOG;
31 
32     char buf[sizeof(long) * 4];
33     int count, fd;
34 
35     fd = open(fname, O_RDONLY);
36     if(fd < 0) {
37         LOGE("HAL:Error opening %s", fname);
38         return -1;
39     }
40     memset(buf, 0, sizeof(buf));
41     count = read_attribute_sensor(fd, buf, sizeof(buf));
42     if(count < 1) {
43         close(fd);
44         return -1;
45     } else {
46         count = sscanf(buf, "%ld", data);
47         if(count)
48             LOGV_IF(EXTRA_VERBOSE, "HAL:Data= %ld", *data);
49     }
50     close(fd);
51 
52     return 0;
53 }
54 
55 /* This one DOES NOT close FDs for you */
56 int read_attribute_sensor(int fd, char* data, unsigned int size)
57 {
58     VFUNC_LOG;
59 
60     int count = 0;
61     if (fd > 0) {
62         count = pread(fd, data, size, 0);
63         if(count < 1) {
64             LOGE("HAL:read fails with error code=%d", count);
65         }
66     }
67     return count;
68 }
69 
70 /**
71  *  @brief  Enable a sensor through the sysfs file descriptor
72  *          provided.
73  *  @note   this function one closes FD after the write
74  *  @param  fd
75  *              the file descriptor to write into
76  *  @param  en
77  *              the value to write, typically 1 or 0
78  *  @return the errno whenever applicable.
79  */
80 int enable_sysfs_sensor(int fd, int en)
81 {
82     VFUNC_LOG;
83 
84     int nb;
85     int err = 0;
86 
87     char c = en ? '1' : '0';
88     nb = write(fd, &c, 1);
89 
90     if (nb <= 0) {
91         err = errno;
92         LOGE("HAL:enable_sysfs_sensor - write %c returned %d (%s / %d)",
93              c, nb, strerror(err), err);
94     }
95     close(fd);
96 
97 
98     return -err;
99 }
100 
101 /* This one closes FDs for you */
102 int write_attribute_sensor(int fd, long data)
103 {
104     VFUNC_LOG;
105 
106     int num_b = 0;
107 
108     if (fd >= 0) {
109         char buf[80];
110         sprintf(buf, "%ld", data);
111         num_b = write(fd, buf, strlen(buf) + 1);
112         if (num_b <= 0) {
113             int err = errno;
114             LOGE("HAL:write fd %d returned '%s' (%d)", fd, strerror(err), err);
115         } else {
116             LOGV_IF(EXTRA_VERBOSE, "HAL:fd=%d write attribute to %ld", fd, data);
117         }
118         close(fd);
119     }
120 
121     return num_b;
122 }
123 
124 /* This one DOES NOT close FDs for you */
125 int write_attribute_sensor_continuous(int fd, long data)
126 {
127     VFUNC_LOG;
128 
129     int num_b = 0;
130 
131     if (fd >= 0) {
132         char buf[80];
133         sprintf(buf, "%ld", data);
134         num_b = write(fd, buf, strlen(buf) + 1);
135         if (num_b <= 0) {
136             int err = errno;
137             LOGE("HAL:write fd %d returned '%s' (%d)", fd, strerror(err), err);
138         } else {
139             LOGV_IF(EXTRA_VERBOSE, "HAL:fd=%d write attribute to %ld", fd, data);
140         }
141     }
142 
143     return num_b;
144 }
145 
146 int read_sysfs_int(char *filename, int *var)
147 {
148     int res=0;
149     FILE  *sysfsfp;
150 
151     sysfsfp = fopen(filename, "r");
152     if (sysfsfp != NULL) {
153         if (fscanf(sysfsfp, "%d\n", var) < 0 || fclose(sysfsfp) < 0) {
154             res = errno;
155             LOGE("HAL:ERR open file %s to read with error %d", filename, res);
156         }
157     }
158     return -res;
159 }
160 
161 int read_sysfs_int64(char *filename, int64_t *var)
162 {
163     int res=0;
164     FILE  *sysfsfp;
165 
166     sysfsfp = fopen(filename, "r");
167     if (sysfsfp != NULL) {
168         if (fscanf(sysfsfp, "%lld\n", var) < 0 || fclose(sysfsfp) < 0) {
169             res = errno;
170             LOGE("HAL:ERR open file %s to read with error %d", filename, res);
171         }
172     }
173     return -res;
174 }
175 
176 void convert_long_to_hex_char(long* quat, unsigned char* hex, int numElement)
177 {
178     int bytePosition = 0;
179     for (int index = 0; index < numElement; index++) {
180         for (int i = 0; i < 4; i++) {
181             hex[bytePosition] = (int) ((quat[index] >> (4-1-i) * 8) & 0xFF);
182             //LOGI("e%d quat[%d]: %x", index, bytePosition, hex[bytePosition]);
183             bytePosition++;
184         }
185     }
186     return;
187 }
188 
189 int write_sysfs_int(char *filename, int var)
190 {
191     int res=0;
192     FILE  *sysfsfp;
193 
194     sysfsfp = fopen(filename, "w");
195     if (sysfsfp != NULL) {
196         if (fprintf(sysfsfp, "%d\n", var) < 0 || fclose(sysfsfp) < 0) {
197             res = errno;
198             LOGE("HAL:ERR open file %s to write with error %d", filename, res);
199         }
200     }
201     return -res;
202 }
203 
204 int write_sysfs_longlong(char *filename, int64_t var)
205 {
206     int res=0;
207     FILE  *sysfsfp;
208 
209     sysfsfp = fopen(filename, "w");
210     if (sysfsfp != NULL) {
211         if (fprintf(sysfsfp, "%lld\n", var) < 0 || fclose(sysfsfp) < 0) {
212             res = errno;
213             LOGE("HAL:ERR open file %s to write with error %d", filename, res);
214         }
215     }
216     return -res;
217 }
218 
219 int fill_dev_full_name_by_prefix(const char* dev_prefix,
220                                  char *dev_full_name, int len)
221 {
222     char cand_name[20];
223     int prefix_len = strlen(dev_prefix);
224     strncpy(cand_name, dev_prefix, sizeof(cand_name) / sizeof(cand_name[0]));
225 
226     // try adding a number, 0-9
227     for(int cand_postfix = 0; cand_postfix < 10; cand_postfix++) {
228         snprintf(&cand_name[prefix_len],
229                  sizeof(cand_name) / sizeof(cand_name[0]),
230                  "%d", cand_postfix);
231         int dev_num = find_type_by_name(cand_name, "iio:device");
232         if (dev_num != -ENODEV) {
233             strncpy(dev_full_name, cand_name, len);
234             return 0;
235         }
236     }
237     // try adding a small letter, a-z
238     for(char cand_postfix = 'a'; cand_postfix <= 'z'; cand_postfix++) {
239         snprintf(&cand_name[prefix_len],
240                  sizeof(cand_name) / sizeof(cand_name[0]),
241                  "%c", cand_postfix);
242         int dev_num = find_type_by_name(cand_name, "iio:device");
243         if (dev_num != -ENODEV) {
244             strncpy(dev_full_name, cand_name, len);
245             return 0;
246         }
247     }
248     // try adding a capital letter, A-Z
249     for(char cand_postfix = 'A'; cand_postfix <= 'Z'; cand_postfix++) {
250         snprintf(&cand_name[prefix_len],
251                  sizeof(cand_name) / sizeof(cand_name[0]),
252                  "%c", cand_postfix);
253         int dev_num = find_type_by_name(cand_name, "iio:device");
254         if (dev_num != -ENODEV) {
255             strncpy(dev_full_name, cand_name, len);
256             return 0;
257         }
258     }
259     return 1;
260 }
261 
262 void dump_dmp_img(const char *outFile)
263 {
264     char sysfs_path[MAX_SYSFS_NAME_LEN];
265     char dmp_path[MAX_SYSFS_NAME_LEN];
266 
267     inv_get_sysfs_path(sysfs_path);
268     sprintf(dmp_path, "%s%s", sysfs_path, "/dmp_firmware");
269 
270     LOGI("HAL DEBUG:dump DMP image");
271     LOGI("HAL DEBUG:open %s\n", dmp_path);
272     LOGI("HAL DEBUG:write to %s", outFile);
273 
274     read_dmp_img(dmp_path, (char *)outFile);
275 }
276 
277 int read_sysfs_dir(bool fileMode, char *sysfs_path)
278 {
279     VFUNC_LOG;
280 
281     int res = 0;
282     char full_path[MAX_SYSFS_NAME_LEN];
283     int fd;
284     char buf[sizeof(long) *4];
285     long data;
286 
287     DIR *dp;
288     struct dirent *ep;
289 
290     dp = opendir (sysfs_path);
291 
292     if (dp != NULL)
293     {
294         LOGI("******************** System Sysfs Dump ***************************");
295         LOGV_IF(0,"HAL DEBUG: opened directory %s", sysfs_path);
296         while ((ep = readdir (dp))) {
297             if(ep != NULL) {
298                 LOGV_IF(0,"file name %s", ep->d_name);
299                 if(!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..") ||
300                          !strcmp(ep->d_name, "uevent") || !strcmp(ep->d_name, "dev") ||
301                          !strcmp(ep->d_name, "self_test"))
302                     continue;
303                 sprintf(full_path, "%s%s%s", sysfs_path, "/", ep->d_name);
304                 LOGV_IF(0,"HAL DEBUG: reading %s", full_path);
305                 fd = open(full_path, O_RDONLY);
306                 if (fd > -1) {
307                     memset(buf, 0, sizeof(buf));
308                     res = read_attribute_sensor(fd, buf, sizeof(buf));
309                     close(fd);
310                     if (res > 0) {
311                         res = sscanf(buf, "%ld", &data);
312                         if (res)
313                             LOGI("HAL DEBUG:sysfs:cat %s = %ld", full_path, data);
314                     } else {
315                          LOGV_IF(0,"HAL DEBUG: error reading %s", full_path);
316                     }
317                 } else {
318                     LOGV_IF(0,"HAL DEBUG: error opening %s", full_path);
319                 }
320                 close(fd);
321             }
322         }
323         closedir(dp);
324     } else{
325         LOGI("HAL DEBUG: could not open directory %s", sysfs_path);
326     }
327 
328     return res;
329 }
330