292 lines
8.4 KiB
C
292 lines
8.4 KiB
C
/*
|
|
* Copyright 2012 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <getopt.h>
|
|
|
|
#define LOG_TAG "bdAddrLoader"
|
|
|
|
#include <log/log.h>
|
|
#include <cutils/properties.h>
|
|
|
|
#define FILE_PATH_MAX 100
|
|
#define BD_ADDR_LEN 6
|
|
#define BD_ADDR_STR_LEN 18
|
|
|
|
|
|
#define ARG_TYPE_PATH_FILE 0x11
|
|
#define ARG_TYPE_PATH_PROP 0x12
|
|
|
|
#define ARG_TYPE_DATA_HEX 0x21
|
|
#define ARG_TYPE_DATA_ASCII 0x22
|
|
|
|
typedef struct _ArgEl
|
|
{
|
|
const char *szSrc; // Source Path
|
|
int nPathType; // Type of Source Path
|
|
int nDataType; // Type of Data
|
|
}ArgEl;
|
|
|
|
typedef ArgEl InArg;
|
|
|
|
#define DEFAULT_BDADDR_PROP "persist.service.bdroid.bdaddr"
|
|
|
|
typedef struct _OutArg {
|
|
ArgEl dest;
|
|
char cSeperator; // a character to be used for sperating like ':' of "XX:XX:XX:XX:XX:XX"
|
|
char bPrintOut; // Print out bd addr in standard out or not
|
|
} OutArg;
|
|
|
|
typedef struct _LoadedData
|
|
{
|
|
union {
|
|
unsigned char bin[BD_ADDR_LEN];
|
|
char sz[BD_ADDR_STR_LEN];
|
|
}data;
|
|
int nDataType;
|
|
}LoadedBDAddr;
|
|
|
|
typedef enum _res
|
|
{
|
|
SUCCESS = 0,
|
|
FAIL
|
|
}Res;
|
|
|
|
int hexa_to_ascii(const unsigned char* hexa, char* ascii, int nHexLen)
|
|
{
|
|
int i, j;
|
|
char hex_table[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'A', 'B', 'C', 'D', 'E', 'F'};
|
|
|
|
for (i = 0, j = 0; i < nHexLen; i++, j += 2) {
|
|
ascii[j] = hex_table[hexa[i] >> 4];
|
|
ascii[j + 1] = hex_table[hexa[i] & 0x0F];
|
|
}
|
|
|
|
ascii[nHexLen*2] = '\0';
|
|
|
|
ALOGI("hex_to_ascii() - converted Data (%s)", ascii);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int readBDAddrData(const char* szFilePath, unsigned char* addrData, int nDataLen)
|
|
{
|
|
int nFd, nRdCnt;
|
|
|
|
nFd = open(szFilePath, O_RDONLY);
|
|
|
|
if(nFd < 0){
|
|
ALOGW("There is no Address File in FTM area : %s\n", szFilePath);
|
|
return FAIL;
|
|
}
|
|
|
|
nRdCnt = read(nFd, addrData, nDataLen);
|
|
if(nRdCnt != nDataLen){
|
|
ALOGE("Fail to read Address data from FTM area\n");
|
|
close(nFd);
|
|
return FAIL;
|
|
}
|
|
close(nFd);
|
|
return SUCCESS;
|
|
}
|
|
|
|
void formattingBdAddr(char *szBDAddr, const char cSep)
|
|
{
|
|
int i = 1, j = 0;
|
|
int pos = 0;
|
|
for (i = 1; i < BD_ADDR_LEN; i++) {
|
|
pos = strlen(szBDAddr);
|
|
for (j = 0; j < (BD_ADDR_LEN * 2) - i * 2; j++) {
|
|
szBDAddr[pos - j] = szBDAddr[pos - j - 1];
|
|
}
|
|
szBDAddr[pos-j]=cSep;
|
|
}
|
|
}
|
|
|
|
int readBDAddr(InArg inArg, LoadedBDAddr *loadedBDAddr)
|
|
{
|
|
ALOGI("Read From %s by Path type(0x%2x), Data type (0x%2x)",
|
|
inArg.szSrc, inArg.nPathType, inArg.nDataType);
|
|
|
|
if (inArg.nPathType == ARG_TYPE_PATH_FILE) {
|
|
switch (inArg.nDataType) {
|
|
case ARG_TYPE_DATA_HEX:
|
|
if (!readBDAddrData(inArg.szSrc, loadedBDAddr->data.bin, BD_ADDR_LEN)) {
|
|
loadedBDAddr->nDataType = ARG_TYPE_DATA_HEX;
|
|
return SUCCESS;
|
|
}
|
|
break;
|
|
case ARG_TYPE_DATA_ASCII:
|
|
if (!readBDAddrData(inArg.szSrc, (unsigned char *)loadedBDAddr->data.sz, BD_ADDR_STR_LEN)) {
|
|
loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
|
|
return SUCCESS;
|
|
}
|
|
break;
|
|
default:
|
|
return FAIL;
|
|
}
|
|
}else if(inArg.nPathType == ARG_TYPE_PATH_PROP){
|
|
char prop_value[PROPERTY_VALUE_MAX];
|
|
switch(inArg.nDataType){
|
|
case ARG_TYPE_DATA_HEX:
|
|
if(property_get(inArg.szSrc, prop_value, "") >= 0 && strlen(prop_value) < BD_ADDR_LEN){
|
|
strlcpy((char *)loadedBDAddr->data.bin, prop_value, BD_ADDR_LEN);
|
|
loadedBDAddr->nDataType = ARG_TYPE_DATA_HEX;
|
|
return SUCCESS;
|
|
}
|
|
break;
|
|
case ARG_TYPE_DATA_ASCII:
|
|
if(property_get(inArg.szSrc, prop_value, "") >= 0 && strlen(prop_value) < BD_ADDR_STR_LEN){
|
|
strlcpy(loadedBDAddr->data.sz, prop_value, BD_ADDR_STR_LEN);
|
|
loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
|
|
return SUCCESS;
|
|
}
|
|
break;
|
|
default:
|
|
return FAIL;
|
|
}
|
|
}else{
|
|
ALOGE("Error invalid argument : (%d)", inArg.nPathType);
|
|
}
|
|
|
|
ALOGE("Fail to read BDAddr from %s", inArg.szSrc);
|
|
return FAIL;
|
|
}
|
|
|
|
int writeBDAddr(OutArg outArg, LoadedBDAddr *loadedBDAddr)
|
|
{
|
|
char szTmp[BD_ADDR_STR_LEN] = {0,};
|
|
|
|
ALOGI("Output Data type(0x%2x), bPrintout(%d), bPath(%s)",
|
|
outArg.dest.nDataType, outArg.bPrintOut, outArg.dest.szSrc);
|
|
|
|
ALOGI("Loaded Data type(0x%2x)", loadedBDAddr->nDataType);
|
|
|
|
if(outArg.dest.nDataType == ARG_TYPE_DATA_ASCII
|
|
&& loadedBDAddr->nDataType == ARG_TYPE_DATA_HEX
|
|
){
|
|
if(!hexa_to_ascii(loadedBDAddr->data.bin, szTmp, BD_ADDR_LEN)){
|
|
memcpy(loadedBDAddr->data.sz, szTmp, BD_ADDR_STR_LEN);
|
|
loadedBDAddr->nDataType = ARG_TYPE_DATA_ASCII;
|
|
}
|
|
else{
|
|
ALOGE("Fail to convert data");
|
|
return FAIL;
|
|
}
|
|
}
|
|
|
|
if(loadedBDAddr->nDataType == ARG_TYPE_DATA_ASCII){
|
|
// check out which addr data is already formated
|
|
if(strchr(loadedBDAddr->data.sz, '.') == NULL
|
|
&& strchr(loadedBDAddr->data.sz, ':') == NULL
|
|
){
|
|
formattingBdAddr(loadedBDAddr->data.sz, outArg.cSeperator);
|
|
}
|
|
}
|
|
// print out szBDAddr
|
|
if(outArg.bPrintOut
|
|
&& loadedBDAddr->nDataType == ARG_TYPE_DATA_ASCII
|
|
&& strlen(loadedBDAddr->data.sz)==(BD_ADDR_STR_LEN-1)) {
|
|
printf("%s",loadedBDAddr->data.sz);
|
|
if (property_set(DEFAULT_BDADDR_PROP, loadedBDAddr->data.sz) < 0)
|
|
ALOGE("Failed to set address in prop %s", DEFAULT_BDADDR_PROP);
|
|
}
|
|
else{
|
|
ALOGE("Invalid Data is loaded : %s", loadedBDAddr->data.sz);
|
|
return FAIL;
|
|
}
|
|
// TODO :: writing File or Property
|
|
return SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int c;
|
|
|
|
InArg inArg;
|
|
OutArg outArg;
|
|
LoadedBDAddr loadedBDAddr;
|
|
|
|
//initialize arg
|
|
memset(&inArg, 0, sizeof(InArg));
|
|
memset(&outArg, 0, sizeof(OutArg));
|
|
memset(&loadedBDAddr, 0, sizeof(LoadedBDAddr));
|
|
|
|
//load args;
|
|
while((c=getopt(argc, argv, ":f:p:hsx")) != -1){
|
|
switch(c){
|
|
case 'f': // input path
|
|
if(optarg != NULL){
|
|
ALOGI("option : f=%s", optarg);
|
|
inArg.szSrc = optarg;
|
|
}else{
|
|
ALOGW("Invalid Argument(%s) of input path", optarg);
|
|
}
|
|
inArg.nPathType = ARG_TYPE_PATH_FILE;
|
|
break;
|
|
case 'p': // output path
|
|
if(optarg != NULL){
|
|
ALOGI("option : p=%s", optarg);
|
|
inArg.szSrc = optarg;
|
|
}else{
|
|
ALOGW("Invalid Argument(%s) of out Path", optarg);
|
|
}
|
|
inArg.nPathType = ARG_TYPE_PATH_PROP;
|
|
break;
|
|
case 'h': // data type to be read is hex
|
|
ALOGI("option : h");
|
|
inArg.nDataType = ARG_TYPE_DATA_HEX;
|
|
break;
|
|
case 's': // data type to be read is ascii
|
|
ALOGI("option : s");
|
|
inArg.nDataType = ARG_TYPE_DATA_ASCII;
|
|
break;
|
|
case 'x':
|
|
ALOGI("option : x");
|
|
outArg.bPrintOut = 1; //true
|
|
break;
|
|
default:
|
|
ALOGW("Unknown option : %c", c);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// setting up Arguments with default value
|
|
outArg.cSeperator = ':';
|
|
outArg.dest.nDataType = ARG_TYPE_DATA_ASCII;
|
|
|
|
// load bd addr and print out bd addr in formated ascii
|
|
if(readBDAddr(inArg, &loadedBDAddr)){
|
|
ALOGE("Fail to load data !!");
|
|
return FAIL;
|
|
}
|
|
|
|
if(writeBDAddr(outArg, &loadedBDAddr)){
|
|
ALOGE("Fail to write data !!");
|
|
return FAIL;
|
|
}
|
|
|
|
return 1;
|
|
}
|