现在选用的方法蓝牙芯片使用串口与CPU进行数据交互。
蓝牙串口初始化在蓝牙enable过程中初始化的。
1: system\bt\btif\src\Bluetooth.c
static int enable(bool start_restricted){
....
stack_manager_get_interface()->start_up_stack_async();
....
}
2: system\bt\btif\src\Stack_manager.c
static void event_start_up_stack(UNUSED_ATTR void *context) {
....
bte_main_enable();
....
}
3: system\bt\main\bte_main.c
void bte_main_enable()
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
// 协议探测开启,可以在配置文件中开启, bt_stack.conf
module_start_up(get_module(BTSNOOP_MODULE));
module_start_up(get_module(HCI_MODULE));
BTU_StartUp();
}
4: module_start_up(get_module(HCI_MODULE)); 转化后等于调用 system\bt\hci\src\hci_layer.c文件的start_up函数
static future_t *start_up(void) {
...
hal->init(&hal_callbacks, thread);
thread_post(thread, event_finish_startup, NULL);
...
}
5 system\bt\hci\src\hci_layer.c
static void event_finish_startup(UNUSED_ATTR void *context) {
LOG_INFO(LOG_TAG, "%s", __func__);
hal->open();
vendor->send_async_command(VENDOR_CONFIGURE_FIRMWARE, NULL);
}
查看代码hci_hal_mct.c hal_open函
static bool hal_open() {
LOG_INFO(LOG_TAG, "%s", __func__);
// TODO(zachoverflow): close if already open / or don't reopen (maybe at the hci layer level)
// 执行hardware层的 open操作, 将open后的句柄传给uart_fds
int number_of_ports = vendor->send_command(VENDOR_OPEN_USERIAL, &uart_fds);
if (number_of_ports != 2 && number_of_ports != 4) {
LOG_ERROR(LOG_TAG, "%s opened the wrong number of ports: got %d, expected 2 or 4.", __func__, number_of_ports);
goto error;
}
LOG_INFO(LOG_TAG, "%s got uart fds: CMD=%d, EVT=%d, ACL_OUT=%d, ACL_IN=%d",
__func__, uart_fds[CH_CMD], uart_fds[CH_EVT], uart_fds[CH_ACL_OUT], uart_fds[CH_ACL_IN]);
if (uart_fds[CH_CMD] == INVALID_FD) {
LOG_ERROR(LOG_TAG, "%s unable to open the command uart serial port.", __func__);
goto error;
}
if (uart_fds[CH_EVT] == INVALID_FD) {
LOG_ERROR(LOG_TAG, "%s unable to open the event uart serial port.", __func__);
goto error;
}
if (uart_fds[CH_ACL_OUT] == INVALID_FD) {
LOG_ERROR(LOG_TAG, "%s unable to open the acl-out uart serial port.", __func__);
goto error;
}
if (uart_fds[CH_ACL_IN] == INVALID_FD) {
LOG_ERROR(LOG_TAG, "%s unable to open the acl-in uart serial port.", __func__);
goto error;
}
#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
event_stream = hci_reader_new(uart_fds[CH_EVT], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
thread, event_event_stream_has_bytes);
if (!event_stream) {
LOG_ERROR("%s unable to create hci reader for the event uart serial port.", __func__);
goto error;
}
acl_stream = hci_reader_new(uart_fds[CH_ACL_IN], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
thread, event_acl_stream_has_bytes);
if (!acl_stream) {
LOG_ERROR("%s unable to create hci reader for the acl-in uart serial port.", __func__);
goto error;
}
#else
event_stream = eager_reader_new(uart_fds[CH_EVT], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
if (!event_stream) {
LOG_ERROR(LOG_TAG, "%s unable to create eager reader for the event uart serial port.", __func__);
goto error;
}
acl_stream = eager_reader_new(uart_fds[CH_ACL_IN], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
if (!acl_stream) {
LOG_ERROR(LOG_TAG, "%s unable to create eager reader for the acl-in uart serial port.", __func__);
goto error;
}
eager_reader_register(event_stream, thread_get_reactor(thread), event_event_stream_has_bytes, NULL);
eager_reader_register(acl_stream, thread_get_reactor(thread), event_acl_stream_has_bytes, NULL);
#endif
// Raise thread priorities to keep up with audio
thread_set_priority(thread, HCI_THREAD_PRIORITY);
return true;
error:;
interface.close();
return false;
}
vendor->send_command(VENDOR_OPEN_USERIAL, &uart_fds);
调用 libbt-vendor.so动态库中的op函数
static int op(bt_vendor_opcode_t opcode, void *param)
{
int ret;
ALOGV("++%s", __FUNCTION__);
pthread_mutex_lock(&q_lock);
if (!q) {
ALOGE("op called with NULL context");
ret = -BT_STATUS_INVAL;
goto out;
}
ret = __op(opcode, param);
out:
pthread_mutex_unlock(&q_lock);
ALOGV("--%s ret = 0x%x", __FUNCTION__, ret);
return ret;
}
/* flavor of op without locks */
static int __op(bt_vendor_opcode_t opcode, void *param)
{
int retval = BT_STATUS_SUCCESS;
int nCnt = 0;
int nState = -1;
bool is_ant_req = false;
bool is_fm_req = false;
char wipower_status[PROPERTY_VALUE_MAX];
char emb_wp_mode[PROPERTY_VALUE_MAX];
char bt_version[PROPERTY_VALUE_MAX];
char lpm_config[PROPERTY_VALUE_MAX];
bool ignore_boot_prop = TRUE;
#ifdef READ_BT_ADDR_FROM_PROP
int i = 0;
static char bd_addr[PROPERTY_VALUE_MAX];
uint8_t local_bd_addr_from_prop[6];
char* tok;
#endif
bool skip_init = true;
int opcode_init = opcode;
ALOGV("++%s opcode %d", __FUNCTION__, opcode);
switch(opcode_init)
{
#ifdef FM_OVER_UART
case FM_VND_OP_POWER_CTRL:
{
is_fm_req = true;
if (is_soc_initialized()) {
// add any FM specific actions if needed in future
break;
}
}
#endif
case BT_VND_OP_POWER_CTRL:
{
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
nState = *(int *) param;
ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
(nState == BT_VND_PWR_ON)? "On" : "Off" );
switch(q->soc_type)
{
case BT_SOC_DEFAULT:
if (readTrpState())
{
ALOGI("bt-vendor : resetting BT status");
hw_config(BT_VND_PWR_OFF);
}
retval = hw_config(nState);
if(nState == BT_VND_PWR_ON
&& retval == 0
&& is_hw_ready() == TRUE){
retval = 0;
}
else {
retval = -1;
}
break;
case BT_SOC_ROME:
case BT_SOC_AR3K:
case BT_SOC_CHEROKEE:
/* BT Chipset Power Control through Device Tree Node */
retval = bt_powerup(nState);
default:
break;
}
}
break;
case BT_VND_OP_FW_CFG: {
/* call hciattach to initalize the stack */
if (q->soc_type == BT_SOC_ROME) {
if (is_soc_initialized()) {
ALOGI("Bluetooth FW and transport layer are initialized");
q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
} else {
ALOGE("bt_vendor_cbacks is null or SoC not initialized");
ALOGE("Error : hci, smd initialization Error");
retval = -1;
}
} else {
ALOGI("Bluetooth FW and transport layer are initialized");
q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
}
}
break;
case BT_VND_OP_SCO_CFG:
q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
break;
#ifdef ENABLE_ANT
case BT_VND_OP_ANT_USERIAL_OPEN:
ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
is_ant_req = true;
goto userial_open;
#endif
#ifdef FM_OVER_UART
case BT_VND_OP_FM_USERIAL_OPEN:
ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
is_fm_req = true;
goto userial_open;
#endif
userial_open:
case BT_VND_OP_USERIAL_OPEN:
{
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
int (*fd_array)[] = (int (*)[]) param;
int idx, fd = -1, fd_filter = -1;
ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
switch(q->soc_type)
{
case BT_SOC_DEFAULT:
{
if(bt_hci_init_transport(q->fd) != -1){
int (*fd_array)[] = (int (*) []) param;
(*fd_array)[CH_CMD] = q->fd[0];
(*fd_array)[CH_EVT] = q->fd[0];
(*fd_array)[CH_ACL_OUT] = q->fd[1];
(*fd_array)[CH_ACL_IN] = q->fd[1];
}
else {
retval = -1;
break;
}
retval = 2;
}
break;
case BT_SOC_AR3K:
{
fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
if (fd != -1) {
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
retval = 1;
}
else {
retval = -1;
break;
}
/* Vendor Specific Process should happened during userial_open process
After userial_open, rx read thread is running immediately,
so it will affect VS event read process.
*/
if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
retval = -1;
}
break;
case BT_SOC_ROME:
{
wait_for_patch_download(is_ant_req);
property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
if (!is_soc_initialized()) {
char* dlnd_inprog = is_ant_req ? "ant" : "bt";
if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
}
fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
if (fd < 0) {
ALOGE("userial_vendor_open returns err");
retval = -1;
break;
}
/* Clock on */
userial_clock_operation(fd, USERIAL_OP_CLK_ON);
if(strcmp(emb_wp_mode, "true") == 0) {
property_get("ro.bluetooth.wipower", wipower_status, false);
if(strcmp(wipower_status, "true") == 0) {
check_embedded_mode(fd);
} else {
ALOGI("Wipower not enabled");
}
}
ALOGV("rome_soc_init is started");
property_set("wc_transport.soc_initialized", "0");
#ifdef READ_BT_ADDR_FROM_PROP
/*Give priority to read BD address from boot property*/
ignore_boot_prop = FALSE;
if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
ALOGV("BD address read from Boot property: %s\n", bd_addr);
tok = strtok(bd_addr, ":");
while (tok != NULL) {
ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
if (i>=6) {
ALOGE("bd property of invalid length");
ignore_boot_prop = TRUE;
break;
}
if (i == 6 && !ignore_boot_prop) {
ALOGV("Valid BD address read from prop");
memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
ignore_boot_prop = FALSE;
} else {
ALOGE("There are not enough tokens in BD addr");
ignore_boot_prop = TRUE;
break;
}
local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
tok = strtok(NULL, ":");
i++;
}
if (i == 6 && !ignore_boot_prop) {
ALOGV("Valid BD address read from prop");
memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
ignore_boot_prop = FALSE;
} else {
ALOGE("There are not enough tokens in BD addr");
ignore_boot_prop = TRUE;
}
}
else {
ALOGE("BD address boot property not set");
ignore_boot_prop = TRUE;
}
#endif //READ_BT_ADDR_FROM_PROP
/* Always read BD address from NV file */
if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
{
/* Since the BD address is configured in boot time We should not be here */
ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
}
if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
retval = -1;
} else {
ALOGV("rome_soc_init is completed");
property_set("wc_transport.soc_initialized", "1");
skip_init = false;
}
}
if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
ALOGE("%s: Failed to set property", __FUNCTION__);
}
property_set("wc_transport.clean_up","0");
if (retval != -1) {
retval = start_hci_filter();
if (retval < 0) {
ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
} else {
#ifdef ENABLE_ANT
if (is_ant_req) {
ALOGI("%s: connect to ant channel", __func__);
q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
}
else
#endif
{
ALOGI("%s: connect to bt channel", __func__);
vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
}
if (fd_filter != -1) {
ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
__func__, fd_filter, is_ant_req,is_fm_req);
if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
if (chipset_ver >= ROME_VER_3_0) {
/* get rome supported feature request */
ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
rome_get_addon_feature_list(fd_filter);
}
}
if (!skip_init) {
/*Skip if already sent*/
enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
skip_init = true;
}
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd_filter;
retval = 1;
}
else {
if (is_ant_req)
ALOGE("Unable to connect to ANT Server Socket!!!");
else
ALOGE("Unable to connect to BT Server Socket!!!");
retval = -1;
}
}
} else {
if (q->soc_type == BT_SOC_ROME)
ALOGE("Failed to initialize ROME Controller!!!");
}
if (fd >= 0) {
userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
/*Close the UART port*/
close(fd);
}
}
break;
case BT_SOC_CHEROKEE:
{
property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
retval = start_hci_filter();
if (retval < 0) {
ALOGE("WCNSS_FILTER wouldn't have started in time\n");
} else {
#ifdef ENABLE_ANT
if (is_ant_req) {
ALOGI("%s: connect to ant channel", __func__);
q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
}
else
#endif
#ifdef FM_OVER_UART
if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
ALOGI("%s: connect to fm channel", __func__);
q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
}
else
#endif
{
ALOGI("%s: connect to bt channel", __func__);
vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
}
if (fd_filter != -1) {
ALOGV("%s: received the socket fd: %d \n",
__func__, fd_filter);
for (idx=0; idx < CH_MAX; idx++) {
(*fd_array)[idx] = fd_filter;
}
retval = 1;
}
else {
#ifdef ENABLE_ANT
if (is_ant_req)
ALOGE("Unable to connect to ANT Server Socket!!!");
else
#endif
#ifdef FM_OVER_UART
if (is_fm_req)
ALOGE("Unable to connect to FM Server Socket!!!");
else
#endif
ALOGE("Unable to connect to BT Server Socket!!!");
retval = -1;
}
}
}
break;
default:
ALOGE("Unknown soc_type: 0x%x", q->soc_type);
break;
}
} break;
#ifdef ENABLE_ANT
case BT_VND_OP_ANT_USERIAL_CLOSE:
{
ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
property_set("wc_transport.clean_up","1");
if (q->ant_fd != -1) {
ALOGE("closing ant_fd");
close(q->ant_fd);
q->ant_fd = -1;
}
}
break;
#endif
#ifdef FM_OVER_UART
case BT_VND_OP_FM_USERIAL_CLOSE:
{
ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
property_set("wc_transport.clean_up","1");
if (q->fm_fd != -1) {
ALOGE("closing fm_fd");
close(q->fm_fd);
q->fm_fd = -1;
}
break;
}
#endif
case BT_VND_OP_USERIAL_CLOSE:
{
ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
switch(q->soc_type)
{
case BT_SOC_DEFAULT:
bt_hci_deinit_transport(q->fd);
break;
case BT_SOC_ROME:
case BT_SOC_AR3K:
case BT_SOC_CHEROKEE:
{
property_set("wc_transport.clean_up","1");
userial_vendor_close();
break;
}
default:
ALOGE("Unknown soc_type: 0x%x", q->soc_type);
break;
}
}
break;
case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
{
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
uint32_t *timeout_ms = (uint32_t *) param;
*timeout_ms = 1000;
}
break;
case BT_VND_OP_LPM_SET_MODE:
if (q->soc_type == BT_SOC_AR3K) {
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
uint8_t *mode = (uint8_t *) param;
if (*mode) {
lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
}
else {
lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
}
q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
} else {
int lpm_result = BT_VND_OP_RESULT_SUCCESS;
property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
__func__, lpm_config);
if (!strcmp(lpm_config, "all")) {
// respond with success since we want to hold wake lock through LPM
lpm_result = BT_VND_OP_RESULT_SUCCESS;
}
else {
lpm_result = BT_VND_OP_RESULT_FAIL;
}
q->cb->lpm_cb(lpm_result);
}
break;
case BT_VND_OP_LPM_WAKE_SET_STATE: {
switch(q->soc_type) {
case BT_SOC_CHEROKEE:
case BT_SOC_ROME: {
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
uint8_t *state = (uint8_t *) param;
uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
if (wake_assert == 0)
ALOGV("ASSERT: Waking up BT-Device");
else if (wake_assert == 1)
ALOGV("DEASSERT: Allowing BT-Device to Sleep");
#ifdef QCOM_BT_SIBS_ENABLE
ALOGI("Invoking HCI H4 callback function");
q->cb->lpm_set_state_cb(wake_assert);
#endif
}
break;
case BT_SOC_AR3K: {
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
uint8_t *state = (uint8_t *) param;
uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
UPIO_ASSERT : UPIO_DEASSERT;
lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
}
case BT_SOC_DEFAULT:
break;
default:
ALOGE("Unknown soc_type: 0x%x", q->soc_type);
break;
}
}
break;
case BT_VND_OP_EPILOG: {
#if (HW_NEED_END_WITH_HCI_RESET == FALSE)
q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
#else
switch(q->soc_type)
{
case BT_SOC_CHEROKEE:
case BT_SOC_ROME:
{
char value[PROPERTY_VALUE_MAX] = {'\0'};
property_get("wc_transport.hci_filter_status", value, "0");
if(is_soc_initialized()&& (strcmp(value,"1") == 0))
{
__hw_epilog_process();
}
else
{
q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
}
}
break;
default:
__hw_epilog_process();
break;
}
#endif
}
break;
case BT_VND_OP_GET_LINESPEED:
{
retval = -1;
if(!is_soc_initialized()) {
ALOGE("BT_VND_OP_GET_LINESPEED: error"
" - transport driver not initialized!");
break;
}
switch(q->soc_type)
{
case BT_SOC_CHEROKEE:
retval = 3200000;
break;
case BT_SOC_ROME:
retval = 3000000;
break;
default:
retval = userial_vendor_get_baud();
break;
}
break;
}
}
out:
ALOGV("--%s", __FUNCTION__);
return retval;
}
蓝牙使能过程中调用 init
/*****************************************************************************
**
** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
**
*****************************************************************************/
static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
{
char prop[PROPERTY_VALUE_MAX] = {0};
struct bt_qcom_struct *temp = NULL;
int ret = BT_STATUS_SUCCESS, i;
ALOGI("++%s", __FUNCTION__);
if (!cb || !bdaddr) {
ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr);
ret = -BT_STATUS_INVAL;
goto out;
}
temp = (struct bt_qcom_struct *) malloc(sizeof(*q));
if (!temp) {
ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno);
ret = -BT_STATUS_NOMEM;
goto out;
}
memset(temp, 0, sizeof(*temp));
temp->rfkill_id = -1;
temp->enable_extldo = FALSE;
temp->cb = cb;
temp->ant_fd = -1;
// 获取蓝牙芯片类型 蓝牙的相关属性的设置在 system/etc/init/init.qcom.bt.sh 脚本中
// qcom.bluetooth.soc 属性没有被设置 则 temp->soc_type = BT_SOC_DEFAULT;
temp->soc_type = get_bt_soc_type();
soc_init(temp->soc_type);
le2bd(bdaddr, temp->bdaddr);
print_bdaddr(temp->bdaddr);
snprintf(prop, sizeof(prop), "%02x:%02x:%02x:%02x:%02x:%02x",
temp->bdaddr[0], temp->bdaddr[1], temp->bdaddr[2],
temp->bdaddr[3], temp->bdaddr[4], temp->bdaddr[5]);
ret = property_set("wc_transport.stack_bdaddr", prop);
if (ret < 0) {
ALOGE("Failed to set wc_transport.stack_bdaddr prop, ret = %d", ret);
ret = -BT_STATUS_PROP_FAILURE;
goto out;
}
/* TODO: Move these fields inside bt_qcom context */
#ifdef WIFI_BT_STATUS_SYNC
isInit = 1;
#endif /* WIFI_BT_STATUS_SYNC */
/* Everything successful */
q = temp;
return ret;
out:
if (temp)
free(temp);
ALOGI("--%s ret %d", __FUNCTION__, ret);
return ret;
}
经过init 后 q->soc_type = BT_SOC_DEFAULT;执行case BT_SOC_DEFAULT 分支;
static int __op(bt_vendor_opcode_t opcode, void *param)
{
.....
switch(opcode_init)
{
.....
case BT_VND_OP_USERIAL_OPEN:
{
if (!param) {
ALOGE("opcode = %d: param is null", opcode_init);
break;
}
int (*fd_array)[] = (int (*)[]) param;
int idx, fd = -1, fd_filter = -1;
ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
switch(q->soc_type)
{
case BT_SOC_DEFAULT:
{
if(bt_hci_init_transport(q->fd) != -1){
int (*fd_array)[] = (int (*) []) param;
(*fd_array)[CH_CMD] = q->fd[0];
(*fd_array)[CH_EVT] = q->fd[0];
(*fd_array)[CH_ACL_OUT] = q->fd[1];
(*fd_array)[CH_ACL_IN] = q->fd[1];
}
else {
retval = -1;
break;
}
retval = 2;
}
break;
}
...
}
bt_hci_init_transport函数
int bt_hci_init_transport(int *pFd)
{
int i = 0;
int fd;
for(i=0; i < NUM_OF_DEVS; i++){
fd = bt_hci_init_transport_id(i);
if(fd < 0 ){
return -1;
}
pFd[i] = fd;
}
return 0;
}
#define NUM_OF_DEVS 2
static char *s_pszDevSmd[] = {
"/dev/smd3",
"/dev/smd2"
};
/*****************************************************************************
** Functions
*****************************************************************************/
int bt_hci_init_transport_id (int chId )
{
struct termios term;
int fd = -1;
int retry = 0;
char ssrvalue[92]= {'\0'};
ssrvalue[0] = '0';
if(chId >= 2 || chId <0)
return -1;
fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
while ((-1 == fd) && (retry < 7)) {
ALOGE("init_transport: Cannot open %s: %s\n. Retry after 2 seconds",
s_pszDevSmd[chId], strerror(errno));
usleep(2000000);
fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
retry++;
}
if (-1 == fd)
{
ALOGE("init_transport: Cannot open %s: %s\n",
s_pszDevSmd[chId], strerror(errno));
return -1;
}
/* Sleep (0.5sec) added giving time for the smd port to be successfully
opened internally. Currently successful return from open doesn't
ensure the smd port is successfully opened.
TODO: Following sleep to be removed once SMD port is successfully
opened immediately on return from the aforementioned open call */
property_get("bluetooth.isSSR", ssrvalue, "");
if(ssrvalue[0] == '1')
{
/*reset the SSR flag */
if(chId == 1)
{
if(property_set("bluetooth.isSSR", "0") < 0)
{
ALOGE("SSR: hci_smd.c:SSR case : error in setting up property new\n ");
}
else
{
ALOGE("SSR: hci_smd.c:SSR case : Reset the SSr Flag new\n ");
}
}
ALOGE("hci_smd.c:IN SSR sleep for 500 msec New \n");
usleep(500000);
}
if (tcflush(fd, TCIOFLUSH) < 0)
{
ALOGE("init_uart: Cannot flush %s\n", s_pszDevSmd[chId]);
close(fd);
return -1;
}
if (tcgetattr(fd, &term) < 0)
{
ALOGE("init_uart: Error while getting attributes\n");
close(fd);
return -1;
}
cfmakeraw(&term);
/* JN: Do I need to make flow control configurable, since 4020 cannot
* disable it?
*/
term.c_cflag |= (CRTSCTS | CLOCAL);
if (tcsetattr(fd, TCSANOW, &term) < 0)
{
ALOGE("init_uart: Error while getting attributes\n");
close(fd);
return -1;
}
ALOGI("Done intiailizing UART\n");
return fd;
}
/dev/smd2 和 /dev/smd3 为 MSM平台AP/CP通信机制, 通过共享内存进行数据通信。
https://blog.csdn.net/loongembedded/article/details/51762918