Home | History | Annotate | Download | only in nanoapp_cmd
      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 
     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 
    162 void sig_handle(__attribute__((unused)) int sig)
    163 {
    164     assert(sig == SIGINT);
    165     printf("Terminating...\n");
    166     stop = true;
    167 }
    168 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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