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