zoukankan      html  css  js  c++  java
  • Android BlueDroid(三):BlueDroid蓝牙开启过程enable

    关键词:bluedroid  enableNative BTIF_TASK  BTU_TASK bt_hc_work_thread set_power  preload GKI
    作者:xubin341719(欢迎转载。请注明作者,请尊重版权,谢谢!)
    画图工具:Edraw Maindmap
    欢迎指正错误。共同学习、共同进步。。


    一、enableNative函数的的实现
    (1)、初始化BTE;
    (2)、创建BTIU_TASK。
    (3)、初始化HCI、串口相关。启动HCI工作主线程:bt_hc_callback,芯片上电、RF參数初始化;

    1、应用部分对enableNative函数的调用
    packagesappsBluetoothsrccomandroidluetoothtserviceAdapterState.java

            public boolean processMessage(Message msg) {
                boolean isTurningOn= isTurningOn();
                boolean isTurningOff = isTurningOff();
    ………………
                    case STARTED:   {
                        if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
                        //Remove start timeout
                        removeMessages(START_TIMEOUT);
    
                        //Enable
                        boolean ret = adapterService.enableNative();//调用Native函数;
                        if (!ret) {
                            Log.e(TAG, "Error while turning Bluetooth On");
                            notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                            transitionTo(mOffState);
                        } else {
                            sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
                        }
                    }
                        break;
    ………………
    }
    /*package*/ native boolean enableNative();
    

    2、JNI函数的实现
    packagesappsBluetoothjnicom_android_bluetooth_btservice_AdapterService.cpp

    static jboolean enableNative(JNIEnv* env, jobject obj) {
        ALOGV("%s:",__FUNCTION__);
    
        jboolean result = JNI_FALSE;
        if (!sBluetoothInterface) return result;
    
        int ret = sBluetoothInterface->enable();//JNI部分Native函数调用C语言中的函数实现;
        result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;//推断是打开还是关闭状态。
        return result;
    }
    

    3、C函数中对enable函数的实现。这部分和init的流程一样
    externalluetoothluedroidtifsrcluetooth.c 

    static int enable( void )
    {
        ALOGI("enable");
    
        /* sanity check */
        if (interface_ready() == FALSE)
            return BT_STATUS_NOT_READY;
    
        return btif_enable_bluetooth();//enable汗的详细实现;
    }
    

    4、btif_enable_bluetooth函数的实现,Performschip power on and kickstarts OS scheduler
    externalluetoothluedroidtifsrctif_core.c|

    bt_status_t btif_enable_bluetooth(void)
    {
        BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");
    
        if (btif_core_state != BTIF_CORE_STATE_DISABLED)
        {
            ALOGD("not disabled
    ");
            return BT_STATUS_DONE;
        }
    
        btif_core_state = BTIF_CORE_STATE_ENABLING;//设定为正在打开状态;
    
        /* Create the GKI tasks and run them */
        bte_main_enable();//BTE部分的enable
    
        return BT_STATUS_SUCCESS;
    }
    

    5、bte_main_enable函数。这个函数是enable函数的详细实现
    BTEMAIN API - Creates all the BTE tasks. Should be called  part of the Bluetooth stack enable sequence
    iexternalluetoothluedroidmainte_main.c

    void bte_main_enable()
    {
        int ret = -1;
    
        APPL_TRACE_DEBUG1("%s", __FUNCTION__);
    
        /* Initialize BTE control block */
        BTE_Init();//(1)、初始化BTE控制块。
    
        lpm_enabled = FALSE;
    //(2)、创建BTU_TASK 进程
        GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
                        (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
                        sizeof(bte_btu_stack));
        bte_hci_enable();//(3)、打开HCI和厂商模块控制。
        GKI_run(0);
        ret = bte_snoop_create_task();//BT  log 进程创建。
        if(ret != 0)
            APPL_TRACE_DEBUG1("bte_snoop_create_task fail %d",ret);
    }
    

    (1)、初始化BTE控制块

    BTE_Init();
    BTU:Bluetooth Upper Layer, The Broadcom implementations of L2CAP RFCOMM, SDP and the BTIf run as one GKI task. The btu_task switches between them.
    

    (2)、创建BTU_TASK 进程

        GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
                        (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
                        sizeof(bte_btu_stack));
    

    externalluetoothluedroidstacktutu_task.c
    This is the main task of the Bluetooth Upper Layers unit. It sits in aloop waiting for messages, and dispatches them to the appropiate handlers.
    btu_task这个函数很重要,大部分event的处理都通过它来完毕;

    BTU_API UINT32 btu_task (UINT32 param)
    {
    …………
        /* Initialize the mandatory core stack control blocks
           (BTU, BTM, L2CAP, and SDP)
         */
        btu_init_core();//1)、初始化核心control block,比方BTU, BTM, L2CAP, and SDP
    
        /* Initialize any optional stack components */
        BTE_InitStack();//2)、初始化BTE控制块,比方RFCOMM, DUN, SPP, HSP2, HFP, OBX, BIP
    
    #if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
        bta_sys_init();//3)、初始化BTA
    #endif
    …………
        /* Wait for, and process, events */
        for (;;)//进入循环状态
        {
            event = GKI_wait (0xFFFF, 0);//4)、获取相应EVENT;
    
            if (event & TASK_MBOX_0_EVT_MASK)
            {…………}
            if (event & TIMER_0_EVT_MASK)
            {…………}
    
    #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
            if (event & TIMER_2_EVT_MASK)
            {
                btu_process_quick_timer_evt();
            }
    #endif
    #if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
            if (event & TASK_MBOX_2_EVT_MASK)//这个状态比較重要
            {
                while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL)
                {
                    bta_sys_event(p_msg);//接收到的event在这里解析,然后运行BTU中的函数。
                }
            }
    
            if (event & TIMER_1_EVT_MASK)
            {
                bta_sys_timer_update();
            }
    #endif
    
            if (event & EVENT_MASK(APPL_EVT_7))
                break;
        }
        return(0);
    }
    

    (3)、bte_hci_enableEnable HCI & Vendor modules,打开HCI和厂商模块
    bte_hci_enable的实现流程例如以下图所看到的

    externalluetoothluedroidmainte_main.c

    static void bte_hci_enable(void)
    {
        APPL_TRACE_DEBUG1("%s", __FUNCTION__);
    
        preload_start_wait_timer();
    
        if (bt_hc_if)
        {
            int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);//初始化串口,HCI_H4、HCI工作线等;
    ………………
            bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);//给相应模块上电;
            bt_hc_if->preload(NULL);//下载相关配置參数;
            if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
                bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);
        }
    }
    

    6、相对于HCI接口库接口函数。这部分跟蓝牙芯片相关
    externalluetoothluedroidhcisrct_hci_bdroid.c

    static const bt_hc_interface_t bluetoothHCLibInterface = {
        sizeof(bt_hc_interface_t),
        init,//HCLib中的init;
        set_power,// HCLib中的power设定;
        lpm,
        preload, HCLib中的preload;
        postload,
        transmit_buf,
        set_rxflow,
        logging,
        cleanup
    };
    

    7、bluetoothHCLibInterface 中INIT实现过程
    完毕H4初始化、串口驱动初始化、LMP初始化、启动bt_hc_worker_thread主线程。

    (1)、init函数实现
    externalluetoothluedroidhcisrct_hci_bdroid.c

    static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
    {
    …………
        /* store reference to user callbacks */
        bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
    
        init_vnd_if(local_bdaddr);//完毕厂商模块的接口函数;    
    userial_init();//串口初始化
        lpm_init();//LPM初始化
    …………
    extern tHCI_IF hci_h4_func_table;// 应用HCI H4接口回调
        p_hci_if = &hci_h4_func_table;
        p_hci_if->init();//调用hci_h4_func_table的init办法,初始化H4模块
        utils_queue_init(&tx_q); //初始化发送队列
    …………
        if (pthread_create(&hc_cb.worker_thread, &thread_attr, 
                           bt_hc_worker_thread, NULL) != 0) //起工作线程
        {
            ALOGE("pthread_create failed!");
            lib_running = 0;
            return BT_HC_STATUS_FAIL;
        }
    …………
    }
    

    1)、bt_hc_callbacks_t*bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; //保存回调。
    2)、init_vnd_if(local_bdaddr);//调用厂商库里面的bt_vendor_interface_t*接口,初始化蓝牙设备;
    3)、p_hci_if =&hci_h4_func_table; //应用HCI H4接口回调;
    4)、p_hci_if->init(); //调用hci_h4_func_table的init办法,初始化H4模块;
    5)、userial_init();//初始化uart数据布局;
    6)、lpm_init();//初始化低功耗模块。调用bt_vendor_interface_t的op接口。
    7)、utils_queue_init(&tx_q); //初始化发送队列;
    8)、pthread_create(&hc_cb.worker_thread。&thread_attr, bt_hc_worker_thread, NULL) != 0) //起工作线程。

    (2)、init_vnd_if 的实现过程
    idh.codeexternalluetoothluedroidhcisrct_hw.c


    void init_vnd_if(unsigned char *local_bdaddr)
    {
        void *dlhandle;
    
    dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);// 1)、dlopen()函数以指定模式打开指定的动态链接库文件。并返回一个句柄给dlsym()的调用进程。
    ………………
        bt_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");//2)、返回符号BLUETOOTH_VENDOR_LIB_INTERFACE,所相应的地址。
    …………
        bt_vnd_if->init(&vnd_callbacks, local_bdaddr);//3)、调用返回地址结构体中的init函数;
    }
    

    1)、dlopen()
    函数以指定模式打开指定的动态链接库文件。并返回一个句柄给dlsym()的调用进程。


    dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);
    void * dlopen( const char * pathname, int mode);
    mode是打开方式,其值有多个,不同操作系统上实现的功能有所不同,在linux下,按功能可分为三类:
    

    解析方式

    RTLD_LAZY:

    在dlopen返回前。对于动态库中的没有定义的符号不运行解析(仅仅对函数引用有效。对于变量引用总是马上解析)。

    RTLD_NOW:

    须要在dlopen返回前,解析出全部没有定义符号,假设解析不出来。在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......

    作用范围,可与解析方式通过“|”组合使用。

    RTLD_GLOBAL:

    动态库中定义的符号可被其后打开的其它库重定位。

    RTLD_LOCAL:

    与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位。

    假设没有指明是RTLD_GLOBAL还是RTLD_LOCAL,则缺省为RTLD_LOCAL。

    作用方式

    RTLD_NODELETE:

    在dlclose()期间不卸载库,而且在以后使用dlopen()又一次载入库时不初始化库中的静态变量。

    这个flag不是POSIX-2001标准。

    RTLD_NOLOAD:

    不载入库。可用于測试库是否已载入(dlopen()返回NULL说明未载入,否则说明已载入),也可用于改变已载入库的flag,如:先前载入库的flag为RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。

    这个flag不是POSIX-2001标准。

    RTLD_DEEPBIND:

    在搜索全局符号前先搜索库内的符号。避免同名符号的冲突。这个flag不是POSIX-2001标准。

    2)、dlsym依据动态链接库操作句柄与符号,返回符号相应的地址
    返回符号BLUETOOTH_VENDOR_LIB_INTERFACE,所相应的地址,也就是:

    const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
        sizeof(bt_vendor_interface_t),
        init,
        op,
        cleanup
    };
    

    3)、调用返回地址结构体中的init函数
    bt_vnd_if->init(&vnd_callbacks,local_bdaddr);
    有两个參数:厂商提供的回调函数vnd_callbacks。蓝牙地址:local_badaddr。
    函数init的实现:
    vendorsprdopen-sourcelibslibbtsrct_vendor_sprd.c

    const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
        sizeof(bt_vendor_interface_t),
        init,
        op,
        cleanup
    };
    

    BLUETOOTH_VENDOR_LIB_INTERFACE中INIT函数实现
    vendorsprdopen-sourcelibslibbtsrct_vendor_sprd.c

    static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
    {
    …………
        /* store reference to user callbacks */
        bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;//把vnd_callbacks回调函数,保存到用户回调bt_vendor_cback;
    …………
    }
    

    vnd_callbacks,这些函数在
    //The libbt-vendor Callback Functions Table

    static const bt_vendor_callbacks_t vnd_callbacks = {
        sizeof(bt_vendor_callbacks_t),
        fwcfg_cb,
        scocfg_cb,
        lpm_vnd_cb,
        alloc,
        dealloc,
        xmit_cb,
        epilog_cb
    };
    

    (3)、hci_h4_func_tableinit函数的初始化

    extern tHCI_IF hci_h4_func_table;
    p_hci_if = &hci_h4_func_table; 
    p_hci_if->init();
    
    1)、hci_h4_func_table结构体成员函数
    const tHCI_IF hci_h4_func_table =
    {
        hci_h4_init,//HCI_H4初始化;
        hci_h4_cleanup,
        hci_h4_send_msg,//发送msg;
        hci_h4_send_int_cmd,//发送int命令;
        hci_h4_get_acl_data_length,
        hci_h4_receive_msg//接收信息;
    };
    

    2)、  p_hci_if->init();调用hci_h4_func_table的init办法,初始化H4模块,相应实现函数相应:hci_h4_init

    void hci_h4_init(void)
    {
        HCIDBG("hci_h4_init");
        memset(&h4_cb, 0, sizeof(tHCI_H4_CB));
        utils_queue_init(&(h4_cb.acl_rx_q));
    
        /* Per HCI spec., always starts with 1 */
        num_hci_cmd_pkts = 1;
    
        /* Give an initial values of Host Controller's ACL data packet length
         * Will update with an internal HCI(_LE)_Read_Buffer_Size request
         */
        h4_cb.hc_acl_data_size = 1021;//hci ACL 数据的最大长度;
        h4_cb.hc_ble_acl_data_size = 27;//BLE  ACL最大数据长度。
    
        btsnoop_init();
    }
    

    (4)、初始化串口、LPM
       userial_init();
       lpm_init();
    (5)、创建工作线程
      if(pthread_create(&hc_cb.worker_thread, &thread_attr,
                          
     bt_hc_worker_thread, NULL) != 0)
    idh.codeexternalluetoothluedroidhcisrct_hci_bdroid.c
    bt_hc_worker_thread工作线程。监听各种状态,处理相相应。


    static void *bt_hc_worker_thread(void *arg)
    {
    …………
            if (events & HC_EVENT_PRELOAD)
            {
                userial_open(USERIAL_PORT_1);
    …………
                    bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL);
      	…………
            }
    
            if (events & HC_EVENT_POSTLOAD)
    
        …………
    
            if (events & HC_EVENT_TX)
           …………
            if (events & HC_EVENT_LPM_ENABLE)
       ………………
    }
    

    8、bluetoothHCLibInterface中set_power流程
    这部分主要完毕上电操作,SPRD的蓝牙芯片集成到AP端。由芯片内部控制。

    假设用其它蓝牙WIFI芯片。这部分应该相应相关power PIN脚操作。


    idh.codeexternalluetoothluedroidhcisrct_hci_bdroid.c

    /** Chip power control */
    static void set_power(bt_hc_chip_power_state_t state)
    {
        int pwr_state;
    …………
        pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
    
        if (bt_vnd_if)
            bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);//设置controller  POWER ON/OFF
    …………
    }
    

    bt_vnd_if这个结构体在idh.codeexternalluetoothluedroidhciincludet_vendor_lib.h中定义,相相应的op函数在bt_vendor_sprd.c中实现。


    (1)、bt_vnd_if结构体:

    typedef struct {
        size_t          size;
        int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);
        int (*op)(bt_vendor_opcode_t opcode, void *param);
        void  (*cleanup)(void);
    } bt_vendor_interface_t;
    

    (2)、bt_vnd_if->op的函数实现
    vendorsprdopen-sourcelibslibbtsrct_vendor_sprd.c
    相相应不同op操作

    BT_VND_OP_POWER_CTRL

    Power on or off the BT Controller

    BT_VND_OP_FW_CFG

    Perform any vendor specific initialization or configuration on the BT Controller. This is called before stack initialization

    BT_VND_OP_SCO_CFG

    Perform any vendor specific SCO/PCM configuration on the BT Controller.This is called after stack initialization.

    BT_VND_OP_USERIAL_OPEN

    Open UART port on where the BT Controller is attached. This is called before stack initialization.

    BT_VND_OP_USERIAL_CLOSE

    Close the previously opened UART port.

    BT_VND_OP_GET_LPM_IDLE_TIMEOUT

    Get the LPM idle timeout in milliseconds.The stack uses this information to launch a timer delay before it attempts to de-assert LPM WAKE signal once downstream HCI packet has been delivered.

    BT_VND_OP_LPM_SET_MODE

    Enable or disable LPM mode on BT Controller.

    BT_VND_OP_LPM_WAKE_SET_STATE

    Assert or Deassert LPM WAKE on BT Controller.

    BT_VND_OP_EPILOG

    The epilog call to the vendor module so that it can perform any vendor-specific processes (e.g. send a HCI_RESET to BT Controller)before the caller calls for cleanup().

    static int op(bt_vendor_opcode_t opcode, void *param)
    {
    …………
        switch(opcode)
        {
            case BT_VND_OP_POWER_CTRL://假设是power控制
                {
    		 ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL");		
    		  #if 0//这部分代码展讯平台没有控制;
    		  nState = *(int *) param;
                    retval = hw_config(nState);
                    if(nState == BT_VND_PWR_ON
                       && retval == 0
                       && is_hw_ready() == TRUE)
                    {
                        retval = 0;
                    }
    		  #endif			
                }
                break;
       …………
    }
    

    9、bluetoothHCLibInterface中Preload流程
     这部分主要完毕蓝牙MAC地址、RF射频相关设定,流程例如以下所看到的。


    (1)、发送HC_EVENT_POSTLOAD 信令,线程bt_hc_worker_thread接收并处理
    externalluetoothluedroidhcisrct_hci_bdroid.c

    /** Called post stack initialization */
    static void postload(TRANSAC transac)
    {
        BTHCDBG("postload");
        bthc_signal_event(HC_EVENT_POSTLOAD);//发送信号量给线程bt_hc_worker_thread
    }
    

    10、bt_hc_worker_thread处理HC_EVENT_PRELOAD

    static void *bt_hc_worker_thread(void *arg)
    {
        uint16_t events;
    HC_BT_HDR *p_msg, *p_next_msg;
    …………
            if (events & HC_EVENT_PRELOAD)
            {
                userial_open(USERIAL_PORT_1);//打开串口。
                /* Calling vendor-specific part */
                if (bt_vnd_if)
                {
                    bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL);//(1)、mac、ini、pskey初始化
                }
                else
                {
                    if (bt_hc_cbacks)
                        bt_hc_cbacks->preload_cb(NULL, BT_HC_PRELOAD_FAIL);(2)、失败preload 回调函数            
    …………
    }
    

    11、bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL);调用
    vendorsprdopen-sourcelibslibbtsrct_vendor_sprd.c中的OP函数:

    static int op(bt_vendor_opcode_t opcode, void *param)
    {
    …………
                   case BT_VND_OP_FW_CFG:
                {
                        ALOGI("bt-vendor : BT_VND_OP_FW_CFG");
                        retval = sprd_config_init(s_bt_fd,NULL,NULL);//初始化展讯平台
                        ALOGI("bt-vendor : sprd_config_init retval = %d.",retval);
                        if(bt_vendor_cbacks)
                        {
                            if(retval == 0)
                            {
                                ALOGI("Bluetooth Firmware and smd is initialized");
                           bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);//初始化成功后回调函数
                            }
                            else
                            {
                                ALOGE("Error : hci, smd initialization Error");
                                bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
                            }
                        }
                }
                break;	
    }
    

    (1)、sprd_config_init的实现
    这部分针对芯片部分,展讯的蓝牙芯片处理流程,在这里完毕:蓝牙MAC地址、RF ini文件相关。
    vendorsprdopen-sourcelibslibbtsrc bt_vendor_sprd.c中sprd_config_init

    //******************create bt addr end***********************
    int sprd_config_init(int fd, char *bdaddr, struct termios *ti)
    {
    ………………
        if(access(BT_MAC_FILE, F_OK) == 0)// MAC地址创建假设btmac不存在,随机生成;
        {
            ALOGI("%s: %s exists",__FUNCTION__, BT_MAC_FILE);
            read_btmac=read_mac_from_file(BT_MAC_FILE,bt_mac);
        }
        if(read_btmac == 1)
        {
            for(i=0; i<6; i++)
            {
                bt_mac_tmp[i*2] = bt_mac[3*(5-i)];
                bt_mac_tmp[i*2+1] = bt_mac[3*(5-i)+1];
            }
            ALOGI("====bt_mac_tmp=%s", bt_mac_tmp);
            ConvertHexToBin((uint8*)bt_mac_tmp, strlen(bt_mac_tmp), bt_mac_bin);
        }
        /* Reset the BT Chip */
        memset(resp, 0, sizeof(resp));
        ret = bt_getPskeyFromFile(&bt_para_tmp);//1)、GETPSKEY FOROMFILE。这里完毕INI文件的初始化
     …………
        {
            ALOGI("get_pskey_from_file ok 
    ");
            /* Send command from pskey_bt.txt*/
            if(read_btmac == 1)
            {
                memcpy(bt_para_tmp.device_addr, bt_mac_bin, sizeof(bt_para_tmp.device_addr));
            }
            if (write(s_bt_fd, (char *)&bt_para_tmp, sizeof(BT_PSKEY_CONFIG_T)) != sizeof(BT_PSKEY_CONFIG_T)) 
            {
                ALOGI("Failed to write pskey command from pskey file
    ");
                return -1;
            }
        }
        ALOGI("sprd_config_init write pskey command ok 
    ");
        while (1) 
        {
            r = read(s_bt_fd, resp, 1);
            if (r <= 0)
            return -1;
            if (resp[0] == 0x05)
            {
                ALOGI("read pskey response ok 
    ");
                break;
            }
        }
        ALOGI("sprd_config_init ok 
    ");
        return 0;
    }
    
    1)、GETPSKEY FOROMFILE,这里完毕INI文件的初始化:这部分内容和芯片相关, 不同厂商的芯片有不同的处理方法;

    ++++++sprd start 其它平台能够不看+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    vendorsprdopen-sourcelibslibbtsrct_vendor_sprd.c

    int bt_getPskeyFromFile(void *pData)
    {
    …………
    #ifdef HW_ADC_ADAPT_SUPPORT//不同INI文件
        char *CFG_2351_PATH[] = {
            "/system/etc/connectivity_configure_hw100.ini",
            "/system/etc/connectivity_configure_hw102.ini",
            "/system/etc/connectivity_configure_hw104.ini"
        };
    #else
        char *CFG_2351_PATH[] = {
            "/system/etc/connectivity_configure.ini"
        };
    #endif
    #ifdef HW_ADC_ADAPT_SUPPORT
    //假设是不同的硬件,获取板子信息,给board_type赋值,后面选择用那个ini文件。

    这个是展讯平台相关。不同平台有不同的做法; char *BOARD_TYPE_PATH = "/dev/board_type"; int fd_board_type; char board_type_str[MAX_BOARD_TYPE_LEN] = {0}; fd_board_type = open(BOARD_TYPE_PATH, O_RDONLY);//(1)、获取硬件版本号信息 if (fd_board_type<0) { ALOGI("#### %s file open %s err #### ", __FUNCTION__, BOARD_TYPE_PATH); board_type = 2; // default is 1.0.4 } else { len = read(fd_board_type, board_type_str, MAX_BOARD_TYPE_LEN); if (strstr(board_type_str, "1.0.0")) { board_type = 0; } ………… #endif ALOGI("begin to bt_getPskeyFromFile"); fd = open(CFG_2351_PATH[board_type], O_RDONLY, 0644); if(-1 != fd) { len = bt_getFileSize(CFG_2351_PATH[board_type]);//(2)、获得相应的版本号的PSKEY。 pBuf = (unsigned char *)malloc(len); ret = read(fd, pBuf, len); ………… ret = bt_getDataFromBuf(pData, pBuf, len); if(-1 == ret) { free(pBuf); return -1; } ALOGI("begin to dumpPskey"); bt_dumpPskey((BT_PSKEY_CONFIG_T *)pData);//(3)、解析相应数据 free(pBuf); return 0; }

    获取硬件版本号信息
    fd_board_type = open(BOARD_TYPE_PATH,O_RDONLY);
    Board_type例如以下图:

    获得相应的版本号的PSKEY;

    char *CFG_2351_PATH[] = {
            "/system/etc/connectivity_configure_hw100.ini",
            "/system/etc/connectivity_configure_hw102.ini",
            "/system/etc/connectivity_configure_hw104.ini"
        };
    


    解析相应数据
    bt_dumpPskey((BT_PSKEY_CONFIG_T*)pData);

    ++++++++++++++sprd end 其它平台能够不看+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    12、  配置成功后回调函数fwcfg_cb

    bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);//初始化成功后回调函数,这部分在case BT_VND_OP_FW_CFG中完毕

    externalluetoothluedroidhcisrct_hw.c

    static void fwcfg_cb(bt_vendor_op_result_tresult)
    {
        bt_hc_postload_result_tstatus = (result == BT_VND_OP_RESULT_SUCCESS) ? 
                                        BT_HC_PRELOAD_SUCCESS : BT_HC_PRELOAD_FAIL;//判定prelaod是否成功;
        fwcfg_acked = TRUE;
        if (bt_hc_cbacks)
            bt_hc_cbacks->preload_cb(NULL, status);//相应preload_cb
    }

    preload_cb的实现。把BT_EVT_PRELOAD_CMPL成功消息通过GKI返回BTU_TASK。

    externalluetoothluedroidmainte_main.c
    static void preload_cb(TRANSACtransac, bt_hc_preload_result_t result)
    {
        APPL_TRACE_EVENT1("HC preload_cb %d[0:SUCCESS 1:FAIL]", result);
        if (result == BT_HC_PRELOAD_SUCCESS)
        {
            preload_stop_wait_timer();
            /* notify BTU task that libbt-hci isready */
            GKI_send_event(BTU_TASK, BT_EVT_PRELOAD_CMPL);//发送BT_EVT_PRELOAD_CMPL到BTU_TASK
        }
    }

    preload完毕后。回调函数返回到BTU_TASK,启动BT其它协议层的初始化。
    下节我们分析:
    1、GKI_send_msg进程间通信怎样完毕。
    2、bta_sys_sendmsg event怎样解析;
    3、GKI_Wait实现流程;

  • 相关阅读:
    各種語系的unicode對應以及local編碼方式
    测试邮箱采集
    devexpress控件例子
    2015结束,2016开始
    MYSQL 导出表结构
    mysql 远程访问
    jQuery的选择器中的通配符[id^='code']
    jquery判断checkbox是否选中及改变checkbox状态
    MYSQL 删除重复记录,只保留最大ID
    java.lang.IllegalArgumentException: Comparison method violates its general contract!
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6784919.html
Copyright © 2011-2022 走看看