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