Skip to content

Commit 77aad12

Browse files
committed
ble/device_information_service: skeleton files
1 parent 08b8a6e commit 77aad12

File tree

7 files changed

+492
-41
lines changed

7 files changed

+492
-41
lines changed

example/Makefile.inc

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ GATT_SERVER += \
8383
att_server.c \
8484

8585
GATT_CLIENT += \
86-
gatt_client.c \
87-
battery_service_client.c \
86+
gatt_client.c \
87+
battery_service_client.c \
88+
device_information_service_client.c \
8889

8990
PAN += \
9091
pan.c \
@@ -213,28 +214,29 @@ EXAMPLES_CLASSIC_ONLY = \
213214

214215
# List of Examples that only use Bluetooth LE
215216

216-
EXAMPLES_LE_ONLY= \
217-
ancs_client_demo \
218-
att_delayed_response \
219-
gap_le_advertisements \
220-
gatt_battery_query \
221-
gatt_browser \
222-
gatt_counter \
223-
gatt_heart_rate_client \
224-
gatt_streamer_server \
225-
hog_keyboard_demo \
226-
hog_mouse_demo \
227-
hog_boot_host_demo \
228-
le_data_channel_client \
229-
le_data_channel_server \
230-
le_mitm \
231-
le_streamer_client \
232-
mesh_node_demo \
233-
nordic_spp_le_counter \
234-
nordic_spp_le_streamer \
235-
sm_pairing_central \
236-
sm_pairing_peripheral \
237-
ublox_spp_le_counter \
217+
EXAMPLES_LE_ONLY= \
218+
ancs_client_demo \
219+
att_delayed_response \
220+
gap_le_advertisements \
221+
gatt_battery_query \
222+
gatt_browser \
223+
gatt_counter \
224+
gatt_device_information_query \
225+
gatt_heart_rate_client \
226+
gatt_streamer_server \
227+
hog_boot_host_demo \
228+
hog_keyboard_demo \
229+
hog_mouse_demo \
230+
le_data_channel_client \
231+
le_data_channel_server \
232+
le_mitm \
233+
le_streamer_client \
234+
mesh_node_demo \
235+
nordic_spp_le_counter \
236+
nordic_spp_le_streamer \
237+
sm_pairing_central \
238+
sm_pairing_peripheral \
239+
ublox_spp_le_counter \
238240

239241
# List of Examples that use Bluetooth BR/EDR/LE = Dual Mode
240242

@@ -246,23 +248,24 @@ EXAMPLES_DUAL_MODE= \
246248

247249
# List of GATT files used by either LE_ONLY or DUAL_MODE examples
248250

249-
EXAMPLES_GATT_FILES = \
250-
att_delayed_response.gatt \
251-
ancs_client_demo.gatt \
252-
gatt_battery_query.gatt \
253-
gatt_browser.gatt \
254-
gatt_counter.gatt \
255-
gatt_streamer_server.gatt \
256-
hog_keyboard_demo.gatt \
257-
hog_mouse_demo.gatt \
258-
le_data_channel_server.gatt \
259-
nordic_spp_le_counter.gatt \
260-
nordic_spp_le_streamer.gatt \
261-
sm_pairing_central.gatt \
262-
sm_pairing_peripheral.gatt \
263-
spp_and_gatt_counter.gatt \
264-
spp_and_gatt_streamer.gatt \
265-
ublox_spp_le_counter.gatt \
251+
EXAMPLES_GATT_FILES = \
252+
ancs_client_demo.gatt \
253+
att_delayed_response.gatt \
254+
gatt_battery_query.gatt \
255+
gatt_browser.gatt \
256+
gatt_counter.gatt \
257+
gatt_device_information_query.gatt \
258+
gatt_streamer_server.gatt \
259+
hog_keyboard_demo.gatt \
260+
hog_mouse_demo.gatt \
261+
le_data_channel_server.gatt \
262+
nordic_spp_le_counter.gatt \
263+
nordic_spp_le_streamer.gatt \
264+
sm_pairing_central.gatt \
265+
sm_pairing_peripheral.gatt \
266+
spp_and_gatt_counter.gatt \
267+
spp_and_gatt_streamer.gatt \
268+
ublox_spp_le_counter.gatt \
266269

