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