mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-25 09:35:42 +00:00
hid_device: fix set report, extract functions for checking report size and report id
This commit is contained in:
parent
36680482ae
commit
a78157dda1
@ -122,7 +122,7 @@ static uint16_t hid_device_get_next_cid(void){
|
||||
|
||||
// TODO: store hid device connection into list
|
||||
static hid_device_t * hid_device_get_instance_for_cid(uint16_t cid){
|
||||
printf("control_cid 0x%02x, interrupt_cid 0x%02x, query_cid 0x%02x \n", _hid_device.control_cid, _hid_device.interrupt_cid, cid);
|
||||
// printf("control_cid 0x%02x, interrupt_cid 0x%02x, query_cid 0x%02x \n", _hid_device.control_cid, _hid_device.interrupt_cid, cid);
|
||||
if (_hid_device.cid == cid || _hid_device.control_cid == cid || _hid_device.interrupt_cid == cid){
|
||||
return &_hid_device;
|
||||
}
|
||||
@ -371,8 +371,6 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
|
||||
}
|
||||
hid_message_type_t message_type = packet[0] >> 4;
|
||||
// printf("L2CAP_DATA_PACKET message_type %d, packet_size %d \n", message_type, packet_size);
|
||||
printf_hexdump(packet, packet_size);
|
||||
|
||||
switch (message_type){
|
||||
case HID_MESSAGE_TYPE_GET_REPORT:
|
||||
device->report_type = packet[0] & 0x03;
|
||||
@ -413,6 +411,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
|
||||
case HID_MESSAGE_TYPE_SET_REPORT:
|
||||
device->state = HID_DEVICE_W2_SET_REPORT;
|
||||
device->max_packet_size = l2cap_max_mtu();
|
||||
device->report_type = packet[0] & 0x03;
|
||||
if (packet_size < 1){
|
||||
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
|
||||
break;
|
||||
@ -426,15 +425,15 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
|
||||
break;
|
||||
}
|
||||
device->report_id = packet[1];
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, device->max_packet_size-1, &packet[1]);
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, packet_size-1, &packet[1]);
|
||||
break;
|
||||
case HID_PROTOCOL_MODE_REPORT:
|
||||
// printf("HID_PROTOCOL_MODE_REPORT \n");
|
||||
if (packet_size >= 2){
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, device->max_packet_size-1, &packet[1]);
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, packet_size-1, &packet[1]);
|
||||
} else {
|
||||
uint8_t payload[] = {0};
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, device->max_packet_size-1, payload);
|
||||
device->report_status = (*hci_device_set_report)(device->cid, device->report_type, 1, payload);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -96,6 +96,11 @@ typedef enum {
|
||||
HID_PROTOCOL_MODE_REPORT
|
||||
} hid_protocol_mode_t;
|
||||
|
||||
typedef enum {
|
||||
HID_REPORT_ID_UNDECLARED,
|
||||
HID_REPORT_ID_VALID,
|
||||
HID_REPORT_ID_INVALID
|
||||
} hid_report_id_status_t;
|
||||
|
||||
/**
|
||||
* @brief Create HID Device SDP service record.
|
||||
|
@ -119,6 +119,7 @@ const uint8_t hid_descriptor_keyboard_boot_mode[] = {
|
||||
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
#define CHAR_ILLEGAL 0xff
|
||||
#define CHAR_RETURN '\n'
|
||||
@ -280,6 +281,53 @@ static int prepare_keyboard_report(hid_report_type_t report_type, int modifier,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int hid_report_size_valid(uint16_t cid, int report_id, hid_report_type_t report_type, int report_size){
|
||||
printf("report size %d, report type %d, report id %d\n", report_size, report_type, report_id);
|
||||
if (!report_size) return 0;
|
||||
if (hid_device_in_boot_protocol_mode(cid)){
|
||||
switch (report_id){
|
||||
case HID_BOOT_MODE_KEYBOARD_ID:
|
||||
if (report_size < 8) return 0;
|
||||
break;
|
||||
case HID_BOOT_MODE_MOUSE_ID:
|
||||
if (report_size < 1) return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
switch (report_type){
|
||||
case HID_REPORT_TYPE_INPUT:
|
||||
if (report_size < 8) return 0;
|
||||
break;
|
||||
case HID_REPORT_TYPE_OUTPUT:
|
||||
if (report_size < 1) return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static hid_report_id_status_t hid_report_id_status(uint16_t cid, uint16_t report_id){
|
||||
if (hid_device_in_boot_protocol_mode(cid)){
|
||||
switch (report_id){
|
||||
case HID_BOOT_MODE_KEYBOARD_ID:
|
||||
case HID_BOOT_MODE_MOUSE_ID:
|
||||
return HID_REPORT_ID_VALID;
|
||||
default:
|
||||
return HID_REPORT_ID_INVALID;
|
||||
}
|
||||
} else {
|
||||
#ifdef REPORT_ID_DECLARED
|
||||
if (report_id != 1) return HID_REPORT_ID_INVALID;
|
||||
return HID_REPORT_ID_VALID;
|
||||
#endif
|
||||
return HID_REPORT_ID_UNDECLARED;
|
||||
}
|
||||
}
|
||||
|
||||
static hid_handshake_param_type_t hid_get_report_callback(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, uint8_t report_max_size, int * out_report_size, uint8_t * out_report){
|
||||
UNUSED(cid);
|
||||
UNUSED(report_max_size);
|
||||
@ -292,8 +340,18 @@ static hid_handshake_param_type_t hid_get_report_callback(uint16_t cid, hid_repo
|
||||
int report_size = 0;
|
||||
int pos = 0;
|
||||
|
||||
hid_report_id_status_t report_id_status = hid_report_id_status(cid, report_id);
|
||||
switch (report_id_status){
|
||||
case HID_REPORT_ID_VALID:
|
||||
report_data[pos++] = report_id;
|
||||
break;
|
||||
case HID_REPORT_ID_INVALID:
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (hid_device_in_boot_protocol_mode(cid)){
|
||||
report_data[pos++] = report_id;
|
||||
switch (report_id){
|
||||
case HID_BOOT_MODE_KEYBOARD_ID:
|
||||
report_size = prepare_keyboard_report(report_type, send_modifier, send_keycode, &report_data[pos], sizeof(report_data) - pos);
|
||||
@ -304,13 +362,6 @@ static hid_handshake_param_type_t hid_get_report_callback(uint16_t cid, hid_repo
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
#ifdef REPORT_ID_DECLARED
|
||||
if (report_id != 1){
|
||||
printf("wrong ID, received %d\n", report_id);
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
|
||||
}
|
||||
report_data[pos++] = report_id;
|
||||
#endif
|
||||
report_size = prepare_keyboard_report(report_type, send_modifier, send_keycode, &report_data[pos], sizeof(report_data) - pos);
|
||||
}
|
||||
if (!report_size) return HID_HANDSHAKE_PARAM_TYPE_ERR_UNSUPPORTED_REQUEST;
|
||||
@ -323,75 +374,42 @@ static hid_handshake_param_type_t hid_get_report_callback(uint16_t cid, hid_repo
|
||||
|
||||
static hid_handshake_param_type_t hid_set_report_callback(uint16_t cid, hid_report_type_t report_type, int report_size, uint8_t * report){
|
||||
UNUSED(cid);
|
||||
UNUSED(report_type);
|
||||
UNUSED(report_size);
|
||||
UNUSED(report);
|
||||
int pos = 0;
|
||||
#ifdef REPORT_ID_DECLARED
|
||||
int report_id = report[pos++];
|
||||
if (report_id != 1) {
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
|
||||
}
|
||||
#endif
|
||||
printf("check report size %d\n", report_size);
|
||||
switch (report_type){
|
||||
case HID_REPORT_TYPE_INPUT:
|
||||
if (report_size < 9) {
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
case HID_REPORT_TYPE_OUTPUT:
|
||||
if (report_size < 2) {
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
printf("set report, size %d\n", report_size);
|
||||
printf_hexdump(report, report_size);
|
||||
printf("\n");
|
||||
|
||||
int report_id = report[0];
|
||||
hid_report_id_status_t report_id_status = hid_report_id_status(cid, report_id);
|
||||
switch (report_id_status){
|
||||
case HID_REPORT_ID_VALID:
|
||||
pos++;
|
||||
break;
|
||||
case HID_REPORT_ID_INVALID:
|
||||
printf("invalid id\n");
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
|
||||
default:
|
||||
report_id = 0;
|
||||
break;
|
||||
}
|
||||
printf(" report_id %d \n", report_id);
|
||||
|
||||
if (!hid_report_size_valid(cid, report_id, report_type, report_size-pos)){
|
||||
printf("invalid report size\n");
|
||||
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
|
||||
}
|
||||
return HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static void hid_report_data_callback(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int report_size, uint8_t * report){
|
||||
UNUSED(cid);
|
||||
UNUSED(report_type);
|
||||
UNUSED(report_size);
|
||||
UNUSED(report);
|
||||
UNUSED(report_id);
|
||||
printf("hid_report_data_callback\n");
|
||||
printf_hexdump(report, report_size);
|
||||
|
||||
if (!report_size){
|
||||
if ( hid_report_id_status(cid, report_id) == HID_REPORT_ID_INVALID ||
|
||||
!hid_report_size_valid(cid, report_id, report_type, report_size)){
|
||||
printf("ignore data packet\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("received report data, type %d, size %d\n", report_type, report_size);
|
||||
printf_hexdump(report, report_size);
|
||||
printf("\n");
|
||||
|
||||
if (hid_device_in_boot_protocol_mode(cid)){
|
||||
printf("Boot protocol mode\n");
|
||||
|
||||
if ( report_id < 2 ||
|
||||
(report_id == HID_BOOT_MODE_KEYBOARD_ID && report_size < 8) ||
|
||||
(report_id == HID_BOOT_MODE_MOUSE_ID && report_size < 1)) {
|
||||
printf("ignore data packet\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
printf("Report protocol mode\n");
|
||||
#ifdef REPORT_ID_DECLARED
|
||||
if (report_id != 1){
|
||||
printf("ignore data packet\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if ((report_type == HID_REPORT_TYPE_INPUT && report_size < 8) ||
|
||||
(report_type == HID_REPORT_TYPE_OUTPUT && report_size < 1)) {
|
||||
printf("ignore data packet\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("do smth with report\n");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user