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_lcd.h" 65 #include "hal_usb.h" 66 #include "UserExperienceGraphics.h" 67 68 #include "btstack.h" 69 70 #define FONT_HEIGHT 12 // Each character has 13 lines 71 #define FONT_WIDTH 8 72 #define MAX_CHR01_VALUE_LENGTH 40 73 74 static uint16_t chr01_value_length = 0; 75 static char chr01_value[MAX_CHR01_VALUE_LENGTH]; 76 static char chr02_value = 0; 77 78 void doLCD(void){ 79 //Initialize LCD and backlight 80 // 138 x 110, 4-level grayscale pixels. 81 halLcdInit(); 82 // halLcdBackLightInit(); 83 // halLcdSetBackLight(0); // 8 for normal 84 halLcdSetContrast(100); 85 halLcdClearScreen(); 86 halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 ); 87 88 halLcdPrintLine("BTstack on ", 0, 0); 89 halLcdPrintLine("TI MSP430", 1, 0); 90 halLcdPrintLine("LE Write Test", 2, 0); 91 halLcdPrintLine("NOT CONNECTED", 4, 0); 92 halLcdPrintLine("Attribute 0x0022:", 6, 0); 93 halLcdPrintLine("- NO VALUE -", 7, 0); 94 } 95 96 void overwriteLine(int line, char *text){ 97 halLcdClearImage(130, FONT_HEIGHT, 0, line*FONT_HEIGHT); 98 halLcdPrintLine(text, line, 0); 99 } 100 101 // enable LE, setup ADV data 102 static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 103 if (packet_type != HCI_EVENT_PACKET) return; 104 bd_addr_t addr; 105 uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; 106 107 switch (hci_event_packet_get_type(packet)) { 108 case BTSTACK_EVENT_STATE: 109 // bt stack activated, get started - set local name 110 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 111 printf("Working!\n"); 112 hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); 113 } 114 break; 115 116 case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED: 117 if (packet[2]) { 118 overwriteLine(4, "CONNECTED"); 119 } else { 120 overwriteLine(4, "NOT CONNECTED"); 121 } 122 break; 123 124 case HCI_EVENT_DISCONNECTION_COMPLETE: 125 // restart advertising 126 hci_send_cmd(&hci_le_set_advertise_enable, 1); 127 break; 128 129 case HCI_EVENT_COMMAND_COMPLETE: 130 if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) { 131 reverse_bd_addr(&packet[6], addr); 132 printf("BD ADDR: %s\n", bd_addr_to_str(addr)); 133 break; 134 } 135 if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA) { 136 hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); 137 break; 138 } 139 if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_LE_SET_SCAN_RESPONSE_DATA) { 140 hci_send_cmd(&hci_le_set_advertise_enable, 1); 141 break; 142 } 143 default: 144 break; 145 } 146 147 } 148 149 // test profile 150 #include "profile.h" 151 152 static uint16_t get_read_att_value_len(uint16_t att_handle){ 153 uint16_t value_len; 154 switch(att_handle){ 155 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 156 value_len = chr01_value_length; 157 break; 158 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 159 value_len = 1; 160 break; 161 default: 162 value_len = 0; 163 break; 164 } 165 return value_len; 166 } 167 168 static uint16_t get_write_att_value_len(uint16_t att_handle){ 169 uint16_t value_len; 170 switch(att_handle){ 171 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 172 value_len = MAX_CHR01_VALUE_LENGTH; 173 break; 174 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 175 value_len = 1; 176 break; 177 default: 178 value_len = 0; 179 break; 180 } 181 return value_len; 182 } 183 184 static uint16_t get_bytes_to_copy(uint16_t value_len, uint16_t offset, uint16_t buffer_size){ 185 if (value_len <= offset ) return 0; 186 187 uint16_t bytes_to_copy = value_len - offset; 188 if (bytes_to_copy > buffer_size) { 189 bytes_to_copy = buffer_size; 190 } 191 return bytes_to_copy; 192 } 193 194 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){ 195 printf("READ Callback, handle %04x\n", att_handle); 196 uint16_t value_len = get_read_att_value_len(att_handle); 197 if (!buffer) return value_len; 198 199 uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset, buffer_size); 200 if (!bytes_to_copy) return 0; 201 202 switch(att_handle){ 203 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 204 memcpy(buffer, &chr01_value[offset], bytes_to_copy); 205 break; 206 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 207 buffer[offset] = chr02_value; 208 break; 209 } 210 return bytes_to_copy; 211 } 212 213 // write requests 214 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){ 215 printf("WRITE Callback, handle %04x\n", att_handle); 216 217 uint16_t value_len = get_write_att_value_len(att_handle); 218 uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset,buffer_size); 219 if (!bytes_to_copy) return ATT_ERROR_INVALID_OFFSET; 220 221 switch(att_handle){ 222 case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE: 223 buffer[buffer_size] = 0; 224 memcpy(&chr01_value[offset], buffer, bytes_to_copy); 225 chr01_value_length = bytes_to_copy + offset; 226 227 printf("New text: %s\n", buffer); 228 overwriteLine(7, (char*)buffer); 229 break; 230 case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE: 231 printf("New value: %u\n", buffer[offset]); 232 if (buffer[offset]) { 233 LED_PORT_OUT |= LED_2; 234 } else { 235 LED_PORT_OUT &= ~LED_2; 236 } 237 chr02_value = buffer[offset]; 238 break; 239 } 240 return 0; 241 } 242 243 int btstack_main(int argc, const char * argv[]); 244 int btstack_main(int argc, const char * argv[]){ 245 246 // show off 247 doLCD(); 248 249 // set up l2cap_le 250 l2cap_init(); 251 252 // setup le device db 253 le_device_db_init(); 254 255 // setup SM: Display only 256 sm_init(); 257 sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); 258 sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); 259 260 // setup ATT server 261 att_server_init(profile_data, NULL, att_write_callback); 262 att_server_register_packet_handler(app_packet_handler); 263 264 printf("Run...\n\r"); 265 266 // turn on! 267 hci_power_control(HCI_POWER_ON); 268 269 LED_PORT_OUT &= ~LED_2; 270 271 return 0; 272 } 273 274