Android蓝牙源码分析——BTA层消息分发

这里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处理。

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/dingjikerbo/article/details/52424631
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