267270
# .h for .gatt
268271
EXAMPLES_GATT_H_FILES = $(EXAMPLES_GATT_FILES:.gatt=.h)
@@ -379,6 +382,9 @@ gatt_browser: gatt_browser.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_
379382
gatt_battery_query: gatt_battery_query.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${GATT_SERVER_OBJ} gatt_battery_query.c
380383
${CC} $(filter-out gatt_battery_query.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
381384

385+
gatt_device_information_query: gatt_device_information_query.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${GATT_SERVER_OBJ} gatt_device_information_query.c
386+
${CC} $(filter-out gatt_device_information_query.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
387+
382388
ancs_client_demo: ancs_client_demo.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${GATT_CLIENT_OBJ} ancs_client.c ancs_client_demo.c
383389
${CC} $(filter-out ancs_client_demo.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
384390

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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+
* contact@bluekitchen-gmbh.com
35+
*
36+
*/
37+
38+
#define BTSTACK_FILE__ "gatt_device_information_query.c"
39+
40+
// *****************************************************************************
41+
/* EXAMPLE_START(gatt_device_information_query): GATT Device Information Client
42+
*
43+
*/
44+
45+
#include <stdint.h>
46+
#include <stdio.h>
47+
#include <stdlib.h>
48+
#include <string.h>
49+
50+
#include "btstack.h"
51+
52+
// gatt_device_information_query.gatt contains the declaration of the provided GATT Services + Characteristics
53+
// gatt_device_information_query.h contains the binary representation of gatt_device_information_query.gatt
54+
// it is generated by the build system by calling: $BTSTACK_ROOT/tool/compile_gatt.py gatt_device_information_query.gatt gatt_device_information_query.h
55+
// it needs to be regenerated when the GATT Database declared in gatt_device_information_query.gatt file is modified
56+
#include "gatt_device_information_query.h"
57+
58+
typedef struct advertising_report {
59+
uint8_t type;
60+
uint8_t event_type;
61+
uint8_t address_type;
62+
bd_addr_t address;
63+
uint8_t rssi;
64+
uint8_t length;
65+
const uint8_t * data;
66+
} advertising_report_t;
67+
68+
static enum {
69+
APP_STATE_IDLE,
70+
APP_STATE_W4_SCAN_RESULT,
71+
APP_STATE_W4_CONNECT,
72+
APP_STATE_CONNECTED
73+
} app_state;
74+
75+
static int blacklist_index = 0;
76+
static bd_addr_t blacklist[20];
77+
static advertising_report_t report;
78+
79+
static hci_con_handle_t connection_handle;
80+
81+
static bd_addr_t cmdline_addr;
82+
static int cmdline_addr_found = 0;
83+
84+
static btstack_packet_callback_registration_t hci_event_callback_registration;
85+
86+
static int blacklist_size(void){
87+
return sizeof(blacklist) / sizeof(bd_addr_t);
88+
}
89+
90+
static int blacklist_contains(bd_addr_t addr){
91+
int i;
92+
for (i=0; i<blacklist_size(); i++){
93+
if (bd_addr_cmp(addr, blacklist[i]) == 0) return 1;
94+
}
95+
return 0;
96+
}
97+
98+
static void add_to_blacklist(bd_addr_t addr){
99+
printf("%s added to blacklist (no device information service found).\n", bd_addr_to_str(addr));
100+
bd_addr_copy(blacklist[blacklist_index], addr);
101+
blacklist_index = (blacklist_index + 1) % blacklist_size();
102+
}
103+
104+
static void dump_advertising_report(uint8_t *packet){
105+
bd_addr_t address;
106+
gap_event_advertising_report_get_address(packet, address);
107+
108+
printf(" * adv. event: evt-type %u, addr-type %u, addr %s, rssi %u, length adv %u, data: ",
109+
gap_event_advertising_report_get_advertising_event_type(packet),
110+
gap_event_advertising_report_get_address_type(packet),
111+
bd_addr_to_str(address),
112+
gap_event_advertising_report_get_rssi(packet),
113+
gap_event_advertising_report_get_data_length(packet));
114+
printf_hexdump(gap_event_advertising_report_get_data(packet), gap_event_advertising_report_get_data_length(packet));
115+
116+
}
117+
118+
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
119+
UNUSED(packet_type);
120+
UNUSED(channel);
121+
UNUSED(size);
122+
123+
124+
if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META){
125+
return;
126+
}
127+
128+
switch (hci_event_gattservice_meta_get_subevent_code(packet)){
129+
130+
default:
131+
break;
132+
}
133+
}
134+
135+
static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
136+
UNUSED(channel);
137+
UNUSED(size);
138+
139+
uint8_t status;
140+
bd_addr_t address;
141+
142+
if (packet_type != HCI_EVENT_PACKET){
143+
return;
144+
}
145+
146+
switch (hci_event_packet_get_type(packet)) {
147+
case BTSTACK_EVENT_STATE:
148+
// BTstack activated, get started
149+
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
150+
if (cmdline_addr_found){
151+
printf("Connect to %s\n", bd_addr_to_str(cmdline_addr));
152+
app_state = APP_STATE_W4_CONNECT;
153+
gap_connect(cmdline_addr, 0);
154+
break;
155+
}
156+
printf("Start scanning!\n");
157+
app_state = APP_STATE_W4_SCAN_RESULT;
158+
gap_set_scan_parameters(0,0x0030, 0x0030);
159+
gap_start_scan();
160+
break;
161+
162+
case GAP_EVENT_ADVERTISING_REPORT:
163+
if (app_state != APP_STATE_W4_SCAN_RESULT) return;
164+
165+
gap_event_advertising_report_get_address(packet, address);
166+
if (blacklist_contains(address)) {
167+
break;
168+
}
169+
dump_advertising_report(packet);
170+
171+
// stop scanning, and connect to the device
172+
app_state = APP_STATE_W4_CONNECT;
173+
gap_stop_scan();
174+
printf("Stop scan. Connect to device with addr %s.\n", bd_addr_to_str(report.address));
175+
gap_connect(report.address,report.address_type);
176+
break;
177+
178+
case HCI_EVENT_LE_META:
179+
// wait for connection complete
180+
if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break;
181+
if (app_state != APP_STATE_W4_CONNECT) return;
182+
connection_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
183+
184+
status = device_information_service_client_query(connection_handle, handle_gatt_client_event);
185+
btstack_assert(status == ERROR_CODE_SUCCESS);
186+
187+
app_state = APP_STATE_CONNECTED;
188+
printf("Device Information service queried.\n");
189+
break;
190+
191+
case HCI_EVENT_DISCONNECTION_COMPLETE:
192+
connection_handle = HCI_CON_HANDLE_INVALID;
193+
194+
if (cmdline_addr_found){
195+
printf("Disconnected %s\n", bd_addr_to_str(cmdline_addr));
196+
return;
197+
}
198+
199+
printf("Disconnected %s\n", bd_addr_to_str(report.address));
200+
printf("Restart scan.\n");
201+
app_state = APP_STATE_W4_SCAN_RESULT;
202+
gap_start_scan();
203+
break;
204+
default:
205+
break;
206+
}
207+
}
208+
209+
int btstack_main(int argc, const char * argv[]);
210+
int btstack_main(int argc, const char * argv[]){
211+
212+
// parse address if command line arguments are provided
213+
int arg = 1;
214+
cmdline_addr_found = 0;
215+
216+
while (arg < argc) {
217+
if(!strcmp(argv[arg], "-a") || !strcmp(argv[arg], "--address")){
218+
arg++;
219+
cmdline_addr_found = sscanf_bd_addr(argv[arg], cmdline_addr);
220+
arg++;
221+
if (!cmdline_addr_found) exit(1);
222+
continue;
223+
}
224+
fprintf(stderr, "\nUsage: %s [-a|--address aa:bb:cc:dd:ee:ff]\n", argv[0]);
225+
fprintf(stderr, "If no argument is provided, GATT browser will start scanning and connect to the first found device.\nTo connect to a specific device use argument [-a].\n\n");
226+
return 0;
227+
}
228+
(void)argv;
229+
230+
l2cap_init();
231+
232+
// setup ATT server - only needed if LE Peripheral does ATT queries on its own, e.g. Android phones
233+
att_server_init(profile_data, NULL, NULL);
234+
235+
// GATT Client setup
236+
gatt_client_init();
237+
device_information_service_client_init();
238+
239+
sm_init();
240+
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
241+
242+
hci_event_callback_registration.callback = &hci_event_handler;
243+
hci_add_event_handler(&hci_event_callback_registration);
244+
245+
app_state = APP_STATE_IDLE;
246+
247+
// turn on!
248+
hci_power_control(HCI_POWER_ON);
249+
250+
return 0;
251+
}
252+
253+
/* EXAMPLE_END */
254+
255+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
PRIMARY_SERVICE, GAP_SERVICE
2+
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "GATT Device Informaition Query"
3+
4+

src/ble/Makefile.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ SRC_BLE_FILES = \
66
att_db_util.c \
77
att_dispatch.c \
88
att_server.c \
9+
battery_service_client.c \
10+
device_information_service_client.c \
911
gatt_client.c \
1012
hids_client.c \
1113
le_device_db_memory.c \

0 commit comments

Comments
 (0)