在蓝牙中,host和controller之间的command和event的交互是底层各种工作开展的基础,在初始化的过程中必然也存在着类似的操作。本章会详细分析在hci_init_req过程中所涉及到的所有command和event的交互。至于command和event的格式意义,请参见bluetooth的core spec,这里不做详细介绍,若想详细了解,spec的研读是必不可少的。
static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
{
struct hci_cp_delete_stored_link_key cp;
struct sk_buff *skb;
__le16 param;
__u8 flt_type;
BT_DBG("%s %ld", hdev->name, opt);
/* Driver initialization */
/* Special commands */
//把hdev->driver_init中的cmd发送完成掉,然后清空hdev->driver_init这个queue
while ((skb = skb_dequeue(&hdev->driver_init))) {
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
skb->dev = (void *) hdev;
skb_queue_tail(&hdev->cmd_q, skb);
tasklet_schedule(&hdev->cmd_task);
}
skb_queue_purge(&hdev->driver_init);
/* Mandatory initialization */
/* Reset */
//因为设置了no reset位,所以这里reset命令是不发送的
if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
set_bit(HCI_RESET, &hdev->flags);
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
}
//这里会连续发送几个cmd:
//read local features, read local version, read buffer size, read bd addr, read class of device, read local name, read voice setting, set event filter, write connection accept timeout, delete stored link key
//下面我们会对这些cmd进行逐个地分析
/* Read Local Supported Features */
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local Version */
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
/* Read BD Address */
hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
/* Read Class of Device */
hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
/* Read Local Name */
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
/* Read Voice Setting */
hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
/* Clear Event Filters */
flt_type = HCI_FLT_CLEAR_ALL;
hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Connection accept timeout ~20 secs */
//7d00*0.625ms=20s
param = cpu_to_le16(0x7d00);
hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
bacpy(&cp.bdaddr, BDADDR_ANY);
cp.delete_all = 1;
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
}
这里各种cmd就已经发送出去了,下面就是对接收到的response要做一些处理了,首先我们来看一下对event是如何处理的。
在之前我们看到,hci dev注册的时候是启动了一个rxtask的,他就是用来接收的,所以我们直接去看一下它的处理
static void hci_rx_task(unsigned long arg){
……
//对于event的处理,就是这里了,所以后期各个event都是这边进行处理的,不再详细地说明如何找了
switch (bt_cb(skb)->pkt_type) {
case HCI_EVENT_PKT:
hci_event_packet(hdev, skb);
break;
}
2.1.1.1 read local features的event的处理
从spec中,我们知道,这个cmd的回应是一个commandcomplete的event。所以,直接去看command complete event的处理:
static inline void hci_cmd_comple