-
Notifications
You must be signed in to change notification settings - Fork 624
/
Copy pathublox_spp_le_counter.c
226 lines (195 loc) · 8.11 KB
/
ublox_spp_le_counter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define BTSTACK_FILE__ "ublox_spp_le_counter.c"
// *****************************************************************************
/* EXAMPLE_START(ublox_spp_le_counter): LE u-blox SPP-like Heartbeat Server
*
*/
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "btstack.h"
#include "ble/gatt-service/device_information_service_server.h"
#include "ble/gatt-service/ublox_spp_service_server.h"
// ublox_spp_le_counter.gatt contains the declaration of the provided GATT Services + Characteristics
// ublox_spp_le_counter.h contains the binary representation of ublox_spp_le_counter.gatt
// it is generated by the build system by calling: $BTSTACK_ROOT/tool/compile_gatt.py ublox_spp_le_counter.gatt ublox_spp_le_counter.h
// it needs to be regenerated when the GATT Database declared in ublox_spp_le_counter.gatt file is modified
#include "ublox_spp_le_counter.h"
#define HEARTBEAT_PERIOD_MS 1000
/* @section Main Application Setup
*
* @text Listing MainConfiguration shows main application code.
* It initializes L2CAP, the Security Manager and configures the ATT Server with the pre-compiled
* ATT Database generated from $ublox_le_counter.gatt$.
* Additionally, it enables the Battery Service Server with the current battery level.
* Finally, it configures the advertisements
* and the heartbeat handler and boots the Bluetooth stack.
* In this example, the Advertisement contains the Flags attribute and the device name.
* The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not supported.
*/
/* LISTING_START(MainConfiguration): Init L2CAP SM ATT Server and start heartbeat timer */
static btstack_timer_source_t heartbeat;
static hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
static btstack_context_callback_registration_t send_request;
static btstack_packet_callback_registration_t hci_event_callback_registration;
const uint8_t adv_data[] = {
// Flags general discoverable, BR/EDR not supported
2, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
// Name
5, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, '6', '-','5', '6',
// UUID ...
17, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS, 0x1, 0xd7, 0xe9, 0x1, 0x4f, 0xf3, 0x44, 0xe7, 0x83, 0x8f, 0xe2, 0x26, 0xb9, 0xe1, 0x56, 0x24,
};
const uint8_t adv_data_len = sizeof(adv_data);
/* LISTING_END */
/*
* @section Heartbeat Handler
*
* @text The heartbeat handler updates the value of the single Characteristic provided in this example,
* and request a ATT_EVENT_CAN_SEND_NOW to send a notification if enabled see Listing heartbeat.
*/
/* LISTING_START(heartbeat): Hearbeat Handler */
static int counter = 0;
static char counter_string[30];
static int counter_string_len;
static void beat(void){
counter++;
counter_string_len = snprintf(counter_string, sizeof(counter_string), "BTstack counter %03u", counter);
}
static void ublox_can_send(void * context){
UNUSED(context);
beat();
printf("SEND: %s\n", counter_string);
ublox_spp_service_server_send(con_handle, (uint8_t*) counter_string, counter_string_len);
}
static void heartbeat_handler(struct btstack_timer_source *ts){
if (con_handle != HCI_CON_HANDLE_INVALID) {
send_request.callback = &ublox_can_send;
ublox_spp_service_server_request_can_send_now(&send_request, con_handle);
}
btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
btstack_run_loop_add_timer(ts);
}
/* LISTING_END */
static void ublox_spp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
switch (packet_type){
case HCI_EVENT_PACKET:
if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META) break;
switch (hci_event_gattservice_meta_get_subevent_code(packet)){
case GATTSERVICE_SUBEVENT_SPP_SERVICE_CONNECTED:
con_handle = gattservice_subevent_spp_service_connected_get_con_handle(packet);
printf("Connected with handle 0x%04x\n", con_handle);
break;
case GATTSERVICE_SUBEVENT_SPP_SERVICE_DISCONNECTED:
con_handle = HCI_CON_HANDLE_INVALID;
break;
default:
break;
}
break;
case RFCOMM_DATA_PACKET:
printf("RECV: ");
printf_hexdump(packet, size);
break;
default:
break;
}
}
/*
* @section Packet Handler
*
* @text The packet handler is used to:
* - stop the counter after a disconnect
*/
/* LISTING_START(packetHandler): Packet Handler */
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_DISCONNECTION_COMPLETE:
con_handle = HCI_CON_HANDLE_INVALID;
break;
default:
break;
}
break;
default:
break;
}
}
/* LISTING_END */
int btstack_main(void);
int btstack_main(void)
{
// register for HCI events
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
l2cap_init();
// setup SM: Display only
sm_init();
// setup ATT server
att_server_init(profile_data, NULL, NULL);
// setup device information service
device_information_service_server_init();
// setup Nordic SPP service
ublox_spp_service_server_init(&ublox_spp_packet_handler);
// setup advertisements
uint16_t adv_int_min = 0x0030;
uint16_t adv_int_max = 0x0030;
uint8_t adv_type = 0;
bd_addr_t null_addr;
memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
gap_advertisements_enable(1);
// set one-shot timer
heartbeat.process = &heartbeat_handler;
btstack_run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
btstack_run_loop_add_timer(&heartbeat);
// beat once
beat();
// turn on!
hci_power_control(HCI_POWER_ON);
return 0;
}
/* EXAMPLE_END */