
BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS
Dependencies: FatFileSystem mbed
Fork of BTstack by
BLE_demo.cpp
- Committer:
- todotani
- Date:
- 2013-02-20
- Revision:
- 6:cf06ba884429
- Parent:
- 5:5fb56e13a1f9
File content as of revision 6:cf06ba884429:
/* * Copyright (C) 2011-2012 by Matthias Ringwald * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * 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. * * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* Change history 2013/2/10: by todotani Modified tick event handler Modified LED control - LED 3 flush when connected - LED 2 OFF in case write attribute, ON in case read attribute - LED 1 OFF of after start of advertisement, then reflect write value to 0xFFF2 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 */ //***************************************************************************** // // att device demo // //***************************************************************************** // TODO: seperate BR/EDR from LE ACL buffers // TODO: move LE init into HCI // .. // NOTE: Supports only a single connection // mbed specific #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" #include "debug.h" #include "btstack/btstack.h" #include "btstack/hci_cmds.h" #include "btstack/run_loop.h" #include "btstack/hal_tick.h" #include "hci.h" #include "l2cap.h" #include "btstack_memory.h" #include "remote_device_db.h" #include "config.h" #include "att.h" 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]; 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++) { 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; // Data for advertisement and scan response 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"); 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); led2 = 1; } 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 case 0x000d: if(buffer && buffer_size) { ledvalue = led1; buffer[0] = ledvalue; log_info("Read value: %u\n", buffer[0]); } ret=1; break; // Correspond to Characteristics 0x00001234-0000-1000-8000-00805F9B34FB 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); led2 = 0; switch(handle) { // Correspond to Characteristics 0xFFF1 case 0x000b: log_info("No action\n"); break; // Correspond to Characteristics 0xFFF2 case 0x000d: log_info("New value: %u\n", buffer[0]); ledvalue = buffer[0]; led1 = ledvalue; break; } } void hal_tick_event(void) { timer_counter++; 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; } } // main int main(void) { pc.baud(921600); //pc.baud(230400); log_info("%s\n", __FILE__); // init LEDs led1 = led2 = led3 = 1; 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(); 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; log_info("Run...\n\n"); // turn on! hci_power_control(HCI_POWER_ON); // go! run_loop_execute(); // happy compiler! return 0; }