Home | History | Annotate | Download | only in bdAddrLoader
      1 /*
      2  * Copyright 2013 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 <errno.h>
     18 #include <fcntl.h>
     19 #include <stdlib.h>
     20 #include <sys/ioctl.h>
     21 #include <sys/socket.h>
     22 #include <sys/types.h>
     23 #include <sys/stat.h>
     24 #include <getopt.h>
     25 
     26 #define LOG_TAG "bdAddrLoader"
     27 
     28 #include <cutils/log.h>
     29 #include <cutils/properties.h>
     30 
     31 #define FILE_PATH_MAX   100
     32 #define BD_ADDR_LEN  6
     33 #define BD_ADDR_STR_LEN 18
     34 
     35 
     36 #define ARG_TYPE_PATH_FILE  0x11
     37 #define ARG_TYPE_PATH_PROP  0x12
     38 
     39 #define ARG_TYPE_DATA_HEX   0x21
     40 #define ARG_TYPE_DATA_ASCII 0x22
     41 
     42 typedef struct _ArgEl {
     43    const char *szSrc;    // Source Path
     44    int nPathType;        // Type of Source Path
     45    int nDataType;        // Type of Data
     46 } ArgEl;
     47 
     48 typedef ArgEl InArg;
     49 
     50 #define DEFAULT_BDADDR_PROP "persist.service.bdroid.bdaddr"
     51 
     52 typedef struct _OutArg {
     53    ArgEl dest;
     54    char  cSeperator;    // a character to be used for sperating like ':' of "XX:XX:XX:XX:XX:XX"
     55    char  bPrintOut;     // Print out bd addr in standard out or not
     56 } OutArg;
     57 
     58 typedef struct _LoadedData {
     59     union {
     60        unsigned char bin[BD_ADDR_LEN];
     61        char sz[BD_ADDR_STR_LEN];
     62     }data;
     63     int nDataType;
     64 } LoadedBDAddr;
     65 
     66 typedef enum _res {
     67     SUCCESS = 0,
     68     FAIL
     69 } Res;
     70 
     71 int hexa_to_ascii(const unsigned char* hexa, char* ascii, int nHexLen)
     72 {
     73     int i, j;
     74     char hex_table[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     75                 'A', 'B', 'C', 'D', 'E', 'F'};
     76 
     77     for (i = 0, j = 0; i <nHexLen; i++, j += 2) {
     78         ascii[j] = hex_table[hexa[i] >> 4];
     79         ascii[j + 1] = hex_table[hexa[i] & 0x0F];
     80     }
     81 
     82     ascii[nHexLen*2] = '\0';
     83 
     84     ALOGI("hex_to_ascii() - converted Data (%s)", ascii);
     85 
     86     return SUCCESS;
     87 }
     88 
     89 int readBDAddrData(const char* szFilePath, unsigned char* addrData, int nDataLen)
     90 {
     91     int nFd, nRdCnt;
     92 
     93     nFd = open(szFilePath, O_RDONLY);
     94 
     95     if (nFd < 0) {
     96         ALOGW("There is no Address File in FTM area : %s\n", szFilePath);
     97         return FAIL;
     98     }
     99 
    100     nRdCnt = read(nFd, addrData, nDataLen);
    101     if (nRdCnt != nDataLen) {
    102         ALOGE("Fail to read Address data from FTM area\n");
    103         close(nFd);
    104         return FAIL;
    105     }
    106     close(nFd);
    107     return SUCCESS;
    108 }
    109 
    110 void formattingBdAddr(char *szBDAddr, const char cSep)
    111 {
    112     int i = 1, j = 0;
    113     int pos = 0;
    114     for (i=1; i<BD_ADDR_LEN; i++) {
    115        pos = strlen(szBDAddr);
    116        for (j=0; j<(BD_ADDR_LEN*2)-i*2; j++) {
    117           szBDAddr[pos-j] = szBDAddr[pos-j-1];
    118        }
    119        szBDAddr[pos-j]=cSep;
    120     }
    121 }
    122 
    123 int readBDAddr(InArg inArg, LoadedBDAddr *loadedBDAddr)
    124 {
    125     Res res = FAIL;
    126     unsigned char addrData[BD_ADDR_LEN] = {0,};
    127     int nDataLen = 0;
    128 
    129     ALOGI("Read From %s by Path type(0x%2x), Data type (0x%2x)",
    130             inArg.szSrc, inArg.nPathType, inArg.nDataType);
    131 
    132     if (inArg.nPathType == ARG_TYPE_PATH_FILE) {
    133         switch (inArg.nDataType) {
    134         case ARG_TYPE_DATA_HEX:
    135             if (!readBDAddrData(inArg.szSrc, loadedBDAddr->data.bin, BD_ADDR_LEN)) {
    136                 loadedBDAddr->nDataType = ARG_TYPE_DATA_HEX;
    137                 return SUCCESS;
    138             }
    139             break;
    140         case ARG_TYPE_DATA_ASCII:
    141            if (!readBDAddrData(inArg.szSrc, (unsigned char *)loadedBDAddr->data.sz, BD_ADDR_STR_LEN)) {
    142                 loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
    143                 return SUCCESS;
    144             }
    145             break;
    146         default:
    147             return FAIL;
    148         }
    149     } else if (inArg.nPathType == ARG_TYPE_PATH_PROP) {
    150         char prop_value[PROPERTY_VALUE_MAX];
    151         switch (inArg.nDataType) {
    152         case ARG_TYPE_DATA_HEX:
    153             if (property_get(inArg.szSrc, prop_value, "") >= 0 && strlen(prop_value) < BD_ADDR_LEN) {
    154                 strlcpy((char *)loadedBDAddr->data.bin, prop_value, BD_ADDR_LEN);
    155                 loadedBDAddr->nDataType = ARG_TYPE_DATA_HEX;
    156                 return SUCCESS;
    157             }
    158             break;
    159         case ARG_TYPE_DATA_ASCII:
    160             if (property_get(inArg.szSrc, prop_value, "") >= 0 && strlen(prop_value) < BD_ADDR_STR_LEN) {
    161                 strlcpy(loadedBDAddr->data.sz, prop_value, BD_ADDR_STR_LEN);
    162                 loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
    163                 return SUCCESS;
    164             }
    165             break;
    166         default:
    167             return FAIL;
    168         }
    169     } else {
    170         ALOGE("Error invalid argument : (%d)", inArg.nPathType);
    171     }
    172 
    173     ALOGE("Fail to read BDAddr from %s", inArg.szSrc);
    174     return FAIL;
    175 }
    176 
    177 int writeBDAddr(OutArg outArg, LoadedBDAddr *loadedBDAddr)
    178 {
    179     char szTmp[BD_ADDR_STR_LEN] = {0,};
    180 
    181     ALOGI("Output Data type(0x%2x), bPrintout(%d), bPath(%s)",
    182         outArg.dest.nDataType, outArg.bPrintOut, outArg.dest.szSrc);
    183 
    184     ALOGI("Loaded Data type(0x%2x)", loadedBDAddr->nDataType);
    185 
    186     if (outArg.dest.nDataType == ARG_TYPE_DATA_ASCII
    187             && loadedBDAddr->nDataType == ARG_TYPE_DATA_HEX) {
    188         if (!hexa_to_ascii(loadedBDAddr->data.bin, szTmp, BD_ADDR_LEN)) {
    189             memcpy(loadedBDAddr->data.sz, szTmp, BD_ADDR_STR_LEN);
    190             loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
    191         } else {
    192             ALOGE("Fail to convert data");
    193             return FAIL;
    194         }
    195     }
    196 
    197     if (loadedBDAddr->nDataType == ARG_TYPE_DATA_ASCII) {
    198        // check out which addr data is already formated
    199        if (strchr(loadedBDAddr->data.sz, '.') == NULL
    200                && strchr(loadedBDAddr->data.sz, ':') == NULL) {
    201            formattingBdAddr(loadedBDAddr->data.sz, outArg.cSeperator);
    202        }
    203     }
    204     // print out szBDAddr
    205     if (outArg.bPrintOut
    206             && loadedBDAddr->nDataType == ARG_TYPE_DATA_ASCII
    207             && strlen(loadedBDAddr->data.sz)==(BD_ADDR_STR_LEN-1)) {
    208        printf("%s",loadedBDAddr->data.sz);
    209        if (property_set(DEFAULT_BDADDR_PROP, loadedBDAddr->data.sz) < 0)
    210            ALOGE("Failed to set address in prop %s", DEFAULT_BDADDR_PROP);
    211     } else {
    212        ALOGE("Invalid Data is loaded : %s", loadedBDAddr->data.sz);
    213        return FAIL;
    214     }
    215     // TODO :: writing File or Property
    216     return SUCCESS;
    217 }
    218 
    219 int main(int argc, char *argv[])
    220 {
    221     int nFd, nRdCnt;
    222     int c;
    223 
    224     InArg inArg;
    225     OutArg outArg;
    226     LoadedBDAddr loadedBDAddr;
    227 
    228     //initialize arg
    229     memset(&inArg, 0, sizeof(InArg));
    230     memset(&outArg, 0, sizeof(OutArg));
    231     memset(&loadedBDAddr, 0, sizeof(LoadedBDAddr));
    232 
    233     //load args;
    234     while((c=getopt(argc, argv, ":f:p:hsx")) != -1){
    235         switch(c){
    236         case 'f': // input path
    237             if (optarg != NULL) {
    238                 ALOGI("option : f=%s", optarg);
    239                 inArg.szSrc = optarg;
    240             } else {
    241                 ALOGW("Invalid Argument(%s) of input path", optarg);
    242             }
    243             inArg.nPathType = ARG_TYPE_PATH_FILE;
    244             break;
    245         case 'p': // output path
    246             if (optarg != NULL) {
    247                 ALOGI("option : p=%s", optarg);
    248                 inArg.szSrc = optarg;
    249             } else {
    250                 ALOGW("Invalid Argument(%s) of out Path", optarg);
    251             }
    252             inArg.nPathType = ARG_TYPE_PATH_PROP;
    253             break;
    254         case 'h': // data type to be read is hex
    255             ALOGI("option : h");
    256             inArg.nDataType = ARG_TYPE_DATA_HEX;
    257             break;
    258         case 's': // data type to be read is ascii
    259             ALOGI("option : s");
    260             inArg.nDataType = ARG_TYPE_DATA_ASCII;
    261             break;
    262         case 'x':
    263             ALOGI("option : x");
    264             outArg.bPrintOut = 1; //true
    265             break;
    266         default:
    267             ALOGW("Unknown option : %c", c);
    268             break;
    269         }
    270     }
    271 
    272     // setting up Arguments with default value
    273     outArg.cSeperator = ':';
    274     outArg.dest.nDataType = ARG_TYPE_DATA_ASCII;
    275 
    276     // load bd addr and print out bd addr in formated ascii
    277     if (readBDAddr(inArg, &loadedBDAddr)) {
    278         ALOGE("Fail to load data !!");
    279         return FAIL;
    280     }
    281 
    282     if (writeBDAddr(outArg, &loadedBDAddr)) {
    283         ALOGE("Fail to write data !!");
    284         return FAIL;
    285     }
    286 
    287     return 1;
    288 }
    289