mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-16 08:42:28 +00:00
hid_host: pass through input report to the app
This commit is contained in:
parent
01a4f16956
commit
a93a968fd2
@ -58,57 +58,7 @@
|
|||||||
#define CONTROL_MESSAGE_BITMASK_EXIT_SUSPEND 2
|
#define CONTROL_MESSAGE_BITMASK_EXIT_SUSPEND 2
|
||||||
#define CONTROL_MESSAGE_BITMASK_VIRTUAL_CABLE_UNPLUG 4
|
#define CONTROL_MESSAGE_BITMASK_VIRTUAL_CABLE_UNPLUG 4
|
||||||
|
|
||||||
// Simplified US Keyboard with Shift modifier
|
|
||||||
|
|
||||||
#define CHAR_ILLEGAL 0xff
|
|
||||||
#define CHAR_RETURN '\n'
|
|
||||||
#define CHAR_ESCAPE 27
|
|
||||||
#define CHAR_TAB '\t'
|
|
||||||
#define CHAR_BACKSPACE 0x7f
|
|
||||||
#define NUM_KEYS 6
|
|
||||||
|
|
||||||
// English (US)
|
|
||||||
//
|
|
||||||
static const uint8_t keytable_us_none [] = {
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 0-3
|
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', // 4-13
|
|
||||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', // 14-23
|
|
||||||
'u', 'v', 'w', 'x', 'y', 'z', // 24-29
|
|
||||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30-39
|
|
||||||
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', // 40-44
|
|
||||||
'-', '=', '[', ']', '\\', CHAR_ILLEGAL, ';', '\'', 0x60, ',', // 45-54
|
|
||||||
'.', '/', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 55-60
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 61-64
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 65-68
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 69-72
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 73-76
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 77-80
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 81-84
|
|
||||||
'*', '-', '+', '\n', '1', '2', '3', '4', '5', // 85-97
|
|
||||||
'6', '7', '8', '9', '0', '.', 0xa7, // 97-100
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t keytable_us_shift[] = {
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 0-3
|
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', // 4-13
|
|
||||||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', // 14-23
|
|
||||||
'U', 'V', 'W', 'X', 'Y', 'Z', // 24-29
|
|
||||||
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', // 30-39
|
|
||||||
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', // 40-44
|
|
||||||
'_', '+', '{', '}', '|', CHAR_ILLEGAL, ':', '"', 0x7E, '<', // 45-54
|
|
||||||
'>', '?', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 55-60
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 61-64
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 65-68
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 69-72
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 73-76
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 77-80
|
|
||||||
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 81-84
|
|
||||||
'*', '-', '+', '\n', '1', '2', '3', '4', '5', // 85-97
|
|
||||||
'6', '7', '8', '9', '0', '.', 0xb1, // 97-100
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t last_keys[NUM_KEYS];
|
|
||||||
|
|
||||||
static uint8_t * hid_host_descriptor_storage;
|
static uint8_t * hid_host_descriptor_storage;
|
||||||
static uint16_t hid_host_descriptor_storage_len;
|
static uint16_t hid_host_descriptor_storage_len;
|
||||||
@ -138,6 +88,28 @@ static uint16_t hid_descriptor_storage_get_available_space(void){
|
|||||||
return free_space;
|
return free_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hid_host_connection_t * hid_host_get_connection_for_hid_cid(uint16_t hid_cid){
|
||||||
|
btstack_linked_list_iterator_t it;
|
||||||
|
btstack_linked_list_iterator_init(&it, &connections);
|
||||||
|
while (btstack_linked_list_iterator_has_next(&it)){
|
||||||
|
hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it);
|
||||||
|
if (connection->hid_cid != hid_cid) continue;
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hid_host_connection_t * hid_host_get_connection_for_l2cap_cid(uint16_t l2cap_cid){
|
||||||
|
btstack_linked_list_iterator_t it;
|
||||||
|
btstack_linked_list_iterator_init(&it, &connections);
|
||||||
|
while (btstack_linked_list_iterator_has_next(&it)){
|
||||||
|
hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it);
|
||||||
|
if ((connection->interrupt_cid != l2cap_cid) && (connection->control_cid != l2cap_cid)) continue;
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void hid_descriptor_storage_init(hid_host_connection_t * connection){
|
static void hid_descriptor_storage_init(hid_host_connection_t * connection){
|
||||||
connection->hid_descriptor_len = 0;
|
connection->hid_descriptor_len = 0;
|
||||||
connection->hid_descriptor_max_len = hid_descriptor_storage_get_available_space();
|
connection->hid_descriptor_max_len = hid_descriptor_storage_get_available_space();
|
||||||
@ -173,11 +145,19 @@ static void hid_descriptor_storage_delete(hid_host_connection_t * connection){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t * hid_descriptor_storage_get_descriptor_data(hid_host_connection_t * connection){
|
const uint8_t * hid_descriptor_storage_get_descriptor_data(uint16_t hid_cid){
|
||||||
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
|
if (!connection){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return &hid_host_descriptor_storage[connection->hid_descriptor_offset];
|
return &hid_host_descriptor_storage[connection->hid_descriptor_offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t hid_descriptor_storage_get_descriptor_len(hid_host_connection_t * connection){
|
const uint16_t hid_descriptor_storage_get_descriptor_len(uint16_t hid_cid){
|
||||||
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
|
if (!connection){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return connection->hid_descriptor_len;
|
return connection->hid_descriptor_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,6 +236,20 @@ static void hid_setup_get_report_event(hid_host_connection_t * context, hid_hand
|
|||||||
buffer[1] = pos + report_len - 2;
|
buffer[1] = pos + report_len - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup report event - potentially in-place of original l2cap packet
|
||||||
|
static void hid_setup_report_event(hid_host_connection_t * context, uint8_t *buffer, uint16_t report_len){
|
||||||
|
uint16_t pos = 0;
|
||||||
|
buffer[pos++] = HCI_EVENT_HID_META;
|
||||||
|
pos++; // skip len
|
||||||
|
buffer[pos++] = HID_SUBEVENT_REPORT;
|
||||||
|
little_endian_store_16(buffer, pos, context->hid_cid);
|
||||||
|
pos += 2;
|
||||||
|
little_endian_store_16(buffer, pos, report_len);
|
||||||
|
pos += 2;
|
||||||
|
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){
|
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];
|
uint8_t event[7];
|
||||||
uint16_t pos = 0;
|
uint16_t pos = 0;
|
||||||
@ -311,27 +305,6 @@ static hid_host_connection_t * hid_host_get_connection_for_bd_addr(bd_addr_t add
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hid_host_connection_t * hid_host_get_connection_for_hid_cid(uint16_t hid_cid){
|
|
||||||
btstack_linked_list_iterator_t it;
|
|
||||||
btstack_linked_list_iterator_init(&it, &connections);
|
|
||||||
while (btstack_linked_list_iterator_has_next(&it)){
|
|
||||||
hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it);
|
|
||||||
if (connection->hid_cid != hid_cid) continue;
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static hid_host_connection_t * hid_host_get_connection_for_l2cap_cid(uint16_t l2cap_cid){
|
|
||||||
btstack_linked_list_iterator_t it;
|
|
||||||
btstack_linked_list_iterator_init(&it, &connections);
|
|
||||||
while (btstack_linked_list_iterator_has_next(&it)){
|
|
||||||
hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it);
|
|
||||||
if ((connection->interrupt_cid != l2cap_cid) && (connection->control_cid != l2cap_cid)) continue;
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hid_host_finalize_connection(hid_host_connection_t * connection){
|
static void hid_host_finalize_connection(hid_host_connection_t * connection){
|
||||||
btstack_linked_list_remove(&connections, (btstack_linked_item_t*) connection);
|
btstack_linked_list_remove(&connections, (btstack_linked_item_t*) connection);
|
||||||
@ -429,9 +402,6 @@ static void hid_host_handle_sdp_client_query_result(uint8_t packet_type, uint16_
|
|||||||
for (i = 0; i < descriptor_len; i++){
|
for (i = 0; i < descriptor_len; i++){
|
||||||
hid_descriptor_storage_store(connection, descriptor[i]);
|
hid_descriptor_storage_store(connection, descriptor[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("Stored Descriptor %d\n", hid_descriptor_storage_get_descriptor_len(connection));
|
|
||||||
// printf_hexdump(hid_descriptor_storage_get_descriptor_data(connection), hid_descriptor_storage_get_descriptor_len(connection));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -473,74 +443,6 @@ static void hid_host_handle_sdp_client_query_result(uint8_t packet_type, uint16_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_host_handle_interrupt_report(hid_host_connection_t * connection, const uint8_t * report, uint16_t report_len){
|
|
||||||
// check if HID Input Report
|
|
||||||
if (report_len < 1) return;
|
|
||||||
if (*report != 0xa1) return;
|
|
||||||
report++;
|
|
||||||
report_len--;
|
|
||||||
|
|
||||||
printf("hid_host_handle_interrupt_report len %d\n", hid_descriptor_storage_get_descriptor_len(connection));
|
|
||||||
printf_hexdump(hid_descriptor_storage_get_descriptor_data(connection), hid_descriptor_storage_get_descriptor_len(connection));
|
|
||||||
|
|
||||||
btstack_hid_parser_t parser;
|
|
||||||
btstack_hid_parser_init(&parser,
|
|
||||||
hid_descriptor_storage_get_descriptor_data(connection),
|
|
||||||
hid_descriptor_storage_get_descriptor_len(connection),
|
|
||||||
HID_REPORT_TYPE_INPUT, report, report_len);
|
|
||||||
|
|
||||||
int shift = 0;
|
|
||||||
uint8_t new_keys[NUM_KEYS];
|
|
||||||
memset(new_keys, 0, sizeof(new_keys));
|
|
||||||
int new_keys_count = 0;
|
|
||||||
while (btstack_hid_parser_has_more(&parser)){
|
|
||||||
uint16_t usage_page;
|
|
||||||
uint16_t usage;
|
|
||||||
int32_t value;
|
|
||||||
btstack_hid_parser_get_field(&parser, &usage_page, &usage, &value);
|
|
||||||
if (usage_page != 0x07) continue;
|
|
||||||
switch (usage){
|
|
||||||
case 0xe1:
|
|
||||||
case 0xe6:
|
|
||||||
if (value){
|
|
||||||
shift = 1;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
case 0x00:
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (usage >= sizeof(keytable_us_none)) continue;
|
|
||||||
|
|
||||||
// store new keys
|
|
||||||
new_keys[new_keys_count++] = usage;
|
|
||||||
|
|
||||||
// check if usage was used last time (and ignore in that case)
|
|
||||||
int i;
|
|
||||||
for (i=0;i<NUM_KEYS;i++){
|
|
||||||
if (usage == last_keys[i]){
|
|
||||||
usage = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (usage == 0) continue;
|
|
||||||
|
|
||||||
uint8_t key;
|
|
||||||
if (shift){
|
|
||||||
key = keytable_us_shift[usage];
|
|
||||||
} else {
|
|
||||||
key = keytable_us_none[usage];
|
|
||||||
}
|
|
||||||
if (key == CHAR_ILLEGAL) continue;
|
|
||||||
if (key == CHAR_BACKSPACE){
|
|
||||||
printf("\b \b"); // go back one char, print space, go back one char again
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("%c", key);
|
|
||||||
}
|
|
||||||
memcpy(last_keys, new_keys, NUM_KEYS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void hid_host_handle_control_packet(hid_host_connection_t * connection, uint8_t *packet, uint16_t size){
|
static void hid_host_handle_control_packet(hid_host_connection_t * connection, uint8_t *packet, uint16_t size){
|
||||||
UNUSED(size);
|
UNUSED(size);
|
||||||
@ -645,7 +547,7 @@ static void hid_host_handle_control_packet(hid_host_connection_t * connection, u
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("HID_MESSAGE_TYPE_DATA ???\n");
|
log_info("ignore invalid HID Control message");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connection->state = HID_HOST_CONNECTION_ESTABLISHED;
|
connection->state = HID_HOST_CONNECTION_ESTABLISHED;
|
||||||
@ -669,9 +571,12 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
if (!connection) break;
|
if (!connection) break;
|
||||||
|
|
||||||
if (channel == connection->interrupt_cid){
|
if (channel == connection->interrupt_cid){
|
||||||
hid_host_handle_interrupt_report(connection, packet, size);
|
uint8_t * in_place_event = packet - 6;
|
||||||
|
hid_setup_report_event(connection, in_place_event, size-1);
|
||||||
|
hid_callback(HCI_EVENT_PACKET, connection->hid_cid, in_place_event, size + 6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel == connection->control_cid){
|
if (channel == connection->control_cid){
|
||||||
hid_host_handle_control_packet(connection, packet, size);
|
hid_host_handle_control_packet(connection, packet, size);
|
||||||
break;
|
break;
|
||||||
@ -742,8 +647,6 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet);
|
|
||||||
|
|
||||||
switch (l2cap_event_channel_opened_get_psm(packet)){
|
switch (l2cap_event_channel_opened_get_psm(packet)){
|
||||||
case PSM_HID_CONTROL:
|
case PSM_HID_CONTROL:
|
||||||
if (connection->state != HID_HOST_W4_CONTROL_CONNECTION_ESTABLISHED) break;
|
if (connection->state != HID_HOST_W4_CONTROL_CONNECTION_ESTABLISHED) break;
|
||||||
@ -776,7 +679,6 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// disconnect?
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_EVENT_CHANNEL_CLOSED:
|
case L2CAP_EVENT_CHANNEL_CLOSED:
|
||||||
@ -838,7 +740,9 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HID_HOST_W2_SEND_SET_REPORT:{
|
case HID_HOST_W2_SEND_SET_REPORT:{
|
||||||
|
printf(" HID_HOST_W2_SEND_SET_REPORT control\n");
|
||||||
uint8_t header = (HID_MESSAGE_TYPE_SET_REPORT << 4) | connection->report_type;
|
uint8_t header = (HID_MESSAGE_TYPE_SET_REPORT << 4) | connection->report_type;
|
||||||
connection->state = HID_HOST_W4_SET_REPORT_RESPONSE;
|
connection->state = HID_HOST_W4_SET_REPORT_RESPONSE;
|
||||||
|
|
||||||
@ -854,6 +758,7 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HID_HOST_W2_SEND_GET_PROTOCOL:{
|
case HID_HOST_W2_SEND_GET_PROTOCOL:{
|
||||||
uint8_t header = (HID_MESSAGE_TYPE_GET_PROTOCOL << 4);
|
uint8_t header = (HID_MESSAGE_TYPE_GET_PROTOCOL << 4);
|
||||||
uint8_t report[] = {header};
|
uint8_t report[] = {header};
|
||||||
@ -861,6 +766,7 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HID_HOST_W2_SEND_SET_PROTOCOL:{
|
case HID_HOST_W2_SEND_SET_PROTOCOL:{
|
||||||
uint8_t header = (HID_MESSAGE_TYPE_SET_PROTOCOL << 4) | connection->protocol_mode;
|
uint8_t header = (HID_MESSAGE_TYPE_SET_PROTOCOL << 4) | connection->protocol_mode;
|
||||||
uint8_t report[] = {header};
|
uint8_t report[] = {header};
|
||||||
@ -869,31 +775,15 @@ static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8
|
|||||||
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
l2cap_send(connection->control_cid, (uint8_t*) report, sizeof(report));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("L2CAP_EVENT_CAN_SEND_NOW, hid_host.state = %d\n", connection->state);
|
|
||||||
switch(connection->state){
|
switch(connection->state){
|
||||||
|
|
||||||
case HID_HOST_W2_SEND_SET_REPORT:{
|
|
||||||
uint8_t header = (HID_MESSAGE_TYPE_SET_REPORT << 4) | connection->report_type;
|
|
||||||
connection->state = HID_HOST_W4_SET_REPORT_RESPONSE;
|
|
||||||
|
|
||||||
l2cap_reserve_packet_buffer();
|
|
||||||
uint8_t * out_buffer = l2cap_get_outgoing_buffer();
|
|
||||||
out_buffer[0] = header;
|
|
||||||
out_buffer[1] = connection->report_id;
|
|
||||||
(void)memcpy(out_buffer + 2, connection->report, connection->report_len);
|
|
||||||
if (connection->boot_mode){
|
|
||||||
l2cap_send_prepared(connection->interrupt_cid, connection->report_len + 2);
|
|
||||||
} else {
|
|
||||||
l2cap_send_prepared(connection->control_cid, connection->report_len + 2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case HID_HOST_W2_SEND_REPORT:{
|
case HID_HOST_W2_SEND_REPORT:{
|
||||||
connection->state = HID_HOST_W4_SEND_REPORT_RESPONSE;
|
connection->state = HID_HOST_W4_SEND_REPORT_RESPONSE;
|
||||||
uint8_t header = (HID_MESSAGE_TYPE_DATA << 4) | connection->report_type;
|
uint8_t header = (HID_MESSAGE_TYPE_DATA << 4) | connection->report_type;
|
||||||
@ -1054,13 +944,6 @@ uint8_t hid_host_send_virtual_cable_unplug(uint16_t hid_cid){
|
|||||||
return hid_host_send_control_message(hid_cid, CONTROL_MESSAGE_BITMASK_VIRTUAL_CABLE_UNPLUG);
|
return hid_host_send_control_message(hid_cid, CONTROL_MESSAGE_BITMASK_VIRTUAL_CABLE_UNPLUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void hid_host_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
|
|
||||||
UNUSED(hid_cid);
|
|
||||||
UNUSED(message);
|
|
||||||
UNUSED(message_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t hid_host_send_get_report(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id){
|
static uint8_t hid_host_send_get_report(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id){
|
||||||
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
|
|
||||||
@ -1091,7 +974,7 @@ uint8_t hid_host_send_get_input_report(uint16_t hid_cid, uint8_t report_id){
|
|||||||
return hid_host_send_get_report(hid_cid, HID_REPORT_TYPE_INPUT, report_id);
|
return hid_host_send_get_report(hid_cid, HID_REPORT_TYPE_INPUT, report_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t hid_host_send_set_report(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
uint8_t hid_host_send_set_report_on_control_channel(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, const uint8_t * report, uint8_t report_len){
|
||||||
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
|
|
||||||
if (!connection || !connection->control_cid){
|
if (!connection || !connection->control_cid){
|
||||||
@ -1099,7 +982,6 @@ static uint8_t hid_host_send_set_report(uint16_t hid_cid, hid_report_type_t repo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED){
|
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED){
|
||||||
log_info("hid_host_send_set_report: unexpected state 0%02x", HID_HOST_CONNECTION_ESTABLISHED);
|
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,18 +999,6 @@ static uint8_t hid_host_send_set_report(uint16_t hid_cid, hid_report_type_t repo
|
|||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t hid_host_send_set_output_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
|
||||||
return hid_host_send_set_report(hid_cid, HID_REPORT_TYPE_OUTPUT, report_id, report, report_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t hid_host_send_set_feature_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
|
||||||
return hid_host_send_set_report(hid_cid, HID_REPORT_TYPE_FEATURE, report_id, report, report_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t hid_host_send_set_input_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
|
||||||
return hid_host_send_set_report(hid_cid, HID_REPORT_TYPE_INPUT, report_id, report, report_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t hid_host_send_get_protocol(uint16_t hid_cid){
|
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);
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
if (!connection || !connection->control_cid){
|
if (!connection || !connection->control_cid){
|
||||||
@ -1145,8 +1015,10 @@ uint8_t hid_host_send_get_protocol(uint16_t hid_cid){
|
|||||||
|
|
||||||
uint8_t hid_host_send_set_protocol_mode(uint16_t hid_cid, hid_protocol_mode_t protocol_mode){
|
uint8_t hid_host_send_set_protocol_mode(uint16_t hid_cid, hid_protocol_mode_t protocol_mode){
|
||||||
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(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 || !connection->control_cid){
|
||||||
if (connection->state != HID_HOST_CONTROL_CONNECTION_ESTABLISHED){
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
|
}
|
||||||
|
if (connection->state != HID_HOST_CONNECTION_ESTABLISHED){
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1158,7 +1030,34 @@ uint8_t hid_host_send_set_protocol_mode(uint16_t hid_cid, hid_protocol_mode_t pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t hid_host_send_report(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
uint8_t hid_host_send_report_on_interrupt_channel(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, const uint8_t * report, uint8_t report_len){
|
||||||
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
|
if (!connection || !connection->control_cid || !connection->interrupt_cid) {
|
||||||
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection->state < HID_HOST_CONNECTION_ESTABLISHED) {
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
if (connection->state >= HID_HOST_W4_INTERRUPT_CONNECTION_DISCONNECTED){
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((l2cap_max_mtu() - 2) < report_len ){
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->state = HID_HOST_W2_SEND_REPORT;
|
||||||
|
connection->report_type = report_type;
|
||||||
|
connection->report_id = report_id;
|
||||||
|
connection->report = report;
|
||||||
|
connection->report_len = report_len;
|
||||||
|
|
||||||
|
l2cap_request_can_send_now_event(connection->interrupt_cid);
|
||||||
|
return ERROR_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hid_host_send_report_on_control_channel(uint16_t hid_cid, hid_report_type_t report_type, const uint8_t report_id, uint8_t * report, uint8_t report_len){
|
||||||
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
hid_host_connection_t * connection = hid_host_get_connection_for_hid_cid(hid_cid);
|
||||||
if (!connection || !connection->control_cid){
|
if (!connection || !connection->control_cid){
|
||||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
@ -1176,8 +1075,3 @@ static uint8_t hid_host_send_report(uint16_t hid_cid, hid_report_type_t report_
|
|||||||
l2cap_request_can_send_now_event(connection->control_cid);
|
l2cap_request_can_send_now_event(connection->control_cid);
|
||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t hid_host_send_output_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len){
|
|
||||||
return hid_host_send_report(hid_cid, HID_REPORT_TYPE_OUTPUT, report_id, report, report_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ typedef struct {
|
|||||||
uint8_t control_tasks;
|
uint8_t control_tasks;
|
||||||
|
|
||||||
// set report
|
// set report
|
||||||
uint8_t * report;
|
const uint8_t * report;
|
||||||
uint16_t report_len;
|
uint16_t report_len;
|
||||||
} hid_host_connection_t;
|
} hid_host_connection_t;
|
||||||
|
|
||||||
@ -156,15 +156,16 @@ uint8_t hid_host_send_virtual_cable_unplug(uint16_t hid_cid);
|
|||||||
* @brief Send HID message on interrupt channel
|
* @brief Send HID message on interrupt channel
|
||||||
* @param hid_cid
|
* @param hid_cid
|
||||||
*/
|
*/
|
||||||
void hid_host_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len);
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t hid_host_send_set_protocol_mode(uint16_t hid_cid, hid_protocol_mode_t protocol_mode);
|
uint8_t hid_host_send_set_protocol_mode(uint16_t hid_cid, hid_protocol_mode_t protocol_mode);
|
||||||
uint8_t hid_host_send_get_protocol(uint16_t hid_cid);
|
uint8_t hid_host_send_get_protocol(uint16_t hid_cid);
|
||||||
|
|
||||||
|
|
||||||
uint8_t hid_host_send_output_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
uint8_t hid_host_send_report_on_interrupt_channel(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, const uint8_t * report, uint8_t report_len);
|
||||||
|
uint8_t hid_host_send_report_on_control_channel(uint16_t hid_cid, hid_report_type_t report_type, const uint8_t report_id, uint8_t * report, uint8_t report_len);
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t hid_host_send_set_report_on_control_channel(uint16_t hid_cid, hid_report_type_t report_type, uint8_t report_id, const uint8_t * report, uint8_t report_len);
|
||||||
uint8_t hid_host_send_set_output_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
uint8_t hid_host_send_set_output_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
||||||
uint8_t hid_host_send_set_feature_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
uint8_t hid_host_send_set_feature_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
||||||
uint8_t hid_host_send_set_input_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
uint8_t hid_host_send_set_input_report(uint16_t hid_cid, uint8_t report_id, uint8_t * report, uint8_t report_len);
|
||||||
@ -174,6 +175,8 @@ uint8_t hid_host_send_get_feature_report(uint16_t hid_cid, uint8_t report_id);
|
|||||||
uint8_t hid_host_send_get_input_report(uint16_t hid_cid, uint8_t report_id);
|
uint8_t hid_host_send_get_input_report(uint16_t hid_cid, uint8_t report_id);
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t * hid_descriptor_storage_get_descriptor_data(uint16_t hid_cid);
|
||||||
|
const uint16_t hid_descriptor_storage_get_descriptor_len(uint16_t hid_cid);
|
||||||
/* API_END */
|
/* API_END */
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,18 +14,18 @@ HID11/HOS/HCT/BV-02-C: c, 4
|
|||||||
HID11/HOS/HCT/BV-03-C: c, 5
|
HID11/HOS/HCT/BV-03-C: c, 5
|
||||||
HID11/HOS/HCT/BV-04-C: c, p
|
HID11/HOS/HCT/BV-04-C: c, p
|
||||||
HID11/HOS/HCT/BV-05-C: c, r
|
HID11/HOS/HCT/BV-05-C: c, r
|
||||||
HID11/HOS/HCT/BV-06-C: c,
|
HID11/HOS/HCT/BV-06-C: c, U, c, u
|
||||||
HID11/HOS/HCT/BV-07-C: c,
|
HID11/HOS/HCT/BV-07-C: c, s
|
||||||
HID11/HOS/HCT/BV-08-C: c,
|
HID11/HOS/HCT/BV-08-C: c, s, S
|
||||||
HID11/HOS/HCT/BI-01-C: c,
|
HID11/HOS/HCT/BI-01-C: c, (wait)
|
||||||
HID11/HOS/HCT/BI-02-C: c,
|
HID11/HOS/HCT/BI-02-C: c, 1, (Confirmation), 3, (Confirmation), 3, (Confirmation)
|
||||||
|
|
||||||
HID11/HOS/BHCT/BV-03-C:
|
HID11/HOS/BHCT/BV-03-C:
|
||||||
HID11/HOS/BHCT/BI-01-C:
|
HID11/HOS/BHCT/BI-01-C:
|
||||||
|
|
||||||
HID11/HOS/HIT/BV-01-C:
|
HID11/HOS/HIT/BV-01-C: c
|
||||||
HID11/HOS/HIT/BV-02-C:
|
HID11/HOS/HIT/BV-02-C: c, 7
|
||||||
HID11/HOS/HIT/BI-01-C:
|
HID11/HOS/HIT/BI-01-C: c, (Confirmation), (Confirmation), (Confirmation)
|
||||||
|
|
||||||
HID11/HOS/BHIT/BV-01-C:
|
HID11/HOS/BHIT/BV-01-C:
|
||||||
HID11/HOS/BHIT/BV-02-C:
|
HID11/HOS/BHIT/BV-02-C:
|
||||||
|
@ -50,16 +50,68 @@
|
|||||||
#include "btstack.h"
|
#include "btstack.h"
|
||||||
|
|
||||||
#define MAX_ATTRIBUTE_VALUE_SIZE 300
|
#define MAX_ATTRIBUTE_VALUE_SIZE 300
|
||||||
|
#define NUM_KEYS 6
|
||||||
|
|
||||||
|
// Simplified US Keyboard with Shift modifier
|
||||||
|
|
||||||
|
#define CHAR_ILLEGAL 0xff
|
||||||
|
#define CHAR_RETURN '\n'
|
||||||
|
#define CHAR_ESCAPE 27
|
||||||
|
#define CHAR_TAB '\t'
|
||||||
|
#define CHAR_BACKSPACE 0x7f
|
||||||
|
|
||||||
|
|
||||||
|
// English (US)
|
||||||
|
//
|
||||||
|
static const uint8_t keytable_us_none [] = {
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 0-3
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', // 4-13
|
||||||
|
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', // 14-23
|
||||||
|
'u', 'v', 'w', 'x', 'y', 'z', // 24-29
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30-39
|
||||||
|
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', // 40-44
|
||||||
|
'-', '=', '[', ']', '\\', CHAR_ILLEGAL, ';', '\'', 0x60, ',', // 45-54
|
||||||
|
'.', '/', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 55-60
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 61-64
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 65-68
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 69-72
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 73-76
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 77-80
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 81-84
|
||||||
|
'*', '-', '+', '\n', '1', '2', '3', '4', '5', // 85-97
|
||||||
|
'6', '7', '8', '9', '0', '.', 0xa7, // 97-100
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t keytable_us_shift[] = {
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 0-3
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', // 4-13
|
||||||
|
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', // 14-23
|
||||||
|
'U', 'V', 'W', 'X', 'Y', 'Z', // 24-29
|
||||||
|
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', // 30-39
|
||||||
|
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', // 40-44
|
||||||
|
'_', '+', '{', '}', '|', CHAR_ILLEGAL, ':', '"', 0x7E, '<', // 45-54
|
||||||
|
'>', '?', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 55-60
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 61-64
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 65-68
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 69-72
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 73-76
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 77-80
|
||||||
|
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, // 81-84
|
||||||
|
'*', '-', '+', '\n', '1', '2', '3', '4', '5', // 85-97
|
||||||
|
'6', '7', '8', '9', '0', '.', 0xb1, // 97-100
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t last_keys[NUM_KEYS];
|
||||||
|
|
||||||
static enum {
|
static enum {
|
||||||
APP_IDLE,
|
APP_IDLE,
|
||||||
APP_CONNECTED
|
APP_CONNECTED
|
||||||
} app_state = APP_IDLE;
|
} app_state = APP_IDLE;
|
||||||
|
|
||||||
static uint16_t hid_host_cid = 0;
|
|
||||||
static bool unplugged;
|
static bool unplugged;
|
||||||
|
|
||||||
|
static uint16_t hid_host_cid = 0;
|
||||||
static bool boot_mode = false;
|
static bool boot_mode = false;
|
||||||
static bool send_through_interrupt_channel = false;
|
static bool send_through_interrupt_channel = false;
|
||||||
|
|
||||||
@ -96,6 +148,80 @@ static void hid_host_setup(void){
|
|||||||
setbuf(stdout, NULL);
|
setbuf(stdout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_input_report(const uint8_t * report, uint16_t report_len){
|
||||||
|
// check if HID Input Report
|
||||||
|
if (report_len < 1){
|
||||||
|
printf("ignore report: len 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*report != 0xa1) {
|
||||||
|
printf("ignore report: header 0x%02x", report[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf_hexdump(report, report_len);
|
||||||
|
|
||||||
|
report++;
|
||||||
|
report_len--;
|
||||||
|
|
||||||
|
btstack_hid_parser_t parser;
|
||||||
|
btstack_hid_parser_init(&parser,
|
||||||
|
hid_descriptor_storage_get_descriptor_data(hid_host_cid),
|
||||||
|
hid_descriptor_storage_get_descriptor_len(hid_host_cid),
|
||||||
|
HID_REPORT_TYPE_INPUT, report, report_len);
|
||||||
|
|
||||||
|
int shift = 0;
|
||||||
|
uint8_t new_keys[NUM_KEYS];
|
||||||
|
memset(new_keys, 0, sizeof(new_keys));
|
||||||
|
int new_keys_count = 0;
|
||||||
|
while (btstack_hid_parser_has_more(&parser)){
|
||||||
|
uint16_t usage_page;
|
||||||
|
uint16_t usage;
|
||||||
|
int32_t value;
|
||||||
|
btstack_hid_parser_get_field(&parser, &usage_page, &usage, &value);
|
||||||
|
if (usage_page != 0x07) continue;
|
||||||
|
switch (usage){
|
||||||
|
case 0xe1:
|
||||||
|
case 0xe6:
|
||||||
|
if (value){
|
||||||
|
shift = 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 0x00:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (usage >= sizeof(keytable_us_none)) continue;
|
||||||
|
|
||||||
|
// store new keys
|
||||||
|
new_keys[new_keys_count++] = usage;
|
||||||
|
|
||||||
|
// check if usage was used last time (and ignore in that case)
|
||||||
|
int i;
|
||||||
|
for (i=0;i<NUM_KEYS;i++){
|
||||||
|
if (usage == last_keys[i]){
|
||||||
|
usage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usage == 0) continue;
|
||||||
|
|
||||||
|
uint8_t key;
|
||||||
|
if (shift){
|
||||||
|
key = keytable_us_shift[usage];
|
||||||
|
} else {
|
||||||
|
key = keytable_us_none[usage];
|
||||||
|
}
|
||||||
|
if (key == CHAR_ILLEGAL) continue;
|
||||||
|
if (key == CHAR_BACKSPACE){
|
||||||
|
printf("\b \b"); // go back one char, print space, go back one char again
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("%c", key);
|
||||||
|
}
|
||||||
|
memcpy(last_keys, new_keys, NUM_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
UNUSED(channel);
|
UNUSED(channel);
|
||||||
@ -160,6 +286,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_SUBEVENT_CONNECTION_CLOSED:
|
case HID_SUBEVENT_CONNECTION_CLOSED:
|
||||||
|
hid_host_cid = 0;
|
||||||
|
boot_mode = false;
|
||||||
|
send_through_interrupt_channel = false;
|
||||||
printf("HID Host disconnected..\n");
|
printf("HID Host disconnected..\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -210,6 +339,12 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
printf("Protocol set.\n");
|
printf("Protocol set.\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HID_SUBEVENT_REPORT:
|
||||||
|
printf("Received input report[%d]: ", hid_subevent_report_get_report_len(packet));
|
||||||
|
handle_input_report(hid_subevent_report_get_report(packet), hid_subevent_report_get_report_len(packet));
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -247,7 +382,10 @@ static void show_usage(void){
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
printf("4 - Set report with id 0x03\n");
|
printf("4 - Set report with id 0x03\n");
|
||||||
printf("5 - Set report with id 0x05\n");
|
printf("5 - Set report with id 0x05\n");
|
||||||
// printf("6 - Set report with id 0x02\n");
|
printf("6 - Set report with id 0x02\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("7 - Send output report with id 0x03 on interrupt channel\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("p - Get protocol\n");
|
printf("p - Get protocol\n");
|
||||||
@ -286,7 +424,7 @@ static void stdin_process(char cmd){
|
|||||||
status = hid_host_send_get_protocol(hid_host_cid);
|
status = hid_host_send_get_protocol(hid_host_cid);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
printf("Set protocol in REPORT mode");
|
printf("Set protocol in REPORT mode\n");
|
||||||
boot_mode = false;
|
boot_mode = false;
|
||||||
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_REPORT);
|
status = hid_host_send_set_protocol_mode(hid_host_cid, HID_PROTOCOL_MODE_REPORT);
|
||||||
break;
|
break;
|
||||||
@ -307,13 +445,9 @@ static void stdin_process(char cmd){
|
|||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
printf("Send \'Unplug\'\n");
|
printf("Send \'Unplug\'\n");
|
||||||
unplugged = true;
|
|
||||||
hid_host_send_virtual_cable_unplug(hid_host_cid);
|
hid_host_send_virtual_cable_unplug(hid_host_cid);
|
||||||
break;
|
break;
|
||||||
case 'u':
|
|
||||||
printf("Reset \'Unplug\'\n");
|
|
||||||
unplugged = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
printf("Get report with id 0x05\n");
|
printf("Get report with id 0x05\n");
|
||||||
@ -328,62 +462,60 @@ static void stdin_process(char cmd){
|
|||||||
status = hid_host_send_get_input_report(hid_host_cid, 0x02);
|
status = hid_host_send_get_input_report(hid_host_cid, 0x02);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '4':{
|
|
||||||
uint8_t report[] = {0, 0};
|
|
||||||
printf("Set output report with id 0x03\n");
|
|
||||||
status = hid_host_send_set_output_report(hid_host_cid, 0x03, report, sizeof(report));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '5':{
|
|
||||||
uint8_t report[] = {0, 0, 0};
|
|
||||||
printf("Set feature report with id 0x05\n");
|
|
||||||
status = hid_host_send_set_feature_report(hid_host_cid, 0x05, report, sizeof(report));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// case '6':{
|
case 'x':
|
||||||
// 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 'X':
|
|
||||||
printf("Set send through interrupt channel\n");
|
printf("Set send through interrupt channel\n");
|
||||||
send_through_interrupt_channel = true;
|
send_through_interrupt_channel = true;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
|
||||||
printf("Set send through control channel\n");
|
|
||||||
send_through_interrupt_channel = true;
|
case '4':{
|
||||||
|
printf("Set output report with id 0x03\n");
|
||||||
|
uint8_t report[] = {0, 0};
|
||||||
|
status = hid_host_send_set_report_on_control_channel(hid_host_cid, HID_REPORT_TYPE_OUTPUT, 0x03, report, sizeof(report));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '5':{
|
||||||
|
printf("Set feature report with id 0x05\n");
|
||||||
|
uint8_t report[] = {0, 0, 0};
|
||||||
|
status = hid_host_send_set_report_on_control_channel(hid_host_cid, HID_REPORT_TYPE_FEATURE, 0x05, report, sizeof(report));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '6':{
|
||||||
|
printf("Set input report with id 0x02\n");
|
||||||
|
uint8_t report[] = {0, 0, 0, 0};
|
||||||
|
status = hid_host_send_set_report_on_control_channel(hid_host_cid, HID_REPORT_TYPE_INPUT, 0x02, report, sizeof(report));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '7':
|
||||||
|
printf("Send output report with id 0x03 on interrupt channel\n");
|
||||||
|
uint8_t report[] = {0, 0};
|
||||||
|
status = hid_host_send_report_on_interrupt_channel(hid_host_cid, HID_REPORT_TYPE_OUTPUT, 0x03, report, sizeof(report));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '8':{
|
|
||||||
uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
// case '8':{
|
||||||
printf("Send output report with id 0x03\n");
|
// uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
status = hid_host_send_output_report(hid_host_cid, 0x03, report, sizeof(report));
|
// printf("Send output report with id 0x03\n");
|
||||||
break;
|
// status = hid_host_send_output_report(hid_host_cid, 0x03, report, sizeof(report));
|
||||||
}
|
// break;
|
||||||
case '9':{
|
// }
|
||||||
uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
// case '9':{
|
||||||
printf("Set output report with id 0x01\n");
|
// uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
status = hid_host_send_set_output_report(hid_host_cid, 0x01, report, sizeof(report));
|
// printf("Set output report with id 0x01\n");
|
||||||
break;
|
// status = hid_host_send_set_output_report(hid_host_cid, 0x01, report, sizeof(report));
|
||||||
}
|
// break;
|
||||||
case '0':{
|
// }
|
||||||
uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
// case '0':{
|
||||||
printf("Send output report with id 0x01\n");
|
// uint8_t report[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
status = hid_host_send_output_report(hid_host_cid, 0x01, report, sizeof(report));
|
// printf("Send output report with id 0x01\n");
|
||||||
break;
|
// status = hid_host_send_output_report(hid_host_cid, 0x01, report, sizeof(report));
|
||||||
}
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user