1. 藍牙設備的發現和同步簡介:
藍牙設備在建立連線之前,會透過在固定的頻段內選擇跳頻頻率或由被查詢的設備地址決定,快速交換握手資訊的時間和地址,迅速完成設備的時間與頻率同步。建立連線後,設備雙方根據通道跳變序列改變頻率,使跳頻頻率呈現隨機特性。
藍牙系統定義了在各種工作狀態下的跳頻序列,包括尋呼、尋呼響應、查詢、查詢響應以及信道跳變序列,不同狀態下的跳頻序列產生策略有所不同。
藍牙定義了32個頻點為一個頻段,劃分為79個子頻段工作的頻段及跳頻順序取決於所輸入的藍牙主控設備時鐘CLK和主控設備地址的最低28位有效位,即BD_ADDR[0…27]或者28位通用查詢接入碼(General Inquiry Access Code, GIAC)。
1)查詢/查詢掃描狀態:
藍牙設備透過查詢來尋找其周圍鄰近的設備,查詢設備每隔312.5微秒選擇一個新的頻率來發送查詢,被查詢設備每隔1.28秒選擇一次新的監聽頻率。查詢和被查詢設備使用通用查詢接入碼(GIAC, General Inquiry Access Code) LAP (低位地址部分) 作為查詢地址,GIAP LAP 為 0x9E8B33。藍牙標準規定不允許任何藍牙設備使用與 GIAP LAP 相同的地址。產生的 32 個查詢跳頻序列 (Inquiring hopping sequence) 均勻分布在 79 個頻率通道上。
2)呼叫/呼叫掃描狀態:
藍牙設備透過尋呼來呼叫其他設備加入其所在的微微網。尋呼設備每隔312.5微秒選擇一個新的頻率來發送尋呼在尋呼掃描時,被尋呼設備每隔1.28秒選擇一個新的監聽頻率。尋呼和被尋呼設備使用被尋呼設備地址(BT_ADDR)的低28個位元,產生的尋呼跳頻序列(paging-hopping sequence)是一個定義明確的週期序列,其各個頻點均勻分布在2.4G的79個頻率信道上。
3)連線狀態:
在目前的狀態下,藍牙通信設備雙方每隔625微秒改變一個頻率,使用主設備地址的最低28位有效位,產生的信道跳頻序列(Channel hopping sequence)週期非常長,而且79跳頻序列在任何一小段時間內都是接近均勻分布的。
2. 藍牙狀態轉換圖:

