1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 39 // ***************************************************************************** 40 // 41 // att device demo 42 // 43 // ***************************************************************************** 44 45 // TODO: seperate BR/EDR from LE ACL buffers 46 // TODO: move LE init into HCI 47 // .. 48 49 // NOTE: Supports only a single connection 50 51 #include <stdint.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 56 #include "btstack_config.h" 57 58 #include <msp430x54x.h> 59 60 #include "btstack_chipset_cc256x.h" 61 #include "hal_board.h" 62 #include "hal_compat.h" 63 #include "hal_usb.h" 64 #include "hal_usb.h" 65 66 #include "btstack.h" 67 68 69 #define FONT_HEIGHT 12 // Each character has 13 lines 70 #define FONT_WIDTH 8 71 #define MAX_CHR01_VALUE_LENGTH 40 72 73 static uint16_t chr01_value_length = 0; 74 static char chr01_value[MAX_CHR01_VALUE_LENGTH]; 75 static char chr02_value = 0; 76 77 // enable LE, setup ADV data 78 static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 79 if (packet_type != HCI_EVENT_PACKET) return; 80 bd_addr_t addr; 81 uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; 82 83 switch (hci_event_packet_get_type(packet)) { 84 case BTSTACK_EVENT_STATE: 85 // bt stack activated, get started - set local name 86 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 87 printf("Working!\n"); 88 hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); 89 } 90 break; 91 92 case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED: 93 if (packet[2]) { 94 printf("CONNECTED"); 95 } else { 96 printf("DISCONNECTED"); 97 } 98 break; 99 100 case HCI_EVENT_DISCONNECTION_COMPLETE: 101 // restart advertising 102 hci_send_cmd(&hci_le_set_advertise_enable, 1); 103 break; 104 105 case HCI_EVENT_COMMAND_COMPLETE: 106 if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) { 107 reverse_bd_addr(&packet[6], addr); 108 printf("BD ADDR: %s\n", bd_addr_to_str(addr)); 109 break; 110 } 111 if (hci_event_command_complete_get_command_opcode(packet) == HCI_HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA) { 112 hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); 113 break; 114 } 115 if (hci_event_command_complete_get_command_opcode(packet) == HCI_HCI_OPCODE_HCI_LE_SET_SCAN_RESPONSE_DATA) { 116 hci_send_cmd(&hci_le_set_advertise_enable, 1); 117 break; 118 } 119 default: 120 break; 121 } 122 123 } 124 125 // test profile 126 #include "profile.h" 127 128 static uint16_t get_read_att_value_len(uint16_t att_handle){ 129 uint16_t value_len; 130 switch(att_handle){ 131 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 132 value_len = chr01_value_length; 133 break; 134 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 135 value_len = 1; 136 break; 137 default: 138 value_len = 0; 139 break; 140 } 141 return value_len; 142 } 143 144 static uint16_t get_write_att_value_len(uint16_t att_handle){ 145 uint16_t value_len; 146 switch(att_handle){ 147 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 148 value_len = MAX_CHR01_VALUE_LENGTH; 149 break; 150 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 151 value_len = 1; 152 break; 153 default: 154 value_len = 0; 155 break; 156 } 157 return value_len; 158 } 159 160 static uint16_t get_bytes_to_copy(uint16_t value_len, uint16_t offset, uint16_t buffer_size){ 161 if (value_len <= offset ) return 0; 162 163 uint16_t bytes_to_copy = value_len - offset; 164 if (bytes_to_copy > buffer_size) { 165 bytes_to_copy = buffer_size; 166 } 167 return bytes_to_copy; 168 } 169 170 uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 171 printf("READ Callback, handle %04x\n", att_handle); 172 uint16_t value_len = get_read_att_value_len(att_handle); 173 if (!buffer) return value_len; 174 175 uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset, buffer_size); 176 if (!bytes_to_copy) return 0; 177 178 switch(att_handle){ 179 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 180 memcpy(buffer, &chr01_value[offset], bytes_to_copy); 181 break; 182 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 183 buffer[offset] = chr02_value; 184 break; 185 } 186 return bytes_to_copy; 187 } 188 189 // write requests 190 static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){ 191 printf("WRITE Callback, handle %04x\n", att_handle); 192 193 uint16_t value_len = get_write_att_value_len(att_handle); 194 uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset,buffer_size); 195 if (!bytes_to_copy) return ATT_ERROR_INVALID_OFFSET; 196 197 switch(att_handle){ 198 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 199 buffer[buffer_size] = 0; 200 memcpy(&chr01_value[offset], buffer, bytes_to_copy); 201 chr01_value_length = bytes_to_copy + offset; 202 203 printf("New text: %s\n", buffer); 204 break; 205 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 206 printf("New value: %u\n", buffer[offset]); 207 #if 0 208 if (buffer[offset]) { 209 LED_PORT_OUT |= LED_2; 210 } else { 211 LED_PORT_OUT &= ~LED_2; 212 } 213 #endif 214 chr02_value = buffer[offset]; 215 break; 216 } 217 return 0; 218 } 219 220 int btstack_main(int argc, const char * argv[]); 221 int btstack_main(int argc, const char * argv[]){ 222 223 // set up l2cap_le 224 l2cap_init(); 225 226 // setup le device db 227 le_device_db_init(); 228 229 // setup SM: Display only 230 sm_init(); 231 sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); 232 sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); 233 234 // setup ATT server 235 att_server_init(profile_data, NULL, att_write_callback); 236 att_server_register_packet_handler(app_packet_handler); 237 238 printf("Run...\n\r"); 239 240 // turn on! 241 hci_power_control(HCI_POWER_ON); 242 243 // LED_PORT_OUT &= ~LED_2; 244 245 return 0; 246 } 247 248