---
# System prepended metadata

title: HID Over I2C Protocol

---

# HID Over I2C Protocol

## INTRODUCTION
HID 最簡單的定義: 人可以控制的計算機系統設備。 市面上最常見的 HID 裝置如下
1. Pointing device(TP,Screen,Stylus)
2. Keyboard
3. Bar-code reader
4. VR

HID 協定是屬於<u>非同步</u>,溝通的規則上會有<u>**HOST**</u>和<u>**DEVICE**</u>。 協定中為 DEVICE 定義一種格式（Descriptors）,以向 HOST 描述其能力。 一旦 HOST 理解了與 DEVICE 的通信格式,就會對 DEVICE 進行認證流程，以便DEVICE將數據發送回 HOST。 

HID protocol spec 由以下幾點所代出:
1. Scenarios
   A.**Touchpad**
   B.**Sensor**
   C.TouchScreen
   D.Stylus
2. Descriptors
3. Reports
4. Requests
5. Power Management Error Correction

## I2C SPECIFIC DETAILS
### BUS SPEEDS

| Mode | Speeds | 
| -------- | -------- | 
| Standard Mode | 100 kbit/s | 
| <font color=#0000FF>**Fast Mode** </font>|<font color=#0000FF> **400 kbit/s** </font>| 
| Fast Mode Plus | 1 Mbit/s | 
| High Speed Mode | 3.4 Mbit/s | 

