我有一个hid_discriptor,看起来像这样:
// from USB HID Specification 1.1, Appendix B.1
const uint8_t hid_descriptor_keyboard_boot_mode[] = {
/*
Keyboard
*/
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xa1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID 1
// Modifier byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0xe0, // Usage Minimum (Keyboard LeftControl)
0x29, 0xe7, // Usage Maxium (Keyboard Right GUI)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Reserved byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x03, // Input (Constant, Variable, Absolute)
// LED report + padding
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maxium (Kana)
0x91, 0x02, // Output (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Constant, Variable, Absolute)
// Keycodes
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xff, // Logical Maximum (1)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (Reserved (no event indicated))
0x29, 0xff, // Usage Maxium (Reserved)
0x81, 0x00, // Input (Data, Array)
0xc0, // End collection
};
适用于键盘代码;
但是,我也想在样本中添加消费者控制,因此我也可以向上/下发送音量。
/*
Consumer Control
*/
0x05, 0x0C, // Usage Page (Consumer Devices)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID
0x75, 0x09, 0x01, // Report Size
0x95, 0x09, 0x01, // Report Count
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x07, // Logical Maximum (2047)
0x19, 0x00, // Usage Minimum (0)
0x2A, 0xFF, 0x07, // Usage Maximum (2047)
0x81, 0x00, // Input (Data, Ary, Abs)
0xC0,
问题是,在提供的演示代码中;发送报告的代码是:
static void send_report(int modifier, int keycode){
uint8_t report[] = { /* 0xa1, */ modifier, 0, 0, keycode, 0, 0, 0, 0, 0};
hids_device_send_input_report(con_handle, report, sizeof(report));
}
这在发送击键方面起作用;当我在源代码中跟踪该调用时,它将转到此功能;
void hids_device_send_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len){
hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle);
if (!instance){
log_error("no instance for handle 0x%02x", con_handle);
return;
}
att_server_notify(con_handle, instance->hid_report_input_value_handle, report, report_len);
}
实际使用 instance->hid_report_input_value_handle
而不是hid_descriptor_keyboard_boot_mode;我也知道为什么(以防人们想知道);规格提到;
HID子类1为引导设备定义了两个描述符。设备可能 将其他数据附加到这些引导报告中,但是键盘报告的前8个字节和鼠标报告的前3个字节必须符合启动报告描述符定义的格式,以便BIOS正确解释数据。/blockquote>
... snip ...
加载HID类驱动程序时,它将发布更改协议, 阅读启动接口的报告描述符后,从引导协议更改为报告协议。
因此,在调用更改协议之后;该报告已加载到
hid_report_input_value_handle
中。因此,到目前为止,一切都清楚了。然后主要的问题出现了;如何将消费者控件发送到配对设备?这只是添加reportId的问题吗?例如
对于键盘键作为键盘事件:
uint8_t report[] = { 0x01, modifier, 0, 0, keycode, 0, 0, 0, 0, 0}; hids_device_send_input_report(con_handle, report, sizeof(report));
和用于消费者控制(播放/暂停)作为键盘事件:
uint8_t report[] = { 0x02, 0xCD, 0x00}; hids_device_send_input_report(con_handle, report, sizeof(report));
这是正确的吗?欢迎任何指导,BLE对我来说是新的。
键盘隐藏了描述符,鉴于它代表以下C结构:
//--------------------------------------------------------------------------------
// Keyboard/Keypad Page inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: CA:Keyboard
uint8_t KB_KeyboardKeyboardLeftControl : 1; // Usage 0x000700E0: Keyboard Left Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftShift : 1; // Usage 0x000700E1: Keyboard Left Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftAlt : 1; // Usage 0x000700E2: Keyboard Left Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftGui : 1; // Usage 0x000700E3: Keyboard Left GUI, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightControl : 1; // Usage 0x000700E4: Keyboard Right Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightShift : 1; // Usage 0x000700E5: Keyboard Right Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightAlt : 1; // Usage 0x000700E6: Keyboard Right Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightGui : 1; // Usage 0x000700E7: Keyboard Right GUI, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t Keyboard[6]; // Value = 0 to 255
} inputReport01_t;
...然后我希望发送功能看起来像:
uint8_t report[] = { 0x01, modifier, 0, keycode, 0, 0, 0, 0, 0}; // <-- i.e. one less byte
hids_device_send_input_report(con_handle, report, sizeof(report));
至于消费者设备报告,HID报告描述符似乎很不错。它应该是类似的(假设它与键盘报告描述符连接):
/*
Consumer Control
*/
0x05, 0x0C, // Usage Page (Consumer Devices)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x26, 0xFF, 0x07, // Logical Maximum (2047)
0x19, 0x00, // Usage Minimum (0)
0x2A, 0xFF, 0x07, // Usage Maximum (2047)
0x81, 0x00, // Input (Data, Ary, Abs)
0xC0,
...代表以下C结构:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 0C (GLOBAL) USAGE_PAGE 0x000C Consumer Device Page
09 01 (LOCAL) USAGE 0x000C0001 Consumer Control (Application Collection)
A1 01 (MAIN) COLLECTION 0x01 Application (Usage=0x000C0001: Page=Consumer Device Page, Usage=Consumer Control, Type=Application Collection)
85 02 (GLOBAL) REPORT_ID 0x02 (2)
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
26 FF07 (GLOBAL) LOGICAL_MAXIMUM 0x07FF (2047)
19 00 (LOCAL) USAGE_MINIMUM 0x000C0000 Unassigned <-- Info: Consider replacing 19 00 with 18
2A FF07 (LOCAL) USAGE_MAXIMUM 0x000C07FF
81 00 (MAIN) INPUT 0x00000000 (1 field x 16 bits) 0=Data 0=Array 0=Absolute
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Consumer Device Page inputReport 02 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
// Collection: CA:ConsumerControl
uint16_t ConsumerControl; // Value = 0 to 2047
} inputReport02_t;
...在这种情况下,发送消费者设备请求的功能应无需修改即可工作:
uint8_t report[] = { 0x02, 0xCD, 0x00};
hids_device_send_input_report(con_handle, report, sizeof(report));
...发送播放/暂停请求。
不要忘记通过按照每次发送(在键盘的情况下)来表示"无键":
:uint8_t report[] = { 0x01, modifier, 0, 0, 0, 0, 0, 0, 0}; // no keys pressed
hids_device_send_input_report(con_handle, report, sizeof(report));
这相当于传统的"密钥"通知。