BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS
Dependencies: FatFileSystem mbed
Fork of BTstack by
Revision 6:cf06ba884429, committed 2013-02-20
- Comitter:
- todotani
- Date:
- Wed Feb 20 14:18:38 2013 +0000
- Parent:
- 5:5fb56e13a1f9
- Commit message:
- Change tick timer to 1ms. Change attribute 0xFFF1 as read of DigitalIn p5
Changed in this revision
--- a/BLE_demo.cpp Mon Feb 11 14:10:57 2013 +0000 +++ b/BLE_demo.cpp Wed Feb 20 14:18:38 2013 +0000 @@ -14,7 +14,7 @@ * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * 4. This software may not be used in a commercial product - * without an explicit license granted by the copyright holder. + * without an explicit license granted by the copyright holder. * * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -32,7 +32,7 @@ */ /* Change history - 2013/2/10: by todotani + 2013/2/10: by todotani Modified tick event handler Modified LED control - LED 3 flush when connected @@ -41,6 +41,9 @@ 2013/2/11: by todotani Changed serial pc.baud (115200 to 921600) to avoid imcomplete connection issue Disable btstack debug-log +2013/2/20: by todotani + Change tick timer interval 250ms to 1ms + Change Attribute 0xFFF1 as read DigitalIn p5 of mbed */ //***************************************************************************** @@ -59,6 +62,7 @@ #include "mbed.h" Serial pc(USBTX, USBRX); DigitalOut led1(LED1), led2(LED2), led3(LED3); +DigitalIn sw1(p5); // from btstack ble_server.c #include "global.h" @@ -83,19 +87,24 @@ static uint16_t att_response_size = 0; static uint8_t att_response_buffer[28]; -void hexdump2(void *data, int size){ +static uint8_t switch_new_state = 1; +static uint8_t switch_old_state = 1; + +void hexdump2(void *data, int size) +{ int i; - for (i=0; i<size;i++){ + for (i=0; i<size; i++) { log_info("%02X ", ((uint8_t *)data)[i]); } log_info("\n"); } -static void att_try_respond(void){ +static void att_try_respond(void) +{ if (!att_response_size) return; if (!att_response_handle) return; if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) return; - + // update state before sending packet uint16_t size = att_response_size; att_response_size = 0; @@ -103,9 +112,10 @@ } -static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ +static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size) +{ if (packet_type != ATT_DATA_PACKET) return; - + att_response_handle = handle; att_response_size = att_handle_request(&att_connection, packet, size, att_response_buffer); att_try_respond(); @@ -113,28 +123,28 @@ // enable LE, setup ADV data -static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ +static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ static bd_addr_t addr; - //uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; // Data for advertisement and scan response - const uint8_t adv_data[31]="\x02\x01\x05" "\x06\x09SBDBT" "\x03\x02\xf0\xff"; + const uint8_t adv_data[31]="\x02\x01\x05" "\x05\x09mbed" "\x03\x02\xf0\xff"; switch (packet_type) { - + case HCI_EVENT_PACKET: switch (packet[0]) { - + case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - log_info("Working!\n"); + log_info("Working!\n"); hci_send_cmd(&hci_read_local_supported_features); } break; - + case DAEMON_EVENT_HCI_PACKET_SENT: att_try_respond(); break; - + case HCI_EVENT_LE_META: switch (packet[2]) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: @@ -155,67 +165,67 @@ log_info("NOT CONNECTED\n"); } break; - + case HCI_EVENT_DISCONNECTION_COMPLETE: att_response_handle =0; att_response_size = 0; - + // restart advertising hci_send_cmd(&hci_le_set_advertise_enable, 1); break; - + case HCI_EVENT_COMMAND_COMPLETE: - if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) { bt_flip_addr(addr, &packet[6]); log_info("BD ADDR: %s\n", bd_addr_to_str(addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_read_local_supported_features)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_read_local_supported_features)) { log_info("Local supported features: %04lX%04lX\n", READ_BT_32(packet, 10), READ_BT_32(packet, 6)); hci_send_cmd(&hci_set_event_mask, 0xffffffff, 0x20001fff); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask)) { hci_send_cmd(&hci_write_le_host_supported, 1, 1); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_le_host_supported)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_write_le_host_supported)) { hci_send_cmd(&hci_le_set_event_mask, 0xffffffff, 0xffffffff); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_event_mask)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_event_mask)) { hci_send_cmd(&hci_le_read_buffer_size); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_buffer_size)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_buffer_size)) { log_info("LE buffer size: %u, count %u\n", READ_BT_16(packet,6), packet[8]); - hci_send_cmd(&hci_le_read_supported_states); - break; + hci_send_cmd(&hci_le_read_supported_states); + break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_supported_states)){ - hci_send_cmd(&hci_le_set_advertising_parameters, 0x0400, 0x0800, 0, 0, 0, &addr, 0x07, 0); - break; + if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_supported_states)) { + hci_send_cmd(&hci_le_set_advertising_parameters, 0x0400, 0x0800, 0, 0, 0, &addr, 0x07, 0); + break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){ - hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); - break; + if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)) { + hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); + break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){ - hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); - break; + if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)) { + hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); + break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){ - hci_send_cmd(&hci_le_set_advertise_enable, 1); - break; + if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)) { + hci_send_cmd(&hci_le_set_advertise_enable, 1); + break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertise_enable)){ + if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertise_enable)) { hci_discoverable_control(1); log_info("startup_state=1\n"); startup_state=1; led1 = 0; break; } - + } } } @@ -227,35 +237,37 @@ static uint8_t ledvalue; // read requests -static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ +static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) +{ uint16_t ret=0,val; - if(buffer){ + if(buffer) { log_info("READ Callback, handle %04x\n", handle); led2 = 1; } - switch(handle){ - // Correspond to Characteristics 0xFFF1 - case 0x000b: - ret=strlen((char*)strbuf); - if(buffer && ret<=buffer_size){ - log_info("Read text: %s\n", strbuf); - memcpy(buffer,strbuf,ret); + switch(handle) { + // Correspond to Characteristics 0xFFF1 + case 0x000b: + if(buffer && ret<=buffer_size) { + buffer[0] = sw1.read(); + log_info("Read value: %u\n", buffer[0]); } + ret = 1; break; - // Correspond to Characteristics 0xFFF2 + // Correspond to Characteristics 0xFFF2 case 0x000d: - if(buffer && buffer_size){ + if(buffer && buffer_size) { + ledvalue = led1; + buffer[0] = ledvalue; log_info("Read value: %u\n", buffer[0]); - buffer[0]=ledvalue; } ret=1; break; - // Correspond to Characteristics 0x00001234-0000-1000-8000-00805F9B34FB + // Correspond to Characteristics 0x00001234-0000-1000-8000-00805F9B34FB case 0x000f: - if(buffer && buffer_size>=2){ + if(buffer && buffer_size>=2) { val=timer_counter; log_info("Read value: %u\n", val); buffer[0]=val&0xff; @@ -268,28 +280,21 @@ } // write requests -static void att_write_callback(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature){ +static void att_write_callback(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature) +{ log_info("WRITE Callback, handle %04x\n", handle); led2 = 0; - switch(handle){ - // Correspond to Characteristics 0xFFF1 + switch(handle) { + // Correspond to Characteristics 0xFFF1 case 0x000b: - buffer[buffer_size]=0; - if(sizeof(strbuf)>buffer_size){ - strcpy((char*)strbuf,(char*)buffer); - } - log_info("New text: %s\n", buffer); + log_info("No action\n"); break; - - // Correspond to Characteristics 0xFFF2 + + // Correspond to Characteristics 0xFFF2 case 0x000d: log_info("New value: %u\n", buffer[0]); - ledvalue=buffer[0]; - if (buffer[0]){ - led1 = 1; - } else { - led1 = 0; - } + ledvalue = buffer[0]; + led1 = ledvalue; break; } } @@ -299,9 +304,17 @@ { timer_counter++; - if(connection_status){ - led3 = !led3; - }else{ + if(connection_status) { + if(timer_counter % 250 == 0) { + led3 = !led3; + // Under testing + // switch_new_state = (uint8_t)sw1.read(); + // if (switch_new_state != switch_old_state) { + // log_info("Fire notification\n"); + // switch_old_state = switch_new_state; + // att_prepare_handle_value_notification(&att_connection, 0x000b, &switch_new_state, 1, att_response_buffer); + } + } else { led3 = 1; } } @@ -310,16 +323,18 @@ int main(void) { pc.baud(921600); + //pc.baud(230400); log_info("%s\n", __FILE__); // init LEDs led1 = led2 = led3 = 1; - - /// GET STARTED with BTstack /// + ledvalue = led1; + + /// GET STARTED with BTstack /// btstack_memory_init(); run_loop_init(RUN_LOOP_EMBEDDED); hal_tick_set_handler(&hal_tick_event); - + // init HCI // use BlueUSB hci_transport_t* transport = hci_transport_usb_instance(); @@ -327,30 +342,30 @@ hci_uart_config_t * config = NULL; remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory; hci_init(transport, config, control, remote_db); - + // use eHCILL // bt_control_cc256x_enable_ehcill(1); - + // set up l2cap_le l2cap_init(); l2cap_register_fixed_channel(att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL); l2cap_register_packet_handler(packet_handler); - + // set up ATT att_set_db(profile_data); att_set_write_callback(att_write_callback); att_set_read_callback(att_read_callback); att_dump_attributes(); att_connection.mtu = 27; - - log_info("Run...\n\r"); + + log_info("Run...\n\n"); // turn on! hci_power_control(HCI_POWER_ON); // go! - run_loop_execute(); - + run_loop_execute(); + // happy compiler! return 0; }
--- a/BTstack/att.c Mon Feb 11 14:10:57 2013 +0000 +++ b/BTstack/att.c Wed Feb 20 14:18:38 2013 +0000 @@ -38,6 +38,7 @@ #include <string.h> #include "att.h" +#include "debug.h" // from src/utils. #define READ_BT_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[pos+1]) << 8)) @@ -53,21 +54,21 @@ static void hexdump2(void const *data, int size){ int i; for (i=0; i<size;i++){ - printf("%02X ", ((uint8_t *)data)[i]); + log_info("%02X ", ((uint8_t *)data)[i]); } - printf("\n"); + log_info("\n"); } static void printUUID128(const uint8_t * uuid){ int i; for (i=15; i >= 0 ; i--){ - printf("%02X", uuid[i]); + log_info("%02X", uuid[i]); switch (i){ case 4: case 6: case 8: case 10: - printf("-"); + log_info("-"); break; default: break; @@ -209,16 +210,16 @@ while (att_iterator_has_next(&it)){ att_iterator_fetch_next(&it); if (it.handle == 0) { - printf("Handle: END\n"); + log_info("Handle: END\n"); return; } - printf("Handle: 0x%04x, flags: 0x%04x, uuid: ", it.handle, it.flags); + log_info("Handle: 0x%04x, flags: 0x%04x, uuid: ", it.handle, it.flags); if (it.flags & ATT_PROPERTY_UUID128){ printUUID128(it.uuid); } else { - printf("%04x", READ_BT_16(it.uuid, 0)); + log_info("%04x", READ_BT_16(it.uuid, 0)); } - printf(", value_len: %u, value: ", it.value_len); + log_info(", value_len: %u, value: ", it.value_len); hexdump2(it.value, it.value_len); } } @@ -268,7 +269,7 @@ static uint16_t handle_find_information_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t start_handle, uint16_t end_handle){ - printf("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X\n", start_handle, end_handle); + log_info("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X\n", start_handle, end_handle); uint16_t offset = 1; uint16_t pair_len = 0; @@ -283,7 +284,7 @@ att_update_value_len(&it); - // printf("Handle 0x%04x\n", it.handle); + // log_debug("Handle 0x%04x\n", it.handle); // check if value has same len as last one uint16_t this_pair_len = 2 + it.value_len; @@ -346,7 +347,7 @@ uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type, uint16_t attribute_len, uint8_t* attribute_value){ - printf("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type); + log_info("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type); hexdump2(attribute_value, attribute_len); uint16_t offset = 1; @@ -365,7 +366,7 @@ if (in_group && (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){ - printf("End of group, handle 0x%04x\n", prev_handle); + log_info("End of group, handle 0x%04x\n", prev_handle); bt_store_16(response_buffer, offset, prev_handle); offset += 2; in_group = 0; @@ -381,7 +382,7 @@ // does current attribute match if (it.handle && att_iterator_match_uuid16(&it, attribute_type) && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){ - printf("Begin of group, handle 0x%04x\n", it.handle); + log_info("Begin of group, handle 0x%04x\n", it.handle); bt_store_16(response_buffer, offset, it.handle); offset += 2; in_group = 1; @@ -410,7 +411,7 @@ uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type_len, uint8_t * attribute_type){ - printf("ATT_READ_BY_TYPE_REQUEST: from %04X to %04X, type: ", start_handle, end_handle); + log_info("ATT_READ_BY_TYPE_REQUEST: from %04X to %04X, type: ", start_handle, end_handle); hexdump2(attribute_type, attribute_type_len); uint16_t offset = 1; @@ -482,14 +483,14 @@ // static uint16_t handle_read_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle){ - printf("ATT_READ_REQUEST: handle %04x\n", handle); + log_info("ATT_READ_REQUEST: handle %04x\n", handle); att_iterator_t it; int ok = att_find_handle(&it, handle); if (!ok){ return setup_error_atribute_not_found(response_buffer, ATT_READ_REQUEST, handle); } - + att_update_value_len(&it); uint16_t offset = 1; @@ -515,7 +516,7 @@ // MARK: ATT_READ_BLOB_REQUEST 0x0c // static uint16_t handle_read_blob_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle, uint16_t value_offset){ - printf("ATT_READ_BLOB_REQUEST: handle %04x, offset %u\n", handle, value_offset); + log_info("ATT_READ_BLOB_REQUEST: handle %04x, offset %u\n", handle, value_offset); att_iterator_t it; int ok = att_find_handle(&it, handle); @@ -552,7 +553,7 @@ // MARK: ATT_READ_MULTIPLE_REQUEST 0x0e // static uint16_t handle_read_multiple_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t num_handles, uint16_t * handles){ - printf("ATT_READ_MULTIPLE_REQUEST: num handles %u\n", num_handles); + log_info("ATT_READ_MULTIPLE_REQUEST: num handles %u\n", num_handles); uint16_t offset = 1; @@ -603,7 +604,7 @@ uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type_len, uint8_t * attribute_type){ - printf("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size); + log_info("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size); hexdump2(attribute_type, attribute_type_len); uint16_t offset = 1; @@ -625,7 +626,7 @@ if (in_group && (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){ // TODO: check if handle is included in start/end range - // printf("End of group, handle 0x%04x, val_len: %u\n", prev_handle, pair_len - 4); + // log_debug("End of group, handle 0x%04x, val_len: %u\n", prev_handle, pair_len - 4); bt_store_16(response_buffer, offset, group_start_handle); offset += 2; @@ -645,7 +646,7 @@ prev_handle = it.handle; // does current attribute match - // printf("compare: %04x == %04x\n", *(uint16_t*) context->attribute_type, *(uint16_t*) uuid); + // log_debug("compare: %04x == %04x\n", *(uint16_t*) context->attribute_type, *(uint16_t*) uuid); if (it.handle && att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) { // check if value has same len as last one @@ -656,7 +657,7 @@ } } - // printf("Begin of group, handle 0x%04x\n", it.handle); + // log_debug("Begin of group, handle 0x%04x\n", it.handle); // first if (offset == 1) { @@ -865,7 +866,7 @@ handle_signed_write_command(request_buffer, request_len, response_buffer, response_buffer_size); break; default: - printf("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]); + log_info("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]); hexdump2(&request_buffer[9], request_len-9); break; }
--- a/BTstack/hal_mbed/hal_tick.cpp Mon Feb 11 14:10:57 2013 +0000 +++ b/BTstack/hal_mbed/hal_tick.cpp Wed Feb 20 14:18:38 2013 +0000 @@ -54,10 +54,10 @@ return; } tick_handler = handler; - tick.attach(tick_handler, 0.25); + tick.attach(tick_handler, 0.001); } int hal_tick_get_tick_period_in_ms(void){ - return 250; + return 1; }
--- a/BTstack/profile.h Mon Feb 11 14:10:57 2013 +0000 +++ b/BTstack/profile.h Wed Feb 20 14:18:38 2013 +0000 @@ -25,10 +25,10 @@ 0x08, 0x00, 0x02, 0x00, 0x08, 0x00, 0x05, 0x2a, // 0x0009 PRIMARY_SERVICE-FFF0 0x0a, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x28, 0xf0, 0xff, - // 0x000a CHARACTERISTIC-FFF1-READ | WRITE | DYNAMIC - 0x0d, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x0a, 0x0b, 0x00, 0xf1, 0xff, - // 0x000b VALUE-FFF1-READ | WRITE | DYNAMIC- - 0x08, 0x00, 0x0a, 0x01, 0x0b, 0x00, 0xf1, 0xff, + // 0x000a CHARACTERISTIC-FFF1-READ | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x02, 0x0b, 0x00, 0xf1, 0xff, + // 0x000b VALUE-FFF1-READ | DYNAMIC- + 0x08, 0x00, 0x02, 0x01, 0x0b, 0x00, 0xf1, 0xff, // 0x000c CHARACTERISTIC-FFF2-READ | WRITE | DYNAMIC 0x0d, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x03, 0x28, 0x0a, 0x0d, 0x00, 0xf2, 0xff, // 0x000d VALUE-FFF2-READ | WRITE | DYNAMIC-