上圖是藍牙狀態轉換圖,從圖中可以看出STANDBY狀態是藍牙設備的預設狀態。在此模式下,設備處於低功耗狀態。
頁面:這個子狀態就是我們通常稱為的連接(尋呼),進行連接/啟動對應的slave的操作我們就稱為page。它是指:發起連接的設備(主設備)知道要連接設備的地址,所以可以直接傳呼。(想想傳呼機,要知道號碼才行)。
頁面掃描:這個子狀態是和page對應的,它就是等待被page的slave所處的狀態,換句話說,若想被page到,我們就要處於page scan的狀態。
詢問這就是我們通常所說的掃描狀態,這個狀態的設備會去掃描周圍的設備。它並不知道周圍有哪些設備,因此需要進行查詢(調查),類似於廣播(呼喊)。處於Inquiry Scan狀態的設備可以回應這個查詢。經過必要的協商之後,它們就可以進行連接了。
這裡需要說明的是:Inquiry之後,不需要進入Page就可以連接上設備。
查詢掃描這就是我們通常看到的可被發現的裝置。體現在上層就是我們在 Android 系統中點擊裝置可被周圍什麼發現,那裝置就處於這樣的狀態。
奴隸回應:這個就是在page的過程中,slave收到了master的page訊息,它會回應對應的page response訊息,同時自己就進入到了slave response的狀態。
主要回應:Master收到Slave回應的訊息後,會進入Master回應的狀態,同時會發送一個FHS的封包。
詢問回覆就是在 inquiry scan 的設備收到 inquiry 的訊息後,會發送 inquiry response 的訊息,之後它就會進入到 inquiry response 的狀態。
以上的各種狀態可以總結到以下的尋呼過程中:即尋呼過程按照以下步驟進行:
1) 一個設備(源)尋呼另一個設備(目的),此時處於尋呼狀態。(Page state)
2) 目標設備接收到該尋呼,此時處於尋呼掃描狀態。(Page Scan state)
3) 目的設備向源設備發送回覆,此時處於子設備回應狀態。(Slave Response state)
4) 源設備發送FHS封包到目的設備,此時處於主設備回應狀態。(Master Response state。)
5) 目的設備發送第二個回覆給源設備,此時處於子設備回應狀態(Slave Response state)。
6) 目的和來源設備切換並採用來源通道的參數,此時處於主設備響應狀態和子設備響應狀態。
3. 各種狀態間的轉換:
待命 -> 查詢當一個設備需要掃描周圍是否有其他設備時,會從standby狀態轉變為inquiry狀態。進入這個狀態後,它會不斷地發送inquiry訊息。inquiry訊息中並未標明任何與來源相關的資訊,但它可能包含應該響應該訊息的設備類型。處於inquiry scan狀態的設備可以響應inquiry訊息,但規範中指出,並非所有處於inquiry scan狀態的設備都必須響應inquiry訊息。因此,設備仍然具有一定的自主權。
處於 inquiry 狀態的設備會收到被搜索到的設備回傳的 response,需要注意的是,inquiry 狀態的設備並不需要對這個 response 做出任何形式的回應。因為在一段時間內進行 inquiry 的頻點範圍是有限的。若想搜尋到所有頻點的設備,需要確保 inquiry 的最短時間是 10.24 秒。這一點尤為重要。這也是為什麼我們通常會看到一些設備,例如 Android,它的搜尋時間通常設定為 10.24 秒,就是這個原因。
詢問->連結在搜尋到一個裝置之後,就可以根據搜尋到的資訊連接該裝置,從而進入到連線的狀態。
查詢->待命:若是未進行連接或者未搜尋到任何設備,在一定時間之後,仍然會回到待機的狀態。
連線->查詢:和standby->inquiry比較類似,唯一的差別在於standby到inquiry可以集中全部的能力去進行inquiry,而connection到inquiry則因為有其他事情需要處理,需要做一些善後的工作,比如將ACL link置於sniff狀態,若是有SCO或者ESCO,則會比inquiry的優先級更高,先確保SCO或者ESCO的傳輸,在空隙時間才能進行inquiry。
待機 -> 掃描查詢:如果一個設備想要被發現,就會進入到 inquiry scan 的狀態。在此狀態下,若收到 inquiry 的訊息,就可以進行回應。
查詢掃描 -> 查詢回應在收到詢問的訊息後,就可以回應對應的詢問訊息,從而進入到詢問回應的狀態。回應的 inquiry response 有兩種情況一種是很單純地只回應對應的FHS的封包,另一種則是包含EIR(Extended Inquiry Result)資料。是否有EIR資料是由FHS中的一個標誌位來決定的。
查詢回應->查詢掃描:這有兩種情況,一種是我們接下來要與主機(master)建立連接,從而進入連接(connection)狀態,必須要先經過搜尋掃描(inquiry scan)狀態後才能進入,而不是直接進入連接狀態。另一種情況則是回到原本的待機(standby)狀態,同樣地,我們仍然需要經過搜尋掃描(inquiry scan)狀態。
查詢掃描->連線:這個和inquiry到connection狀態是類似的,就不多說了。
連線->查詢掃描:這個狀態的變化和standy->inquiry scan是類似的,也就不多說了。
待機 -> 頁面掃描:若是一個設備想被page到,則需要進入page scan狀態。
頁面掃描->從屬回應:在收到page的訊息後,page scan的設備就會發送對應的回應訊息,然後進入到slave response的狀態。
從屬回應->連線:在第一次回應 response 之後,master 和 slave 的互動並沒有完全結束。他們仍然還有其他 msg 的互動,在 master 收到 slave 的 response 之後,他會發送對應的 FHS packet 過來,這時候 slave 處於 response 狀態的設備需要再次回覆一個 response。在 master 收到這第二個 response 的時候,他會發送一個 poll 的 packet 下來,從這個時間點開始,slave 正式進入到 connection 的狀態(step5)。具體可以參見下面的圖。

從屬回應->頁面掃描:這個就是上面這個過程出問題了,就會回到pagescan的狀態。
頁面掃描->連線:需要注意,這不是一個正常的流程,它發生在 connection->pagescan 後 page 失敗,然後會返回到 connection 狀態,而不是從 standby->page scan->connection。這和 page scan 到 standby 的情況類似。
頁面掃描->待命:頁面失敗,返回之前的待命狀態。
連線->頁面掃描:和standby到page scan類似。
待機/連線->頁面:若想要page到一個設備,就需要進入page的狀態。
頁面->待機/連線:同樣的頁面失敗回覆對應到初始狀態。
頁面->主控回應:在收到slave的response之後,就回應對應的FHS封包,從而進入到master response的狀態。
主伺服器回應->連線:和 slaveresponse 到 connection 是同步類似的,不詳細解釋。
主回應->頁面:同樣的是在上面出問題了,就回到頁面的狀態了。
連接->待機:這這個就是斷開連線了,建立連線需要經過很多中間步驟,斷開連線就沒那麼麻煩了,直接搞定。當然理論上還是需要透過reset或者detach指令來進行。
評論