Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android藍牙源碼分析——BTA層消息分發

Android藍牙源碼分析——BTA層消息分發

編輯:關於Android編程

這裡BTA是Bluetooth Application的縮寫,從上層下來的請求都要經過這個BTA層,通過發送消息的方式將請求丟到BTA層中處理。這個發送消息的函數定義在bta_sys_main.c中,如下:

void bta_sys_sendmsg(void *p_msg)
{
    GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
}

我們在進入GKI_send_msg前,先搞清楚bta_sys_cb,這貨定義在bta_sys_main.c中,如下:

/* system manager control block definition */
tBTA_SYS_CB bta_sys_cb;

這個bta_sys_cb是BTA層的總體Control Block。數據結構定義在bta_sys_int.h中,如下:

/* system manager control block */
typedef struct
{
    tBTA_SYS_REG            *reg[BTA_ID_MAX];       /* registration structures */
    BOOLEAN                 is_reg[BTA_ID_MAX];     /* registration structures */
    ......

} tBTA_SYS_CB;

這裡值得注意的是reg,這是個數組,數組類型是tBTA_SYS_REG,裡面是BTA下面的各個子系統的回調,最多有BTA_ID_MAX個。我們看看tBTA_SYS_REG的定義:

/* registration structure */
typedef struct
{
    tBTA_SYS_EVT_HDLR   *evt_hdlr;
    tBTA_SYS_DISABLE    *disable;
} tBTA_SYS_REG;

/* event handler function type */
typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);

/* disable function type */
typedef void (tBTA_SYS_DISABLE)(void);

原來就是兩個函數,一個是關於事件處理的,一個是關於disable的。就是說BTA下面的各個子系統都有自己的事件處理邏輯和disable邏輯。

我們再看看有哪些子系統,各子系統ID定義如下:

/* SW sub-systems */
#define BTA_ID_SYS          0            /* system manager */
/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
#define BTA_ID_DM           1            /* device manager */
#define BTA_ID_DM_SEARCH    2            /* device manager search */
#define BTA_ID_DM_SEC       3            /* device manager security */
#define BTA_ID_DG           4            /* data gateway */
#define BTA_ID_AG           5            /* audio gateway */
#define BTA_ID_OPC          6            /* object push client */
#define BTA_ID_OPS          7            /* object push server */
#define BTA_ID_FTS          8            /* file transfer server */
#define BTA_ID_CT           9            /* cordless telephony terminal */
#define BTA_ID_FTC          10           /* file transfer client */
#define BTA_ID_SS           11           /* synchronization server */
#define BTA_ID_PR           12           /* Printer client */
#define BTA_ID_BIC          13           /* Basic Imaging Client */
#define BTA_ID_PAN          14           /* Personal Area Networking */
#define BTA_ID_BIS          15           /* Basic Imaging Server */
#define BTA_ID_ACC          16           /* Advanced Camera Client */
#define BTA_ID_SC           17           /* SIM Card Access server */
#define BTA_ID_AV           18           /* Advanced audio/video */
#define BTA_ID_AVK          19           /* Audio/video sink */
#define BTA_ID_HD           20           /* HID Device */
#define BTA_ID_CG           21           /* Cordless Gateway */
#define BTA_ID_BP           22           /* Basic Printing Client */
#define BTA_ID_HH           23           /* Human Interface Device Host */
#define BTA_ID_PBS          24           /* Phone Book Access Server */
#define BTA_ID_PBC          25           /* Phone Book Access Client */
#define BTA_ID_JV           26           /* Java */
#define BTA_ID_HS           27           /* Headset */
#define BTA_ID_MSE          28           /* Message Server Equipment */
#define BTA_ID_MCE          29           /* Message Client Equipment */
#define BTA_ID_HL           30           /* Health Device Profile*/
#define BTA_ID_GATTC        31           /* GATT Client */
#define BTA_ID_GATTS        32           /* GATT Client */
#define BTA_ID_BLUETOOTH_MAX   33        /* last BT profile */

/* FM */
#define BTA_ID_FM           34           /* FM  */
#define BTA_ID_FMTX         35           /* FM TX */

/* SENSOR */
#define BTA_ID_SSR          36           /* Sensor  */

/* GPS */
#define BTA_ID_GPS          37           /* GPS  */

/* GENERIC */
#define BTA_ID_PRM          38
#define BTA_ID_SYSTEM       39           /* platform-specific */
#define BTA_ID_SWRAP        40           /* Insight script wrapper */
#define BTA_ID_MIP          41           /* Multicase Individual Polling */
#define BTA_ID_RT           42           /* Audio Routing module: This module is always on. */


/* JV */
#define BTA_ID_JV1          43           /* JV1 */
#define BTA_ID_JV2          44           /* JV2 */

#define BTA_ID_MAX          (43 + BTA_DM_NUM_JV_ID)

可見一共有43個ID,另外加兩個JV_ID。這些ID中比較眼熟的有BTA_ID_GATTC和BTA_ID_GATTS,應該都是和GATT相關的,一個是Server,一個是Client。

