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