xref: /btstack/port/archive/msp-exp430f5438-cc2564b/example/ble_server.c (revision b29e92f97ffd81bc8a1057634c8d1552fc963a6a)
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