11664436fSMatthias Ringwald /*
21664436fSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH
31664436fSMatthias Ringwald *
41664436fSMatthias Ringwald * Redistribution and use in source and binary forms, with or without
51664436fSMatthias Ringwald * modification, are permitted provided that the following conditions
61664436fSMatthias Ringwald * are met:
71664436fSMatthias Ringwald *
81664436fSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
91664436fSMatthias Ringwald * notice, this list of conditions and the following disclaimer.
101664436fSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
111664436fSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the
121664436fSMatthias Ringwald * documentation and/or other materials provided with the distribution.
131664436fSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
141664436fSMatthias Ringwald * contributors may be used to endorse or promote products derived
151664436fSMatthias Ringwald * from this software without specific prior written permission.
161664436fSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for
171664436fSMatthias Ringwald * personal benefit and not for any commercial purpose or for
181664436fSMatthias Ringwald * monetary gain.
191664436fSMatthias Ringwald *
201664436fSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211664436fSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221664436fSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251664436fSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261664436fSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271664436fSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281664436fSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291664436fSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301664436fSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311664436fSMatthias Ringwald * SUCH DAMAGE.
321664436fSMatthias Ringwald *
331664436fSMatthias Ringwald * Please inquire about commercial licensing options at
341664436fSMatthias Ringwald * [email protected]
351664436fSMatthias Ringwald *
361664436fSMatthias Ringwald */
371664436fSMatthias Ringwald
381664436fSMatthias Ringwald
391664436fSMatthias Ringwald // *****************************************************************************
401664436fSMatthias Ringwald //
411664436fSMatthias Ringwald // att device demo
421664436fSMatthias Ringwald //
431664436fSMatthias Ringwald // *****************************************************************************
441664436fSMatthias Ringwald
451664436fSMatthias Ringwald // TODO: seperate BR/EDR from LE ACL buffers
461664436fSMatthias Ringwald // TODO: move LE init into HCI
471664436fSMatthias Ringwald // ..
481664436fSMatthias Ringwald
491664436fSMatthias Ringwald // NOTE: Supports only a single connection
501664436fSMatthias Ringwald
511664436fSMatthias Ringwald #include <stdint.h>
521664436fSMatthias Ringwald #include <stdio.h>
531664436fSMatthias Ringwald #include <stdlib.h>
541664436fSMatthias Ringwald #include <string.h>
551664436fSMatthias Ringwald
561664436fSMatthias Ringwald #include "btstack_config.h"
571664436fSMatthias Ringwald
581664436fSMatthias Ringwald #include <msp430x54x.h>
591664436fSMatthias Ringwald
601664436fSMatthias Ringwald #include "btstack_chipset_cc256x.h"
611664436fSMatthias Ringwald #include "hal_board.h"
621664436fSMatthias Ringwald #include "hal_compat.h"
631664436fSMatthias Ringwald #include "hal_usb.h"
641664436fSMatthias Ringwald #include "hal_lcd.h"
651664436fSMatthias Ringwald #include "hal_usb.h"
661664436fSMatthias Ringwald #include "UserExperienceGraphics.h"
671664436fSMatthias Ringwald
681664436fSMatthias Ringwald #include "btstack.h"
691664436fSMatthias Ringwald
701664436fSMatthias Ringwald #define FONT_HEIGHT 12 // Each character has 13 lines
711664436fSMatthias Ringwald #define FONT_WIDTH 8
721664436fSMatthias Ringwald #define MAX_CHR01_VALUE_LENGTH 40
731664436fSMatthias Ringwald
741664436fSMatthias Ringwald static uint16_t chr01_value_length = 0;
751664436fSMatthias Ringwald static char chr01_value[MAX_CHR01_VALUE_LENGTH];
761664436fSMatthias Ringwald static char chr02_value = 0;
771664436fSMatthias Ringwald
doLCD(void)781664436fSMatthias Ringwald void doLCD(void){
791664436fSMatthias Ringwald //Initialize LCD and backlight
801664436fSMatthias Ringwald // 138 x 110, 4-level grayscale pixels.
811664436fSMatthias Ringwald halLcdInit();
821664436fSMatthias Ringwald // halLcdBackLightInit();
831664436fSMatthias Ringwald // halLcdSetBackLight(0); // 8 for normal
841664436fSMatthias Ringwald halLcdSetContrast(100);
851664436fSMatthias Ringwald halLcdClearScreen();
861664436fSMatthias Ringwald halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 );
871664436fSMatthias Ringwald
881664436fSMatthias Ringwald halLcdPrintLine("BTstack on ", 0, 0);
891664436fSMatthias Ringwald halLcdPrintLine("TI MSP430", 1, 0);
901664436fSMatthias Ringwald halLcdPrintLine("LE Write Test", 2, 0);
911664436fSMatthias Ringwald halLcdPrintLine("NOT CONNECTED", 4, 0);
921664436fSMatthias Ringwald halLcdPrintLine("Attribute 0x0022:", 6, 0);
931664436fSMatthias Ringwald halLcdPrintLine("- NO VALUE -", 7, 0);
941664436fSMatthias Ringwald }
951664436fSMatthias Ringwald
overwriteLine(int line,char * text)961664436fSMatthias Ringwald void overwriteLine(int line, char *text){
971664436fSMatthias Ringwald halLcdClearImage(130, FONT_HEIGHT, 0, line*FONT_HEIGHT);
981664436fSMatthias Ringwald halLcdPrintLine(text, line, 0);
991664436fSMatthias Ringwald }
1001664436fSMatthias Ringwald
1011664436fSMatthias Ringwald // enable LE, setup ADV data
app_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)1021664436fSMatthias Ringwald static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1031664436fSMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return;
1041664436fSMatthias Ringwald bd_addr_t addr;
1051664436fSMatthias Ringwald uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff };
1061664436fSMatthias Ringwald
1071664436fSMatthias Ringwald switch (hci_event_packet_get_type(packet)) {
1081664436fSMatthias Ringwald case BTSTACK_EVENT_STATE:
1091664436fSMatthias Ringwald // bt stack activated, get started - set local name
1101664436fSMatthias Ringwald if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
1111664436fSMatthias Ringwald printf("Working!\n");
1121664436fSMatthias Ringwald hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
1131664436fSMatthias Ringwald }
1141664436fSMatthias Ringwald break;
1151664436fSMatthias Ringwald
1161664436fSMatthias Ringwald case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED:
1171664436fSMatthias Ringwald if (packet[2]) {
1181664436fSMatthias Ringwald overwriteLine(4, "CONNECTED");
1191664436fSMatthias Ringwald } else {
1201664436fSMatthias Ringwald overwriteLine(4, "NOT CONNECTED");
1211664436fSMatthias Ringwald }
1221664436fSMatthias Ringwald break;
1231664436fSMatthias Ringwald
1241664436fSMatthias Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE:
1251664436fSMatthias Ringwald // restart advertising
1261664436fSMatthias Ringwald hci_send_cmd(&hci_le_set_advertise_enable, 1);
1271664436fSMatthias Ringwald break;
1281664436fSMatthias Ringwald
1291664436fSMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE:
130*d39264f2SMatthias Ringwald if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) {
1311664436fSMatthias Ringwald reverse_bd_addr(&packet[6], addr);
1321664436fSMatthias Ringwald printf("BD ADDR: %s\n", bd_addr_to_str(addr));
1331664436fSMatthias Ringwald break;
1341664436fSMatthias Ringwald }
135*d39264f2SMatthias Ringwald if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA) {
1361664436fSMatthias Ringwald hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data);
1371664436fSMatthias Ringwald break;
1381664436fSMatthias Ringwald }
139*d39264f2SMatthias Ringwald if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_LE_SET_SCAN_RESPONSE_DATA) {
1401664436fSMatthias Ringwald hci_send_cmd(&hci_le_set_advertise_enable, 1);
1411664436fSMatthias Ringwald break;
1421664436fSMatthias Ringwald }
1431664436fSMatthias Ringwald default:
1441664436fSMatthias Ringwald break;
1451664436fSMatthias Ringwald }
1461664436fSMatthias Ringwald
1471664436fSMatthias Ringwald }
1481664436fSMatthias Ringwald
1491664436fSMatthias Ringwald // test profile
1501664436fSMatthias Ringwald #include "profile.h"
1511664436fSMatthias Ringwald
get_read_att_value_len(uint16_t att_handle)1521664436fSMatthias Ringwald static uint16_t get_read_att_value_len(uint16_t att_handle){
1531664436fSMatthias Ringwald uint16_t value_len;
1541664436fSMatthias Ringwald switch(att_handle){
1551664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
1561664436fSMatthias Ringwald value_len = chr01_value_length;
1571664436fSMatthias Ringwald break;
1581664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
1591664436fSMatthias Ringwald value_len = 1;
1601664436fSMatthias Ringwald break;
1611664436fSMatthias Ringwald default:
1621664436fSMatthias Ringwald value_len = 0;
1631664436fSMatthias Ringwald break;
1641664436fSMatthias Ringwald }
1651664436fSMatthias Ringwald return value_len;
1661664436fSMatthias Ringwald }
1671664436fSMatthias Ringwald
get_write_att_value_len(uint16_t att_handle)1681664436fSMatthias Ringwald static uint16_t get_write_att_value_len(uint16_t att_handle){
1691664436fSMatthias Ringwald uint16_t value_len;
1701664436fSMatthias Ringwald switch(att_handle){
1711664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
1721664436fSMatthias Ringwald value_len = MAX_CHR01_VALUE_LENGTH;
1731664436fSMatthias Ringwald break;
1741664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
1751664436fSMatthias Ringwald value_len = 1;
1761664436fSMatthias Ringwald break;
1771664436fSMatthias Ringwald default:
1781664436fSMatthias Ringwald value_len = 0;
1791664436fSMatthias Ringwald break;
1801664436fSMatthias Ringwald }
1811664436fSMatthias Ringwald return value_len;
1821664436fSMatthias Ringwald }
1831664436fSMatthias Ringwald
get_bytes_to_copy(uint16_t value_len,uint16_t offset,uint16_t buffer_size)1841664436fSMatthias Ringwald static uint16_t get_bytes_to_copy(uint16_t value_len, uint16_t offset, uint16_t buffer_size){
1851664436fSMatthias Ringwald if (value_len <= offset ) return 0;
1861664436fSMatthias Ringwald
1871664436fSMatthias Ringwald uint16_t bytes_to_copy = value_len - offset;
1881664436fSMatthias Ringwald if (bytes_to_copy > buffer_size) {
1891664436fSMatthias Ringwald bytes_to_copy = buffer_size;
1901664436fSMatthias Ringwald }
1911664436fSMatthias Ringwald return bytes_to_copy;
1921664436fSMatthias Ringwald }
1931664436fSMatthias Ringwald
att_read_callback(hci_con_handle_t con_handle,uint16_t att_handle,uint16_t offset,uint8_t * buffer,uint16_t buffer_size)1941664436fSMatthias 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){
1951664436fSMatthias Ringwald printf("READ Callback, handle %04x\n", att_handle);
1961664436fSMatthias Ringwald uint16_t value_len = get_read_att_value_len(att_handle);
1971664436fSMatthias Ringwald if (!buffer) return value_len;
1981664436fSMatthias Ringwald
1991664436fSMatthias Ringwald uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset, buffer_size);
2001664436fSMatthias Ringwald if (!bytes_to_copy) return 0;
2011664436fSMatthias Ringwald
2021664436fSMatthias Ringwald switch(att_handle){
2031664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
2041664436fSMatthias Ringwald memcpy(buffer, &chr01_value[offset], bytes_to_copy);
2051664436fSMatthias Ringwald break;
2061664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
2071664436fSMatthias Ringwald buffer[offset] = chr02_value;
2081664436fSMatthias Ringwald break;
2091664436fSMatthias Ringwald }
2101664436fSMatthias Ringwald return bytes_to_copy;
2111664436fSMatthias Ringwald }
2121664436fSMatthias Ringwald
2131664436fSMatthias Ringwald // write requests
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)2141664436fSMatthias 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){
2151664436fSMatthias Ringwald printf("WRITE Callback, handle %04x\n", att_handle);
2161664436fSMatthias Ringwald
2171664436fSMatthias Ringwald uint16_t value_len = get_write_att_value_len(att_handle);
2181664436fSMatthias Ringwald uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset,buffer_size);
2191664436fSMatthias Ringwald if (!bytes_to_copy) return ATT_ERROR_INVALID_OFFSET;
2201664436fSMatthias Ringwald
2211664436fSMatthias Ringwald switch(att_handle){
2221664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
2231664436fSMatthias Ringwald buffer[buffer_size] = 0;
2241664436fSMatthias Ringwald memcpy(&chr01_value[offset], buffer, bytes_to_copy);
2251664436fSMatthias Ringwald chr01_value_length = bytes_to_copy + offset;
2261664436fSMatthias Ringwald
2271664436fSMatthias Ringwald printf("New text: %s\n", buffer);
2281664436fSMatthias Ringwald overwriteLine(7, (char*)buffer);
2291664436fSMatthias Ringwald break;
2301664436fSMatthias Ringwald case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
2311664436fSMatthias Ringwald printf("New value: %u\n", buffer[offset]);
2321664436fSMatthias Ringwald if (buffer[offset]) {
2331664436fSMatthias Ringwald LED_PORT_OUT |= LED_2;
2341664436fSMatthias Ringwald } else {
2351664436fSMatthias Ringwald LED_PORT_OUT &= ~LED_2;
2361664436fSMatthias Ringwald }
2371664436fSMatthias Ringwald chr02_value = buffer[offset];
2381664436fSMatthias Ringwald break;
2391664436fSMatthias Ringwald }
2401664436fSMatthias Ringwald return 0;
2411664436fSMatthias Ringwald }
2421664436fSMatthias Ringwald
2431664436fSMatthias Ringwald int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])2441664436fSMatthias Ringwald int btstack_main(int argc, const char * argv[]){
2451664436fSMatthias Ringwald
2461664436fSMatthias Ringwald // show off
2471664436fSMatthias Ringwald doLCD();
2481664436fSMatthias Ringwald
2491664436fSMatthias Ringwald // set up l2cap_le
2501664436fSMatthias Ringwald l2cap_init();
2511664436fSMatthias Ringwald
2521664436fSMatthias Ringwald // setup le device db
2531664436fSMatthias Ringwald le_device_db_init();
2541664436fSMatthias Ringwald
2551664436fSMatthias Ringwald // setup SM: Display only
2561664436fSMatthias Ringwald sm_init();
2571664436fSMatthias Ringwald sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
2581664436fSMatthias Ringwald sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
2591664436fSMatthias Ringwald
2601664436fSMatthias Ringwald // setup ATT server
2611664436fSMatthias Ringwald att_server_init(profile_data, NULL, att_write_callback);
2621664436fSMatthias Ringwald att_server_register_packet_handler(app_packet_handler);
2631664436fSMatthias Ringwald
2641664436fSMatthias Ringwald printf("Run...\n\r");
2651664436fSMatthias Ringwald
2661664436fSMatthias Ringwald // turn on!
2671664436fSMatthias Ringwald hci_power_control(HCI_POWER_ON);
2681664436fSMatthias Ringwald
2691664436fSMatthias Ringwald LED_PORT_OUT &= ~LED_2;
2701664436fSMatthias Ringwald
2711664436fSMatthias Ringwald return 0;
2721664436fSMatthias Ringwald }
2731664436fSMatthias Ringwald
274