我們再來看bta_sys_cb是在哪裡初始化的,在bta_sys_main.c中,如下:

BTA_API void bta_sys_init(void)
{
    memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
    ptim_init(&bta_sys_cb.ptim_cb, BTA_SYS_TIMER_PERIOD, p_bta_sys_cfg->timer);
    bta_sys_cb.task_id = GKI_get_taskid();

    /* register BTA SYS message handler */
    bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);

    /* register for BTM notifications */
    BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );
}

這個bta_sys_init就是初始化整個BTA的,是在btu_task線程中調用的。而btu_task線程入口是在bte_main.c的bte_main_enable中,再往上走是btif_core.c的btif_enable_bluetooth中,看樣子這是打開藍牙時調用的,再往上走是bluetooth.c的enable函數。而btif_task初始化是在btif_core.c中的btif_init_bluetooth,往上是bluetooth.c中的init函數,相比btu_task還是簡單些。

我們回到bta_sys_init,這裡我們關注的邏輯是首先設置bta_sys_cb的task_id為BTU TASK。然後注冊BTA_ID_SYS的消息處理函數。我們看這個bta_sys_register是怎麼注冊的,如下:

void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
    bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
    bta_sys_cb.is_reg[id] = TRUE;
}

邏輯很簡單,我們看看GATTC是在哪裡注冊的,是在bta_gattc_api.c中的BTA_GATTC_AppRegister,如下:

void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
{
    tBTA_GATTC_API_REG  *p_buf;

    if (bta_sys_is_register(BTA_ID_GATTC) == FALSE)
    {
        bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);
    }

    ......
    return;
}

這個函數是在btif_gatt_client.c的btgattc_handle_event中調用,往上走是注冊clientIf時也就是打開gatt時。所以我們了解了當打開gatt連接時,會自動去注冊GATTC子系統。這個子系統的回調在bta_gattc_api.c中:

static const tBTA_SYS_REG bta_gattc_reg =
{
    bta_gattc_hdl_event,  // 在bta_gattc_main.c中
    BTA_GATTC_Disable
};

我們重點關注GATTC子系統下的事件處理函數為bta_gattc_hdl_event,這個之後會用到的。因為所有Gatt相關的事件處理最終都調到了這個。

我們回到bta_sys_sendmsg,這裡調用了GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);,這個bta_sys_cb的task_id毫無疑問是btu_task了,其中的mbox是什麼呢?我們來看p_bta_sys_cfg是在哪裡初始化的,在bta_sys_cfg.c中,如下:

/* GKI task mailbox event for BTA. */
#ifndef BTA_MBOX_EVT
#define BTA_MBOX_EVT                TASK_MBOX_2_EVT_MASK
#endif

/* GKI task mailbox for BTA. */
#ifndef BTA_MBOX
#define BTA_MBOX                    TASK_MBOX_2
#endif

/* GKI timer id used for protocol timer for BTA. */
#ifndef BTA_TIMER
#define BTA_TIMER                   TIMER_1
#endif

const tBTA_SYS_CFG bta_sys_cfg =
{
    BTA_MBOX_EVT,               /* GKI mailbox event */
    BTA_MBOX,                   /* GKI mailbox id */
    BTA_TIMER,                  /* GKI timer id */
    APPL_INITIAL_TRACE_LEVEL    /* initial trace level */
};

tBTA_SYS_CFG *p_bta_sys_cfg = (tBTA_SYS_CFG *)&bta_sys_cfg;

就是說bta對應的mailbox是BTA_MBOX,也就是TASK_MBOX_2。每個task都有4個mailbox用於接收buff,這個是2號郵箱。

好了,bta_sys_sendmsg就是向btu task的2號郵箱發送了msg。處理函數在哪裡呢?在btu_task中如下:

if (event & TASK_MBOX_2_EVT_MASK)
{
    while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL)
    {
        bta_sys_event(p_msg);
    }
}

是在bta_sys_event中,發送消息可以在別的線程,但是處理消息都回到了btu_task線程內部。

BTA_API void bta_sys_event(BT_HDR *p_msg)
{
    UINT8       id;
    BOOLEAN     freebuf = TRUE;

    /* get subsystem id from event */
    id = (UINT8) (p_msg->event >> 8);

    /* verify id and call subsystem event handler */
    if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
    {
        freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
    }

    if (freebuf)
    {
        GKI_freebuf(p_msg);
    }

}

這裡根據event獲取id,然後獲取到對應BTA的子系統的回調,每個子系統有自己的事件處理函數的。所以如果這裡是GATT相關的事件,則會走到GATT的事件處理函數,為bta_gattc_hdl_event,在bta_gattc_main.c中。

總結一下,所有BTA消息最終都送到了BTU TASK中,由bta_sys_event來處理。如果是Gatt相關的消息,則最終由bta_gattc_hdl_event處理。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved