BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS

Dependencies:   FatFileSystem mbed

Fork of BTstack by Norimasa Okamoto

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;
+}