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
doLCD(void)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
overwriteLine(int line,char * text)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
app_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
get_read_att_value_len(uint16_t att_handle)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
get_write_att_value_len(uint16_t att_handle)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
get_bytes_to_copy(uint16_t value_len,uint16_t offset,uint16_t buffer_size)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
att_read_callback(hci_con_handle_t con_handle,uint16_t att_handle,uint16_t offset,uint8_t * buffer,uint16_t buffer_size)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
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)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[]);
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