android蓝牙串口初始化过程

现在选用的方法蓝牙芯片使用串口与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

https://blog.csdn.net/newtonnl/article/details/7728589

猜你喜欢

转载自blog.csdn.net/zmk0810612124/article/details/82494136
今日推荐