• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #include <android/log.h>
18 #include <assert.h>
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <stdbool.h>
24 #include <stdint.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <eventnums.h>
29 #include <sensType.h>
30 #include <signal.h>
31 #include <inttypes.h>
32 #include <errno.h>
33 
34 #define LOG_TAG "nanoapp_cmd"
35 #define SENSOR_RATE_ONCHANGE    0xFFFFFF01UL
36 #define SENSOR_RATE_ONESHOT     0xFFFFFF02UL
37 #define SENSOR_HZ(_hz)          ((uint32_t)((_hz) * 1024.0f))
38 #define MAX_INSTALL_CNT         8
39 #define MAX_DOWNLOAD_RETRIES    4
40 
41 #define LOGE(fmt, ...) do { \
42         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__); \
43         printf(fmt "\n", ##__VA_ARGS__); \
44     } while (0)
45 
46 enum ConfigCmds
47 {
48     CONFIG_CMD_DISABLE      = 0,
49     CONFIG_CMD_ENABLE       = 1,
50     CONFIG_CMD_FLUSH        = 2,
51     CONFIG_CMD_CFG_DATA     = 3,
52     CONFIG_CMD_CALIBRATE    = 4,
53 };
54 
55 struct ConfigCmd
56 {
57     uint32_t evtType;
58     uint64_t latency;
59     uint32_t rate;
60     uint8_t sensorType;
61     uint8_t cmd;
62     uint16_t flags;
63 } __attribute__((packed));
64 
65 struct AppInfo
66 {
67     uint32_t num;
68     uint64_t id;
69     uint32_t version;
70     uint32_t size;
71 };
72 
setType(struct ConfigCmd * cmd,char * sensor)73 static int setType(struct ConfigCmd *cmd, char *sensor)
74 {
75     if (strcmp(sensor, "accel") == 0) {
76         cmd->sensorType = SENS_TYPE_ACCEL;
77     } else if (strcmp(sensor, "gyro") == 0) {
78         cmd->sensorType = SENS_TYPE_GYRO;
79     } else if (strcmp(sensor, "mag") == 0) {
80         cmd->sensorType = SENS_TYPE_MAG;
81     } else if (strcmp(sensor, "uncal_gyro") == 0) {
82         cmd->sensorType = SENS_TYPE_GYRO;
83     } else if (strcmp(sensor, "uncal_mag") == 0) {
84         cmd->sensorType = SENS_TYPE_MAG;
85     } else if (strcmp(sensor, "als") == 0) {
86         cmd->sensorType = SENS_TYPE_ALS;
87     } else if (strcmp(sensor, "prox") == 0) {
88         cmd->sensorType = SENS_TYPE_PROX;
89     } else if (strcmp(sensor, "baro") == 0) {
90         cmd->sensorType = SENS_TYPE_BARO;
91     } else if (strcmp(sensor, "temp") == 0) {
92         cmd->sensorType = SENS_TYPE_TEMP;
93     } else if (strcmp(sensor, "orien") == 0) {
94         cmd->sensorType = SENS_TYPE_ORIENTATION;
95     } else if (strcmp(sensor, "gravity") == 0) {
96         cmd->sensorType = SENS_TYPE_GRAVITY;
97     } else if (strcmp(sensor, "geomag") == 0) {
98         cmd->sensorType = SENS_TYPE_GEO_MAG_ROT_VEC;
99     } else if (strcmp(sensor, "linear_acc") == 0) {
100         cmd->sensorType = SENS_TYPE_LINEAR_ACCEL;
101     } else if (strcmp(sensor, "rotation") == 0) {
102         cmd->sensorType = SENS_TYPE_ROTATION_VECTOR;
103     } else if (strcmp(sensor, "game") == 0) {
104         cmd->sensorType = SENS_TYPE_GAME_ROT_VECTOR;
105     } else if (strcmp(sensor, "win_orien") == 0) {
106         cmd->sensorType = SENS_TYPE_WIN_ORIENTATION;
107         cmd->rate = SENSOR_RATE_ONCHANGE;
108     } else if (strcmp(sensor, "tilt") == 0) {
109         cmd->sensorType = SENS_TYPE_TILT;
110         cmd->rate = SENSOR_RATE_ONCHANGE;
111     } else if (strcmp(sensor, "step_det") == 0) {
112         cmd->sensorType = SENS_TYPE_STEP_DETECT;
113         cmd->rate = SENSOR_RATE_ONCHANGE;
114     } else if (strcmp(sensor, "step_cnt") == 0) {
115         cmd->sensorType = SENS_TYPE_STEP_COUNT;
116         cmd->rate = SENSOR_RATE_ONCHANGE;
117     } else if (strcmp(sensor, "double_tap") == 0) {
118         cmd->sensorType = SENS_TYPE_DOUBLE_TAP;
119         cmd->rate = SENSOR_RATE_ONCHANGE;
120     } else if (strcmp(sensor, "flat") == 0) {
121         cmd->sensorType = SENS_TYPE_FLAT;
122         cmd->rate = SENSOR_RATE_ONCHANGE;
123     } else if (strcmp(sensor, "anymo") == 0) {
124         cmd->sensorType = SENS_TYPE_ANY_MOTION;
125         cmd->rate = SENSOR_RATE_ONCHANGE;
126     } else if (strcmp(sensor, "nomo") == 0) {
127         cmd->sensorType = SENS_TYPE_NO_MOTION;
128         cmd->rate = SENSOR_RATE_ONCHANGE;
129     } else if (strcmp(sensor, "sigmo") == 0) {
130         cmd->sensorType = SENS_TYPE_SIG_MOTION;
131         cmd->rate = SENSOR_RATE_ONESHOT;
132     } else if (strcmp(sensor, "gesture") == 0) {
133         cmd->sensorType = SENS_TYPE_GESTURE;
134         cmd->rate = SENSOR_RATE_ONESHOT;
135     } else if (strcmp(sensor, "hall") == 0) {
136         cmd->sensorType = SENS_TYPE_HALL;
137         cmd->rate = SENSOR_RATE_ONCHANGE;
138     } else if (strcmp(sensor, "vsync") == 0) {
139         cmd->sensorType = SENS_TYPE_VSYNC;
140         cmd->rate = SENSOR_RATE_ONCHANGE;
141     } else if (strcmp(sensor, "activity") == 0) {
142         cmd->sensorType = SENS_TYPE_ACTIVITY;
143         cmd->rate = SENSOR_RATE_ONCHANGE;
144     } else if (strcmp(sensor, "twist") == 0) {
145         cmd->sensorType = SENS_TYPE_DOUBLE_TWIST;
146         cmd->rate = SENSOR_RATE_ONCHANGE;
147     } else {
148         return 1;
149     }
150 
151     return 0;
152 }
153 
154 bool drain = false;
155 bool stop = false;
156 char *buf;
157 int nread, buf_size = 2048;
158 struct AppInfo apps[32];
159 uint8_t appCount;
160 char appsToInstall[MAX_INSTALL_CNT][32];
161 
sig_handle(int sig)162 void sig_handle(__attribute__((unused)) int sig)
163 {
164     assert(sig == SIGINT);
165     printf("Terminating...\n");
166     stop = true;
167 }
168 
openFile(const char * fname,const char * mode)169 FILE *openFile(const char *fname, const char *mode)
170 {
171     FILE *f = fopen(fname, mode);
172     if (f == NULL) {
173         LOGE("Failed to open %s: err=%d [%s]", fname, errno, strerror(errno));
174     }
175     return f;
176 }
177 
parseInstalledAppInfo()178 void parseInstalledAppInfo()
179 {
180     FILE *fp;
181     char *line = NULL;
182     size_t len;
183     ssize_t numRead;
184 
185     appCount = 0;
186 
187     fp = openFile("/sys/class/nanohub/nanohub/app_info", "r");
188     if (!fp)
189         return;
190 
191     while ((numRead = getline(&line, &len, fp)) != -1) {
192         struct AppInfo *currApp = &apps[appCount++];
193         sscanf(line, "app: %d id: %" PRIx64 " ver: %" PRIx32 " size: %" PRIx32 "\n", &currApp->num, &currApp->id, &currApp->version, &currApp->size);
194     }
195 
196     fclose(fp);
197 
198     if (line)
199         free(line);
200 }
201 
findApp(uint64_t appId)202 struct AppInfo *findApp(uint64_t appId)
203 {
204     uint8_t i;
205 
206     for (i = 0; i < appCount; i++) {
207         if (apps[i].id == appId) {
208             return &apps[i];
209         }
210     }
211 
212     return NULL;
213 }
214 
parseConfigAppInfo()215 int parseConfigAppInfo()
216 {
217     FILE *fp;
218     char *line = NULL;
219     size_t len;
220     ssize_t numRead;
221     int installCnt;
222 
223     fp = openFile("/vendor/firmware/napp_list.cfg", "r");
224     if (!fp)
225         return -1;
226 
227     parseInstalledAppInfo();
228 
229     installCnt = 0;
230     while (((numRead = getline(&line, &len, fp)) != -1) && (installCnt < MAX_INSTALL_CNT)) {
231         uint64_t appId;
232         uint32_t appVersion;
233         struct AppInfo* installedApp;
234 
235         sscanf(line, "%32s %" PRIx64 " %" PRIx32 "\n", appsToInstall[installCnt], &appId, &appVersion);
236 
237         installedApp = findApp(appId);
238         if (!installedApp || (installedApp->version < appVersion)) {
239             installCnt++;
240         }
241     }
242 
243     fclose(fp);
244 
245     if (line)
246         free(line);
247 
248     return installCnt;
249 }
250 
fileWriteData(const char * fname,const void * data,size_t size)251 bool fileWriteData(const char *fname, const void *data, size_t size)
252 {
253     int fd;
254     bool result;
255 
256     fd = open(fname, O_WRONLY);
257     if (fd < 0) {
258         LOGE("Failed to open %s: err=%d [%s]", fname, errno, strerror(errno));
259         return false;
260     }
261 
262     result = true;
263     if ((size_t)write(fd, data, size) != size) {
264         LOGE("Failed to write to %s; err=%d [%s]", fname, errno, strerror(errno));
265         result = false;
266     }
267     close(fd);
268 
269     return result;
270 }
271 
downloadNanohub()272 void downloadNanohub()
273 {
274     char c = '1';
275 
276     printf("Updating nanohub OS [if required]...");
277     fflush(stdout);
278     if (fileWriteData("/sys/class/nanohub/nanohub/download_bl", &c, sizeof(c)))
279         printf("done\n");
280 }
281 
downloadApps(int updateCnt)282 void downloadApps(int updateCnt)
283 {
284     int i;
285 
286     for (i = 0; i < updateCnt; i++) {
287         printf("Downloading \"%s.napp\"...", appsToInstall[i]);
288         fflush(stdout);
289         if (fileWriteData("/sys/class/nanohub/nanohub/download_app", appsToInstall[i], strlen(appsToInstall[i])))
290             printf("done\n");
291     }
292 }
293 
eraseSharedArea()294 void eraseSharedArea()
295 {
296     char c = '1';
297 
298     printf("Erasing entire nanohub shared area...");
299     fflush(stdout);
300     if (fileWriteData("/sys/class/nanohub/nanohub/erase_shared", &c, sizeof(c)))
301         printf("done\n");
302 }
303 
resetHub()304 void resetHub()
305 {
306     char c = '1';
307 
308     printf("Resetting nanohub...");
309     fflush(stdout);
310     if (fileWriteData("/sys/class/nanohub/nanohub/reset", &c, sizeof(c)))
311         printf("done\n");
312 }
313 
main(int argc,char * argv[])314 int main(int argc, char *argv[])
315 {
316     struct ConfigCmd mConfigCmd;
317     int fd;
318     int i;
319 
320     if (argc < 3 && (argc < 2 || strcmp(argv[1], "download") != 0)) {
321         printf("usage: %s <action> <sensor> <data> -d\n", argv[0]);
322         printf("       action: config|calibrate|flush|download\n");
323         printf("       sensor: accel|(uncal_)gyro|(uncal_)mag|als|prox|baro|temp|orien\n");
324         printf("               gravity|geomag|linear_acc|rotation|game\n");
325         printf("               win_orien|tilt|step_det|step_cnt|double_tap\n");
326         printf("               flat|anymo|nomo|sigmo|gesture|hall|vsync\n");
327         printf("               activity|twist\n");
328         printf("       data: config: <true|false> <rate in Hz> <latency in u-sec>\n");
329         printf("             calibrate: [N.A.]\n");
330         printf("             flush: [N.A.]\n");
331         printf("       -d: if specified, %s will keep draining /dev/nanohub until cancelled.\n", argv[0]);
332 
333         return 1;
334     }
335 
336     if (strcmp(argv[1], "config") == 0) {
337         if (argc != 6 && argc != 7) {
338             printf("Wrong arg number\n");
339             return 1;
340         }
341         if (argc == 7) {
342             if(strcmp(argv[6], "-d") == 0) {
343                 drain = true;
344             } else {
345                 printf("Last arg unsupported, ignored.\n");
346             }
347         }
348         if (strcmp(argv[3], "true") == 0)
349             mConfigCmd.cmd = CONFIG_CMD_ENABLE;
350         else if (strcmp(argv[3], "false") == 0) {
351             mConfigCmd.cmd = CONFIG_CMD_DISABLE;
352         } else {
353             printf("Unsupported data: %s For action: %s\n", argv[3], argv[1]);
354             return 1;
355         }
356         mConfigCmd.evtType = EVT_NO_SENSOR_CONFIG_EVENT;
357         mConfigCmd.rate = SENSOR_HZ((float)atoi(argv[4]));
358         mConfigCmd.latency = atoi(argv[5]) * 1000ull;
359         if (setType(&mConfigCmd, argv[2])) {
360             printf("Unsupported sensor: %s For action: %s\n", argv[2], argv[1]);
361             return 1;
362         }
363     } else if (strcmp(argv[1], "calibrate") == 0) {
364         if (argc != 3) {
365             printf("Wrong arg number\n");
366             return 1;
367         }
368         mConfigCmd.evtType = EVT_NO_SENSOR_CONFIG_EVENT;
369         mConfigCmd.rate = 0;
370         mConfigCmd.latency = 0;
371         mConfigCmd.cmd = CONFIG_CMD_CALIBRATE;
372         if (setType(&mConfigCmd, argv[2])) {
373             printf("Unsupported sensor: %s For action: %s\n", argv[2], argv[1]);
374             return 1;
375         }
376     } else if (strcmp(argv[1], "flush") == 0) {
377         if (argc != 3) {
378             printf("Wrong arg number\n");
379             return 1;
380         }
381         mConfigCmd.evtType = EVT_NO_SENSOR_CONFIG_EVENT;
382         mConfigCmd.rate = 0;
383         mConfigCmd.latency = 0;
384         mConfigCmd.cmd = CONFIG_CMD_FLUSH;
385         if (setType(&mConfigCmd, argv[2])) {
386             printf("Unsupported sensor: %s For action: %s\n", argv[2], argv[1]);
387             return 1;
388         }
389     } else if (strcmp(argv[1], "download") == 0) {
390         if (argc != 2) {
391             printf("Wrong arg number\n");
392             return 1;
393         }
394         downloadNanohub();
395         for (i = 0; i < MAX_DOWNLOAD_RETRIES; i++) {
396             int updateCnt = parseConfigAppInfo();
397             if (updateCnt > 0) {
398                 if (i == MAX_DOWNLOAD_RETRIES - 1) {
399                     LOGE("Download failed after %d retries; erasing all apps "
400                          "before final attempt", i);
401                     eraseSharedArea();
402                 }
403                 downloadApps(updateCnt);
404                 resetHub();
405             } else if (!updateCnt){
406                 return 0;
407             }
408         }
409 
410         if (parseConfigAppInfo() != 0) {
411             LOGE("Failed to download all apps!");
412         }
413         return 1;
414     } else {
415         printf("Unsupported action: %s\n", argv[1]);
416         return 1;
417     }
418 
419     while (!fileWriteData("/dev/nanohub", &mConfigCmd, sizeof(mConfigCmd)))
420         continue;
421 
422     if (drain) {
423         signal(SIGINT, sig_handle);
424         fd = open("/dev/nanohub", O_RDONLY);
425         while (!stop) {
426             (void) read(fd, buf, buf_size);
427         }
428         close(fd);
429     }
430     return 0;
431 }
432