hid_host: implement set report and get protocol response

This commit is contained in:
Milanka Ringwald 2021-01-12 11:54:12 +01:00 committed by Matthias Ringwald
parent baccf17d8f
commit 4a4b5586fb
3 changed files with 155 additions and 50 deletions

View File

@ -213,6 +213,19 @@ static void hid_emit_event(hid_host_connection_t * context, uint8_t subevent_typ
hid_callback(HCI_EVENT_PACKET, context->hid_cid, &event[0], pos);
}
static void hid_emit_event_with_status(hid_host_connection_t * context, uint8_t subevent_type, hid_handshake_param_type_t status){
uint8_t event[6];
uint16_t pos = 0;
event[pos++] = HCI_EVENT_HID_META;
pos++; // skip len
event[pos++] = subevent_type;
little_endian_store_16(event,pos,context->hid_cid);
pos += 2;
event[pos++] = status;
event[1] = pos - 2;
hid_callback(HCI_EVENT_PACKET, context->hid_cid, &event[0], pos);
}
static void hid_emit_incoming_connection_event(hid_host_connection_t * context){
uint8_t event[13];
uint16_t pos = 0;
@ -243,6 +256,20 @@ static void hid_setup_get_report_event(hid_host_connection_t * context, hid_hand
buffer[1] = pos + report_len - 2;
}
static void hid_emit_get_protocol_event(hid_host_connection_t * context, hid_handshake_param_type_t status, hid_protocol_mode_t protocol_mode){
uint8_t event[7];
uint16_t pos = 0;
event[pos++] = HCI_EVENT_HID_META;
pos++; // skip len
event[pos++] = HID_SUBEVENT_GET_PROTOCOL_RESPONSE;
little_endian_store_16(event,pos,context->hid_cid);
pos += 2;
event[pos++] = status;
event[pos++] = protocol_mode;
event[1] = pos - 2;
hid_callback(HCI_EVENT_PACKET, context->hid_cid, &event[0], pos);
}
// HID Host
static uint16_t hid_host_get_next_cid(void){
@ -520,7 +547,8 @@ static void hid_host_handle_control_packet(hid_host_connection_t * connection, u
uint8_t param;
hid_message_type_t message_type;
hid_handshake_param_type_t message_status;
// hid_report_type_t report_type;
hid_protocol_mode_t protocol_mode;
uint8_t * in_place_event;
uint8_t status;
@ -537,12 +565,13 @@ static void hid_host_handle_control_packet(hid_host_connection_t * connection, u
}
}
message_status = (hid_handshake_param_type_t)(packet[0] & 0x0F);
switch (connection->state){
case HID_HOST_W4_GET_REPORT_RESPONSE:
switch (message_type){
case HID_MESSAGE_TYPE_HANDSHAKE:{
uint8_t event[8];
message_status = (hid_handshake_param_type_t)(packet[0] & 0x0F);
hid_setup_get_report_event(connection, message_status, event, 0);
hid_callback(HCI_EVENT_PACKET, connection->hid_cid, event, sizeof(event));
break;
@ -557,18 +586,37 @@ static void hid_host_handle_control_packet(hid_host_connection_t * connection, u
break;
}
break;
case HID_HOST_W4_SET_REPORT_RESPONSE:
printf("HID_HOST_W4_SET_REPORT_RESPONSE \n");
hid_emit_event_with_status(connection, HID_SUBEVENT_SET_REPORT_RESPONSE, message_status);
break;
case HID_HOST_W4_GET_PROTOCOL_RESPONSE:
printf("HID_HOST_W4_GET_PROTOCOL_RESPONSE \n");
break;
case HID_HOST_W4_SEND_REPORT_RESPONSE:
printf("HID_HOST_W4_SEND_REPORT_RESPONSE\n");
protocol_mode = connection->protocol_mode;
switch (message_type){
case HID_MESSAGE_TYPE_DATA:
protocol_mode = (hid_protocol_mode_t)packet[1];
switch (protocol_mode){
case HID_PROTOCOL_MODE_BOOT:
case HID_PROTOCOL_MODE_REPORT:
message_status = HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL;
break;
default:
message_status = HID_HANDSHAKE_PARAM_TYPE_ERR_INVALID_PARAMETER;
break;
}
break;
default:
break;
}
hid_emit_get_protocol_event(connection, message_status, protocol_mode);
break;
case HID_HOST_W4_SET_PROTOCOL_RESPONSE:
printf("HID_HOST_W4_SET_PROTOCOL_RESPONSE \n");
message_status = (hid_handshake_param_type_t)(packet[0] & 0x0F);
hid_emit_event_with_status(connection, HID_SUBEVENT_SET_PROTOCOL_RESPONSE, message_status);
switch (message_status){
case HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL:
switch(connection->protocol_mode){
@ -591,6 +639,11 @@ static void hid_host_handle_control_packet(hid_host_connection_t * connection, u
break;
}
break;
case HID_HOST_W4_SEND_REPORT_RESPONSE:
printf("HID_HOST_W4_SEND_REPORT_RESPONSE\n");
break;
default:
printf("HID_MESSAGE_TYPE_DATA ???\n");
break;
@ -1046,10 +1099,14 @@ static uint8_t hid_host_send_set_report(uint16_t hid_cid, hid_report_type_t repo
}
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED){
printf("hid_host_send_set_report: unexpected state 0%02x\n", HID_HOST_CONNECTION_ESTABLISHED);
log_info("hid_host_send_set_report: unexpected state 0%02x", HID_HOST_CONNECTION_ESTABLISHED);
return ERROR_CODE_COMMAND_DISALLOWED;
}
if ((l2cap_max_mtu() - 2) < report_len ){
return ERROR_CODE_COMMAND_DISALLOWED;
}
connection->state = HID_HOST_W2_SEND_SET_REPORT;
connection->report_type = report_type;
connection->report_id = report_id;
@ -1074,11 +1131,14 @@ uint8_t hid_host_send_set_input_report(uint16_t hid_cid, uint8_t report_id, uint
uint8_t hid_host_send_get_protocol(uint16_t hid_cid){
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
if (!connection || !connection->control_cid) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED) return ERROR_CODE_COMMAND_DISALLOWED;
if (!connection || !connection->control_cid){
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED){
return ERROR_CODE_COMMAND_DISALLOWED;
}
connection->state = HID_HOST_W2_SEND_GET_PROTOCOL;
l2cap_request_can_send_now_event(connection->control_cid);
return ERROR_CODE_SUCCESS;
}

View File

@ -10,15 +10,15 @@ HID11/HOS/HCR/BV-03-I: c, U, c, "OK"
HID11/HOS/HCR/BV-04-I: c
HID11/HOS/HCT/BV-01-C: c, 1, 2, 3
HID11/HOS/HCT/BV-02-C:
HID11/HOS/HCT/BV-03-C:
HID11/HOS/HCT/BV-04-C:
HID11/HOS/HCT/BV-05-C:
HID11/HOS/HCT/BV-06-C:
HID11/HOS/HCT/BV-07-C:
HID11/HOS/HCT/BV-08-C:
HID11/HOS/HCT/BI-01-C:
HID11/HOS/HCT/BI-02-C:
HID11/HOS/HCT/BV-02-C: c, 4
HID11/HOS/HCT/BV-03-C: c, 5
HID11/HOS/HCT/BV-04-C: c, p
HID11/HOS/HCT/BV-05-C: c, r
HID11/HOS/HCT/BV-06-C: c,
HID11/HOS/HCT/BV-07-C: c,
HID11/HOS/HCT/BV-08-C: c,
HID11/HOS/HCT/BI-01-C: c,
HID11/HOS/HCT/BI-02-C: c,
HID11/HOS/BHCT/BV-03-C:
HID11/HOS/BHCT/BI-01-C:

View File

@ -166,7 +166,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
case HID_SUBEVENT_GET_REPORT_RESPONSE:
status = hid_subevent_get_report_response_get_handshake_status(packet);
if (status != HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL){
printf("Error get report result, status 0x%02x\n", status);
printf("Error get report, status 0x%02x\n", status);
break;
}
printf("Received report[%d]: ", hid_subevent_get_report_response_get_report_len(packet));
@ -174,6 +174,42 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
printf("\n");
break;
case HID_SUBEVENT_SET_REPORT_RESPONSE:
status = hid_subevent_set_report_response_get_handshake_status(packet);
if (status != HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL){
printf("Error set report, status 0x%02x\n", status);
break;
}
printf("Report set.\n");
break;
case HID_SUBEVENT_GET_PROTOCOL_RESPONSE:
status = hid_subevent_get_protocol_response_get_handshake_status(packet);
if (status != HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL){
printf("Error get report, status 0x%02x\n", status);
break;
}
switch ((hid_protocol_mode_t)hid_subevent_get_protocol_response_get_protocol_mode(packet)){
case HID_PROTOCOL_MODE_BOOT:
printf("HID device is in BOOT mode.\n");
break;
case HID_PROTOCOL_MODE_REPORT:
printf("HID device is in REPORT mode.\n");
break;
default:
break;
}
break;
case HID_SUBEVENT_SET_PROTOCOL_RESPONSE:
status = hid_subevent_set_report_response_get_handshake_status(packet);
if (status != HID_HANDSHAKE_PARAM_TYPE_SUCCESSFUL){
printf("Error set protocol, status 0x%02x\n", status);
break;
}
printf("Protocol set.\n");
break;
default:
break;
}
@ -206,9 +242,18 @@ static void show_usage(void){
printf("\n");
printf("1 - Get report with id 0x05\n");
printf("2 - Get report with id 0x03\n");
printf("3 - Get input report from with id 0x02\n");
printf("3 - Get report with id 0x02\n");
printf("\n");
printf("4 - Set report with id 0x03\n");
printf("5 - Set report with id 0x05\n");
// printf("6 - Set report with id 0x02\n");
printf("\n");
printf("p - Get protocol\n");
printf("r - Set protocol in REPORT mode\n");
printf("b - Set protocol in BOOT mode\n");
printf("o - get output report\n");
printf("Ctrl-c - exit\n");
printf("---\n");
}
@ -216,22 +261,6 @@ static void show_usage(void){
static void stdin_process(char cmd){
uint8_t status = ERROR_CODE_SUCCESS;
switch (cmd){
case 'R':
printf("Set Protocol mode\n");
boot_mode = false;
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_REPORT);
break;
case 'b':
printf("Set Boot mode\n");
boot_mode = false;
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_BOOT);
break;
case 'B':
printf("Set Boot mode\n");
boot_mode = true;
break;
case 'c':
if (unplugged){
printf("Cannot connect, host is unplugged.\n");
@ -251,6 +280,23 @@ static void stdin_process(char cmd){
hid_host_disconnect(hid_host_cid);
break;
case 'p':
printf("Get protocol\n");
status = hid_host_send_get_protocol(hid_host_cid);
break;
case 'r':
printf("Set protocol in REPORT mode");
boot_mode = false;
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_REPORT);
break;
case 'b':
printf("Set protocol in BOOT mode\n");
boot_mode = true;
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_BOOT);
break;
case 's':
printf("Send \'Suspend\'\n");
hid_host_send_suspend(hid_host_cid);
@ -295,22 +341,21 @@ static void stdin_process(char cmd){
break;
}
case '6':{
uint8_t report[] = {0, 0, 0, 0};
printf("Set input report with id 0x02\n");
status = hid_host_send_set_input_report(hid_host_cid, 0x02, report, sizeof(report));
break;
}
// case '6':{
// uint8_t report[] = {0, 0, 0, 0};
// printf("Set input report with id 0x02\n");
// status = hid_host_send_set_input_report(hid_host_cid, 0x02, report, sizeof(report));
// break;
// }
case '7':{
uint8_t report[] = {0,0,0, 0,0,0, 0,0};
printf("Set output report with id 0x01\n");
status = hid_host_send_set_output_report(hid_host_cid, 0x01, report, sizeof(report));
break;
}
case 'p':
printf("Get Protocol\n");
status = hid_host_send_get_protocol(hid_host_cid);
break;
case 'X':
printf("Set send through interrupt channel\n");