Bluetooth HCI Data format

HCI (Host Control Interface) 是 Bluetooth SIG 設計用來提供Host 與 Bluetooth Module 連接的軟體介面(Software Inferface),在實際連結的硬體上目前制定了Transport 可以使HOST 與BT Module 實際連結有所依據,目前已經制定的Transport 有

  • UART
  • USB
  • SD
  • 3-Wire UART
HCI 有四種基本型態的封包,在不同的傳輸層透過不同的方式區別,
  • Commands, 用於Host 對 BT Module的控制
    • 在UART  Transport 使用 0x01 放在packet的開頭作識別
    • USB Transport  是 control endpoint(endpoint 0)
  • ACL, 用於傳輸一般性資料具有基本的資料可靠性保證
    • UART transport 使用 0x02
    • USB transport用Bulk endpoint 傳輸
  • SCO, 用於語音資料的傳遞
    • UART transport 使用 0x03
    • USB transport用Isochronous endpoint 傳輸
  • Event, 用於BT Module 回應 Host 的控制
    • UART transport 使用 0x04
    • USB transport 則用 Interrupt endpoint
typedef  enum _HCI_PACKET_TYPE_ {
HCI_ACL = 0x02,
HCI_SCL = 0x03,
HCI_EVENT = 0x04
HCI 是採用 Little Endian, signal 採用2’s 補數表示(Refer Section 5.2, Part E, Volume 2, Core Spec.)
HCI 命令封包(Command Packet) 是由一個16bits 唯一操作碼(Opcode)開始, 操作碼由兩部份組成 分別是 OGF(OpCode Group Field, Lenght: 6bits) 與 OCF (OpCode Command Field, 10bits) OGF:0x3F (111111B)是保留給Vendor-Specific 測試使用, OGF:0x3E(111110B)則是保留給 Bluetooth Logo Test。
當OGF與OCF 都為0 時則是一個 NOP 命令,在流量控制中可能會需要使用到。
接在Opcode 後的就是命令參數總長度具有 8bits 長,每個參數有多長則依據不同的命令有所不同

HCI Command Packet Format
用C Strruce 可以這樣表示
UINT16 code;
struct {
unsigned int ocf :10;
unsigned int ogf : 6;
} op;
unsigned char Size;     // parameter total length
unsgined char* body; // context of parameters

OGF 目前定義了 6 個 Group

  1. 連結控制命令(Link Control Command), OGF: 0x01
  2. 連結方式命令(Link Policy Command), OGF: 0x02
  3. 控制器與基頻命令(Controller & Baseband Command), OGF: 0x03
  4. 資訊參數(Informational Parameters), OGF: 0x04
  5. 狀態參數(Status Parameters), OGF: 0x05
  6. 測試命令(Testing Command), OGF: 0x06
因此要對一個BT Module 下達進入測試模式(Enable Device Under Test Mode)的話透過 HCI 需要使用 OGF:0x06, 而OCF:0x03(Refer Section 7.6.3 Part E, Volume 2, Core Spec.)。而要離開的話則是使用 HCI_Reset (OGF:0x03, OCF:0x03, Refer Section 7.3.2 Part E, Volume 2, Core Spec. ) 。每當一個Command 下達給BT Module內的Control 後,會回應一個HCI Command Complete Event 給Host端表示完成命令,除了HCI_RESET 命令外。因為HCI_RESET是使得Controller進入重置狀態,因此當收到HCI_RESET 的 Command Complete Event 是表示Controller 正準備執行HCI_RESET 而已。
HCI Event 是BT Module 用來回應 HCI Command 的封包,基本結構如下

HCI Event Packet Format

對「Bluetooth HCI Data format」的想法

  1. Is there any HCI library for calling from Java or C++?

    My Bluetooth is connected with USB. I want to have a class which can provide at least 2 methods for interface like:

    Boolean isConnected(Bluetooth Profile) //I’m working with Handsfree AudioGateway
    String atCommand() // at commands in the data channel

    you’re very appreciated if you can build it so i can take a test.

    • the note just is HCI layer date, not for application
      I guess your program should work on a OS, like Windows and Linux
      you should to read about bluetooth application interface

      isConnected should to observed drivre status
      atCommand() may be to see RFCOMM profile

      • Thank you for your reply.

        I’m using Windows, Widcomm(Broadcom) Stack is my favorite, though BlueSoleil works fine.

        Both support Bluetooth Handsfree Profile. I’m using this profile to connect Bluetooth Handsfree unit and PC to enjoy Skype experience. It works fine.

        Bluetooth handsfree profile is RFCOMM dependent. Once connected, there’s a virtual RFCOMM is associated. I want to use an application to read the AT COMMAND pass through this RFCOMM port during connection. Unfortunately it is protected from accessing by other application. This is why I’m resolving the HCI layer. Widcomm SDK doesn’t support handsfree application. BlueSoleil SDK supports it, but I’m not sure the RFCOMM channel could be opened.

        I’m trying a way around, that is: how to read the AT COMMAND from the associated RFCOMM channel during the Handsfree connection.

  2. Great, I didn’t test the Portman, just wondering if it supports Virtual RFCOMM. It’s a GUI application. If I want to read the AT COMMAND passing through the virtual RFCOMM, how to do it in my program: use Winsock, or HCI interfacing? and how?

    • you can see PortMon describe " When you select a port to monitor, Portmon sends a request to its device driver that includes the NT name (e.g. \device\serial0) that you are interested in. The driver uses standard filtering APIs to attach its own filter device object to the target device object. First, it uses ZwCreateFile to open the target device. Then it translates the handle it receives back from ZwCreateFile to a device object pointer. After creating its own filter device object that matches the characteristics of the target, the driver calls IoAttachDeviceByPointer to establish the filter. From that point on the Portmon", you need to implement a filter driver to hook the RFCOMM port


在下方填入你的資料或按右方圖示以社群網站登入: 標誌

您的留言將使用 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )


您的留言將使用 Facebook 帳號。 登出 /  變更 )


連結到 %s