hid_device: get report fixes for no declared IDS case

This commit is contained in:
Milanka Ringwald 2018-10-10 12:02:03 +02:00
parent a1118d1129
commit c8cb324e27
3 changed files with 161 additions and 128 deletions

View File

@ -351,24 +351,74 @@ static inline void hid_device_emit_event(hid_device_t * context, uint8_t subeven
hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
}
static int hid_report_size_valid(uint16_t cid, int report_id, hid_report_type_t report_type, int report_size){
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 {
int size = btstack_hid_get_report_size_for_id(report_id, report_type, hid_descriptor_len, hid_descriptor);
if (size == 0 || size != report_size) return 0;
}
return 1;
}
static int hid_get_report_size_for_id(uint16_t cid, int report_id, hid_report_type_t report_type, uint16_t hid_descriptor_len, const uint8_t * hid_descriptor){
if (hid_device_in_boot_protocol_mode(cid)){
switch (report_id){
case HID_BOOT_MODE_KEYBOARD_ID:
return 8;
case HID_BOOT_MODE_MOUSE_ID:
return 3;
default:
return 0;
}
} else {
return btstack_hid_get_report_size_for_id(report_id, report_type, hid_descriptor_len, hid_descriptor);
}
}
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 {
return btstack_hid_id_valid(report_id, hid_descriptor_len, hid_descriptor);
}
}
static hid_handshake_param_type_t hid_device_set_report_cmd_is_valid(uint16_t cid, hid_report_type_t report_type, int report_size, uint8_t * report){
int pos = 0;
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;
}
int report_id = 0;
if (btstack_hid_report_id_declared(hid_descriptor_len, hid_descriptor)){
report_id = report[pos++];
hid_report_id_status_t report_id_status = hid_report_id_status(cid, report_id);
switch (report_id_status){
case HID_REPORT_ID_INVALID:
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
default:
break;
}
// printf("hid_device_set_report_cmd_is_valid: report_id %d, status %d \n", report_id, report_id_status);
}
if (!hid_report_size_valid(cid, report_id, report_type, report_size-pos)){
printf("invalid report size\n");
// printf("invalid report size\n");
// TODO clarify DCT/BI-03c
return HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
}
return HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL;
@ -404,10 +454,10 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
device->report_id = 0;
device->report_status = HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL;
device->state = HID_DEVICE_W2_GET_REPORT;
switch (device->protocol_mode){
case HID_PROTOCOL_MODE_BOOT:
if (!btstack_hid_report_id_declared(hid_descriptor_len, hid_descriptor) || packet_size < 2){
if (packet_size < 2){
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
break;
}
@ -415,7 +465,16 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
break;
case HID_PROTOCOL_MODE_REPORT:
if (!btstack_hid_report_id_declared(hid_descriptor_len, hid_descriptor)) {
printf("id are not in report\n");
if (packet_size < 2) break;
if (packet[0] & 0x08){
if (packet_size > 2) {
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
}
} else {
if (packet_size > 1) {
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
}
}
break;
}
if (packet_size < 2){
@ -423,29 +482,29 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
break;
}
device->report_id = packet[pos++];
hid_report_id_status_t report_id_status = hid_report_id_status(device->cid, device->report_id);
switch (report_id_status){
case HID_REPORT_ID_INVALID:
printf("id %d invalid\n", device->report_id);
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
break;
default:
printf("id %d, status %d\n", device->report_id,report_id_status);
break;
}
break;
}
device->expected_report_size = btstack_hid_get_report_size_for_id(device->report_id, device->report_type, hid_descriptor_len, hid_descriptor);
if (device->report_status != HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL){
hid_device_request_can_send_now_event(channel);
break;
}
hid_report_id_status_t report_id_status = hid_report_id_status(device->cid, device->report_id);
switch (report_id_status){
case HID_REPORT_ID_INVALID:
device->report_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_REPORT_ID;
break;
default:
break;
}
device->expected_report_size = hid_get_report_size_for_id(device->cid, device->report_id, device->report_type, hid_descriptor_len, hid_descriptor);
report_size = device->expected_report_size + pos; // add 1 for header size and report id
printf("report size with header and id %d\n", report_size);
if ((packet[0] & 0x08) && packet_size >= pos + 1){
device->report_size = btstack_min(btstack_min(little_endian_read_16(packet, pos), report_size), sizeof(report));
} else {
device->report_size = btstack_min(btstack_min(l2cap_max_mtu(), report_size), sizeof(report));
}
printf("report size with header and id, after %d\n", device->report_size);
hid_device_request_can_send_now_event(channel);
break;
@ -679,7 +738,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
report_size = 0;
status = (*hci_device_get_report)(device->cid, device->report_type, device->report_id, &report_size, &report[pos]);
printf(" report size %d, status after callback %d, expected report_size %d\n", report_size + pos, status, device->report_size);
printf(" report size %d, status after callback %d, expected report_size %d\n", report_size + pos, status, device->report_size + pos);
switch (status){
case 0:
@ -919,40 +978,3 @@ int hid_device_in_boot_protocol_mode(uint16_t hid_cid){
}
return hid_device->protocol_mode == HID_PROTOCOL_MODE_BOOT;
}
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 {
int size = btstack_hid_get_report_size_for_id(report_id, report_type, hid_descriptor_len, hid_descriptor);
if (size == 0 || size != report_size) return 0;
}
return 1;
}
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 {
return btstack_hid_id_valid(report_id, hid_descriptor_len, hid_descriptor);
}
}

