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){
const char * attribute_name;
switch (packet[0]){
case ANCS_EVENT_CLIENT_CONNECTED:
if (packet[0] != HCI_EVENT_ANCS_META) return;
switch (packet[2]){
case ANCS_SUBEVENT_CLIENT_CONNECTED:
printf("ANCS Client: Connected\n");
break;
case ANCS_EVENT_CLIENT_DISCONNECTED:
case ANCS_SUBEVENT_CLIENT_DISCONNECTED:
printf("ANCS Client: Disconnected\n");
break;
case ANCS_EVENT_CLIENT_NOTIFICATION:
attribute_name = ancs_client_attribute_name_for_id(ancs_event_client_notification_get_attribute_id(packet));
case ANCS_SUBEVENT_CLIENT_NOTIFICATION:
attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet));
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;
default:
break;

View File

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

View File

@ -42,16 +42,16 @@
#include <stdlib.h>
#include <string.h>
#include "btstack_run_loop.h"
#include "classic/sdp_util.h"
#include "ancs_client.h"
#include "ble/att_db.h"
#include "btstack_debug.h"
#include "gap.h"
#include "ble/gatt_client.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
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){
if (!client_handler) return;
uint8_t event[6 + sizeof(ancs_notification_buffer) + 1];
event[0] = event_type;
event[1] = 6 + ancs_attribute_len;
little_endian_store_16(event, 2, gc_handle);
little_endian_store_16(event, 4, ancs_attribute_id);
memcpy(&event[6], ancs_notification_buffer, ancs_attribute_len);
uint8_t event[7 + sizeof(ancs_notification_buffer) + 1];
event[0] = HCI_EVENT_ANCS_META;
event[1] = 5 + ancs_attribute_len;
event[2] = event_type;
little_endian_store_16(event, 3, gc_handle);
little_endian_store_16(event, 5, ancs_attribute_id);
memcpy(&event[7], ancs_notification_buffer, ancs_attribute_len);
// we're nice
event[6+ancs_attribute_len] = 0;
event[7+ancs_attribute_len] = 0;
(*client_handler)(HCI_EVENT_PACKET, event, event[1] + 2);
}
static void notify_client_simple(int event_type){
if (!client_handler) return;
uint8_t event[4];
event[0] = event_type;
event[1] = 2;
little_endian_store_16(event, 2, gc_handle);
uint8_t event[5];
event[0] = HCI_EVENT_ANCS_META;
event[1] = 3;
event[2] = event_type;
little_endian_store_16(event, 3, gc_handle);
(*client_handler)(HCI_EVENT_PACKET, event, sizeof(event));
}
@ -167,7 +169,7 @@ static void ancs_chunk_parser_handle_byte(uint8_t data){
break;
case W4_ATTRIBUTE_COMPLETE:
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_needed = 1;
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){
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]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
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
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;
// 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;
gatt_client_discover_primary_services_by_uuid128(handle_hci_event, gc_handle, ancs_service_uuid);
return;
case HCI_EVENT_DISCONNECTION_COMPLETE:
notify_client_simple(ANCS_EVENT_CLIENT_DISCONNECTED);
notify_client_simple(ANCS_SUBEVENT_CLIENT_DISCONNECTED);
return;
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:
switch(packet[0]){
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;
break;
case GATT_EVENT_QUERY_COMPLETE:
if (!ancs_service_found){
printf("ANCS Service not found");
log_info("ANCS Service not found");
tc_state = TC_IDLE;
break;
}
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);
break;
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:
switch(packet[0]){
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){
printf("ANCS Notification Source Characterisic found\n");
log_info("ANCS Notification Source Characterisic found");
ancs_notification_source_characteristic = characteristic;
ancs_characteristcs++;
break;
}
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_characteristcs++;
break;
}
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_characteristcs++;
break;
}
break;
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;
gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_notification_source_characteristic,
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:
switch(packet[0]){
case GATT_EVENT_QUERY_COMPLETE:
printf("ANCS Notification Source subscribed\n");
log_info("ANCS Notification 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_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:
switch(packet[0]){
case GATT_EVENT_QUERY_COMPLETE:
printf("ANCS Data Source subscribed\n");
log_info("ANCS Data Source subscribed");
tc_state = TC_SUBSCRIBED;
notify_client_simple(ANCS_EVENT_CLIENT_CONNECTED);
notify_client_simple(ANCS_SUBEVENT_CLIENT_CONNECTED);
break;
default:
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){
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);
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);
@ -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,
sizeof(get_notification_attributes), get_notification_attributes);
} else {
printf("Unknown Source: ");
printf_hexdump(value , value_length);
log_info("Unknown Source: ");
log_info_hexdump(value , value_length);
}
break;
default:

View File

@ -753,12 +753,18 @@ typedef uint8_t sm_key_t[16];
#define GAP_LE_EVENT_ADVERTISING_REPORT 0xE2
// Meta Events, see below for sub events
#define HCI_EVENT_HSP_META 0xE8
#define HCI_EVENT_HFP_META 0xE9
#define HCI_EVENT_ANCS_META 0xEA
// HSP Subevents
// Potential other meta groups
// #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
@ -840,32 +846,26 @@ typedef uint8_t sm_key_t[16];
// ANCS Client
/**
* @format H
* @format 1H
* @param subevent_code
* @param handle
*/
#define ANCS_EVENT_CLIENT_CONNECTED 0xF0
#define ANCS_SUBEVENT_CLIENT_CONNECTED 0xF0
/**
* @format H2T
* @format 1H2T
* @param subevent_code
* @param handle
* @param attribute_id
* @param text
*/
#define ANCS_EVENT_CLIENT_NOTIFICATION 0xF1
#define ANCS_SUBEVENT_CLIENT_NOTIFICATION 0xF1
/**
* @format H
* @format 1H
* @param subevent_code
* @param handle
*/
#define ANCS_EVENT_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
#define ANCS_SUBEVENT_CLIENT_DISCONNECTED 0xF2
#endif

View File

@ -51,7 +51,6 @@
extern "C" {
#endif
#include "btstack_config.h"
#include "btstack_util.h"
#include <stdint.h>
@ -1378,55 +1377,82 @@ static inline uint8_t sm_event_authorization_result_get_authorization_result(con
#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
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t ancs_event_client_connected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2);
static inline hci_con_handle_t ancs_subevent_client_connected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 3);
}
#endif
#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
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t ancs_event_client_notification_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2);
static inline hci_con_handle_t ancs_subevent_client_notification_get_handle(const uint8_t * event){
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
* @return attribute_id
* @note: btstack_type 2
*/
static inline uint16_t ancs_event_client_notification_get_attribute_id(const uint8_t * event){
return little_endian_read_16(event, 4);
static inline uint16_t ancs_subevent_client_notification_get_attribute_id(const uint8_t * event){
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
* @return text
* @note: btstack_type T
*/
static inline const char * ancs_event_client_notification_get_text(const uint8_t * event){
return (const char *) &event[6];
static inline const char * ancs_subevent_client_notification_get_text(const uint8_t * event){
return (const char *) &event[7];
}
#endif
#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
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t ancs_event_client_disconnected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2);
static inline hci_con_handle_t ancs_subevent_client_disconnected_get_handle(const uint8_t * event){
return little_endian_read_16(event, 3);
}
#endif