mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-26 03:35:20 +00:00
hids_client: implement enable and disable notifications
This commit is contained in:
parent
5b4ead15f4
commit
cd28e7b103
@ -487,6 +487,9 @@ static bool hids_client_report_next_notification_report_index(hids_client_t * cl
|
||||
}
|
||||
|
||||
static bool hids_client_report_notifications_init(hids_client_t * client){
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
printf("\nRegister for Notifications: \n");
|
||||
#endif
|
||||
client->report_index = 0;
|
||||
|
||||
if (hids_client_get_next_notification_report_index(client) != HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||
@ -496,6 +499,28 @@ static bool hids_client_report_notifications_init(hids_client_t * client){
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hids_client_report_next_notifications_configuration_report_index(hids_client_t * client){
|
||||
client->report_index++;
|
||||
if (hids_client_get_next_notification_report_index(client) != HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||
client->state = HIDS_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hids_client_notifications_configuration_init(hids_client_t * client){
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
printf("\nConfigure for Notifications: \n");
|
||||
#endif
|
||||
client->report_index = 0;
|
||||
|
||||
if (hids_client_get_next_notification_report_index(client) != HIDS_CLIENT_INVALID_REPORT_INDEX){
|
||||
client->state = HIDS_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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();
|
||||
if (!client){
|
||||
@ -537,6 +562,18 @@ static void hids_emit_connection_established(hids_client_t * client, uint8_t sta
|
||||
(*client->client_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void hids_emit_notifications_configuration(hids_client_t * client){
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_GATTSERVICE_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = GATTSERVICE_SUBEVENT_HID_SERVICE_REPORTS_NOTIFICATION;
|
||||
little_endian_store_16(event, pos, client->cid);
|
||||
pos += 2;
|
||||
event[pos++] = client->value;
|
||||
(*client->client_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void hids_client_setup_report_event(hids_client_t * client, uint8_t report_index, uint8_t *buffer, uint16_t report_len){
|
||||
uint16_t pos = 0;
|
||||
buffer[pos++] = HCI_EVENT_GATTSERVICE_META;
|
||||
@ -754,7 +791,54 @@ static void hids_run_for_client(hids_client_t * client){
|
||||
UNUSED(att_status);
|
||||
break;
|
||||
|
||||
case HIDS_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS:
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
if (client->value > 0){
|
||||
printf(" Notification configuration enable ");
|
||||
} else {
|
||||
printf(" Notification configuration disable ");
|
||||
}
|
||||
printf("[%d, %d, 0x%04X]:\n",
|
||||
client->report_index,
|
||||
client->reports[client->report_index].service_index, client->reports[client->report_index].value_handle);
|
||||
#endif
|
||||
|
||||
client->state = HIDS_CLIENT_STATE_W4_NOTIFICATIONS_CONFIGURED;
|
||||
|
||||
characteristic.value_handle = client->reports[client->report_index].value_handle;
|
||||
characteristic.end_handle = client->reports[client->report_index].end_handle;
|
||||
characteristic.properties = client->reports[client->report_index].properties;
|
||||
|
||||
// end of write marked in GATT_EVENT_QUERY_COMPLETE
|
||||
|
||||
att_status = gatt_client_write_client_characteristic_configuration(&handle_gatt_client_event, client->con_handle, &characteristic, client->value);
|
||||
|
||||
if (att_status == ERROR_CODE_SUCCESS){
|
||||
switch(client->value){
|
||||
case GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION:
|
||||
gatt_client_listen_for_characteristic_value_updates(
|
||||
&client->reports[client->report_index].notification_listener,
|
||||
&handle_notification_event, client->con_handle, &characteristic);
|
||||
break;
|
||||
default:
|
||||
gatt_client_stop_listening_for_characteristic_value_updates(&client->reports[client->report_index].notification_listener);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (hids_client_report_next_notifications_configuration_report_index(client)){
|
||||
hids_run_for_client(client);
|
||||
break;
|
||||
}
|
||||
client->state = HIDS_CLIENT_STATE_CONNECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case HIDS_CLIENT_STATE_W2_ENABLE_INPUT_REPORTS:
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
printf(" Notification enable [%d, %d, 0x%04X]:\n",
|
||||
client->report_index,
|
||||
client->reports[client->report_index].service_index, client->reports[client->report_index].value_handle);
|
||||
#endif
|
||||
client->state = HIDS_CLIENT_STATE_W4_INPUT_REPORTS_ENABLED;
|
||||
|
||||
characteristic.value_handle = client->reports[client->report_index].value_handle;
|
||||
@ -764,27 +848,22 @@ static void hids_run_for_client(hids_client_t * client){
|
||||
// end of write marked in GATT_EVENT_QUERY_COMPLETE
|
||||
att_status = gatt_client_write_client_characteristic_configuration(&handle_gatt_client_event, client->con_handle, &characteristic, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
|
||||
|
||||
if (att_status != ERROR_CODE_SUCCESS){
|
||||
if (att_status == ERROR_CODE_SUCCESS){
|
||||
gatt_client_listen_for_characteristic_value_updates(
|
||||
&client->reports[client->report_index].notification_listener,
|
||||
&handle_notification_event, client->con_handle, &characteristic);
|
||||
} else {
|
||||
if (hids_client_report_next_notification_report_index(client)){
|
||||
hids_run_for_client(client);
|
||||
break;
|
||||
}
|
||||
client->state = HIDS_CLIENT_STATE_CONNECTED;
|
||||
hids_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
} else {
|
||||
gatt_client_listen_for_characteristic_value_updates(
|
||||
&client->reports[client->report_index].notification_listener,
|
||||
&handle_notification_event, client->con_handle, &characteristic);
|
||||
|
||||
client->state = HIDS_CLIENT_STATE_CONNECTED;
|
||||
hids_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
}
|
||||
UNUSED(att_status);
|
||||
break;
|
||||
|
||||
|
||||
case HIDS_CLIENT_W2_SEND_WRITE_REPORT:
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
printf(" Write report [%d, %d, 0x%04X]:\n",
|
||||
client->report_index,
|
||||
@ -1291,6 +1370,14 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
hids_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
break;
|
||||
|
||||
case HIDS_CLIENT_STATE_W4_NOTIFICATIONS_CONFIGURED:
|
||||
if (hids_client_report_next_notifications_configuration_report_index(client)){
|
||||
break;
|
||||
}
|
||||
hids_emit_notifications_configuration(client);
|
||||
client->state = HIDS_CLIENT_STATE_CONNECTED;
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
case HIDS_CLIENT_W4_CHARACTERISTIC_CONFIGURATION_RESULT:
|
||||
client->state = HIDS_CLIENT_W2_SEND_GET_REPORT;
|
||||
@ -1515,6 +1602,42 @@ uint8_t hids_client_send_exit_suspend(uint16_t hids_cid, uint8_t service_index){
|
||||
return hids_client_send_control_point_cmd(hids_cid, service_index, 1);
|
||||
}
|
||||
|
||||
uint8_t hids_client_send_enable_notifications(uint16_t hids_cid){
|
||||
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;
|
||||
}
|
||||
client->value = GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
|
||||
if (hids_client_notifications_configuration_init(client)){
|
||||
hids_run_for_client(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
hids_emit_notifications_configuration(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t hids_client_send_disable_notifications(uint16_t hids_cid){
|
||||
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;
|
||||
}
|
||||
|
||||
client->value = GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE;
|
||||
if (hids_client_notifications_configuration_init(client)){
|
||||
hids_run_for_client(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
hids_emit_notifications_configuration(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void hids_client_init(uint8_t * hid_descriptor_storage, uint16_t hid_descriptor_storage_len){
|
||||
hids_client_descriptor_storage = hid_descriptor_storage;
|
||||
|
@ -97,7 +97,7 @@ typedef enum {
|
||||
HIDS_CLIENT_STATE_W4_INPUT_REPORTS_ENABLED,
|
||||
|
||||
HIDS_CLIENT_STATE_CONNECTED,
|
||||
|
||||
|
||||
HIDS_CLIENT_W2_SEND_WRITE_REPORT,
|
||||
HIDS_CLIENT_W4_WRITE_REPORT_DONE,
|
||||
|
||||
@ -109,6 +109,9 @@ typedef enum {
|
||||
|
||||
HIDS_CLIENT_W2_WRITE_VALUE_OF_CHARACTERISTIC_WITHOUT_RESPONSE,
|
||||
|
||||
HIDS_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS,
|
||||
HIDS_CLIENT_STATE_W4_NOTIFICATIONS_CONFIGURED,
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
HIDS_CLIENT_W2_READ_CHARACTERISTIC_CONFIGURATION,
|
||||
HIDS_CLIENT_W4_CHARACTERISTIC_CONFIGURATION_RESULT,
|
||||
@ -235,6 +238,10 @@ uint8_t hids_client_send_suspend(uint16_t hids_cid, uint8_t service_index);
|
||||
|
||||
uint8_t hids_client_send_exit_suspend(uint16_t hids_cid, uint8_t service_index);
|
||||
|
||||
uint8_t hids_client_send_enable_notifications(uint16_t hids_cid);
|
||||
|
||||
uint8_t hids_client_send_disable_notifications(uint16_t hids_cid);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from Battery Service.
|
||||
* @param hids_cid
|
||||
|
@ -40,5 +40,11 @@ HOGP/RH/HGWF/BV-05-I: h, w, s, S
|
||||
HOGP/RH/HGWF/BV-06-I: h, w, e, E
|
||||
HOGP/RH/HGWF/BV-07-I: h, w, p, P
|
||||
|
||||
HOGP/RH/HGCF/BV-01-I: h
|
||||
HOGP/RH/HGCF/BV-02-I: h, w, N
|
||||
|
||||
HOGP/RH/HGNF/BV-01-I:
|
||||
HOGP/RH/HGNF/BI-01-I:
|
||||
HOGP/RH/HGNF/BI-02-I:
|
||||
|
||||
|
||||
|
@ -421,6 +421,13 @@ static void hid_service_gatt_client_event_handler(uint8_t packet_type, uint16_t
|
||||
HID_PROTOCOL_MODE_BOOT,HID_PROTOCOL_MODE_REPORT);
|
||||
break;
|
||||
|
||||
case GATTSERVICE_SUBEVENT_HID_SERVICE_REPORTS_NOTIFICATION:
|
||||
if (gattservice_subevent_hid_service_reports_notification_get_configuration(packet) == 0){
|
||||
printf("Reports disabled\n");
|
||||
} else {
|
||||
printf("Reports enabled\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -563,6 +570,8 @@ static void show_usage(void){
|
||||
printf("S - Suspend service 1\n");
|
||||
printf("e - Exit suspend service 0\n");
|
||||
printf("E - Exit suspend service 1\n");
|
||||
printf("n - Enable all notifications\n");
|
||||
printf("N - Disable all notifications\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -774,7 +783,16 @@ static void stdin_process(char character){
|
||||
hids_client_send_set_protocol_mode(hids_cid, HID_PROTOCOL_MODE_REPORT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':{
|
||||
printf("Enable all notifications\n");
|
||||
hids_client_send_enable_notifications(hids_cid);
|
||||
break;
|
||||
}
|
||||
case 'N':{
|
||||
printf("Disable all notifications\n");
|
||||
hids_client_send_disable_notifications(hids_cid);
|
||||
break;
|
||||
}
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user