View File

@ -189,9 +189,6 @@ void hid_device_send_control_message(uint16_t hid_cid, const uint8_t * message,
*/
int hid_device_in_boot_protocol_mode(uint16_t hid_cid);
int hid_report_size_valid(uint16_t cid, int report_id, hid_report_type_t report_type, int report_size);
hid_report_id_status_t hid_report_id_status(uint16_t cid, uint16_t report_id);
/* API_END */
/* Only needed for PTS Testing */

View File

@ -236,12 +236,16 @@ static void send_key(int modifier, int keycode){
}
static void send_keyboard_report_on_interrupt_channel(int modifier, int keycode){
uint8_t report[] = {0xa1, 0x01, modifier, 0, 0, keycode, 0, 0, 0, 0};
uint8_t report[] = {0xa1,
0x01,
modifier, 0, 0, keycode, 0, 0, 0, 0};
hid_device_send_interrupt_message(hid_cid, &report[0], sizeof(report));
}
static void send_mouse_report_on_interrupt_channel(uint8_t buttons, int8_t dx, int8_t dy){
uint8_t report[] = {0xa1, 0x02, buttons, dx, dy, 0};
uint8_t report[] = {0xa1,
0x02,
buttons, dx, dy, 0};
hid_device_send_interrupt_message(hid_cid, &report[0], sizeof(report));
}
@ -253,6 +257,8 @@ static int prepare_mouse_report(hid_report_type_t report_type, uint8_t buttons,
buffer[pos++] = buttons;
buffer[pos++] = (uint8_t) dx;
buffer[pos++] = (uint8_t) dy;
// buffer[pos++] = 0;
return pos;
}
@ -282,6 +288,7 @@ static int prepare_keyboard_report(hid_report_type_t report_type, int modifier,
}
static int hid_get_report_callback(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int * out_report_size, uint8_t * out_report){
UNUSED(report_id);
if (!report_data_ready){
printf("report_data_ready not ready\n");
return 0;
@ -306,11 +313,18 @@ static int hid_get_report_callback(uint16_t cid, hid_report_type_t report_type,
}
static void 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);
printf("set report\n");
}
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_id);
UNUSED(report_size);
UNUSED(report);
printf("do smth with report\n");
}
@ -335,48 +349,48 @@ static void stdin_process(char character){
uint8_t modifier;
uint8_t keycode;
int found;
// switch (character){
// case 'D':
// printf("Disconnect from %s...\n", bd_addr_to_str(device_addr));
// hid_device_disconnect(hid_cid);
// break;
// case 'c':
// printf("Connecting %s...\n", bd_addr_to_str(device_addr));
// hid_device_connect(device_addr, &hid_cid);
// return;
// case 'I':
// printf("Disconnect from intrrupt channel %s...\n", bd_addr_to_str(device_addr));
// hid_device_disconnect_interrupt_channel(hid_cid);
// break;
// case 'C':
// printf("Disconnect from control channel %s...\n", bd_addr_to_str(device_addr));
// hid_device_disconnect_control_channel(hid_cid);
// break;
// case 'l':
// printf("set limited discoverable mode\n");
// gap_discoverable_control(1);
// // TODO move into HCI init
// hci_send_cmd(&hci_write_current_iac_lap_two_iacs, 2, GAP_IAC_GENERAL_INQUIRY, GAP_IAC_LIMITED_INQUIRY);
// return;
// case 'm':
// send_mouse_on_interrupt_channel = 1;
// hid_device_request_can_send_now_event(hid_cid);
// break;
// case 'M':
// send_keyboard_on_interrupt_channel = 1;
// hid_device_request_can_send_now_event(hid_cid);
// break;
// case 'L':
// gap_discoverable_control(0);
// printf("reset limited discoverable mode\n");
// return;
// case '\n':
// case '\r':
// break;
// default:
// // show_usage();
// break;
// }
switch (character){
case 'D':
printf("Disconnect from %s...\n", bd_addr_to_str(device_addr));
hid_device_disconnect(hid_cid);
break;
case 'c':
printf("Connecting %s...\n", bd_addr_to_str(device_addr));
hid_device_connect(device_addr, &hid_cid);
return;
case 'I':
printf("Disconnect from intrrupt channel %s...\n", bd_addr_to_str(device_addr));
hid_device_disconnect_interrupt_channel(hid_cid);
break;
case 'C':
printf("Disconnect from control channel %s...\n", bd_addr_to_str(device_addr));
hid_device_disconnect_control_channel(hid_cid);
break;
case 'l':
printf("set limited discoverable mode\n");
gap_discoverable_control(1);
// TODO move into HCI init
hci_send_cmd(&hci_write_current_iac_lap_two_iacs, 2, GAP_IAC_GENERAL_INQUIRY, GAP_IAC_LIMITED_INQUIRY);
return;
case 'm':
send_mouse_on_interrupt_channel = 1;
hid_device_request_can_send_now_event(hid_cid);
break;
case 'M':
send_keyboard_on_interrupt_channel = 1;
hid_device_request_can_send_now_event(hid_cid);
break;
case 'L':
gap_discoverable_control(0);
printf("reset limited discoverable mode\n");
return;
case '\n':
case '\r':
break;
default:
// show_usage();
break;
}
switch (app_state){
case APP_BOOTING:
@ -494,18 +508,18 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * pack
break;
case HID_SUBEVENT_CAN_SEND_NOW:
// if (send_mouse_on_interrupt_channel){
// send_mouse_on_interrupt_channel = 0;
// printf("send mouse on interrupt channel\n");
// send_mouse_report_on_interrupt_channel(0,0,0);
// break;
// }
// if (send_keyboard_on_interrupt_channel){
// send_keyboard_on_interrupt_channel = 0;
// send_keyboard_report_on_interrupt_channel(send_modifier, send_keycode);
// send_keycode = 0;
// send_modifier = 0;
// }
if (send_mouse_on_interrupt_channel){
send_mouse_on_interrupt_channel = 0;
printf("send mouse on interrupt channel\n");
send_mouse_report_on_interrupt_channel(0,0,0);
break;
}
if (send_keyboard_on_interrupt_channel){
send_keyboard_on_interrupt_channel = 0;
send_keyboard_report_on_interrupt_channel(send_modifier, send_keycode);
send_keycode = 0;
send_modifier = 0;
}
if (send_keycode){
send_keyboard_report_on_interrupt_channel(send_modifier, send_keycode);