### INTERFACE LAYOUT
![](https://i.imgur.com/lSj5vLU.png)
目前的DEVICE HW設計是I2C BUS Controller(<font color=#FF0000>SDA、SCL</font>) + GPIO Controller(<font color=#FF0000>INT</font>)。 INT是當DEVICE需要將資料傳給HOST時,將電壓 pull low,已通知HOST,HOST 才開始震動CLK,來讓DEVICE 透過SDA傳送由1bit組成的資料。



### Byte Ordering 
傳送所有封包(Descriptors、Requests、Responses)是以<font color=#FF0000>Little endiend</font>方式→ 
LSB先，接著是MSB。
假設Device傳送 X軸資料 0x05,0xE1，收到後要轉換成 0xE105。

### SLAVE ADDRESS
每個裝置 or Sensor的datasheet都會說明自己的address。
實作時，雙方coder(Device and Host)要溝通好是<font color=#FF0000>7 or 8 </font>bits address。
LSB bit是表示這次的通訊資料，是Read or Write，所以address最多還是7-bit。

7bit 
![](https://i.imgur.com/mVBTE30.png)

8bit
![](https://i.imgur.com/XPuTBoK.png)

#### 科普小教室:傳統I2C
1.沒有INT pin
2.一條I2C Bus上面有多種Device
3.HOST Always Polling

## DESCRIPTORS

### HID Descriptor
目前介紹的是<font color=#FF0000>I2C</font>的HID Descriptor，USB HID Descriptor會不一樣。

#### HOST to DEVICE Command: 

| Address | HID Desc Addr-LSB | HID Desc Addr-MSB  | 
| -------- | -------- | -------- | 
| SLAVE Addr | 0x01 or 0x00 | 0x00 |


回覆封包的<font color=#FF0000>固定長度為30 bytes</font>,第一筆封包固定為0x1E。 資訊如下列

| Field              | Byte Offset | Size(Bytes) | Example |
| ------------------ | ----------- | -- | -- |
| HIDDescLength      | Index 0     | 2  | 0x001E |
| bcdVersion         | Index 2     | 2  | 0x0000 |
| ReportDescLength   | Index 4     | 2  | 0x0A30 |
| ReportDescRegister | Index 6     | 2  |0x0002 |
| InputRegister      | Index 8     | 2  | 0x0003 |
| MaxInputLength     | Index 10    | 2  | 0x0010 |
| OutputRegister     | Index 12    | 2  | 0x0000 |
| MaxOutputLength    | Index 14    | 2  | 0x0000 |
| CommandRegister    | Index 16    | 2  | 0x0000 |
| DataRegister       | Index 18    | 2  | 0x0000 |
| VendorID           | Index 20    | 2  | 0x0000 |
| ProductID          | Index 22    | 2  | 0x0000 |
| VersionID          | Index 24    | 2  | 0x0000 |
| Reserved           | Index 26    | 4  | 0x0000 |

Input、Output 、Feature Command 都會依照宣告的HID Descritpor執行。

Note:
以下必須唯一: 
**1. ReportDescRegister
2. InputRegister
3. OutputRegister
4. CommandRegister
5. DataRegister**

### Report Descriptor
ReportDescRegister與ReportDescLength是透過`Device Descriptor`得知。並非固定值。
意即DEVICE的**自我介紹**，讓HOST了解此DEVICE。
1. 哪一類的HID CLASS
2. Raw Data每一個byte所代表的意義，更可以細分成每一個bit。
PS.須以<font color=#FF0000>1bytes</font>為單位，意即定義bits要補齊成1bytes。

#### HOST to DEVICE Command: 

| Address | Report Desc Addr-LSB | Report Desc Addr-MSB   | 
| -------- | -------- | -------- | 
| SLAVE Addr | ReportDescRegister LSB | ReportDescRegister MSB |


#### 如何建立一個合格的Report Descriptor
1.[HID Descriptor tool 輔助工具](https://www.usb.org/document-library/hid-descriptor-tool)(From USB.Org, 年代久遠，Usage部分很久沒更新)
2.自己寫

[教學](https://hackmd.io/tvH-lr4tRJOoj5Q4OzpkOQ?both)

#### 專案上遇到的問題
1. Yellow Band(YB)的發生，大部分都會在Report Desc，因為長度較長，且有Power State切換的過程。

## REPORT PROTOCOL
HOST與DEVICE之間,透過三種Report方式做傳遞資料。資料長度 與 Report方式是透過 Report Descritpor去定義的。

1. Input Reports: DEVICE -> HOST , 單方向。
2. Output Reports: HOST -> DEVICE , 單方向。
3. Feature Report: HOST <-> DEVICE , 雙方向。

### Input Reports and Output Reports
資料的長度是透過HID Descriptor得知(wMaxInputLength,wMaxOutputLength)

根據Report Descriptor的Collection 宣告的方式，分成
1. SINGLE TOP LEVEL COLLECTION 
2. MULTIPLE TOP LEVEL COLLECTIONS。

如果有多個DEVICE宣告下，每個DEVICE都需要一個REPORT ID，讓HOST知道是哪個DEVICE的資料。

#### SINGLE TOP LEVEL COLLECTION
| Length| Report | 
| -------- | -------- | 
| 2 Unsigned Bytes | .... | 

#### MULTIPLE TOP LEVEL COLLECTION
| Length| Report ID | Report | 
| -------- | --------  | -------- | 
| 2 Unsigned Bytes| 1 Byte |  .... | 

### Feature Reports 
HOST只需要少許的資料長度，即可得到DEVICE設定或狀態。並且有以下特點
1. 不需要判斷INT pin的狀態。
2. 只能透過GET_REPORT,SET_REPORT的"Request"來處理。

#### 科普小教室: I2C over HID and USB 封包
1. USB:<font color=#FF0000>不</font>需要長度封包
2. I2C over HID:需要長度封包→MaxInputLength要包含長度2bytes

#### 專案上遇到的問題
假設HID Descriptor Max Input Len ，超過Report Desc的定義的長度，是否會有問題?

## REQUEST
HOST透過Command and Data Registers, 來管理DEVICE跟Info or 狀態為何。

### Command Register
除了Register之外，還須包含2 bytes value。Command Register只能透過HOST寫入，並由DEVICE讀取。

Data Value的定義
MSB
![](https://i.imgur.com/CfjvTsu.png)
LSB
![](https://i.imgur.com/m4llu6j.png)

* Reserved必須填0
* Repor Type的表示value如下:
    * 00 - Reserved
    * 01 - Input
    * 02 - Output
    * 11 - Feature
* Reprot ID是Report Descriptor定義的Feature Report ID。

### Data Register
要詢問DEVICE的Info或狀態，就要使用到，不能單獨使用，必須接在Command Register後面。Data Register的後面2bytes，必須包含長度(2bytes)
,再計算長度時，也需要將長度計算進去。
意即，長度後面有5bytes，長度必須為5+2=7。

### 常用到的Request

#### 1.RESET
有兩種RESETs方式:
1. HOST initiated Reset(HIR)
2. Device initiated Reset(DIR)

##### HIR
HOST可以隨時要求DEVICE進行initial，DEVICE須回到初始狀態
![](https://i.imgur.com/rauPmqs.png)
當HOST執行了此REQUEST,DEVICE需在<font color=#FF0000>5secs</font>內，將INT pull low，並且將2bytes 0x00回覆給HOST。不然HOST就不會將Input Report Data往<font color=#FF0000>Inbox Driver</font>送。

##### RESET Command:
| Command Register-LSB | Command Register-MSB |  Command Value-LSB | Command Value-MSB |
| -------- | -------- | -------- | -------- |
| Command Register LSB |Command Register MSB | 0x00 | 0x01 |

##### DIR
如果DEVICE遭遇到下列情況，也可以透過Input Report方式，將2bytes 0x00回覆給HOST,告知HOST 自己已經Reset了
1. ESD 打到Reset
2. 跑到錯誤的State Machine、無窮迴圈,執行了watch dog(Software Reset)

###### 專案上遇到的問題
1. HIR Reset CMD沒有回覆2bytes 0x00，是否會YB(Yellow Band)?

---

#### SET POWER
告知DEVICE,需要將Power State切成 Enable or Sleep。
![](https://i.imgur.com/F3gwr4B.png)
Power State Value:
* 00 - ON
* 01 - SLEEP
* 1X - RESERVED

#### SET POWER ENABLE Command:
| Command Register-LSB | Command Register-MSB |  Command Value-LSB | Command Value-MSB |
| -------- | -------- | -------- | -------- |
| Command Register LSB | Command Register MSB | 0x00 | 0x08 |

#### SET POWER SLEEP Command:
| Command Register-LSB | Command Register-MSB |  Command Value-LSB | Command Value-MSB |
| -------- | -------- | -------- | -------- |
| Command Register LSB | Command Register MSB | 0x01 | 0x08 |

#### SET REPORT
使用SET "FEATURE" REPORT的情況有兩種
1. 讓DEVICE執行對應的設定，與Driver or AP互相搭配。ex:進入update、Lid off sleep mode 等等
2. 請DEVICE"準備"回覆目前對應的狀態，不可以直接回傳，在Get Report之前。
ex: PID、IC Type、IC Status、Setting 跳頻 Threshold 等等。

![](https://i.imgur.com/o7Vha9p.png)

按照上述所提到的<font color=#FF0000>Data Register</font>，此時就要派他上場了。

#### SET FEATURE REPORT Command:(Feature Report 4 bytes,且 Get VID為例)
| Command Register-LSB | Command Register-MSB | Command Value-LSB | Command Value-MSB | Data Register-LSB | Data Register-MSB | Length-LSB | Length-MSB |Report ID | Extension Register-LSB | Extension Register-MSB | Extension Value-LSB | Extension Value-MSB |
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
| Command Register LSB | Command Register MSB | 0x30 + Report ID | 0x03 | Data Register LSB |  Data Register MSB | 0x07  | 0x00 | Report ID | 0x05 | 0x03 | 0xA0 | 0x01 |

#### GET REPORT
透過SET "FEATURE" REPORT準備好資料，接著等待HOST使用GET "FEATURE" REPORT來回覆DEVICE的狀態與資訊。
![](https://i.imgur.com/gDfoTWz.png)

#### GET FEATURE REPORT Command:
| Command Register-LSB | Command Register-MSB |  Command Value-LSB | Command Value-MSB | Data Register-LSB | Data Register-MSB |
| -- | -- | -- | -- |-- |-- |
| Command Register LSB | Command Register MSB | 0x30 + Report ID | 0x02 | Data Register LSB |  Data Register MSB |

回覆 GET FEATURE REPORT: (Feature Report 4 bytes,且 Get VID為例)

| Length-LSB | Length-MSB |Report ID | Extension Value-LSB | Extension Value-MSB | Reply Value-LSB | Reply Value-MSB |
| -- | -- | -- | -- | -- | -- | --|
| 0x07 | 0x00 | Report ID | 0xA0 | 0x01 | 0x05 | 0x0B |

#### 實例

##### SET REPORT(PTP 切 mode)
![](https://i.imgur.com/BhKvynO.png)

##### GET REPORT(Get VID)
![](https://i.imgur.com/qEd1yLp.png)

## DEVICE INITIAL 流程
HOST依序對DEVICE下此一連串Command:
Device Desc→ Set Power ON→ Reset→ Report Desc
![](https://i.imgur.com/iZ36n74.png)


