mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 22:20:37 +00:00
hids_client: implement hids_client_send_report
This commit is contained in:
parent
4274fa7022
commit
1624214b8f
@ -57,6 +57,7 @@
|
|||||||
|
|
||||||
static btstack_linked_list_t clients;
|
static btstack_linked_list_t clients;
|
||||||
static uint16_t hids_cid_counter = 0;
|
static uint16_t hids_cid_counter = 0;
|
||||||
|
static uint16_t hids_report_counter = 0;
|
||||||
|
|
||||||
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||||
|
|
||||||
@ -69,6 +70,15 @@ static uint16_t hids_get_next_cid(void){
|
|||||||
return hids_cid_counter;
|
return hids_cid_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t hids_get_next_report_index(void){
|
||||||
|
if (hids_report_counter < HIDS_CLIENT_NUM_REPORTS) {
|
||||||
|
hids_report_counter++;
|
||||||
|
} else {
|
||||||
|
hids_report_counter = HIDS_CLIENT_INVALID_REPORT_INDEX;
|
||||||
|
}
|
||||||
|
return hids_report_counter;
|
||||||
|
}
|
||||||
|
|
||||||
static hids_client_t * hids_create_client(hci_con_handle_t con_handle, uint16_t cid){
|
static hids_client_t * hids_create_client(hci_con_handle_t con_handle, uint16_t cid){
|
||||||
hids_client_t * client = btstack_memory_hids_client_get();
|
hids_client_t * client = btstack_memory_hids_client_get();
|
||||||
if (!client){
|
if (!client){
|
||||||
@ -182,6 +192,15 @@ static void hids_run_for_client(hids_client_t * client){
|
|||||||
hids_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
hids_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HIDS_CLIENT_W2_SEND_REPORT:{
|
||||||
|
client->state = HIDS_CLIENT_STATE_CONNECTED;
|
||||||
|
|
||||||
|
att_status = gatt_client_write_value_of_characteristic_without_response(client->con_handle,
|
||||||
|
client->reports[client->active_report_index].value_handle,
|
||||||
|
client->report_len, (uint8_t *)client->report);
|
||||||
|
UNUSED(att_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -230,6 +249,26 @@ static void handle_boot_mouse_hid_event(uint8_t packet_type, uint16_t channel, u
|
|||||||
(*client->client_handler)(HCI_EVENT_PACKET, client->cid, in_place_event, size);
|
(*client->client_handler)(HCI_EVENT_PACKET, client->cid, in_place_event, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t find_report_index_for_value_handle(hids_client_t * client, uint16_t value_handle){
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < client->num_reports; client++){
|
||||||
|
if (client->reports[i].value_handle == value_handle){
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HIDS_CLIENT_INVALID_REPORT_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t find_report_index_for_report_id(hids_client_t * client, uint8_t report_id){
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < client->num_reports; client++){
|
||||||
|
if (client->reports[i].report_id == report_id){
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HIDS_CLIENT_INVALID_REPORT_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
UNUSED(packet_type);
|
UNUSED(packet_type);
|
||||||
UNUSED(channel);
|
UNUSED(channel);
|
||||||
@ -239,7 +278,8 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
|||||||
uint8_t att_status;
|
uint8_t att_status;
|
||||||
gatt_client_service_t service;
|
gatt_client_service_t service;
|
||||||
gatt_client_characteristic_t characteristic;
|
gatt_client_characteristic_t characteristic;
|
||||||
|
uint8_t report_index;
|
||||||
|
|
||||||
switch(hci_event_packet_get_type(packet)){
|
switch(hci_event_packet_get_type(packet)){
|
||||||
case GATT_EVENT_SERVICE_QUERY_RESULT:
|
case GATT_EVENT_SERVICE_QUERY_RESULT:
|
||||||
client = hids_get_client_for_con_handle(gatt_event_service_query_result_get_handle(packet));
|
client = hids_get_client_for_con_handle(gatt_event_service_query_result_get_handle(packet));
|
||||||
@ -267,17 +307,38 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
|||||||
switch (characteristic.uuid16){
|
switch (characteristic.uuid16){
|
||||||
case ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT:
|
case ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT:
|
||||||
client->boot_keyboard_input_value_handle = characteristic.value_handle;
|
client->boot_keyboard_input_value_handle = characteristic.value_handle;
|
||||||
client->boot_keyboard_input_end_handle = characteristic.end_handle;
|
client->boot_keyboard_input_end_handle = characteristic.end_handle;
|
||||||
client->boot_keyboard_input_properties = characteristic.properties;
|
client->boot_keyboard_input_properties = characteristic.properties;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT:
|
case ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT:
|
||||||
client->boot_mouse_input_value_handle = characteristic.value_handle;
|
client->boot_mouse_input_value_handle = characteristic.value_handle;
|
||||||
client->boot_mouse_input_end_handle = characteristic.end_handle;
|
client->boot_mouse_input_end_handle = characteristic.end_handle;
|
||||||
client->boot_mouse_input_properties = characteristic.properties;
|
client->boot_mouse_input_properties = characteristic.properties;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE:
|
case ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE:
|
||||||
client->protocol_mode_value_handle = characteristic.value_handle;
|
client->protocol_mode_value_handle = characteristic.value_handle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT:
|
||||||
|
report_index = find_report_index_for_value_handle(client, characteristic.value_handle);
|
||||||
|
if (report_index != HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_index = hids_get_next_report_index();
|
||||||
|
|
||||||
|
if (report_index != HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||||
|
client->reports[report_index].value_handle = characteristic.value_handle;
|
||||||
|
client->reports[report_index].report_id = HID_BOOT_MODE_KEYBOARD_ID;
|
||||||
|
client->reports[report_index].report_type = HID_REPORT_TYPE_OUTPUT;
|
||||||
|
client->num_reports++;
|
||||||
|
} else {
|
||||||
|
log_info("not enough storage, increase HIDS_CLIENT_NUM_REPORTS");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -437,6 +498,41 @@ uint8_t hids_client_disconnect(uint16_t hids_cid){
|
|||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t hids_client_send_report(uint16_t hids_cid, uint8_t report_id, const uint8_t * report, uint8_t report_len){
|
||||||
|
hids_client_t * client = hids_get_client_for_cid(hids_cid);
|
||||||
|
if (client == NULL){
|
||||||
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->state != HIDS_CLIENT_STATE_CONNECTED) {
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t report_index = find_report_index_for_report_id(client, report_id);
|
||||||
|
if (report_index == HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||||
|
return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t mtu;
|
||||||
|
uint8_t status = gatt_client_get_mtu(client->con_handle, &mtu);
|
||||||
|
|
||||||
|
if (status != ERROR_CODE_SUCCESS){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtu - 2 < report_len){
|
||||||
|
return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->state = HIDS_CLIENT_W2_SEND_REPORT;
|
||||||
|
client->active_report_index = report_index;
|
||||||
|
client->report = report;
|
||||||
|
client->report_len = report_len;
|
||||||
|
|
||||||
|
hids_run_for_client(client);
|
||||||
|
return ERROR_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void hids_client_init(void){}
|
void hids_client_init(void){}
|
||||||
|
|
||||||
void hids_client_deinit(void){}
|
void hids_client_deinit(void){}
|
||||||
|
@ -52,6 +52,9 @@ extern "C" {
|
|||||||
#ifndef MAX_NUM_HID_SERVICES
|
#ifndef MAX_NUM_HID_SERVICES
|
||||||
#define MAX_NUM_HID_SERVICES 3
|
#define MAX_NUM_HID_SERVICES 3
|
||||||
#endif
|
#endif
|
||||||
|
#define HIDS_CLIENT_INVALID_REPORT_INDEX 0xFF
|
||||||
|
|
||||||
|
#define HIDS_CLIENT_NUM_REPORTS 10
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HIDS_CLIENT_STATE_IDLE,
|
HIDS_CLIENT_STATE_IDLE,
|
||||||
@ -65,18 +68,22 @@ typedef enum {
|
|||||||
HIDS_CLIENT_STATE_W4_MOUSE_ENABLED,
|
HIDS_CLIENT_STATE_W4_MOUSE_ENABLED,
|
||||||
HIDS_CLIENT_STATE_W2_SET_PROTOCOL_MODE,
|
HIDS_CLIENT_STATE_W2_SET_PROTOCOL_MODE,
|
||||||
HIDS_CLIENT_STATE_W4_SET_PROTOCOL_MODE,
|
HIDS_CLIENT_STATE_W4_SET_PROTOCOL_MODE,
|
||||||
HIDS_CLIENT_STATE_CONNECTED
|
HIDS_CLIENT_STATE_CONNECTED,
|
||||||
|
HIDS_CLIENT_W2_SEND_REPORT
|
||||||
} hid_service_client_state_t;
|
} hid_service_client_state_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// service
|
uint16_t value_handle;
|
||||||
|
uint8_t report_id;
|
||||||
|
hid_report_type_t report_type;
|
||||||
|
} hids_client_report_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
uint16_t start_handle;
|
uint16_t start_handle;
|
||||||
uint16_t end_handle;
|
uint16_t end_handle;
|
||||||
|
|
||||||
} hid_service_t;
|
} hid_service_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
btstack_linked_item_t item;
|
btstack_linked_item_t item;
|
||||||
|
|
||||||
@ -105,6 +112,13 @@ typedef struct {
|
|||||||
uint16_t boot_mouse_input_properties;
|
uint16_t boot_mouse_input_properties;
|
||||||
gatt_client_notification_t boot_mouse_notifications;
|
gatt_client_notification_t boot_mouse_notifications;
|
||||||
|
|
||||||
|
// send report
|
||||||
|
hids_client_report_t reports[HIDS_CLIENT_NUM_REPORTS];
|
||||||
|
uint8_t num_reports;
|
||||||
|
|
||||||
|
uint8_t active_report_index;
|
||||||
|
uint16_t report_len;
|
||||||
|
const uint8_t * report;
|
||||||
} hids_client_t;
|
} hids_client_t;
|
||||||
|
|
||||||
/* API_START */
|
/* API_START */
|
||||||
@ -124,6 +138,16 @@ void hids_client_init(void);
|
|||||||
*/
|
*/
|
||||||
uint8_t hids_client_connect(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler, hid_protocol_mode_t protocol_mode, uint16_t * hids_cid);
|
uint8_t hids_client_connect(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler, hid_protocol_mode_t protocol_mode, uint16_t * hids_cid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send HID output report.
|
||||||
|
* @param hids_cid
|
||||||
|
* @param report_id
|
||||||
|
* @param report
|
||||||
|
* @param report_len
|
||||||
|
* @result status ERROR_CODE_SUCCESS on success, otherwise ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, ERROR_CODE_COMMAND_DISALLOWED
|
||||||
|
*/
|
||||||
|
uint8_t hids_client_send_report(uint16_t hids_cid, uint8_t report_id, const uint8_t * report, uint8_t report_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disconnect from Battery Service.
|
* @brief Disconnect from Battery Service.
|
||||||
* @param hids_cid
|
* @param hids_cid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user