introduce meta event for ANCS Client events

This commit is contained in:
Matthias Ringwald 2016-02-18 20:59:42 +01:00
parent 39d235cb94
commit e10ce42608
5 changed files with 109 additions and 101 deletions

View File

@ -107,17 +107,18 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
static void ancs_callback(uint8_t packet_type, uint8_t *packet, uint16_t size){ static void ancs_callback(uint8_t packet_type, uint8_t *packet, uint16_t size){
const char * attribute_name; const char * attribute_name;
switch (packet[0]){ if (packet[0] != HCI_EVENT_ANCS_META) return;
case ANCS_EVENT_CLIENT_CONNECTED: switch (packet[2]){
case ANCS_SUBEVENT_CLIENT_CONNECTED:
printf("ANCS Client: Connected\n"); printf("ANCS Client: Connected\n");
break; break;
case ANCS_EVENT_CLIENT_DISCONNECTED: case ANCS_SUBEVENT_CLIENT_DISCONNECTED:
printf("ANCS Client: Disconnected\n"); printf("ANCS Client: Disconnected\n");
break; break;
case ANCS_EVENT_CLIENT_NOTIFICATION: case ANCS_SUBEVENT_CLIENT_NOTIFICATION:
attribute_name = ancs_client_attribute_name_for_id(ancs_event_client_notification_get_attribute_id(packet)); attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet));
if (!attribute_name) break; if (!attribute_name) break;
printf("Notification: %s - %s\n", attribute_name, ancs_event_client_notification_get_text(packet)); printf("Notification: %s - %s\n", attribute_name, ancs_subevent_client_notification_get_text(packet));
break; break;
default: default:
break; break;

View File

@ -74,20 +74,21 @@ void loop(void){
/* LISTING_START(ANCSCallback): ANCS Callback */ /* LISTING_START(ANCSCallback): ANCS Callback */
void ancs_callback(uint8_t packet_type, uint8_t *packet, uint16_t size){ void ancs_callback(uint8_t packet_type, uint8_t *packet, uint16_t size){
const char * attribute_name; const char * attribute_name;
if (packet[0] != HCI_EVENT_ANCS_META) return;
switch (packet[0]){ switch (packet[0]){
case ANCS_EVENT_CLIENT_CONNECTED: case ANCS_SUBEVENT_CLIENT_CONNECTED:
Serial.println("ANCS Client: Connected"); Serial.println("ANCS Client: Connected");
break; break;
case ANCS_EVENT_CLIENT_DISCONNECTED: case ANCS_SUBEVENT_CLIENT_DISCONNECTED:
Serial.println("ANCS Client: Disconnected"); Serial.println("ANCS Client: Disconnected");
break; break;
case ANCS_EVENT_CLIENT_NOTIFICATION: case ANCS_SUBEVENT_CLIENT_NOTIFICATION:
attribute_name = ancs_client_attribute_name_for_id(ancs_client_notification_event_get_attribute_id(packet)); attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet));
if (!attribute_name) break; if (!attribute_name) break;
Serial.print("Notification: "); Serial.print("Notification: ");
Serial.print(attribute_name); Serial.print(attribute_name);
Serial.print(" - "); Serial.print(" - ");
Serial.println(ancs_client_notification_event_get_text(packet)); Serial.println(ancs_subevent_client_notification_get_text(packet));
break; break;
default: default:
break; break;

View File

@ -42,16 +42,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "btstack_run_loop.h"
#include "classic/sdp_util.h"
#include "ancs_client.h" #include "ancs_client.h"
#include "ble/att_db.h" #include "ble/att_db.h"
#include "btstack_debug.h"
#include "gap.h"
#include "ble/gatt_client.h" #include "ble/gatt_client.h"
#include "ble/sm.h" #include "ble/sm.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_run_loop.h"
#include "classic/sdp_util.h"
#include "gap.h"
// ancs_client.h Start // ancs_client.h Start
typedef enum ancs_chunk_parser_state { typedef enum ancs_chunk_parser_state {
@ -113,23 +113,25 @@ void ancs_client_register_callback(void (*handler)(uint8_t packet_type, uint8_t
static void notify_client_text(int event_type){ static void notify_client_text(int event_type){
if (!client_handler) return; if (!client_handler) return;
uint8_t event[6 + sizeof(ancs_notification_buffer) + 1]; uint8_t event[7 + sizeof(ancs_notification_buffer) + 1];
event[0] = event_type; event[0] = HCI_EVENT_ANCS_META;
event[1] = 6 + ancs_attribute_len; event[1] = 5 + ancs_attribute_len;
little_endian_store_16(event, 2, gc_handle); event[2] = event_type;
little_endian_store_16(event, 4, ancs_attribute_id); little_endian_store_16(event, 3, gc_handle);
memcpy(&event[6], ancs_notification_buffer, ancs_attribute_len); little_endian_store_16(event, 5, ancs_attribute_id);
memcpy(&event[7], ancs_notification_buffer, ancs_attribute_len);
// we're nice // we're nice
event[6+ancs_attribute_len] = 0; event[7+ancs_attribute_len] = 0;
(*client_handler)(HCI_EVENT_PACKET, event, event[1] + 2); (*client_handler)(HCI_EVENT_PACKET, event, event[1] + 2);
} }
static void notify_client_simple(int event_type){ static void notify_client_simple(int event_type){
if (!client_handler) return; if (!client_handler) return;
uint8_t event[4]; uint8_t event[5];
event[0] = event_type; event[0] = HCI_EVENT_ANCS_META;
event[1] = 2; event[1] = 3;
little_endian_store_16(event, 2, gc_handle); event[2] = event_type;
little_endian_store_16(event, 3, gc_handle);
(*client_handler)(HCI_EVENT_PACKET, event, sizeof(event)); (*client_handler)(HCI_EVENT_PACKET, event, sizeof(event));
} }
@ -167,7 +169,7 @@ static void ancs_chunk_parser_handle_byte(uint8_t data){
break; break;
case W4_ATTRIBUTE_COMPLETE: case W4_ATTRIBUTE_COMPLETE:
ancs_notification_buffer[ancs_bytes_received] = 0; ancs_notification_buffer[ancs_bytes_received] = 0;
notify_client_text(ANCS_EVENT_CLIENT_NOTIFICATION); notify_client_text(ANCS_SUBEVENT_CLIENT_NOTIFICATION);
ancs_bytes_received = 0; ancs_bytes_received = 0;
ancs_bytes_needed = 1; ancs_bytes_needed = 1;
chunk_parser_state = W4_ATTRIBUTE_ID; chunk_parser_state = W4_ATTRIBUTE_ID;
@ -175,28 +177,6 @@ static void ancs_chunk_parser_handle_byte(uint8_t data){
} }
} }
static void extract_service(gatt_client_service_t * service, uint8_t * packet){
service->start_group_handle = little_endian_read_16(packet, 4);
service->end_group_handle = little_endian_read_16(packet, 6);
service->uuid16 = 0;
reverse_128(&packet[8], service->uuid128);
if (uuid_has_bluetooth_prefix(service->uuid128)){
service->uuid16 = big_endian_read_32(service->uuid128, 0);
}
}
static void extract_characteristic(gatt_client_characteristic_t * characteristic, uint8_t * packet){
characteristic->start_handle = little_endian_read_16(packet, 4);
characteristic->value_handle = little_endian_read_16(packet, 6);
characteristic->end_handle = little_endian_read_16(packet, 8);
characteristic->properties = little_endian_read_16(packet, 10);
characteristic->uuid16 = 0;
reverse_128(&packet[12], characteristic->uuid128);
if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
}
}
static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
int connection_encrypted; int connection_encrypted;
@ -207,7 +187,7 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
switch (packet[2]) { switch (packet[2]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
gc_handle = little_endian_read_16(packet, 4); gc_handle = little_endian_read_16(packet, 4);
printf("Connection handle 0x%04x, request encryption\n", gc_handle); log_info("Connection handle 0x%04x, request encryption", gc_handle);
// we need to be paired to enable notifications // we need to be paired to enable notifications
tc_state = TC_W4_ENCRYPTED_CONNECTION; tc_state = TC_W4_ENCRYPTED_CONNECTION;
@ -226,13 +206,13 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
if (tc_state != TC_W4_ENCRYPTED_CONNECTION) return; if (tc_state != TC_W4_ENCRYPTED_CONNECTION) return;
// let's start // let's start
printf("\nANCS Client - CONNECTED, discover ANCS service\n"); log_info("\nANCS Client - CONNECTED, discover ANCS service");
tc_state = TC_W4_SERVICE_RESULT; tc_state = TC_W4_SERVICE_RESULT;
gatt_client_discover_primary_services_by_uuid128(handle_hci_event, gc_handle, ancs_service_uuid); gatt_client_discover_primary_services_by_uuid128(handle_hci_event, gc_handle, ancs_service_uuid);
return; return;
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
notify_client_simple(ANCS_EVENT_CLIENT_DISCONNECTED); notify_client_simple(ANCS_SUBEVENT_CLIENT_DISCONNECTED);
return; return;
default: default:
@ -248,17 +228,17 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
case TC_W4_SERVICE_RESULT: case TC_W4_SERVICE_RESULT:
switch(packet[0]){ switch(packet[0]){
case GATT_EVENT_SERVICE_QUERY_RESULT: case GATT_EVENT_SERVICE_QUERY_RESULT:
extract_service(&ancs_service, packet); gatt_event_service_query_result_get_service(packet, &ancs_service);
ancs_service_found = 1; ancs_service_found = 1;
break; break;
case GATT_EVENT_QUERY_COMPLETE: case GATT_EVENT_QUERY_COMPLETE:
if (!ancs_service_found){ if (!ancs_service_found){
printf("ANCS Service not found"); log_info("ANCS Service not found");
tc_state = TC_IDLE; tc_state = TC_IDLE;
break; break;
} }
tc_state = TC_W4_CHARACTERISTIC_RESULT; tc_state = TC_W4_CHARACTERISTIC_RESULT;
printf("ANCS Client - Discover characteristics for ANCS SERVICE \n"); log_info("ANCS Client - Discover characteristics for ANCS SERVICE ");
gatt_client_discover_characteristics_for_service(handle_hci_event, gc_handle, &ancs_service); gatt_client_discover_characteristics_for_service(handle_hci_event, gc_handle, &ancs_service);
break; break;
default: default:
@ -269,28 +249,28 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
case TC_W4_CHARACTERISTIC_RESULT: case TC_W4_CHARACTERISTIC_RESULT:
switch(packet[0]){ switch(packet[0]){
case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
extract_characteristic(&characteristic, packet); gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
if (memcmp(characteristic.uuid128, ancs_notification_source_uuid, 16) == 0){ if (memcmp(characteristic.uuid128, ancs_notification_source_uuid, 16) == 0){
printf("ANCS Notification Source Characterisic found\n"); log_info("ANCS Notification Source Characterisic found");
ancs_notification_source_characteristic = characteristic; ancs_notification_source_characteristic = characteristic;
ancs_characteristcs++; ancs_characteristcs++;
break; break;
} }
if (memcmp(characteristic.uuid128, ancs_control_point_uuid, 16) == 0){ if (memcmp(characteristic.uuid128, ancs_control_point_uuid, 16) == 0){
printf("ANCS Control Point found\n"); log_info("ANCS Control Point found");
ancs_control_point_characteristic = characteristic; ancs_control_point_characteristic = characteristic;
ancs_characteristcs++; ancs_characteristcs++;
break; break;
} }
if (memcmp(characteristic.uuid128, ancs_data_source_uuid, 16) == 0){ if (memcmp(characteristic.uuid128, ancs_data_source_uuid, 16) == 0){
printf("ANCS Data Source Characterisic found\n"); log_info("ANCS Data Source Characterisic found");
ancs_data_source_characteristic = characteristic; ancs_data_source_characteristic = characteristic;
ancs_characteristcs++; ancs_characteristcs++;
break; break;
} }
break; break;
case GATT_EVENT_QUERY_COMPLETE: case GATT_EVENT_QUERY_COMPLETE:
printf("ANCS Characteristcs count %u\n", ancs_characteristcs); log_info("ANCS Characteristcs count %u", ancs_characteristcs);
tc_state = TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED; tc_state = TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED;
gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_notification_source_characteristic, gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_notification_source_characteristic,
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION); GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
@ -302,7 +282,7 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
case TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED: case TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED:
switch(packet[0]){ switch(packet[0]){
case GATT_EVENT_QUERY_COMPLETE: case GATT_EVENT_QUERY_COMPLETE:
printf("ANCS Notification Source subscribed\n"); log_info("ANCS Notification Source subscribed");
tc_state = TC_W4_DATA_SOURCE_SUBSCRIBED; tc_state = TC_W4_DATA_SOURCE_SUBSCRIBED;
gatt_client_listen_for_characteristic_value_updates(&client_notification, gc_handle, &ancs_data_source_characteristic); gatt_client_listen_for_characteristic_value_updates(&client_notification, gc_handle, &ancs_data_source_characteristic);
gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_data_source_characteristic, gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_data_source_characteristic,
@ -315,9 +295,9 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
case TC_W4_DATA_SOURCE_SUBSCRIBED: case TC_W4_DATA_SOURCE_SUBSCRIBED:
switch(packet[0]){ switch(packet[0]){
case GATT_EVENT_QUERY_COMPLETE: case GATT_EVENT_QUERY_COMPLETE:
printf("ANCS Data Source subscribed\n"); log_info("ANCS Data Source subscribed");
tc_state = TC_SUBSCRIBED; tc_state = TC_SUBSCRIBED;
notify_client_simple(ANCS_EVENT_CLIENT_CONNECTED); notify_client_simple(ANCS_SUBEVENT_CLIENT_CONNECTED);
break; break;
default: default:
break; break;
@ -337,7 +317,7 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
} }
} else if (value_handle == ancs_notification_source_characteristic.value_handle){ } else if (value_handle == ancs_notification_source_characteristic.value_handle){
ancs_notification_uid = little_endian_read_32(value, 4); ancs_notification_uid = little_endian_read_32(value, 4);
printf("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x\n", log_info("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x",
value[0], value[1], value[2], value[3], (int) ancs_notification_uid); value[0], value[1], value[2], value[3], (int) ancs_notification_uid);
static uint8_t get_notification_attributes[] = {0, 0,0,0,0, 0, 1,32,0, 2,32,0, 3,32,0, 4, 5}; static uint8_t get_notification_attributes[] = {0, 0,0,0,0, 0, 1,32,0, 2,32,0, 3,32,0, 4, 5};
little_endian_store_32(get_notification_attributes, 1, ancs_notification_uid); little_endian_store_32(get_notification_attributes, 1, ancs_notification_uid);
@ -346,8 +326,8 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
gatt_client_write_value_of_characteristic(handle_hci_event, gc_handle, ancs_control_point_characteristic.value_handle, gatt_client_write_value_of_characteristic(handle_hci_event, gc_handle, ancs_control_point_characteristic.value_handle,
sizeof(get_notification_attributes), get_notification_attributes); sizeof(get_notification_attributes), get_notification_attributes);
} else { } else {
printf("Unknown Source: "); log_info("Unknown Source: ");
printf_hexdump(value , value_length); log_info_hexdump(value , value_length);
} }
break; break;
default: default:

View File

@ -753,12 +753,18 @@ typedef uint8_t sm_key_t[16];
#define GAP_LE_EVENT_ADVERTISING_REPORT 0xE2 #define GAP_LE_EVENT_ADVERTISING_REPORT 0xE2
// Meta Events, see below for sub events
#define HCI_EVENT_HSP_META 0xE8 #define HCI_EVENT_HSP_META 0xE8
#define HCI_EVENT_HFP_META 0xE9 #define HCI_EVENT_HFP_META 0xE9
#define HCI_EVENT_ANCS_META 0xEA
// Potential other meta groups
// HSP Subevents // #define HCI_EVENT_BNEP_META 0xxx
// #define HCI_EVENT_GAP_META 0xxx
// #define HCI_EVENT_GATT_META 0xxx
// #define HCI_EVENT_PAN_META 0xxx
// #define HCI_EVENT_SDP_META 0xxx
// #define HCI_EVENT_SM_META 0xxx
/** /**
* @format 11 * @format 11
@ -840,32 +846,26 @@ typedef uint8_t sm_key_t[16];
// ANCS Client // ANCS Client
/** /**
* @format H * @format 1H
* @param subevent_code
* @param handle * @param handle
*/ */
#define ANCS_EVENT_CLIENT_CONNECTED 0xF0 #define ANCS_SUBEVENT_CLIENT_CONNECTED 0xF0
/** /**
* @format H2T * @format 1H2T
* @param subevent_code
* @param handle * @param handle
* @param attribute_id * @param attribute_id
* @param text * @param text
*/ */
#define ANCS_EVENT_CLIENT_NOTIFICATION 0xF1 #define ANCS_SUBEVENT_CLIENT_NOTIFICATION 0xF1
/** /**
* @format H * @format 1H
* @param subevent_code
* @param handle * @param handle
*/ */
#define ANCS_EVENT_CLIENT_DISCONNECTED 0xF2 #define ANCS_SUBEVENT_CLIENT_DISCONNECTED 0xF2
// #define HCI_EVENT_HFP_META 0xxx
// #define HCI_EVENT_GATT_META 0xxx
// #define HCI_EVENT_SDP_META 0xxx
// #define HCI_EVENT_ANCS_META 0xxx
// #define HCI_EVENT_SM_META 0xxx
// #define HCI_EVENT_GAP_META 0xxx
// #define HCI_EVENT_BNEP_META 0xxx
// #define HCI_EVENT_PAN_META 0xxx
#endif #endif

View File

@ -51,7 +51,6 @@
extern "C" { extern "C" {
#endif #endif
#include "btstack_config.h"
#include "btstack_util.h" #include "btstack_util.h"
#include <stdint.h> #include <stdint.h>
@ -1378,55 +1377,82 @@ static inline uint8_t sm_event_authorization_result_get_authorization_result(con
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
/** /**
* @brief Get field handle from event ancs_event_client_connected * @brief Get field subevent_code from event ancs_subevent_client_connected
* @param Event packet
* @return subevent_code
* @note: btstack_type 1
*/
static inline uint8_t ancs_subevent_client_connected_get_subevent_code(const uint8_t * event){
return event[2];
}
/**
* @brief Get field handle from event ancs_subevent_client_connected
* @param Event packet * @param Event packet
* @return handle * @return handle
* @note: btstack_type H * @note: btstack_type H
*/ */
static inline hci_con_handle_t ancs_event_client_connected_get_handle(const uint8_t * event){ static inline hci_con_handle_t ancs_subevent_client_connected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2); return little_endian_read_16(event, 3);
} }
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
/** /**
* @brief Get field handle from event ancs_event_client_notification * @brief Get field subevent_code from event ancs_subevent_client_notification
* @param Event packet
* @return subevent_code
* @note: btstack_type 1
*/
static inline uint8_t ancs_subevent_client_notification_get_subevent_code(const uint8_t * event){
return event[2];
}
/**
* @brief Get field handle from event ancs_subevent_client_notification
* @param Event packet * @param Event packet
* @return handle * @return handle
* @note: btstack_type H * @note: btstack_type H
*/ */
static inline hci_con_handle_t ancs_event_client_notification_get_handle(const uint8_t * event){ static inline hci_con_handle_t ancs_subevent_client_notification_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2); return little_endian_read_16(event, 3);
} }
/** /**
* @brief Get field attribute_id from event ancs_event_client_notification * @brief Get field attribute_id from event ancs_subevent_client_notification
* @param Event packet * @param Event packet
* @return attribute_id * @return attribute_id
* @note: btstack_type 2 * @note: btstack_type 2
*/ */
static inline uint16_t ancs_event_client_notification_get_attribute_id(const uint8_t * event){ static inline uint16_t ancs_subevent_client_notification_get_attribute_id(const uint8_t * event){
return little_endian_read_16(event, 4); return little_endian_read_16(event, 5);
} }
/** /**
* @brief Get field text from event ancs_event_client_notification * @brief Get field text from event ancs_subevent_client_notification
* @param Event packet * @param Event packet
* @return text * @return text
* @note: btstack_type T * @note: btstack_type T
*/ */
static inline const char * ancs_event_client_notification_get_text(const uint8_t * event){ static inline const char * ancs_subevent_client_notification_get_text(const uint8_t * event){
return (const char *) &event[6]; return (const char *) &event[7];
} }
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
/** /**
* @brief Get field handle from event ancs_event_client_disconnected * @brief Get field subevent_code from event ancs_subevent_client_disconnected
* @param Event packet
* @return subevent_code
* @note: btstack_type 1
*/
static inline uint8_t ancs_subevent_client_disconnected_get_subevent_code(const uint8_t * event){
return event[2];
}
/**
* @brief Get field handle from event ancs_subevent_client_disconnected
* @param Event packet * @param Event packet
* @return handle * @return handle
* @note: btstack_type H * @note: btstack_type H
*/ */
static inline hci_con_handle_t ancs_event_client_disconnected_get_handle(const uint8_t * event){ static inline hci_con_handle_t ancs_subevent_client_disconnected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2); return little_endian_read_16(event, 3);
} }
#endif #endif