xref: /btstack/example/nordic_spp_le_counter.c (revision ebdf3c684b9b7659b2b3d23a00b29177ce5829dc)
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 MATTHIAS
24  * RINGWALD 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 #define __BTSTACK_FILE__ "nordic_le_counter.c"
39 
40 // *****************************************************************************
41 /* EXAMPLE_START(nordic_le_counter): LE Peripheral - Nordic SPP-like profile
42  *
43  */
44  // *****************************************************************************
45 
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 
51 #include "nordic_le_counter.h"
52 #include "btstack.h"
53 #include "ble/gatt-service/nordic_spp_service_server.h"
54 
55 #define HEARTBEAT_PERIOD_MS 1000
56 
57 /* @section Main Application Setup
58  *
59  * @text Listing MainConfiguration shows main application code.
60  * It initializes L2CAP, the Security Manager and configures the ATT Server with the pre-compiled
61  * ATT Database generated from $nordic_le_counter.gatt$.
62  * Additionally, it enables the Battery Service Server with the current battery level.
63  * Finally, it configures the advertisements
64  * and the heartbeat handler and boots the Bluetooth stack.
65  * In this example, the Advertisement contains the Flags attribute and the device name.
66  * The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not supported.
67  */
68 
69 /* LISTING_START(MainConfiguration): Init L2CAP SM ATT Server and start heartbeat timer */
70 static btstack_timer_source_t heartbeat;
71 static hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
72 static btstack_context_callback_registration_t send_request;
73 static btstack_packet_callback_registration_t  hci_event_callback_registration;
74 
75 const uint8_t adv_data[] = {
76     // Flags general discoverable, BR/EDR not supported
77     2, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
78     // Name
79     6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'A', 'M', 'B', 'E', 'R',
80     // UUID ...
81     17, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS, 0x6e, 0x40, 0x0, 0x1, 0xc3, 0x52, 0x11, 0xe5, 0x95, 0x3d, 0x0, 0x2, 0xa5, 0xd5, 0xc5, 0x1b,
82 };
83 const uint8_t adv_data_len = sizeof(adv_data);
84 
85 /* LISTING_END */
86 
87 /*
88  * @section Heartbeat Handler
89  *
90  * @text The heartbeat handler updates the value of the single Characteristic provided in this example,
91  * and request a ATT_EVENT_CAN_SEND_NOW to send a notification if enabled see Listing heartbeat.
92  */
93 
94  /* LISTING_START(heartbeat): Hearbeat Handler */
95 static int  counter = 0;
96 static char counter_string[30];
97 static int  counter_string_len;
98 
99 static void beat(void){
100     counter++;
101     counter_string_len = sprintf(counter_string, "BTstack counter %03u", counter);
102 }
103 
104 static void nordic_can_send(void * context){
105     UNUSED(context);
106     printf("SEND: %s\n", counter_string);
107     nordic_spp_service_server_send(con_handle, (uint8_t*) counter_string, counter_string_len);
108 }
109 
110 static void heartbeat_handler(struct btstack_timer_source *ts){
111     if (con_handle != HCI_CON_HANDLE_INVALID) {
112         beat();
113         send_request.callback = &nordic_can_send;
114         nordic_spp_service_server_request_can_send_now(&send_request, con_handle);
115     }
116     btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
117     btstack_run_loop_add_timer(ts);
118 }
119 /* LISTING_END */
120 
121 static void nordic_data_received(hci_con_handle_t tx_con_handle, const uint8_t * data, uint16_t size){
122     if (size == 0 && con_handle == HCI_CON_HANDLE_INVALID ){
123         con_handle = tx_con_handle;
124         printf("Connected with handle 0x%04x\n", con_handle);
125     } else {
126         printf("RECV: ");
127         printf_hexdump(data, size);
128     }
129 }
130 
131 /*
132  * @section Packet Handler
133  *
134  * @text The packet handler is used to:
135  *        - stop the counter after a disconnect
136  */
137 
138 /* LISTING_START(packetHandler): Packet Handler */
139 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
140     UNUSED(channel);
141     UNUSED(size);
142 
143     switch (packet_type) {
144         case HCI_EVENT_PACKET:
145             switch (hci_event_packet_get_type(packet)) {
146                 case HCI_EVENT_DISCONNECTION_COMPLETE:
147                     con_handle = HCI_CON_HANDLE_INVALID;
148                     break;
149                 default:
150                     break;
151             }
152             break;
153     }
154 }
155 /* LISTING_END */
156 
157 
158 int btstack_main(void);
159 int btstack_main(void)
160 {
161     // register for HCI events
162     hci_event_callback_registration.callback = &packet_handler;
163     hci_add_event_handler(&hci_event_callback_registration);
164 
165     l2cap_init();
166 
167     // setup LE device DB
168     le_device_db_init();
169 
170     // setup SM: Display only
171     sm_init();
172 
173     // setup ATT server
174     att_server_init(profile_data, NULL, NULL);
175 
176     // setup Nordic SPP service
177     nordic_spp_service_server_init(&nordic_data_received);
178 
179     // setup advertisements
180     uint16_t adv_int_min = 0x0030;
181     uint16_t adv_int_max = 0x0030;
182     uint8_t adv_type = 0;
183     bd_addr_t null_addr;
184     memset(null_addr, 0, 6);
185     gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
186     gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
187     gap_advertisements_enable(1);
188 
189     // set one-shot timer
190     heartbeat.process = &heartbeat_handler;
191     btstack_run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
192     btstack_run_loop_add_timer(&heartbeat);
193 
194     // beat once
195     beat();
196 
197     // turn on!
198 	hci_power_control(HCI_POWER_ON);
199 
200     return 0;
201 }
202 /* EXAMPLE_END */
203