我有一个看起来像这样的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,
问题是,in the provided demo code;发送报告的代码是这样的:
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));
}
这在发送键击方面有效;当我在源代码中跟踪该调用时,它将转到to this function;
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;我也知道为什么(如果人们想知道的话); The spec mentions;
HID子类1为启动设备定义了两个描述符。设备可能 将其他数据添加到这些引导报告中,但是键盘报告的前8个字节和鼠标报告的前3个字节必须符合引导报告描述符所定义的格式,以便BIOS可以正确解释数据。>
... 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对我来说是新的,因此是一个问题。
答案 0 :(得分:0)
对于键盘HID描述符,假设它表示以下C结构:
This user lacks sufficient permissions to access this resource
...然后我希望send函数看起来像这样:
//--------------------------------------------------------------------------------
// 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;
至于“消费类设备”报告,HID报告描述符似乎非常错误。应该是这样的(假设它已连接到您的键盘报告描述符):
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));
...代表以下C结构:
/*
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,
...在这种情况下,您发送消费者设备请求的功能应该无需修改即可工作:
//--------------------------------------------------------------------------------
// 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));
这等效于传统的“按键”通知。