蓝牙地址的NV项是447项,蓝牙地址一般从NV读取,所以连接上QXDM,修改NV447项就可以修改蓝牙的MAC地址。Android修改NV 447项之后,发现修改不起作用。原来Android的蓝牙地址可以从/persist/.bt_nv.bin读,也可以从NV447读,关键就看一个 vendor/.../bt/hci_qcomm_init/Android.mk的设置 如果要从nv447读, 则
BT_QSOC_GET_ITEMS_FROM_NV = 1
BT_QSOC_GET_ITEMS_FROM_PERSIST = 1
BT_QSOC_GET_ITEMS_FROM_PERSIST_THEN_NV = 1
将BT_QSOC_GET_ITEMS_FROM_PERSIST_THEN_NV注释掉,如果从.bt_nv.bin读就取消注释。
读取蓝牙地址的代码在同一目录下的 bthci_qcomm_linux.cpp,修改了Android.mk文件后,要保证 bthci_qcomm_linux.cpp能被重新编译下修改才能起作用 。获得蓝牙地址代码如下:
boolean bt_hci_qcomm_pfal_get_bdaddress ( uint8 *pCmdBuffer )
{
boolean bd_set = FALSE;
if (verbose > 2)
{
fprintf (stderr, "get_bdaddr: before: 0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x\n",
BD_addr[0], BD_addr[1], BD_addr[2], BD_addr[3], BD_addr[4], BD_addr[5]);
}
if (BD_addr_string != NULL) /* BD_ADDR was passed in as -b arg */
{
/* convert ASCII HEX representation to 48 bits */
/* BD_addr is little-endian, but string is as printed */
BD_addr[5] = strtol (&BD_addr_string[ 0], 0, 16);
BD_addr[4] = strtol (&BD_addr_string[ 3], 0, 16);
BD_addr[3] = strtol (&BD_addr_string[ 6], 0, 16);
BD_addr[2] = strtol (&BD_addr_string[ 9], 0, 16);
BD_addr[1] = strtol (&BD_addr_string[12], 0, 16);
BD_addr[0] = strtol (&BD_addr_string[15], 0, 16);
bd_set = TRUE;
}
else /* get BD_ADDR from NV or set it to RANDOM */
{
#if defined(BT_QSOC_GET_ITEMS_FROM_PERSIST_THEN_NV)
static nv_persist_item_type my_nv_persist_item; /* nv_bd_addr_type */
static nv_persist_stat_enum_type persistcmd_result;
persistcmd_result = (nv_persist_stat_enum_type)bt_nv_cmd(NV_PERSIST_READ_F, NV_PERSIST_BD_ADDR_I, &my_nv_persist_item);
if (NV_PERSIST_SUCCESS != persistcmd_result)
{
if (verbose > 0)
{
fprintf (stderr, "bt_nv_cmd failed to get BD_ADDR from NV, code %d\n", persistcmd_result);
}
static nv_item_type my_nv_item; /* nv_bd_addr_type */
static nv_stat_enum_type cmd_result;
if (nv_available)
{
cmd_result = nv_cmd_remote(NV_READ_F, NV_BD_ADDR_I, &my_nv_item);
}
else
{
cmd_result = NV_FAIL_S;
}
if (NV_DONE_S != cmd_result)
{
if (verbose > 0)
{
fprintf (stderr, "nv_cmd_remote failed to get BD_ADDR from NV, code %d\n", cmd_result);
}
}
else
{
/* copy bytes */
BD_addr[5] = my_nv_item.bd_addr.bd_addr[5];
BD_addr[4] = my_nv_item.bd_addr.bd_addr[4];
BD_addr[3] = my_nv_item.bd_addr.bd_addr[3];
BD_addr[2] = my_nv_item.bd_addr.bd_addr[2];
BD_addr[1] = my_nv_item.bd_addr.bd_addr[1];
BD_addr[0] = my_nv_item.bd_addr.bd_addr[0];
bd_set = TRUE;
}
}
else
{
/* copy bytes */
BD_addr[5] = my_nv_persist_item.bd_addr[5];
BD_addr[4] = my_nv_persist_item.bd_addr[4];
BD_addr[3] = my_nv_persist_item.bd_addr[3];
BD_addr[2] = my_nv_persist_item.bd_addr[2];
BD_addr[1] = my_nv_persist_item.bd_addr[1];
BD_addr[0] = my_nv_persist_item.bd_addr[0];
bd_set = TRUE;
}
#else
#if defined(BT_QSOC_GET_ITEMS_FROM_NV)
static nv_item_type my_nv_persist_item; /* nv_bd_addr_type */
static nv_stat_enum_type persistcmd_result;
if (nv_available)
{
persistcmd_result = nv_cmd_remote(NV_READ_F, NV_BD_ADDR_I, &my_nv_persist_item);
}
else
{
persistcmd_result = NV_FAIL_S;
}
if (NV_DONE_S != persistcmd_result)
{
if (verbose > 0)
{
fprintf (stderr, "nv_cmd_remote failed to get BD_ADDR from NV, code %d\n", persistcmd_result);
}
}
else
{
/* copy bytes */
BD_addr[5] = my_nv_persist_item.bd_addr.bd_addr[5];
BD_addr[4] = my_nv_persist_item.bd_addr.bd_addr[4];
BD_addr[3] = my_nv_persist_item.bd_addr.bd_addr[3];
BD_addr[2] = my_nv_persist_item.bd_addr.bd_addr[2];
BD_addr[1] = my_nv_persist_item.bd_addr.bd_addr[1];
BD_addr[0] = my_nv_persist_item.bd_addr.bd_addr[0];
bd_set = TRUE;
}
#elif defined(BT_QSOC_GET_ITEMS_FROM_PERSIST)
static nv_persist_item_type my_nv_persist_item; /* nv_bd_addr_type */
static nv_persist_stat_enum_type persistcmd_result;
persistcmd_result = (nv_persist_stat_enum_type)bt_nv_cmd(NV_PERSIST_READ_F, NV_PERSIST_BD_ADDR_I, &my_nv_persist_item);
if (NV_PERSIST_SUCCESS != persistcmd_result)
{
if (verbose > 0)
{
fprintf (stderr, "bt_nv_cmd failed to get BD_ADDR from NV, code %d\n", cmd_result);
}
}
else
{
/* copy bytes */
BD_addr[5] = my_nv_persist_item.bd_addr[5];
BD_addr[4] = my_nv_persist_item.bd_addr[4];
BD_addr[3] = my_nv_persist_item.bd_addr[3];
BD_addr[2] = my_nv_persist_item.bd_addr[2];
BD_addr[1] = my_nv_persist_item.bd_addr[1];
BD_addr[0] = my_nv_persist_item.bd_addr[0];
bd_set = TRUE;
}
#else /* not BT_QSOC_GET_ITEMS_FROM_NV - running on PC not MSM */
/* then set the non-manufacturer part to random */
BTHCI_QCOMM_TRACE ("bt_hci_qcomm_pfal_get_bdaddress: BD_ADDR not avialable from NV.\n");
#endif /* not on PC */
#endif
}
if (!bd_set)
{
int seed;
struct timespec sTime;
if (-1 == clock_gettime (CLOCK_REALTIME, &sTime))
{
perror ("clock_gettime\n" );
return (FALSE);
}
seed = sTime.tv_nsec;
srand ((unsigned int) seed);
BD_addr[0] = (rand() & 0x0FF00000) >> 20;
BD_addr[1] = (rand() & 0x0FF00000) >> 20;
BD_addr[2] = (rand() & 0x0FF00000) >> 20;
}
memcpy( pCmdBuffer, BD_addr, sizeof(BD_addr) );
if (verbose > 2)
{
fprintf (stderr, "get_bdaddr: after: %02x.%02x.%02x.%02x.%02x.%02x\n",
BD_addr[0], BD_addr[1], BD_addr[2], BD_addr[3], BD_addr[4], BD_addr[5]);
}
return TRUE; /* for now -- need error checking? */
}
BT_QSOC_GET_ITEMS_FROM_PERSIST_THEN_NV不仅控制蓝牙地址,在bt_hci_qcomm_pfal_is_refclock_19P2MHz和bt_hci_qcomm_pfal_is_clocksharing_enabled这两个函数中也有用到。不过不用担心这个注释会影响蓝牙的时钟读取,时钟信息都是写死在芯片里,不用从NV或者配置文件获得。