seo的網(wǎng)站建設(shè)湖南企業(yè)競(jìng)價(jià)優(yōu)化公司
一、前言
? ? ? ? 最近拿著藍(lán)牙自拍桿出去拍照時(shí),突然想了解下其中的原理,寫下了自己的學(xué)習(xí)過程,本文測(cè)試平臺(tái)為瑞昱8762C。
二、藍(lán)牙自拍桿
1、藍(lán)牙自拍桿實(shí)現(xiàn)拍照的原理
? ? ? ? 手機(jī)在拍照模式下按音量調(diào)節(jié)鍵就可以觸發(fā)快門按下拍照,藍(lán)牙自拍桿的原理也是通過模擬音量鍵觸發(fā),從而實(shí)現(xiàn)遠(yuǎn)程控制拍照。
2、藍(lán)牙自拍桿的藍(lán)牙服務(wù)
? ? ? ? 首先用nrf connect看下手上的藍(lán)牙自拍桿的廣播包和服務(wù)是怎么樣的,如下:
????????廣播:
????????
????????服務(wù):
????????
? ? ? ? ?即對(duì)于HID設(shè)備,廣播包數(shù)據(jù)中需要有HID設(shè)備的服務(wù)UUID(0x1812)和設(shè)備外觀(0x03C1(Keyboard))。
? ? ? ? 服務(wù)中需要有Human Interface Device服務(wù)和Battery Service服務(wù)。藍(lán)牙自拍桿通過Report特性Notify數(shù)據(jù)到手機(jī)。
????????同時(shí)還注意到,連接上藍(lán)牙自拍桿后手機(jī)需要能夠與藍(lán)牙自拍桿進(jìn)行連接和綁定,并且在連接后自拍桿的藍(lán)牙廣播消失,即功能上只能被一個(gè)設(shè)備連接。?
?3、代碼實(shí)現(xiàn)
? ? ? ? ?SDK目錄sdk\inc\bluetooth\profile\server下有好幾個(gè)HID設(shè)備的例程可以直接套用,其實(shí)像是
廣播和服務(wù)這些都沒什么可講的,是定好的標(biāo)準(zhǔn)。就是關(guān)于 hid report map部分可以講講,HID設(shè)備被連接上后,HOST會(huì)獲取hid report map來確定這個(gè)設(shè)備具有哪些功能(比如每次上報(bào)數(shù)據(jù)有幾個(gè)字節(jié),有什么按鍵,每個(gè)按鍵對(duì)應(yīng)上報(bào)數(shù)據(jù)的哪個(gè)字節(jié)和實(shí)現(xiàn)什么功能等等)。所以重點(diǎn)就是了解hid report map,下面附上一張自己用“HID Descriptor tool”工具(保存為.h文件)生成的hid report map:
// 藍(lán)牙自拍桿
static const uint8_t hids_report_descriptor[] =
{
? ? // Report ID 1: Advanced buttons
? ? 0x05, 0x0C, ? ? ? ? // Usage Page (Consumer)
? ? 0x09, 0x01, ? ? ? ? // Usage (Consumer Control)
? ? 0xA1, 0x01, ? ? ? ? // Collection (Application)
? ? 0x85, 0x01, ? ? ? ? // ? ? ?Report Id (1)
? ? 0x15, 0x00, ? ? ? ? // ? ? ?Logical minimum (0)
? ? 0x25, 0x01, ? ? ? ? // ? ? ?Logical maximum (1)
? ? 0x75, 0x01, ? ? ? ? // ? ? ?Report Size (1)
? ? 0x95, 0x01, ? ? ? ? // ? ? ?Report Count (1)
? ? 0x09, 0x94, ? ? ? ? // ? ? ?(Quit)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0x95, ? ? ? ? // ? ? ?(Help)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xEA, ? ? ? ? // ? ? ?(Volume Down)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xE9, ? ? ? ? // ? ? ?(Volume Up)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xCB, ? ? ? ? // ? ? ?(Tracking Decrement)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xCA, ? ? ? ? // ? ? ?(tracking Increment)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xB6, ? ? ? ? // ? ? ?(Scan Previous Track)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xB5, ? ? ? ? // ? ? ?(Scan Next Track)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xB1, ? ? ? ? // ? ? ?(Pause)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x09, 0xB0, ? ? ? ? // ? ? ?(Play)
? ? 0x81, 0x06, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0x75, 0x01, ? ? ? ? // ? ? ?Report Size (1)
? ? 0x95, 0x06, ? ? ? ? // ? ? ?Report Count (6)
? ? 0x81, 0x07, ? ? ? ? // ? ? ?Input (Data,Value,Relative,Bit Field)
? ? 0xC0 ? ? ? ? ? ? ? ?// End Collection
};
hid report map具體的了解可以參考文章(USB HID報(bào)告描述符教程 - 知乎),但是建議再粗略讀下手冊(cè)《Device Class Definition?for Human Interface?Devices (HID)》會(huì)有更好的理解,這個(gè)手冊(cè)里有講hid report map的解析機(jī)制。
根據(jù)自定義的hid report map每次上報(bào)需要有兩個(gè)字節(jié),每個(gè)bit的含義如下表:
bit位置 | 功能 |
bit 0 | Quit |
bit 1 | Help |
bit 2 | Volume Down |
bit 3 | Volume Up |
bit 4 | Tracking Decrement |
bit 5 | Tracking Increment |
bit 6 | Scan Previous Track |
bit 7 | Scan Next Track |
bit 8 | Pause |
bit 9 | Play |
bit 10~15 | Reserve |
以觸發(fā)Volume Up為例,上報(bào)數(shù)據(jù) 0x80 0x00(按下)后,再上報(bào)數(shù)據(jù)0x00 0x00(松開),就可以表示一次音量鍵按下和松開的過程,在手機(jī)相機(jī)模式下實(shí)現(xiàn)了單次拍照。
當(dāng)然,也可以用電腦藍(lán)牙連接,也可以控制電腦的音量,Pause 和 Play可以在電腦上控制視頻播放器的暫停和開始,更多的按鍵功能大家可以自己探索。
uint8_t rptData[2] = {0};
bool ret;rptData[0] = 0x08;
rptData[1] = 0x00;
ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, rptData, 2);os_delay(200);rptData[0] = 0x00;
rptData[1] = 0x00;
ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, rptData, 2);
三、藍(lán)牙鍵盤
1、代碼實(shí)現(xiàn)
? ? ? ? hid report map如下:
// 鍵盤
static const uint8_t hids_report_descriptor[] =
{
? ? 0x05, 0x01, ? ? ?// USAGE_PAGE (Generic Desktop)
? ? 0x09, 0x06, ? ? ?// USAGE (Keyboard)
? ? 0xa1, 0x01, ? ? ?// COLLECTION (Application)
? ? 0x85, 0x01, ? ? ?// ? ? REPORT_ID (1)
? ? 0x75, 0x01, ? ? ?// ? ? Report Size (1)
? ? 0x95, 0x08, ? ? ?// ? ? Report Count (8)
? ? 0x05, 0x07, ? ? ?// ? ? Usage Page (Key Codes)
? ? 0x19, 0xE0, ? ? ?// ? ? Usage Minimum (224)
? ? 0x29, 0xE7, ? ? ?// ? ? Usage Maximum (231)
? ? 0x15, 0x00, ? ? ?// ? ? Logical Minimum (0)
? ? 0x25, 0x01, ? ? ?// ? ? Logical Maximum (1)
? ? 0x81, 0x02, ? ? ?// ? ? Input (Data, Variable, Absolute); Modifier byte
? ? 0x95, 0x01, ? ? ?// ? ? Report Count (1)
? ? 0x75, 0x08, ? ? ?// ? ? Report Size (8)
? ? 0x81, 0x01, ? ? ?// ? ? Input (Constant); Reserved byte
? ? 0x95, 0x05, ? ? ?// ? ? Report Count (5)
? ? 0x75, 0x01, ? ? ?// ? ? Report Size (1)
? ? 0x05, 0x08, ? ? ?// ? ? Usage Page (LEDs)
? ? 0x19, 0x01, ? ? ?// ? ? Usage Minimum (1)
? ? 0x29, 0x05, ? ? ?// ? ? Usage Maximum (5)
? ? 0x91, 0x02, ? ? ?// ? ? Output (Data, Variable, Absolute); LED report
? ? 0x95, 0x01, ? ? ?// ? ? Report Count (1)
? ? 0x75, 0x03, ? ? ?// ? ? Report Size (3)
? ? 0x91, 0x01, ? ? ?// ? ? Output (Constant); LED report padding
? ? 0x95, 0x06, ? ? ?// ? ? Report Count (6)
? ? 0x75, 0x08, ? ? ?// ? ? Report Size (8)
? ? 0x15, 0x00, ? ? ?// ? ? Logical Minimum (0)
? ? 0x25, 0x65, ? ? ?// ? ? Logical Maximum (101)
? ? 0x05, 0x07, ? ? ?// ? ? Usage Page (Key Codes)
? ? 0x19, 0x00, ? ? ?// ? ? Usage Minimum (0)
? ? 0x29, 0x65, ? ? ?// ? ? Usage Maximum (101)
? ? 0x81, 0x00, ? ? ?// ? ? Input (Data, Array); Key array (6 bytes)
? ? 0xc0 ? ? ? ? ? ? // END_COLLECTION
}
第一個(gè)字節(jié)表示8個(gè)特殊的按鍵,第二個(gè)字節(jié)保留,后面6個(gè)字節(jié)的每個(gè)字節(jié)都可以表示一個(gè)按鍵的狀態(tài),可以同時(shí)有多個(gè)按鍵按下。
這里有個(gè)問題,hid report map中指示,224到231號(hào)鍵由第一個(gè)字節(jié)表示,0到101號(hào)鍵由最后6個(gè)字節(jié)的任意一個(gè)字節(jié)表示,那么這些鍵的號(hào)碼和實(shí)際上的按鍵是怎么樣的對(duì)應(yīng)關(guān)系呢?可以在手冊(cè)《HID Usage Tables FOR Universal Serial Bus (USB)》中找到這樣的對(duì)應(yīng)關(guān)系表,粘貼一段如下:?
?我們要上報(bào)的鍵號(hào)是這份表中的Usage ID,這個(gè)Usage ID和USB 鍵盤通信中上報(bào)的那個(gè)Keycode值是不一樣的東西。
當(dāng)上報(bào)0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00時(shí),就相當(dāng)于按下“A”鍵;當(dāng)上報(bào)0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00時(shí),就相當(dāng)于按下“win”鍵。
連接電腦和手機(jī)都可以使用,我用的小米手機(jī),藍(lán)牙鍵盤連上之后會(huì)默認(rèn)關(guān)閉屏幕鍵盤,需要設(shè)置同時(shí)支持屏幕鍵盤在輸入文字界面才會(huì)有屏幕鍵盤跳出來。
上面是標(biāo)準(zhǔn)的鍵盤,當(dāng)然我們也可以自定義鍵盤,比如只有三個(gè)按鍵Ctrl、C和V。hid report map如下:
// 自定義鍵盤
static const uint8_t hids_report_descriptor[] =
{
? ? 0x05, 0x01, ? ? ? ? ? ? ? ? ? ?// USAGE_PAGE (Generic Desktop)
? ? 0x09, 0x06, ? ? ? ? ? ? ? ? ? ?// USAGE (Keyboard)
? ? 0xa1, 0x01, ? ? ? ? ? ? ? ? ? ?// COLLECTION (Application)
? ? 0x85, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_ID (1)
? ? 0x75, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_SIZE (1)
? ? 0x95, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_COUNT (1)
? ? 0x15, 0x00, ? ? ? ? ? ? ? ? ? ?// ? LOGICAL_MINIMUM (0)
? ? 0x25, 0x01, ? ? ? ? ? ? ? ? ? ?// ? LOGICAL_MAXIMUM (1)
? ? 0x05, 0x07, ? ? ? ? ? ? ? ? ? ?// ? USAGE_PAGE (Keyboard)
? ? 0x09, 0xe0, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard LeftControl)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x09, 0x06, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard c and C)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x09, 0x19, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard v and V)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x95, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_COUNT (1)
? ? 0x75, 0x05, ? ? ? ? ? ? ? ? ? ?// ? REPORT_SIZE (5)
? ? 0x81, 0x07, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Cnst,Var,Rel) ? ? ? ? ? ? ? ? ? ?
? ? 0xc0, ? ? ? ? ? ? ? ? ? ? ? ? ?// END_COLLECTION
};
bit 0代表“Ctrl”鍵,bit 1代表“C”鍵,bit 2代表“V”鍵,bit 3~7預(yù)留。
當(dāng)我們上報(bào)0x03時(shí)代表按下Ctrl C(復(fù)制),上報(bào)0x05時(shí)代表按下Ctrl V(粘貼)。
四、藍(lán)牙鼠標(biāo)
1、代碼實(shí)現(xiàn)
hid report map如下:
// 鼠標(biāo)
static const uint8_t hids_report_descriptor[] =
{
? ? 0x05, 0x01, ? // USAGE_PAGE (Generic Desktop)
? ? 0x09, 0x02, ? // USAGE (Mouse)
? ? 0xa1, 0x01, ? // COLLECTION (Application)
? ? 0x85, 0x01, ? // ? REPORT_ID (1)
? ? 0x09, 0x01, ? // ? USAGE (Pointer)
? ? 0xa1, 0x00, ? // ? COLLECTION (Physical)
? ? 0x05, 0x09, ? // ? ? ? ? Usage Page (Buttons)
? ? 0x19, 0x01, ? // ? ? ? ? Usage Minimum (1)
? ? 0x29, 0x03, ? // ? ? ? ? Usage Maximum (3)
? ? 0x15, 0x00, ? // ? ? ? ? Logical Minimum (0)
? ? 0x25, 0x01, ? // ? ? ? ? Logical Maximum (1)
? ? 0x95, 0x03, ? // ? ? ? ? Report Count (3)
? ? 0x75, 0x01, ? // ? ? ? ? Report Size (1)
? ? 0x81, 0x02, ? // ? ? ? ? Input(Data, Variable, Absolute); 3 button bits
? ? 0x95, 0x01, ? // ? ? ? ? Report Count(1)
? ? 0x75, 0x05, ? // ? ? ? ? Report Size(5)
? ? 0x81, 0x03, ? // ? ? ? ? Input(Constant); ? ? ? ? ? ? ? ? 5 bit padding
? ? 0x05, 0x01, ? // ? ? ? ? Usage Page (Generic Desktop)
? ? 0x09, 0x30, ? // ? ? ? ? Usage (X)
? ? 0x09, 0x31, ? // ? ? ? ? Usage (Y)
? ? 0x09, 0x38, ? // ? ? ? ? Usage (Wheel)
? ? 0x15, 0x81, ? // ? ? ? ? Logical Minimum (-127)
? ? 0x25, 0x7F, ? // ? ? ? ? Logical Maximum (127)
? ? 0x75, 0x08, ? // ? ? ? ? Report Size (8)
? ? 0x95, 0x03, ? // ? ? ? ? Report Count (3)
? ? 0x81, 0x06, ? // ? ? ? ? Input(Data, Variable, Relative); 3 position bytes (X,Y,Wheel)
? ? 0xc0, ? ? ? ? // ? END_COLLECTION
? ? 0xc0 ? ? ? ? ?// END_COLLECTION
};
上報(bào)有4個(gè)字節(jié),bit 0 鼠標(biāo)左鍵,bit 1鼠標(biāo)右鍵,bit 2鼠標(biāo)中鍵,第二字節(jié)鼠標(biāo)X軸移動(dòng),第三字節(jié)鼠標(biāo)Y軸移動(dòng),第四字節(jié)滾輪移動(dòng)。
注意在調(diào)試的時(shí)候,hid report map變了要重新和設(shè)備綁定,不然會(huì)發(fā)現(xiàn)代碼改了測(cè)試時(shí)卻不生效。廣播包的設(shè)備外觀0x03C1(keyboard)記得改成0x03C2(mouse),這樣就可以看到鍵盤圖標(biāo)變成了鼠標(biāo)的圖標(biāo)。
五、復(fù)合設(shè)備
1、代碼實(shí)現(xiàn)
也可以像USB插線的設(shè)備一樣做成復(fù)合設(shè)備,把鍵盤和鼠標(biāo)兩個(gè)設(shè)備復(fù)合在一起,這樣連接一個(gè)藍(lán)牙設(shè)備就相當(dāng)于同時(shí)連接了一個(gè)藍(lán)牙鍵盤和一個(gè)藍(lán)牙鼠標(biāo)。
hid report map如下:
#define HIDS_KB_REPORT_ID ? ? ? ? ? ? ? ? ? ? ?1
#if FEATURE_SUPPORT_MULTIMEDIA_KEYBOARD
#define HIDS_MM_KB_REPORT_ID ? ? ? ? ? ? ? ? ? 2
#endif
// 復(fù)合設(shè)備
static const uint8_t hids_report_descriptor[] =
{
? ? 0x05, 0x01, ? ? ? ? ? ? ? ? ? ?// USAGE_PAGE (Generic Desktop)
? ? 0x09, 0x06, ? ? ? ? ? ? ? ? ? ?// USAGE (Keyboard)
? ? 0xa1, 0x01, ? ? ? ? ? ? ? ? ? ?// COLLECTION (Application)
? ? 0x85, HIDS_KB_REPORT_ID, ? ? ? ? ? ? ? ? ? ?// ? REPORT_ID (1)
? ? 0x75, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_SIZE (1)
? ? 0x95, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_COUNT (1)
? ? 0x15, 0x00, ? ? ? ? ? ? ? ? ? ?// ? LOGICAL_MINIMUM (0)
? ? 0x25, 0x01, ? ? ? ? ? ? ? ? ? ?// ? LOGICAL_MAXIMUM (1)
? ? 0x05, 0x07, ? ? ? ? ? ? ? ? ? ?// ? USAGE_PAGE (Keyboard)
? ? 0x09, 0xe0, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard LeftControl)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x09, 0x06, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard c and C)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x09, 0x19, ? ? ? ? ? ? ? ? ? ?// ? USAGE (Keyboard v and V)
? ? 0x81, 0x06, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Data,Var,Rel)
? ? 0x95, 0x01, ? ? ? ? ? ? ? ? ? ?// ? REPORT_COUNT (1)
? ? 0x75, 0x05, ? ? ? ? ? ? ? ? ? ?// ? REPORT_SIZE (5)
? ? 0x81, 0x07, ? ? ? ? ? ? ? ? ? ?// ? INPUT (Cnst,Var,Rel) ? ? ? ? ? ? ? ? ? ?
? ? 0xc0, ? ? ? ? ? ? ? ? ? ? ? ? ?// END_COLLECTION
#if FEATURE_SUPPORT_MULTIMEDIA_KEYBOARD
? ? 0x05, 0x01, ? // USAGE_PAGE (Generic Desktop)
? ? 0x09, 0x02, ? // USAGE (Mouse)
? ? 0xa1, 0x01, ? // COLLECTION (Application)
? ? 0x85, HIDS_MM_KB_REPORT_ID, ? // ? REPORT_ID (2)
? ? 0x09, 0x01, ? // ? USAGE (Pointer)
? ? 0xa1, 0x00, ? // ? COLLECTION (Physical)
? ? 0x05, 0x09, ? // ? ? ? ? Usage Page (Buttons)
? ? 0x19, 0x01, ? // ? ? ? ? Usage Minimum (1)
? ? 0x29, 0x03, ? // ? ? ? ? Usage Maximum (3)
? ? 0x15, 0x00, ? // ? ? ? ? Logical Minimum (0)
? ? 0x25, 0x01, ? // ? ? ? ? Logical Maximum (1)
? ? 0x95, 0x03, ? // ? ? ? ? Report Count (3)
? ? 0x75, 0x01, ? // ? ? ? ? Report Size (1)
? ? 0x81, 0x02, ? // ? ? ? ? Input(Data, Variable, Absolute); 3 button bits
? ? 0x95, 0x01, ? // ? ? ? ? Report Count(1)
? ? 0x75, 0x05, ? // ? ? ? ? Report Size(5)
? ? 0x81, 0x03, ? // ? ? ? ? Input(Constant); ? ? ? ? ? ? ? ? 5 bit padding
? ? 0x05, 0x01, ? // ? ? ? ? Usage Page (Generic Desktop)
? ? 0x09, 0x30, ? // ? ? ? ? Usage (X)
? ? 0x09, 0x31, ? // ? ? ? ? Usage (Y)
? ? 0x09, 0x38, ? // ? ? ? ? Usage (Wheel)
? ? 0x15, 0x81, ? // ? ? ? ? Logical Minimum (-127)
? ? 0x25, 0x7F, ? // ? ? ? ? Logical Maximum (127)
? ? 0x75, 0x08, ? // ? ? ? ? Report Size (8)
? ? 0x95, 0x03, ? // ? ? ? ? Report Count (3)
? ? 0x81, 0x06, ? // ? ? ? ? Input(Data, Variable, Relative); 3 position bytes (X,Y,Wheel)
? ? 0xc0, ? ? ? ? // ? END_COLLECTION
? ? 0xc0 ? ? ? ? ?// END_COLLECTION
#endif
};
?復(fù)合設(shè)備就是簡(jiǎn)單的把前面自定義鍵盤和鼠標(biāo)兩部分的report map拼在了一起。注意更改廣播包中的外觀屬性為0x03C0(HID),這樣連上電腦時(shí)可以顯示出鍵盤和鼠標(biāo)復(fù)合在一起的圖標(biāo),如果不改的話實(shí)測(cè)對(duì)功能也沒影響。
?對(duì)于兩個(gè)或以上的HID復(fù)合設(shè)備來說,是要在上報(bào)數(shù)據(jù)前加一個(gè)字節(jié)的report ID的,在這里鍵盤的report ID是1,鼠標(biāo)的report ID是2。那么上報(bào)0x01 0x02代表按下字母“C”鍵,上報(bào)0x02 0x02 0x00 0x00 0x00代表按下鼠標(biāo)右鍵。
對(duì)于瑞昱8762C平臺(tái)而言,在實(shí)際調(diào)試過程中,發(fā)現(xiàn)這樣發(fā)送數(shù)據(jù)不生效,需要打開宏“FEATURE_SUPPORT_MULTIMEDIA_KEYBOARD”即在Human Interface Device服務(wù)下再創(chuàng)建一個(gè)report特性給report ID為2的鼠標(biāo)上報(bào)數(shù)據(jù)用,這兩個(gè)report特性的特征值ID是一樣的,用nrf connect看的話只能看到一個(gè)report點(diǎn)。由于不同的設(shè)備數(shù)據(jù)通過不同的特征值上報(bào)給HOST,所以在瑞昱8762C這里上報(bào)的數(shù)據(jù)前不用加report ID。目前手里沒有抓包工具驗(yàn)證是否平臺(tái)在后續(xù)的內(nèi)部處理過程中加上了這個(gè)report ID。
六、部分測(cè)試代碼邏輯
? ? ? ? 我的調(diào)試過程是,在Human Interface Device服務(wù)外額外創(chuàng)建一個(gè)調(diào)試的服務(wù)來接收調(diào)試命令,實(shí)際上就是我要上報(bào)給HOST的數(shù)據(jù)先寫入調(diào)試命令,然后開發(fā)板再將命令轉(zhuǎn)交給HOST。
void cmd_process(uint8_t *cmdBuf, uint8_t len)
{
#if FEATURE_SUPPORT_MULTIMEDIA_KEYBOARDbool ret;// 首先區(qū)分發(fā)給誰if (cmdBuf[0] == HIDS_KB_REPORT_ID){ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, cmdBuf + 1, len - 1);os_delay(200);// 按鍵松開memset(cmdBuf, 0, len);ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, cmdBuf + 1, len - 1);}else{ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_MM_KB_INPUT_INDEX, cmdBuf + 1, len - 1);os_delay(200);// 按鍵松開memset(cmdBuf, 0, len);ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_MM_KB_INPUT_INDEX, cmdBuf + 1, len - 1);}myprintf("[%s] ret = %d\r\n", __func__, ret);
#elsebool ret;ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, cmdBuf, len);os_delay(200);memset(cmdBuf, 0, len);ret = hids_send_report(0, hids_srv_id, GATT_SRV_HID_KB_INPUT_INDEX, cmdBuf, len);myprintf("[%s] ret = %d\r\n", __func__, ret);
#endif
}
在復(fù)合設(shè)備的調(diào)試中,通過調(diào)試命令中的report ID區(qū)分從哪個(gè)report特性點(diǎn)上報(bào)數(shù)據(jù)給HOST。
七、參考資料
【低功耗藍(lán)牙】⑤ HID協(xié)議 - 嗶哩嗶哩
USB HID報(bào)告描述符教程 - 知乎
《Universal Serial Bus (USB)_Device Class Definition .pdf》
《HID Usage Tables FOR Universal Serial Bus (USB).pdf》
《HID Descriptor tool.zip》
《hids_rtl8762c.rar》hid設(shè)備調(diào)試demo,僅供參考
鏈接:https://pan.baidu.com/s/1UVz56o377uD3OTKnO5P5kg? 提取碼:hqus?
?