BlueTooth: 藍芽歷史與發展
藍芽歷史:
藍芽(Bluetooth),或稱為藍芽,是一種無線個人區域網(Wireless PAN),最初由愛立信創制,後來由藍芽技術聯盟訂定技術標準。據說因為此技術尚在萌芽的階段,故將Bluetooth以“藍芽”的中文譯名在臺灣進行商 業的註冊,不過在2006年,該組織已將全球中文統一為“藍芽”。
1999年5月20日,索尼愛立信、IBM、英特爾、諾基亞及東芝等業界龍頭創立藍芽特別興趣組(SIG,Special Interest Group),制訂藍芽技術標準。
“藍芽”(Bluetooth)這名稱來自10世紀的丹麥國王哈拉爾德(Harald Gormsson)的外號。出身海盜家庭的哈拉爾德統一了北歐四分五裂的國家,成為維京王國的國王。由於他喜歡吃藍莓,牙齒常常被染成藍色,而獲得“藍 牙”的綽號,當時藍莓因為顏色怪異的緣故被認為是不適合食用的東西,因此這位愛嘗新的國王也成為創新與勇於嘗試的象徵。1998年,愛立信公司希望無線通訊技術能統一標準而取名“藍芽”。
1998年時Bluetooth推出0.7版,支援 Baseband 與 LMP(Link Manager Protocol)通訊協定兩部份。1999年推出0.8版,0.9版、1.0
Draft版,1.0a版、1.0B版。1.0 Draft版,完成SDP(Service Discovery Protocol)協定、TCS(Telephony Control Specification)協定。
2001年的1.1版正式列入IEEE標準,Bluetooth 1.1即為IEEE 802.15.1。
Bluetooth 2.0將傳輸率提升至2Mbps、3Mbps,遠大於1.x版的1Mbps(實際約723.2kbps)。
藍芽的標準是IEEE 802.15.1,藍芽協議工作在無需許可的ISM(Industrial Scientific Medical)頻段的2.45GHz。最高速度可達723.1kb/s。為了避免干擾可能使用2.45GHz的其它協議, 藍芽協議將該頻段劃分成79頻道,(頻寬為1MHZ)每秒的頻道轉換可達1600次。
1.2版本
這個版本向下相容1.1版,其主要改進包括:
(1)匿名方式:遮蔽裝置的硬體地址(BD_ADDR),保護使用者免受身分嗅探攻擊和跟蹤。從1.1版開始已經可以實現硬體匿名,但未被實施,因此對普通 消費者來說還是沒有此功能。
(2)自適應頻率跳躍(AFH,Adaptive Frequency Hopping):通過避免使用跳躍序列中的擁擠頻率,從而改善對無線電干涉的抵抗。
(3)更高的實際傳輸速度,實際測試約為 24KB/S(192Kbps) 左右。
(4)L2CAP層引入了流量控制和錯誤糾正機制
2.0版本
2.0版的內容還沒有什麼明確的資訊,但愛立信的研究者公佈了一些內容:
(1)加入了“非跳躍窄頻通道”(Non-hopping narrowband channel )。
(1.1)因為不需要與每個裝置交換應答訊號,這種通道可以用來將各種器件的藍芽服務概要同時廣播到巨量的藍芽器件。應答訊號交換過程當前需要大約一秒。
(1.2)實時公共交通時刻表、基本的交通暢通性資訊和高階交通指向指示等未加密資訊可以以高速度傳送給裝置。
(2)更高的連線速度 (實際測試速度為72KB/s)
(3)支援多個速度水平
--------------------------------------------------------------------------------------------------------------------------
藍芽訪問技術的概述:
就像其他許多通訊技術,藍芽的模組層次構成了堆疊。其結構如下:
藍芽堆疊:
藍芽主機控制器模組Bluetooth Host Controller作為藍芽的底層,是典型的硬體實現,應用程式(或在藍芽上新增的服務)不能直接控制。藍芽主機模組允許應用程式通過藍芽連線傳送/接 受資料,或者配置連線引數:
· RFCOMM允許應用程式將藍芽連線模擬為串列埠進行操作。這樣可以支援傳統的協議。
· 邏輯連線控制和適配協議The Logical Link Control And Adaptation Protocol (L2CAP) 允許連線的finer-grained(?)控制。它用來控制多使用者的連線,處理報文的分割和組合。這是應用程式的常用選擇
· 服務發現協議The Service Discovery Protocol (SDP)用來定位和描述藍芽裝置提供或者可用的服務。應用程式主要在設定和另外的藍芽裝置通訊時使用它
· 主機控制介面The Host Controller Interface (HCI)驅動包裝了和硬體通訊的高層模組。
下面提到的API將為應用程式提供對RFCOMM, L2CAP, SDP,和部分的HCI操作支援。
描述
使用下面的API提供了藍芽的相應功能:
藍芽套接字——藍芽套接字通過一個類似TCP/IP套接字的介面封裝了對L2CAP和RFCOMM的操作。
藍芽服務發現數據庫——服務發現數據庫封裝了SDP的一側:本地服務用它來記錄服務的引數,以便讓遠端服務發現,並判斷是否適合使用。
藍芽服務發現代理——服務發現代理封裝了SDP的另外一側:它用來發現遠端裝置的服務和相應的服務的引數。
藍芽安全管理器——安全管理器提供了對於接入連線設直所需要的安全配置。
--------------------------------------------------------------------------------------------------------------------------
藍芽套接字概述:
目的發現其他藍芽裝置,並通過藍芽讀寫資料。
在通過藍芽建立通訊頻道中有兩個角色:發起方和接受方。接受方進行配置後等待發起方建立連 接。一旦連線建立,兩方是對等的,都可以傳送或接受資料。這個API可以在兩方進行程式設計。
結構關係
藍芽套接字API支援在L2CAP和RFCOMM層上的通訊。API基於客戶端套接字 API,客戶端套接字API是允許客戶端和遠端裝置連線或者讓遠端裝置連線自身,並在斷開前傳送和接收資料標準API。藍芽套接字API中還為藍芽的應用 加入了適當的型別和常量
描述
API有五個關鍵的概念:套接字地址,遠端裝置詢問,RFCOMM命令和選項,L2CAP命 令和HCI命令
套接字地址
每個藍芽裝置都有一個唯一的48位地址,封裝在TBTDevAddr。
套接字API通過TSockAddr封裝了一個泛化的通訊終點,而藍芽則提供了一個專門的版 本TBTSockAddr,裡面添加了藍芽裝置地址。
遠端裝置質詢
客戶端能通過RHostResolver詢問遠端裝置是否可用。一個 TinquirySockAddr型別的引數用來提供這樣地詢問:主要是用來限制對裝置細節類的發現。
命令和選項
我們能夠通過呼叫RSocket::Ioctl()傳送命令到一個RFCOMM套接字。套接 字的選項則能夠分別通過Rsocket::GetOpt()和Rsocket::SetOpt()來設定。通過Rsocket::Ioctl(),我們能 傳送命令到L2CAP套接字和HCI層。
-------------------------------------------------------------------------------------------------------------------------
Bluetooth link:
這個連線會有以下內容:
Bluetooth OS Design Development
Bluetooth Application Development
Bluetooth Registry Settings
Bluetooth Security
Bluetooth Performance Best Practices
Bluetooth Migration
Bluetooth Reference
這個連線詳細講了藍芽 Winsock Interface Sample
Bluetooth Application Development Samples
Bluetooth Samples
-------------------------------------------------------------------------------------------------------------------------
網上找的BlueTooth Socket的例子:
WORD wVersionRequested = 0x202;
WSADATA m_data;
SOCKET s, s1;
if( 0 == ::WSAStartup( wVersionRequested, &m_data ) ) {
s = socket( AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM );
if ( s == INVALID_SOCKET ) {
return;
}
SOCKADDR_BTH address;
memset( &address, 0x00, sizeof(address) );
address.addressFamily = AF_BTH;
address.btAddr = (BTH_ADDR)0x000123456789;
address.serviceClassId = SerialPortServiceClass_UUID;
address.port = 17; // channel value gets from Mobile Phone.
s1 = connect( s, (sockaddr*)&address, sizeof(address) );
// S1 == 0
if( s1 == SOCKET_ERROR || s1 != 0 ) {
closesocket( s );
WSACleanup();
return;
}
char buf[512];
memset( buf, 0x00, sizeof(buf) );
int ret = recv( s1, (char*)buf, sizeof( buf ), 0 );
// ret == SOCKET_ERROR
// WSAGetLastError() == 0
}