LMP 全稱是Link Manager Protocol,咱們仍是要一張圖,說明LMP 在哪裏?網絡
他是在HCI 如下,baseband 以上,實如今藍牙控制器中。架構
按照協議規範,咱們分幾個部分來分別介紹LMP加密
下面咱們先來看看 總體的介紹部分:spa
LMP是用來控制和協商兩個設備鏈接行爲的協議,涉及的方面包括邏輯傳輸鏈接的創建和控制,以及對於物理鏈路的控制等等,它是兩個設備的LMP模塊以前的交流,其消息是傳輸在ACL-C 的邏輯鏈路上,對於這一點,咱們在baseband的概述中已經提過:debug
這裏須要注意的一點是,LMP 是實如今控制器裏面,其消息並不會通過HCI 接口傳輸到HOST 端,其架構以下圖:3d
咱們能夠看到其是 兩個設備的LMP 模塊以前的通訊。code
這裏描述的就是三個點:orm
LMP 傳輸在ACL-C的邏輯鏈路上面,但這並不能保證傳輸的時間的以及對方ack的及時性。blog
LMP 的數據包的格式有兩種,一種是7bit的opcode,另一種是15bit的opcode接口
咱們發現除了opcode,在最低位還有一個TID,他是transtransaction ID,當它是0 的時候,說明這個LMP message是 master 發起的,當它是1的是時候說明是slave 發起的。
上圖中是 header的最低位是0,表明是Transaction ID Initiated by master。
transaction 就是一次完整的打成某種目的的傳輸。全部屬於同一個transaction 的單次傳輸的transaction ID 都是想同的。
好比下面:
LMP version exchange 的Transaction ID 都是 Initiated by slave
另外LMP_setup_complete 是一個 獨立PDU,它本身造成一個transaction,
上面兩個OpCode LMP_setup_complete 的transaction ID 是不一樣的,他們是獨立的PDU
LMP response的timeout 時間是30s
關於出錯處理,每個錯誤都分配了一個錯誤碼,常見的錯誤以下:
general response 在不少的procedure中,被用來對於各類流程的應答消息,若是opcode是7bit,那麼應該使用前兩種 PDU,若是opcode 是15bit,那麼應答的PDU 應該使用後兩種。
device feature,顧名思義,這裏面定義了不少的設備的特性,而且這些特定是能夠用特定的LMP message 來獲取的。那麼這些feature 是如何傳輸的呢?其實就是定義了一些bit 位來表明相應的feature,當這些位被設置爲1的時候,就說明支持該feature,這個咱們在程序代碼實現中常常見到這樣的技巧。
這些feature 定義在兩個page 上面,page1 裏面使用8個字節,64bit 定義了64個feature,page2用2個字節定義了12個feature,其中包括2個reserved 位。
這裏簡單列舉幾個feature:
這裏包含了不少的基本流程,主要有以下的項目:
Connection control
咱們下面分別看看這幾個流程:
這裏每個流程都有不少的子流程,這裏只簡單介紹下Connection establishment和Detach的流程:
下面先看一下Connection establishment的流程圖
在通過了page的流程以後,可能的行爲是請求時鐘的偏移量,LMP的版本,對端支持的feature請求,對端的name請求,以及可能的deteach行爲。
以後若是要創建鏈接的話,paging的設備就會發送LMP_host_connection_req,對端若是贊成創建鏈接就會回覆LMP_accepted 不然就是LMP_not_accepted
後續可能走得關於認證和加密的流程,最後是LMP_setup_complete,下面咱們來看一個例子:
下面的創建鏈接的PDU:
下面咱們看看detach 的流程:
咱們發現關於detach 是沒有LMP response 的消息的過來的,從實際的air log 中,也的確沒有detach response 回覆,對端設置只會簡單的ack 該 消息:
下面咱們看看 從設備的host 端 去斷開對端設備的 LMP 與HCI 的message 流向:
咱們發現是 A設備再收到了對端的ACK 以後就會向host 端上傳斷開完成事件。
關於 驗證和加密的部分,會在分析配對的文章中專門講述。
下面咱們咱們看看
這一類的message 交互都是 信息請求類型的,具體的有以下幾種:
Timing accuracy
這幾個流程也是很是的類型,咱們也是挑選其中一個來 看一下:
咱們看看lmp version 的流程:
其交互流程很簡單,發起端發起一個LMP_version_req,對端迴應一個LMP_version_res
涉及到的PDU的包以下:
這裏咱們發現,發起這個LMP version請求的時候,還會攜帶本端的LMP version,Company ID 以及Sub Version Number,這個Sub Version Number 應該是公司內部的編號了,那這樣一來,一個request,一個response,就完成了LMP 相關版本信息的交互。咱們看看air log 關於這交互的消息:
response 以下:
這裏須要提一點就是LMP 數據包的payload header 裏面也是有流控相關的,可是這個流控對於LMP 是不起做用的。其應該是主要針對ACL-U的數據。
這裏再簡單名字的獲取的流程,當沒有創建物理link的時候,獲取名字和已經創建了link的獲取的名字的流程有點區別。咱們先下有link的時候 流程:
有link的時候,很簡單,直接是在LMP 層進行LMP_name_req的交互,收到對方的應答以後,經過HCI接口上報的到host端,若是是沒有link的話,那麼是要先創建一個臨時的link,其流程見下圖:
咱們能夠看到兩個設備通過page 以後,會先進行LMP feature exchange以及extend feature exchange,而後上報到host 端,接下來才進行LMP_name_req 的交互,最後是detach 這個臨時的link,
咱們看看 air log 中實際的交互狀況:
實際狀況和上面的流程也是很是的吻合,最後會把這個 臨時創建起來的獲取名字的link斷開。
下面咱們看看role switch 相關的
關於role switch ,由於咱們日常在debug 中會遇到,值得仔細講一下:
role switch的執行須要符合幾個條件:
role switch 從字面含義上來看,很是的簡單,就是交互角色,咱們知道兩個設備鏈接以後,一開始發起配對的那個設備在創建鏈接以後就是master,這樣一種默認模式不能老是符合應用場景,因此常常在兩個設備以後須要交互角色。
role switch 是master 和slave 均可以發起的,咱們先看一下,master 發起的角色交換的流程:
LMP 層面的交互很簡單,就三個指令。下面咱們詳細講一下LMP_switch_req和LMP_slot_offset的 做用。
咱們看出 LMP_slot_offset 攜帶兩個關鍵的信息,一個slot offset,另一個 藍牙設備地址。這個地址是當前 slave 地址,也是role switch 以後master的地址。這個slot offset 是幹嗎的呢?
這個在specification中原話是「The slot offset shall be the time in microseconds between the start of a master transmission in the current piconet to the start of the next following master transmission in the piconet where the BD_ADDR device (normally the slave) is master at the time that the request is interpreted by the BD_ADDR device.」
其含義就是,當前網絡的master的開始傳輸的時機(時鐘上升沿)到交換後的網絡master 進行傳輸的時機(時鐘上升沿)的時間間隔,次時間是用ms 來描述的。
從這裏,咱們可以覺悟出,slot offset 應該都是由當前網絡的slave(role switch 以後的master) 來發送,而不論是 哪一端的設備先發起的,下面咱們看看slave 端發起的role switch的交互流程:
咱們發現,slot offset,的確是由slave端送出,以後才送出 LMP_switch_req,如今咱們看看一下LMP_switch_req這個命令:
咱們能夠設想一下,藍牙設備之間的交互是要保持時鐘同步的,不然就會「失去聯繫」,那麼咱們在進行role swtich 以後仍是要保持時鐘同步才能繼續通訊,那在什麼樣的時機進行role switch呢?
咱們先看下LMP_switch_req的參數:
咱們發現其有一個參數是 switch instant ,這就是 描述 具體在哪個時間點進行TDD switch。
這個instant 應該是一個將來的時間,若是是過去的時間,那麼當接受者受到這個instant的時候,並不會接受這樣的參數,會回覆 LMP_not_accepted PDU with the error code Instant Passed (0x28)。
當role switch 完成的時候,兩個設備都要向各自的host 上報HCI_Role_Change event,以下圖:
hold mode 不多遇到,這裏主要講一下 sniff mode ,
sniff mode 就是呼吸模式,主要是爲了省電而應用的,好比一些藍牙設備,好比鍵盤鼠標,當他們在active mode的時候,每個master to slave slot,設備都要去監聽master是否有數據發過來。而當他們不使用的時候,若是仍是一直處於active mode 的話,那麼這段時間的消耗的電量就浪費了,而進入到sniff mode 可使得設備進入了相似睡眠的狀態,只是按期去監聽master 的封包,這樣能夠節省電量。
咱們先看看 進入sniff mode 的流程圖:
咱們這裏主要着眼於LMP層面,當host端有進入sniff mode的命令下來,那麼控制器 將向對方發出LMP_sniff_req的請求,對方若是贊成,那麼回覆LMP_accepted。由於這是一個協商的過程,上圖只顯示了一次協商的過程,其實可能存在有發屢次的LMP_sniff_req的狀況。如今咱們看看 LMP_sniff_req的參數:
Dsniff = Clock_Value (bits 26-1) mod Tsniff
Tsniff 是 sniff interval,就是每次起來監聽的時間間隔
Tsniff 就是 相鄰的兩個sniff anchor point的時間間隔。
sniff attempt 是 每次起來以後 嘗試去監聽的次數,若是監聽了sniff attempt 次數以後發現master 沒有發數據過來,那麼再次進入到睡眠的狀態。
sniff timeout 是 在slave 去監聽master 的封包的時候,若是有封包發過來,那麼就要繼續監聽額外的sniff timeout 個master to slave slot。
咱們這裏說一下Sniff 第一個錨點的計算方法:Dsniff = Clock_Value (bits 26-1) mod Tsniff
這裏Dsniff 和Tsniff 是參數已經給出的,那麼就是根據上面的公式去反推第一個錨點的clk的值。咱們這裏舉一個例子來講明:
其當前的clk值是Clock[27-0] 0x04301E02 這裏的Dsniff 的值是0,
bit27 = 0,咱們先看看當前的clk是0x04301E02,那麼下一個錨點必定是 大於當前值而小於(0x04301E02+800*2)
咱們先看看當前的Clock_Value (bits 26-1) mod Tsniff = (0x04301E02>>1)mod(800) = 737
那麼下一個錨點的clk = ((800-737)+ (0x04301E02>>1))*2 = 0x4301E80
那麼關於LMP 的概述就先介紹到這裏。