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

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

     一、   蓝牙开启流程概述,例如以下图所看到的:init、enable

    和一般的函数调用同样。android上层通过APP-->Native-->JNI-->bluetoothinterface-->bluetooth HCIinterface。

    HCI interface中实现了init、set_power、preload对应函数
    init、enable函数主要实现的功能:
    (1)、创建:btif_task/BTIF_TASK
    (2)、初始化BTE
    (3)、创建:btu_task/BTU_TASK
    (4)、初始化HCI、串口相关,启动HCI工作主线程:bt_hc_callback。芯片上电、RF參数初始化、蓝牙地址名称相关设定;
    (5)、创建:bt_hc_worker_thread蓝牙工作主线程,发送接收命令;
    (6)、初始化蓝牙协议栈;
    二、initNative函数的的实现
            这部分主要启动对应sock、协议栈初始化、启动btif_task,监听处理蓝牙接口相关的状态消息。实现流程例如以下所看到的。


     1、应用部分函数调用(从adatper開始)
    packagesappsBluetoothsrccomandroidluetoothtservice AdapterService.java

        public void onCreate() {
            super.onCreate();
            if (DBG) debugLog("onCreate");
            mBinder = new AdapterServiceBinder(this);
            mAdapterProperties = new AdapterProperties(this);
            mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
            mJniCallbacks =  new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
            initNative();//调用initNative函数;
            mNativeAvailable=true;
            mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
            //Load the name and address
            getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
            getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
    }
    private native boolean initNative();
    

    2、JNI函数的实现,这部分跟其它JNI实现同样。
    packagesappsBluetoothjnicom_android_bluetooth_btservice_AdapterService.cpp

    static JNINativeMethod sMethods[] = {
        /* name, signature, funcPtr */
        {"classInitNative", "()V", (void *) classInitNative},
        {"initNative", "()Z", (void *) initNative},//Native函数实现
    …………
    }
    

    packagesappsBluetoothjnicom_android_bluetooth_btservice_AdapterService.cpp
    initNative函数的详细实现。通过bt_interface_t结构体,调用到C中的init函数实现。同一时候传入sBluetoothCallbacks回调函数结构体。这个函数结构体比較重要,底层的状态变化都是通过这个回调函数结构体中的函数实现。

    static const bt_interface_t *sBluetoothInterface = NULL;
    static bool initNative(JNIEnv* env, jobject obj) {
        sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
        if (sBluetoothInterface) {
            int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//调用到C的对应接口函数
            if (ret != BT_STATUS_SUCCESS) {//假设出错,错误处理;
                ALOGE("Error while setting the callbacks 
    ");
                sBluetoothInterface = NULL;
                return JNI_FALSE;
            }
            if ( (sBluetoothSocketInterface = (btsock_interface_t *)
                      sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
                    ALOGE("Error getting socket interface");
            }
            return JNI_TRUE;
        }
        return JNI_FALSE;
    }
    

    3、JNI调用C中函数实现
    C语言实现了上层调用的函数。终于实现了JAVA调用C函数的动作。

    这是android系统对kernel操作的详细步骤。

    假设是刚開始学习的人,建议把这部分内容搞清楚,整个android系统对底层的操作都是通过这样的方法实现。
    externalluetoothluedroidtifsrcluetooth.c

    static const bt_interface_t bluetoothInterface = {//蓝牙接口函数对应的函数
        sizeof(bluetoothInterface),
        init,//C函数中对init函数的实现;
        enable,
        disable,
        cleanup,
        get_adapter_properties,
        get_adapter_property,
        set_adapter_property,
        get_remote_device_properties,
        get_remote_device_property,
        set_remote_device_property,
        get_remote_service_record,
        get_remote_services,
        start_discovery,
        cancel_discovery,
        create_bond,
        remove_bond,
        cancel_bond,
        pin_reply,
        ssp_reply,
        get_profile_interface,
        dut_mode_configure,
        dut_mode_send,
    #if BLE_INCLUDED == TRUE
        le_test_mode,
    #else
        NULL,
    #endif
        config_hci_snoop_log
    };
    

    4、蓝牙接口函数中Init函数实现过程
    externalluetoothluedroidtifsrcluetooth.c

    static int init(bt_callbacks_t* callbacks )
    {
        ALOGI("init");
        /* sanity check */
        if (interface_ready() == TRUE)//检查接口函数是否准备好;
            return BT_STATUS_DONE;
        /* store reference to user callbacks */
        bt_hal_cbacks = callbacks;//把对应的回调函数,保存。这个很重要,刚開始看代码是忽略这部分。我们单独一节解说这部分回调函数的实现和作用;
        /* add checks for individual callbacks ? */
        bt_utils_init();//工具集初始化,初始化一个相互排斥锁。
        /* init btif */
    btif_init_bluetooth();//初始化蓝牙接口bluetoothinterface
        return BT_STATUS_SUCCESS;
    }
    

    5、蓝牙接口初始化详细实现,btif_init_bluetooth创建BTIF任务。准备蓝牙开启相关调度程序。
    详细实现流程例如以下所看到的。我们以下对代码做详解。主要完毕了:
    (1)、bt_config.xml文件里的蓝牙名称等处理;
    (2)、GKI初始化,这部分后面单一节做详细分析。
    (3)、BlueHCLibInterface初始化。实现powerpreload等函数,BlueDreoid  log等级设定;
    (4)、BTIF_TASK线程创建。这个部分也比較重要。



    externalluetoothluedroidtifsrctif_core.c

    bt_status_t btif_init_bluetooth()
    {
        UINT8 status;
        btif_config_init();//创建sock线程。初始化初始化/data/misc/bluedroid/
    bt_config.xml中相关数据。
        bte_main_boot_entry();//(1)、BTE芯片协议栈入口API,蓝牙协议栈/芯片初始化,GKI init;
        /* As part of the init, fetch the local BD ADDR */
        memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t));//取蓝牙地址写入相关文件。
        btif_fetch_local_bdaddr(&btif_local_bd_addr);
        /* start btif task */
        status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,
                    (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),
                    sizeof(btif_task_stack));
    //(2)、Creates BTIF task and prepares BT scheduler for startup  创建蓝牙任务接口,为开启做调度准备
        if (status != GKI_SUCCESS)
            return BT_STATUS_FAIL;
        return BT_STATUS_SUCCESS;
    }
    

    (1)、BTE芯片协议栈入口API。蓝牙协议栈/芯片初始化。GKI init。
    externalluetoothluedroidmainte_main.c

    void bte_main_boot_entry(void)
    {
        /* initialize OS */
        GKI_init();//1)、GKI初始化。仅仅在初始化的时候调用一次。
    
        bte_main_in_hw_init();//2)、初始化结构体static bt_hc_interface_t *bt_hc_if=NULL;
    
        bte_load_conf(BTE_STACK_CONF_FILE);//3)、初始化bluedroid调试信息等级;
    
    #if (BTTRC_INCLUDED == TRUE)//相关信息打印初始化。
        /* Initialize trace feature */
        BTTRC_TraceInit(MAX_TRACE_RAM_SIZE, &BTE_TraceLogBuf[0], BTTRC_METHOD_RAM);
    #endif
    }
    


    1)、GKI初始化。仅仅在初始化的时候调用一次
    參考相互排斥锁:http://blog.csdn.net/kingmax26/article/details/5338065  。
    externalluetoothluedroidgkiulinuxgki_ulinux.c

    void GKI_init(void)
    {
        pthread_mutexattr_t attr;
        tGKI_OS             *p_os;
    
        memset (&gki_cb, 0, sizeof (gki_cb));
    
        gki_buffer_init();//1))、GKI 缓冲、缓冲池初始化;
        gki_timers_init();//2))、GKI定时器初始化。
        gki_cb.com.OSTicks = (UINT32) times(0);
    
        pthread_mutexattr_init(&attr);//3))、初始化pthread_mutexattr_t结构;
    
    #ifndef __CYGWIN__
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);//4))、设置相互排斥锁类型
    #endif
        p_os = &gki_cb.os;
        pthread_mutex_init(&p_os->GKI_mutex, &attr);//5))、初始化相互排斥量GKI_mutex;
        /* pthread_mutex_init(&GKI_sched_mutex, NULL); */
    #if (GKI_DEBUG == TRUE)
        pthread_mutex_init(&p_os->GKI_trace_mutex, NULL);//  6))、初始化相互排斥量GKI_trace_mutex;
    #endif
        /* pthread_mutex_init(&thread_delay_mutex, NULL); */  /* used in GKI_delay */
        /* pthread_cond_init (&thread_delay_cond, NULL); */
    
        /* Initialiase GKI_timer_update suspend variables & mutexes to be in running state.
         * this works too even if GKI_NO_TICK_STOP is defined in btld.txt */
        p_os->no_timer_suspend = GKI_TIMER_TICK_RUN_COND;
        pthread_mutex_init(&p_os->gki_timer_mutex, NULL);7))、初始化相互排斥量gki_timer_mutex。
    #ifndef NO_GKI_RUN_RETURN
        pthread_cond_init(&p_os->gki_timer_cond, NULL);
    #endif
    }
    

    2)、初始化结构体static bt_hc_interface_t *bt_hc_if=NULL;
    bte_main_in_hw_init();
    给bt_hc_if赋值:

    static const bt_hc_interface_t bluetoothHCLibInterface = {
        sizeof(bt_hc_interface_t),
        init,//HCI LIB中init函数的实现;
        set_power,
        lpm,
        preload,
        postload,
        transmit_buf,
        set_rxflow,
        logging,
        cleanup
    };
    

    3)、初始化bluedroid调试信息等级
        bte_load_conf(BTE_STACK_CONF_FILE);
    解析bt_stack.conf文件里的配置信息。
    (2)、创建蓝牙任务接口。为开启做调度准备Creates BTIF task and prepares BT scheduler for startup  

      status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,
                    (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),
                    sizeof(btif_task_stack));
    

    6、btif_task进程相关处理函数
    externalluetoothluedroidtifsrctif_dm.c
    btif_task 等待接收bta_sys_sendmsg发送的对应的状态做对应处理。

    static void btif_task(UINT32 params)
    {
    ………………
        for(;;)
    {
            /* wait for specified events */
            event = GKI_wait(0xFFFF, 0);//GKI进程间通信后面单开一节介绍;
            if (event == BT_EVT_TRIGGER_STACK_INIT)//协议栈初始化完毕;
    …………
            if (event == BT_EVT_HARDWARE_INIT_FAIL)//硬件初始化错误
    …………
            if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))//收到关闭信息。
     …………
            if(event & TASK_MBOX_1_EVT_MASK)
    …………
    }
    }

  • 相关阅读:
    程序打包(通过VS2015插件 InstallShield2015 Limited Edition 方式)
    QSS单独设置四个边角
    Qt 设置窗口圆角
    Qt实现鼠标拖动窗口
    关于split切割的几种情况
    java开发过程中,报错Dangling meta character '*' near index 0,解决办法
    关于ArrayList的contains方法
    WPS文档按回车键不能换行怎么解决
    正则表达式截取数字
    如何用hibernate中查询出一个表数量总数
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6916330.html
Copyright © 2011-2022 走看看