• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
hexa_to_ascii(const unsigned char * hexa,char * ascii,int nHexLen)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 
readBDAddrData(const char * szFilePath,unsigned char * addrData,int nDataLen)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 
formattingBdAddr(char * szBDAddr,const char cSep)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 
readBDAddr(InArg inArg,LoadedBDAddr * loadedBDAddr)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 
writeBDAddr(OutArg outArg,LoadedBDAddr * loadedBDAddr)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 
main(int argc,char * argv[])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