diff --git a/ble/ancs_client_lib.c b/ble/ancs_client_lib.c index 8ec6d75c4..33841516f 100644 --- a/ble/ancs_client_lib.c +++ b/ble/ancs_client_lib.c @@ -293,7 +293,7 @@ static void handle_gatt_client_event(le_event_t * event){ } else if (value_event->value_handle == ancs_notification_source_characteristic.value_handle){ ancs_notification_uid = READ_BT_32(value_event->blob, 4); printf("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x\n", - value_event->blob[0], value_event->blob[1], value_event->blob[2], value_event->blob[3], ancs_notification_uid); + value_event->blob[0], value_event->blob[1], value_event->blob[2], value_event->blob[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}; bt_store_32(get_notification_attributes, 1, ancs_notification_uid); ancs_notification_uid = 0; diff --git a/ble/att_server.c b/ble/att_server.c index d1d32c745..59a7a3974 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "btstack-config.h" @@ -257,7 +258,7 @@ static void att_run(void){ // check counter uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12); uint32_t counter_db = le_device_db_remote_counter_get(att_ir_le_device_db_index); - log_info("ATT Signed Write, DB counter %u, packet counter %u", counter_db, counter_packet); + log_info("ATT Signed Write, DB counter %"PRIu32", packet counter %"PRIu32, counter_db, counter_packet); if (counter_packet < counter_db){ log_info("ATT Signed Write, db reports higher counter, abort"); att_server_state = ATT_SERVER_IDLE; diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 3ee3154af..b4b178a13 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -426,19 +426,19 @@ static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac); } - -static uint16_t get_last_result_handle(uint8_t * packet, uint16_t size){ +static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){ uint8_t attr_length = packet[1]; - uint8_t handle_offset = 0; - switch (packet[0]){ - case ATT_READ_BY_TYPE_RESPONSE: - handle_offset = 3; - break; - case ATT_READ_BY_GROUP_TYPE_RESPONSE: - handle_offset = 2; - break; - } - return READ_BT_16(packet, size - attr_length + handle_offset); + return READ_BT_16(packet, size - attr_length + 2); +} + +static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){ + uint8_t attr_length = packet[1]; + return READ_BT_16(packet, size - attr_length + 3); +} + +static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){ + uint8_t attr_length = packet[1]; + return READ_BT_16(packet, size - attr_length); } static void gatt_client_handle_transaction_complete(gatt_client_t * peripheral){ @@ -948,7 +948,7 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, switch(peripheral->gatt_client_state){ case P_W4_SERVICE_QUERY_RESULT: report_gatt_services(peripheral, packet, size); - trigger_next_service_query(peripheral, get_last_result_handle(packet, size)); + trigger_next_service_query(peripheral, get_last_result_handle_from_service_list(packet, size)); // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done break; default: @@ -968,12 +968,12 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, switch (peripheral->gatt_client_state){ case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT: report_gatt_characteristics(peripheral, packet, size); - trigger_next_characteristic_query(peripheral, get_last_result_handle(packet, size)); + trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size)); // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done break; case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT: report_gatt_characteristics(peripheral, packet, size); - trigger_next_characteristic_query(peripheral, get_last_result_handle(packet, size)); + trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size)); // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done break; case P_W4_INCLUDED_SERVICE_QUERY_RESULT: @@ -998,7 +998,7 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, report_gatt_included_service(peripheral, NULL, uuid16); } - trigger_next_included_service_query(peripheral, get_last_result_handle(packet, size)); + trigger_next_included_service_query(peripheral, get_last_result_handle_from_included_services_list(packet, size)); // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done break; } diff --git a/ble/gatt_client.h b/ble/gatt_client.h index 1878ac86d..6a91d2024 100644 --- a/ble/gatt_client.h +++ b/ble/gatt_client.h @@ -289,7 +289,7 @@ le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid16 ( le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid128(uint16_t gatt_client_id, uint16_t con_handle, le_service_t *service, uint8_t * uuid128); /** - * @brief Discovers attribute handle and UUID of a characteristic descriptor within the specified characteristic. For each found descriptor, an le_characteristic_descriptor_event_t with type set to GATT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT will be generated and passed to the registered callback. The gatt_complete_event_t with type set to GATT_QUERY_COMPLETE, marks the end of discovery. + * @brief Discovers attribute handle and UUID of a characteristic descriptor within the specified characteristic. For each found descriptor, an le_characteristic_descriptor_event_t with type set to GATT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT will be generated and passed to the registered callback. The gatt_complete_event_t with type set to GATT_QUERY_COMPLETE, marks the end of discovery. */ le_command_status_t gatt_client_discover_characteristic_descriptors(uint16_t gatt_client_id, uint16_t con_handle, le_characteristic_t *characteristic); diff --git a/ble/sm.c b/ble/sm.c index 8ce2cf93c..8b0296321 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -37,6 +37,7 @@ #include #include +#include #include @@ -470,7 +471,7 @@ static void sm_notify_client(uint8_t type, uint8_t addr_type, bd_addr_t address, event.passkey = passkey; event.le_device_db_index = index; - log_info("sm_notify_client %02x, addres_type %u, address %s, num '%06u', index %u", event.type, event.addr_type, bd_addr_to_str(event.address), event.passkey, event.le_device_db_index); + log_info("sm_notify_client %02x, addres_type %u, address %s, num '%06"PRIu32"', index %u", event.type, event.addr_type, bd_addr_to_str(event.address), event.passkey, event.le_device_db_index); if (!sm_client_packet_handler) return; sm_client_packet_handler(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event)); diff --git a/chipset-cc256x/convert_bts_init_scripts.py b/chipset-cc256x/convert_bts_init_scripts.py index 6d138bdc3..a0ba27ed4 100755 --- a/chipset-cc256x/convert_bts_init_scripts.py +++ b/chipset-cc256x/convert_bts_init_scripts.py @@ -274,13 +274,19 @@ if not files: # convert each of them for name in files: + name_lower = name.lower() # skip BLE and AVRP add-ons - if name.lower().startswith('ble_init_cc'): + if name_lower.startswith('ble_init_cc'): print "Skipping BLE add-on", name continue - if name.lower().startswith('avpr_init_cc'): + if name_lower.startswith('avpr_init_cc'): print "Skipping AVPR add-on", name continue + if re.match("initscripts_tiinit_.*_ble_add-on.bts", name_lower): + print "Skipping BLE add-on", name + continue + if re.match("initscripts_tiinit_.*_avpr_add-on.bts", name_lower): + print "Skipping AVPR add-on", name # check for BLE add-on add_on = "" @@ -291,6 +297,13 @@ for name in files: add_on = potential_add_on print "Found", add_on, "add on for", name + name_parts = re.match('initscripts_TIInit_(\d*\.\d*\.\d*)_.*.bts', name) + if name_parts: + potential_add_on = 'initscripts_TIInit_%s_ble_add-on.bts' % name_parts.group(1) + if os.path.isfile(potential_add_on): + add_on = potential_add_on + print "Found", add_on, "add on for", name + convert_bts(name, add_on) # done diff --git a/docs/manual/docs/quick_start.md b/docs/manual/docs/quick_start.md index 64e65dc9e..e44a7a9fc 100644 --- a/docs/manual/docs/quick_start.md +++ b/docs/manual/docs/quick_start.md @@ -176,6 +176,10 @@ the BLE part. The conversion script has been updated to detect *bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts* if present and merges them into a single .c file. +**Update 2:** In May 2015, TI renamed the init scripts to match +the naming scheme previously used on Linux systems. The conversion +script has been updated to also detect *initscripts_TIInit_6.7.16_bt_spec_4.1.bts* +and integrates *initscripts_TIInit_6.7.16_ble_add-on.bts* if present. ### MSP-EXP430F5438 + CC256x Platform {#sec:platformMSP430QuickStart} diff --git a/platforms/ez430-rf2560/Makefile b/platforms/ez430-rf2560/Makefile index 6afdf0017..de1e0b6db 100644 --- a/platforms/ez430-rf2560/Makefile +++ b/platforms/ez430-rf2560/Makefile @@ -1,8 +1,5 @@ # Makefile for MSP-EXP430F5438 board with CC2560B/CC2564B/CC2567 modules -# -# Please check instructions at https://code.google.com/p/btstack/wiki/CC256x on downloading -# and converting the init scripts for use with BTstack -# +## # mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki # @@ -96,14 +93,14 @@ LCD_OBJ = $(LCD:.c=.o) # create firmware image from common objects and example source file -all: led_counter.hex spp_counter.hex gap_inquiry.hex spp_flowcontrol.hex \ - sdp_rfcomm_query.hex sdp_general_query.hex +all: led_counter.hex gap_inquiry.hex # fetch and convert init scripts include ${BTSTACK_ROOT}/chipset-cc256x/Makefile.inc # compiling requires a 20-bit mspgcc version -# spp_and_le_counter.hex spp_accel.hex +# spp_and_le_counter.hex spp_accel.hex spp_flowcontrol.hex spp_counter.hex +# sdp_rfcomm_query.hex sdp_general_query.hex # compiling ant-test requires special ant init script # ant-test.hex diff --git a/platforms/ios/src/Makefile b/platforms/ios/src/Makefile index dcbea0479..26c94b004 100644 --- a/platforms/ios/src/Makefile +++ b/platforms/ios/src/Makefile @@ -50,7 +50,7 @@ BTdaemon_FILES = \ $(BTSTACK_ROOT)/platforms/cocoa/remote_device_db_cocoa.m \ BTdaemon_CFLAGS = -I$(BTSTACK_ROOT)/include -I$(BTSTACK_ROOT)/ble -I$(BTSTACK_ROOT)/src -I.. -BTdaemon_LDFLAGS += $(SYSROOT)/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit +BTdaemon_PRIVATE_FRAMEWORKS = IOKIT before-all:: ../../../tools/get_version.sh diff --git a/platforms/msp-exp430f5438-cc2564b/Makefile b/platforms/msp-exp430f5438-cc2564b/Makefile index 54276f215..ae34fe923 100644 --- a/platforms/msp-exp430f5438-cc2564b/Makefile +++ b/platforms/msp-exp430f5438-cc2564b/Makefile @@ -1,8 +1,5 @@ # Makefile for MSP-EXP430F5438 board with CC2560B/CC2564B/CC2567 modules -# -# Please check instructions at https://code.google.com/p/btstack/wiki/CC256x on downloading -# and converting the init scripts for use with BTstack -# +## # mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki # @@ -96,8 +93,7 @@ LCD_OBJ = $(LCD:.c=.o) # create firmware image from common objects and example source file -all: led_counter.hex spp_counter.hex gap_inquiry.hex spp_flowcontrol.hex \ - sdp_rfcomm_query.hex sdp_general_query.hex +all: led_counter.hex gap_inquiry.hex sdp_general_query.hex # fetch and convert init scripts include ${BTSTACK_ROOT}/chipset-cc256x/Makefile.inc @@ -106,7 +102,10 @@ include ${BTSTACK_ROOT}/chipset-cc256x/Makefile.inc # hid_demo.hex # spp_and_le_counter.hex # spp_accel.hex -# ble_server.hex +# ble_server.hex +# spp_counter.hex +# spp_flowcontrol.hex +# sdp_rfcomm_query.hex # compiling ant-test requires special ant init script # ant-test.hex diff --git a/platforms/msp430f5229lp-cc2564b/Makefile b/platforms/msp430f5229lp-cc2564b/Makefile index 131443c5c..2f51b46c3 100644 --- a/platforms/msp430f5229lp-cc2564b/Makefile +++ b/platforms/msp430f5229lp-cc2564b/Makefile @@ -1,8 +1,5 @@ # Makefile for MSP-EXP430F5438 board with CC2560B/CC2564B/CC2567 modules # -# Please check instructions at https://code.google.com/p/btstack/wiki/CC256x on downloading -# and converting the init scripts for use with BTstack -# # mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki # diff --git a/src/debug.h b/src/debug.h index f0469f6ba..7762ff57a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -63,17 +63,17 @@ static inline void __log_unused(const char *format, ...) { #ifdef __AVR__ #define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log_P(log_level, PSTR(format), ## __VA_ARGS__) -#define PRINTF(format, ...) printf_P(PSTR(format), ## __VA_ARGS__) +#define BTSTACK_PRINTF(format, ...) printf_P(PSTR(format), ## __VA_ARGS__) #else #define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log(log_level, format, ## __VA_ARGS__) -#define PRINTF(format, ...) printf(format, ## __VA_ARGS__) +#define BTSTACK_PRINTF(format, ...) printf(format, ## __VA_ARGS__) #endif #ifdef ENABLE_LOG_DEBUG #ifdef HAVE_HCI_DUMP #define log_debug(format, ...) HCI_DUMP_LOG(LOG_LEVEL_DEBUG, format, ## __VA_ARGS__) #else -#define log_debug(format, ...) PRINTF(format "\n", ## __VA_ARGS__) +#define log_debug(format, ...) BTSTACK_PRINTF(format "\n", ## __VA_ARGS__) #endif #else #define log_debug(...) __log_unused(__VA_ARGS__) @@ -83,7 +83,7 @@ static inline void __log_unused(const char *format, ...) { #ifdef HAVE_HCI_DUMP #define log_info(format, ...) HCI_DUMP_LOG(LOG_LEVEL_INFO, format, ## __VA_ARGS__) #else -#define log_info(format, ...) PRINTF(format "\n", ## __VA_ARGS__) +#define log_info(format, ...) BTSTACK_PRINTF(format "\n", ## __VA_ARGS__) #endif #else #define log_info(...) __log_unused(__VA_ARGS__) @@ -93,7 +93,7 @@ static inline void __log_unused(const char *format, ...) { #ifdef HAVE_HCI_DUMP #define log_error(format, ...) HCI_DUMP_LOG(LOG_LEVEL_ERROR, format, ## __VA_ARGS__) #else -#define log_error(format, ...) PRINTF(format "\n", ## __VA_ARGS__) +#define log_error(format, ...) BTSTACK_PRINTF(format "\n", ## __VA_ARGS__) #endif #else #define log_error(...) __log_unused(__VA_ARGS__) diff --git a/src/hci.c b/src/hci.c index c7cf90f92..32e4be948 100644 --- a/src/hci.c +++ b/src/hci.c @@ -54,6 +54,7 @@ #include #include #include +#include #ifndef EMBEDDED #ifdef _WIN32 @@ -829,7 +830,7 @@ static void hci_initialization_timeout_handler(timer_source_t * ds){ hci_stack->num_cmd_packets = 1; hci_run(); case HCI_INIT_W4_SEND_BAUD_CHANGE: - log_info("Local baud rate change to %u", ((hci_uart_config_t *)hci_stack->config)->baudrate_main); + log_info("Local baud rate change to %"PRIu32, ((hci_uart_config_t *)hci_stack->config)->baudrate_main); hci_stack->hci_transport->set_baudrate(((hci_uart_config_t *)hci_stack->config)->baudrate_main); break; default: @@ -1103,7 +1104,7 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){ // for CC256x, baud rate gets changed now if (hci_stack->manufacturer != 0x0030){ uint32_t new_baud = ((hci_uart_config_t *)hci_stack->config)->baudrate_main; - log_info("Local baud rate change to %u", new_baud); + log_info("Local baud rate change to %"PRIu32, new_baud); hci_stack->hci_transport->set_baudrate(new_baud); } hci_stack->substate = HCI_INIT_CUSTOM_INIT; diff --git a/src/run_loop_embedded.c b/src/run_loop_embedded.c index d456d2b66..5f94af9a3 100644 --- a/src/run_loop_embedded.c +++ b/src/run_loop_embedded.c @@ -83,7 +83,7 @@ static linked_list_t timers; #endif #ifdef HAVE_TICK -static uint32_t system_ticks; +static volatile uint32_t system_ticks; #endif static int trigger_event_received = 0; diff --git a/src/sdp_parser.c b/src/sdp_parser.c index c88047a8b..067572516 100644 --- a/src/sdp_parser.c +++ b/src/sdp_parser.c @@ -145,7 +145,7 @@ void parse(uint8_t eventByte){ case GET_ATTRIBUTE_ID_HEADER_LENGTH: if (!de_state_size(eventByte, &de_header_state)) break; attribute_id = 0; - log_info("ID data is stored in %d bytes.", de_header_state.de_size); + log_info("ID data is stored in %d bytes.", (int) de_header_state.de_size); state = GET_ATTRIBUTE_ID; break; diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index af6da30f9..f40f9bec8 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -77,7 +77,9 @@ typedef enum { CENTRAL_W4_NAME_VALUE, CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE, CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE, - CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE + CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE, + CENTRAL_W4_PRIMARY_SERVICES, + CENTRAL_W4_CHARACTERISTICS, } central_state_t; typedef struct advertising_report { @@ -109,6 +111,11 @@ static int peer_addr_type; static bd_addr_t peer_address; static int ui_passkey = 0; static int ui_digits_for_passkey = 0; +static int ui_uuid16_request = 0; +static int ui_uuid16 = 0; +static int ui_uuid128_request = 0; +static int ui_uuid128_pos = 0; +static uint8_t ui_uuid128[16]; static uint16_t handle = 0; static uint16_t gc_id; @@ -329,10 +336,50 @@ void handle_gatt_client_event(le_event_t * event){ le_characteristic_value_event_t * value; uint8_t address_type; bd_addr_t flipped_address; + le_service_t * service; switch(event->type){ case GATT_SERVICE_QUERY_RESULT: - // service = ((le_service_event_t *) event)->service; - // dump_service(&service); + switch (central_state){ + case CENTRAL_W4_PRIMARY_SERVICES: + service = &((le_service_event_t *) event)->service; + printf("Primary Service with UUID "); + printUUID(service->uuid128, service->uuid16); + printf(", start group handle 0x%04x, end group handle 0x%04x\n", service->start_group_handle, service->end_group_handle); + break; + default: + break; + } + break; + case GATT_INCLUDED_SERVICE_QUERY_RESULT: + service = &((le_service_event_t *) event)->service; + printf("Included Service with UUID "); + printUUID(service->uuid128, service->uuid16); + printf(", start group handle 0x%04x, end group handle 0x%04x\n", service->start_group_handle, service->end_group_handle); + break; + case GATT_CHARACTERISTIC_QUERY_RESULT: + switch (central_state) { + case CENTRAL_W4_NAME_QUERY_COMPLETE: + gap_name_characteristic = ((le_characteristic_event_t *) event)->characteristic; + printf("GAP Name Characteristic found, value handle: 0x04%x\n", gap_name_characteristic.value_handle); + break; + case CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE: + gap_reconnection_address_characteristic = ((le_characteristic_event_t *) event)->characteristic; + printf("GAP Reconnection Address Characteristic found, value handle: 0x04%x\n", gap_reconnection_address_characteristic.value_handle); + break; + case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE: + gap_peripheral_privacy_flag_characteristic = ((le_characteristic_event_t *) event)->characteristic; + printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle); + break; + case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE: + signed_write_characteristic = ((le_characteristic_event_t *) event)->characteristic; + printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle); + break; + case CENTRAL_W4_CHARACTERISTICS: + printf("Characteristic found with handle 0x%04x\n", (((le_characteristic_event_t *) event)->characteristic).value_handle); + break; + default: + break; + } break; case GATT_CHARACTERISTIC_VALUE_QUERY_RESULT: value = (le_characteristic_value_event_t *) event; @@ -348,6 +395,8 @@ void handle_gatt_client_event(le_event_t * event){ // printf("\ntest client - CHARACTERISTIC for SERVICE "); // printUUID128(service.uuid128); printf("\n"); break; + + case GATT_QUERY_COMPLETE: switch (central_state){ case CENTRAL_W4_NAME_QUERY_COMPLETE: @@ -386,33 +435,15 @@ void handle_gatt_client_event(le_event_t * event){ printf("Signed write on Characteristic with UUID 0x%04x\n", pts_signed_write_characteristic_uuid); gatt_client_signed_write_without_response(gc_id, handle, signed_write_characteristic.value_handle, sizeof(signed_write_value), signed_write_value); break; + case CENTRAL_W4_PRIMARY_SERVICES: + printf("Primary Service Discovery complete\n"); + central_state = CENTRAL_IDLE; + break; default: break; } break; - case GATT_CHARACTERISTIC_QUERY_RESULT: - switch (central_state) { - case CENTRAL_W4_NAME_QUERY_COMPLETE: - gap_name_characteristic = ((le_characteristic_event_t *) event)->characteristic; - printf("GAP Name Characteristic found, value handle: 0x04%x\n", gap_name_characteristic.value_handle); - break; - case CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE: - gap_reconnection_address_characteristic = ((le_characteristic_event_t *) event)->characteristic; - printf("GAP Reconnection Address Characteristic found, value handle: 0x04%x\n", gap_reconnection_address_characteristic.value_handle); - break; - case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE: - gap_peripheral_privacy_flag_characteristic = ((le_characteristic_event_t *) event)->characteristic; - printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle); - break; - case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE: - signed_write_characteristic = ((le_characteristic_event_t *) event)->characteristic; - printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle); - break; - default: - break; - } - break; default: break; } @@ -470,6 +501,12 @@ void show_usage(void){ printf("W - signed write on attribute with handle 0x%04x and value 0x12\n", pts_signed_write_characteristic_handle); printf("z - Update L2CAP Connection Parameters\n"); printf("---\n"); + printf("e - Discover all Primary Services\n"); + printf("f - Discover Primary Service by UUID16\n"); + printf("F - Discover Primary Service by UUID128\n"); + printf("g - Discover all characteristics by UUID16\n"); + printf("i - Find all included services\n"); + printf("---\n"); printf("4 - IO_CAPABILITY_DISPLAY_ONLY\n"); printf("5 - IO_CAPABILITY_DISPLAY_YES_NO\n"); printf("6 - IO_CAPABILITY_NO_INPUT_NO_OUTPUT\n"); @@ -507,7 +544,20 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){ l2cap_send_prepared_connectionless(handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12); } -int stdin_process(struct data_source *ds){ +int hexForChar(char c){ + if (c >= '0' && c <= '9'){ + return c - '0'; + } + if (c >= 'a' && c <= 'f'){ + return c - 'a' + 10; + } + if (c >= 'A' && c <= 'F'){ + return c - 'A' + 10; + } + return -1; +} + +int stdin_process(struct data_source *ds){ char buffer; read(ds->fd, &buffer, 1); int res; @@ -530,6 +580,78 @@ int stdin_process(struct data_source *ds){ return 0; } + // uuid input + if (ui_uuid16_request){ + if (buffer == '\n' || buffer == '\r'){ + switch (central_state){ + case CENTRAL_W4_PRIMARY_SERVICES: + printf("\nDiscover Primary Services with UUID16 %04x\n", ui_uuid16); + ui_uuid16_request = 0; + gatt_client_discover_primary_services_by_uuid16(gc_id, handle, ui_uuid16); + return 0; + case CENTRAL_W4_CHARACTERISTICS: + printf("\nDiscover Characteristics with UUID16 %04x\n", ui_uuid16); + ui_uuid16_request = 0; + gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 0x0001, 0xffff, ui_uuid16); + default: + return 0; + } + } + int hex = hexForChar(buffer); + if (hex < 0){ + printf("stdinprocess: invalid input 0x%02x\n", buffer); + return 0; + } + printf("%c", buffer); + fflush(stdout); + ui_uuid16 = ui_uuid16 << 4 | hex; + return 0; + } + + if (ui_uuid128_request){ + if (buffer == '-') return 0; // skip - + int hex = hexForChar(buffer); + if (hex < 0){ + printf("stdinprocess: invalid input 0x%02x\n", buffer); + return 0; + } + printf("%c", buffer); + fflush(stdout); + if (ui_uuid128_pos & 1){ + ui_uuid128[ui_uuid128_pos >> 1] |= hex; + } else { + ui_uuid128[ui_uuid128_pos >> 1] = hex << 4; + } + ui_uuid128_pos++; + if (ui_uuid128_pos == 32){ + switch (central_state){ + case CENTRAL_W4_PRIMARY_SERVICES: + printf("\nDiscover Primary Services with UUID128 "); + printUUID128(ui_uuid128); + printf("\n"); + ui_uuid128_request = 0; + gatt_client_discover_primary_services_by_uuid128(gc_id, handle, ui_uuid128); + return 0; + default: + return 0; + } + } + switch(ui_uuid128_pos){ + case 8: + case 12: + case 16: + case 20: + printf("-"); + fflush(stdout); + break; + default: + break; + } + return 0; + + + } + switch (buffer){ case '1': printf("Enabling non-resolvable private address\n"); @@ -697,6 +819,50 @@ int stdin_process(struct data_source *ds){ printf("Updating l2cap connection parameters\n"); gap_update_connection_parameters(handle, 50, 120, 0, 550); break; + + // GATT commands + case 'e': + central_state = CENTRAL_W4_PRIMARY_SERVICES; + gatt_client_discover_primary_services(gc_id, handle); + break; + case 'f': + central_state = CENTRAL_W4_PRIMARY_SERVICES; + printf("Please enter UUID16: "); + fflush(stdout); + ui_uuid16_request = 1; + ui_uuid16 = 0; + break; + case 'F': + central_state = CENTRAL_W4_PRIMARY_SERVICES; + printf("Please enter UUID128: "); + fflush(stdout); + ui_uuid128_request = 1; + ui_uuid128_pos = 0; + memset(ui_uuid128, 0, 16); + break; + case 'g': + // central_state = CENTRAL_W4_CHARACTERISTICS; + // printf("Please enter UUID16: "); + // fflush(stdout); + // ui_uuid16_request = 1; + // ui_uuid16 = 0; + // break; + { + central_state = CENTRAL_W4_CHARACTERISTICS; + le_service_t service; + service.start_group_handle = 0x0001; + service.end_group_handle = 0xffff; + gatt_client_discover_characteristics_for_service(gc_id, handle, &service); + } + case 'i': + { + central_state = CENTRAL_W4_CHARACTERISTICS; + le_service_t service; + service.start_group_handle = 0x0001; + service.end_group_handle = 0xffff; + gatt_client_find_included_services_for_service(gc_id, handle, &service); + } + break; default: show_usage(); break;