BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS
Dependencies: FatFileSystem mbed
Fork of BTstack by
Diff: BLE_demo.cpp
- Revision:
- 1:6078e430af82
- Child:
- 2:24b33d92e086
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BLE_demo.cpp Thu Feb 07 14:01:01 2013 +0000 @@ -0,0 +1,302 @@ +/* + * BLE_demo + */ + +// mbed specific +#include "mbed.h" +Serial pc(USBTX, USBRX); +DigitalOut led1(LED1), led2(LED2), led3(LED3); + +#define HEARTBEAT_PERIOD_MS 500 + +// from btstack ble_server.c +#include "global.h" +#include "debug.h" +#include "btstack/btstack.h" +#include "btstack/hci_cmds.h" +#include "btstack/run_loop.h" + +#include "hci.h" +#include "l2cap.h" +#include "btstack_memory.h" +#include "remote_device_db.h" +#include "config.h" + +#include "att.h" + +unsigned timer_counter=0; +uint8_t startup_state=0; + + +hci_transport_t * hci_transport_picusb_instance(); + +static att_connection_t att_connection; +static uint16_t att_response_handle = 0; +static uint16_t att_response_size = 0; +static uint8_t att_response_buffer[28]; + +uint8_t connection_status=0; + +void hexdump2(void *data, int size){ + int i; + for (i=0; i<size;i++){ + log_info("%02X ", ((uint8_t *)data)[i]); + } + log_info("\n"); +} + +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; + l2cap_send_connectionless(att_response_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_buffer, 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(); +} + + +// 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 bd_addr_t addr; +// uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; + const uint8_t adv_data[31]="\x02\x01\x05" "\x06\x09SBDBT"; + 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"); + 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: + // reset connection MTU + att_connection.mtu = 23; + break; + default: + break; + } + break; + + case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED: + if (packet[2]) { + connection_status=1; + log_info("CONNECTED\n"); + } else { + connection_status=0; + 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)){ + 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)){ + 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)){ + hci_send_cmd(&hci_write_le_host_supported, 1, 1); + break; + } + 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)){ + hci_send_cmd(&hci_le_read_buffer_size); + break; + } + 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; + } + 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_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_advertise_enable)){ + hci_discoverable_control(1); + log_info("startup_state=1\n"); + startup_state=1; + led1 = 0; + break; + } + + } + } +} + +// test profile +#include "profile.h" + +static uint8_t strbuf[80]; +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){ + uint16_t ret=0,val; + + if(buffer){ + log_info("READ Callback, handle %04x\n", handle); + led1 = 1; + } + switch(handle){ + case 0x000b: + ret=strlen((char*)strbuf); + if(buffer && ret<=buffer_size){ + log_info("Read text: %s\n", strbuf); + memcpy(buffer,strbuf,ret); + } + break; + case 0x000d: + if(buffer && buffer_size){ + log_info("Read value: %u\n", buffer[0]); + buffer[0]=ledvalue; + } + ret=1; + break; + case 0x000f: + if(buffer && buffer_size>=2){ + val=timer_counter; + log_info("Read value: %u\n", val); + buffer[0]=val&0xff; + buffer[1]=val>>8; + } + ret=2; + break; + } + return ret; +} + +// 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){ + log_info("WRITE Callback, handle %04x\n", handle); + led1 = 1; + switch(handle){ + case 0x000b: + buffer[buffer_size]=0; + if(sizeof(strbuf)>buffer_size){ + strcpy((char*)strbuf,(char*)buffer); + } + log_info("New text: %s\n", buffer); + break; + case 0x000d: + log_info("New value: %u\n", buffer[0]); + ledvalue=buffer[0]; + if (buffer[0]){ + led1 = 1; + } else { + led1 = 0; + } + break; + } +} + + +static void heartbeat_handler(struct timer *ts){ + run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS); + run_loop_add_timer(ts); + led2 = !led2; +} + + +// main +int main(void) +{ + pc.baud(115200); + log_info("%s\n", __FILE__); + + // init LEDs + led1 = led2 = led3 = 1; + + /// GET STARTED with BTstack /// + btstack_memory_init(); + run_loop_init(RUN_LOOP_EMBEDDED); + + // init HCI + // use BlueUSB + hci_transport_t* transport = hci_transport_usb_instance(); + bt_control_t * control = NULL; + 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; + + // set one-shot timer + timer_source_t heartbeat; + heartbeat.process = &heartbeat_handler; + run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); + run_loop_add_timer(&heartbeat); + + log_info("Run...\n\r"); + + // turn on! + hci_power_control(HCI_POWER_ON); + + // go! + run_loop_execute(); + + // happy compiler! + return 0; +}