xref: /btstack/example/gatt_battery_query.c (revision 4c517414ddb85700d40bb91c4010208117fc5030)
1bcf00d8fSMatthias Ringwald /*
2bcf00d8fSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3bcf00d8fSMatthias Ringwald  *
4bcf00d8fSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5bcf00d8fSMatthias Ringwald  * modification, are permitted provided that the following conditions
6bcf00d8fSMatthias Ringwald  * are met:
7bcf00d8fSMatthias Ringwald  *
8bcf00d8fSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9bcf00d8fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10bcf00d8fSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11bcf00d8fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12bcf00d8fSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13bcf00d8fSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14bcf00d8fSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15bcf00d8fSMatthias Ringwald  *    from this software without specific prior written permission.
16bcf00d8fSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17bcf00d8fSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18bcf00d8fSMatthias Ringwald  *    monetary gain.
19bcf00d8fSMatthias Ringwald  *
20bcf00d8fSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21bcf00d8fSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22bcf00d8fSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23bcf00d8fSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24bcf00d8fSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25bcf00d8fSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26bcf00d8fSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27bcf00d8fSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28bcf00d8fSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29bcf00d8fSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30bcf00d8fSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31bcf00d8fSMatthias Ringwald  * SUCH DAMAGE.
32bcf00d8fSMatthias Ringwald  *
33bcf00d8fSMatthias Ringwald  * Please inquire about commercial licensing options at
34bcf00d8fSMatthias Ringwald  * [email protected]
35bcf00d8fSMatthias Ringwald  *
36bcf00d8fSMatthias Ringwald  */
37bcf00d8fSMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "gatt_battery_query.c"
39ab2c6ae4SMatthias Ringwald 
40bcf00d8fSMatthias Ringwald // *****************************************************************************
41*4c517414SMilanka Ringwald /* EXAMPLE_START(gatt_battery_query): GATT Battery Service Client
42ec8ae085SMilanka Ringwald  *
43*4c517414SMilanka Ringwald  * @text This example demonstrates how to use the GATT Battery Service client to
44*4c517414SMilanka Ringwald  * receive battery level information. The client supports querying of multiple
45*4c517414SMilanka Ringwald  * battery services instances of on the remote device.
46*4c517414SMilanka Ringwald  * The example scans for remote devices and connects to the first found device
47*4c517414SMilanka Ringwald  * and starts the battery service client.
48ec8ae085SMilanka Ringwald  */
49*4c517414SMilanka Ringwald // *****************************************************************************
50bcf00d8fSMatthias Ringwald 
51bcf00d8fSMatthias Ringwald #include <stdint.h>
52bcf00d8fSMatthias Ringwald #include <stdio.h>
53bcf00d8fSMatthias Ringwald #include <stdlib.h>
54bcf00d8fSMatthias Ringwald #include <string.h>
55bcf00d8fSMatthias Ringwald 
56bcf00d8fSMatthias Ringwald #include "btstack.h"
57a63a688aSMatthias Ringwald 
58a63a688aSMatthias Ringwald // gatt_battery_query.gatt contains the declaration of the provided GATT Services + Characteristics
59a63a688aSMatthias Ringwald // gatt_battery_query.h    contains the binary representation of gatt_battery_query.gatt
60a63a688aSMatthias Ringwald // it is generated by the build system by calling: $BTSTACK_ROOT/tool/compile_gatt.py gatt_battery_query.gatt gatt_battery_query.h
61a63a688aSMatthias Ringwald // it needs to be regenerated when the GATT Database declared in gatt_battery_query.gatt file is modified
62add9769eSMatthias Ringwald #include "gatt_battery_query.h"
63bcf00d8fSMatthias Ringwald 
64bcf00d8fSMatthias Ringwald typedef struct advertising_report {
65bcf00d8fSMatthias Ringwald     uint8_t   type;
66bcf00d8fSMatthias Ringwald     uint8_t   event_type;
67bcf00d8fSMatthias Ringwald     uint8_t   address_type;
68bcf00d8fSMatthias Ringwald     bd_addr_t address;
69bcf00d8fSMatthias Ringwald     uint8_t   rssi;
70bcf00d8fSMatthias Ringwald     uint8_t   length;
713ee82ab1SMilanka Ringwald     const uint8_t * data;
72bcf00d8fSMatthias Ringwald } advertising_report_t;
73bcf00d8fSMatthias Ringwald 
7483b6788cSMilanka Ringwald static enum {
7583b6788cSMilanka Ringwald     APP_STATE_IDLE,
7683b6788cSMilanka Ringwald     APP_STATE_W4_SCAN_RESULT,
7783b6788cSMilanka Ringwald     APP_STATE_W4_CONNECT,
7883b6788cSMilanka Ringwald     APP_STATE_CONNECTED
7983b6788cSMilanka Ringwald } app_state;
80bcf00d8fSMatthias Ringwald 
810f09bd96SMilanka Ringwald static int blacklist_index = 0;
820f09bd96SMilanka Ringwald static bd_addr_t blacklist[20];
830f09bd96SMilanka Ringwald static advertising_report_t report;
840f09bd96SMilanka Ringwald 
8583b6788cSMilanka Ringwald static hci_con_handle_t connection_handle;
8683b6788cSMilanka Ringwald static uint16_t battery_service_cid;
87bcf00d8fSMatthias Ringwald 
88c30af2ffSMatthias Ringwald static bd_addr_t cmdline_addr;
89bcf00d8fSMatthias Ringwald static int cmdline_addr_found = 0;
90bcf00d8fSMatthias Ringwald 
91bcf00d8fSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
92bcf00d8fSMatthias Ringwald 
93*4c517414SMilanka Ringwald /* @section Main Application Setup
94*4c517414SMilanka Ringwald  *
95*4c517414SMilanka Ringwald  * @text The Listing MainConfiguration shows how to setup Battery Service client.
96*4c517414SMilanka Ringwald  * Besides calling init() method for each service, you'll also need to register HCI packet handler
97*4c517414SMilanka Ringwald  * to handle advertisements, as well as connect and disconect events.
98*4c517414SMilanka Ringwald  *
99*4c517414SMilanka Ringwald  * @text Handling of GATT Battery Service events will be later delegated to a sepparate packet
100*4c517414SMilanka Ringwald  * handler, i.e. gatt_client_event_handler.
101*4c517414SMilanka Ringwald  *
102*4c517414SMilanka Ringwald  * @note There are two additional files associated with this client to allow a remote device to query out GATT database:
103*4c517414SMilanka Ringwald  * - gatt_battary_query.gatt - contains the declaration of the provided GATT Services and Characteristics.
104*4c517414SMilanka Ringwald  * - gatt_battary_query.h    - contains the binary representation of gatt_battary_query.gatt.
105*4c517414SMilanka Ringwald  *
106*4c517414SMilanka Ringwald  * gatt_battary_query.h is generated by the build system by calling:
107*4c517414SMilanka Ringwald  * $BTSTACK_ROOT/tool/compile_gatt.py gatt_battary_query.gatt gatt_battary_query.h
108*4c517414SMilanka Ringwald  * This file needs to be regenerated when the GATT Database declared in gatt_battary_query.gatt file is modified.
109*4c517414SMilanka Ringwald  */
110*4c517414SMilanka Ringwald 
111*4c517414SMilanka Ringwald /* LISTING_START(MainConfiguration): Setup Device Battery Client service */
112*4c517414SMilanka Ringwald static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
113*4c517414SMilanka Ringwald static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
114*4c517414SMilanka Ringwald 
115*4c517414SMilanka Ringwald static void battery_service_client_setup(void){
116*4c517414SMilanka Ringwald     // Init L2CAP
117*4c517414SMilanka Ringwald     l2cap_init();
118*4c517414SMilanka Ringwald 
119*4c517414SMilanka Ringwald     // Setup ATT server - only needed if LE Peripheral does ATT queries on its own, e.g. Android phones
120*4c517414SMilanka Ringwald     att_server_init(profile_data, NULL, NULL);
121*4c517414SMilanka Ringwald 
122*4c517414SMilanka Ringwald     // GATT Client setup
123*4c517414SMilanka Ringwald     gatt_client_init();
124*4c517414SMilanka Ringwald     // Device Information Service Client setup
125*4c517414SMilanka Ringwald     battery_service_client_init();
126*4c517414SMilanka Ringwald 
127*4c517414SMilanka Ringwald     sm_init();
128*4c517414SMilanka Ringwald     sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
129*4c517414SMilanka Ringwald 
130*4c517414SMilanka Ringwald     hci_event_callback_registration.callback = &hci_event_handler;
131*4c517414SMilanka Ringwald     hci_add_event_handler(&hci_event_callback_registration);
132*4c517414SMilanka Ringwald }
133*4c517414SMilanka Ringwald /* LISTING_END */
134*4c517414SMilanka Ringwald 
135287eecffSMilanka Ringwald static int blacklist_size(void){
1360f09bd96SMilanka Ringwald     return sizeof(blacklist) / sizeof(bd_addr_t);
1370f09bd96SMilanka Ringwald }
1380f09bd96SMilanka Ringwald 
1390f09bd96SMilanka Ringwald static int blacklist_contains(bd_addr_t addr){
1400f09bd96SMilanka Ringwald     int i;
1410f09bd96SMilanka Ringwald     for (i=0; i<blacklist_size(); i++){
1420f09bd96SMilanka Ringwald         if (bd_addr_cmp(addr, blacklist[i]) == 0) return 1;
1430f09bd96SMilanka Ringwald     }
1440f09bd96SMilanka Ringwald     return 0;
1450f09bd96SMilanka Ringwald }
1460f09bd96SMilanka Ringwald 
1470f09bd96SMilanka Ringwald static void add_to_blacklist(bd_addr_t addr){
14889b171cfSMilanka Ringwald     printf("%s added to blacklist (no battery service found).\n", bd_addr_to_str(addr));
1490f09bd96SMilanka Ringwald     bd_addr_copy(blacklist[blacklist_index], addr);
1500f09bd96SMilanka Ringwald     blacklist_index = (blacklist_index + 1) % blacklist_size();
1510f09bd96SMilanka Ringwald }
1520f09bd96SMilanka Ringwald 
15383b6788cSMilanka Ringwald static void dump_advertising_report(uint8_t *packet){
15483b6788cSMilanka Ringwald     bd_addr_t address;
15583b6788cSMilanka Ringwald     gap_event_advertising_report_get_address(packet, address);
15683b6788cSMilanka Ringwald 
15783b6788cSMilanka Ringwald     printf("    * adv. event: evt-type %u, addr-type %u, addr %s, rssi %u, length adv %u, data: ",
15883b6788cSMilanka Ringwald         gap_event_advertising_report_get_advertising_event_type(packet),
15983b6788cSMilanka Ringwald         gap_event_advertising_report_get_address_type(packet),
16083b6788cSMilanka Ringwald         bd_addr_to_str(address),
16183b6788cSMilanka Ringwald         gap_event_advertising_report_get_rssi(packet),
16283b6788cSMilanka Ringwald         gap_event_advertising_report_get_data_length(packet));
16383b6788cSMilanka Ringwald     printf_hexdump(gap_event_advertising_report_get_data(packet), gap_event_advertising_report_get_data_length(packet));
164bcf00d8fSMatthias Ringwald 
165bcf00d8fSMatthias Ringwald }
166bcf00d8fSMatthias Ringwald 
167*4c517414SMilanka Ringwald /* LISTING_START(packetHandler): Packet Handler */
168*4c517414SMilanka Ringwald static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
169*4c517414SMilanka Ringwald     /* LISTING_PAUSE */
170*4c517414SMilanka Ringwald     UNUSED(channel);
171*4c517414SMilanka Ringwald     UNUSED(size);
172*4c517414SMilanka Ringwald 
173*4c517414SMilanka Ringwald     /* LISTING_RESUME */
174*4c517414SMilanka Ringwald     uint8_t status;
175*4c517414SMilanka Ringwald     bd_addr_t address;
176*4c517414SMilanka Ringwald 
177*4c517414SMilanka Ringwald     if (packet_type != HCI_EVENT_PACKET){
178*4c517414SMilanka Ringwald         return;
179*4c517414SMilanka Ringwald     }
180*4c517414SMilanka Ringwald 
181*4c517414SMilanka Ringwald     switch (hci_event_packet_get_type(packet)) {
182*4c517414SMilanka Ringwald         /* LISTING_PAUSE */
183*4c517414SMilanka Ringwald 
184*4c517414SMilanka Ringwald         case BTSTACK_EVENT_STATE:
185*4c517414SMilanka Ringwald             // BTstack activated, get started
186*4c517414SMilanka Ringwald             if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
187*4c517414SMilanka Ringwald             if (cmdline_addr_found){
188*4c517414SMilanka Ringwald                 printf("Connect to %s\n", bd_addr_to_str(cmdline_addr));
189*4c517414SMilanka Ringwald                 app_state = APP_STATE_W4_CONNECT;
190*4c517414SMilanka Ringwald                 gap_connect(cmdline_addr, 0);
191*4c517414SMilanka Ringwald                 break;
192*4c517414SMilanka Ringwald             }
193*4c517414SMilanka Ringwald             printf("Start scanning!\n");
194*4c517414SMilanka Ringwald             app_state = APP_STATE_W4_SCAN_RESULT;
195*4c517414SMilanka Ringwald             gap_set_scan_parameters(0,0x0030, 0x0030);
196*4c517414SMilanka Ringwald             gap_start_scan();
197*4c517414SMilanka Ringwald             break;
198*4c517414SMilanka Ringwald 
199*4c517414SMilanka Ringwald         case GAP_EVENT_ADVERTISING_REPORT:
200*4c517414SMilanka Ringwald             if (app_state != APP_STATE_W4_SCAN_RESULT) return;
201*4c517414SMilanka Ringwald 
202*4c517414SMilanka Ringwald             gap_event_advertising_report_get_address(packet, address);
203*4c517414SMilanka Ringwald             if (blacklist_contains(address)) {
204*4c517414SMilanka Ringwald                 break;
205*4c517414SMilanka Ringwald             }
206*4c517414SMilanka Ringwald             dump_advertising_report(packet);
207*4c517414SMilanka Ringwald 
208*4c517414SMilanka Ringwald             // stop scanning, and connect to the device
209*4c517414SMilanka Ringwald             app_state = APP_STATE_W4_CONNECT;
210*4c517414SMilanka Ringwald             gap_stop_scan();
211*4c517414SMilanka Ringwald             printf("Stop scan. Connect to device with addr %s.\n", bd_addr_to_str(report.address));
212*4c517414SMilanka Ringwald             gap_connect(report.address,report.address_type);
213*4c517414SMilanka Ringwald             break;
214*4c517414SMilanka Ringwald 
215*4c517414SMilanka Ringwald         /* LISTING_RESUME */
216*4c517414SMilanka Ringwald         case HCI_EVENT_LE_META:
217*4c517414SMilanka Ringwald             // Wait for connection complete
218*4c517414SMilanka Ringwald             if (hci_event_le_meta_get_subevent_code(packet) !=  HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break;
219*4c517414SMilanka Ringwald 
220*4c517414SMilanka Ringwald             /* LISTING_PAUSE */
221*4c517414SMilanka Ringwald             if (app_state != APP_STATE_W4_CONNECT) return;
222*4c517414SMilanka Ringwald 
223*4c517414SMilanka Ringwald             /* LISTING_RESUME */
224*4c517414SMilanka Ringwald             // Get connection handle from event
225*4c517414SMilanka Ringwald             connection_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
226*4c517414SMilanka Ringwald 
227*4c517414SMilanka Ringwald             // Connect to remote Battery Service.
228*4c517414SMilanka Ringwald             // On succesful connection, the client tries to register for notifications. If notifications
229*4c517414SMilanka Ringwald             // are not supported by remote Battery Service, the client will automatically poll the battery level - here every 2 seconds.
230*4c517414SMilanka Ringwald             // If poll_interval_ms is 0, polling is disabled, and only notifications will be received (for manual polling,
231*4c517414SMilanka Ringwald             // see battery_service_client.h).
232*4c517414SMilanka Ringwald             // All GATT Battery Service events are handled by the gatt_client_event_handler.
233*4c517414SMilanka Ringwald             status = battery_service_client_connect(connection_handle, gatt_client_event_handler, 2000, &battery_service_cid);
234*4c517414SMilanka Ringwald             btstack_assert(status == ERROR_CODE_SUCCESS);
235*4c517414SMilanka Ringwald 
236*4c517414SMilanka Ringwald             app_state = APP_STATE_CONNECTED;
237*4c517414SMilanka Ringwald             printf("Battery service connected.\n");
238*4c517414SMilanka Ringwald             break;
239*4c517414SMilanka Ringwald 
240*4c517414SMilanka Ringwald         case HCI_EVENT_DISCONNECTION_COMPLETE:
241*4c517414SMilanka Ringwald             connection_handle = HCI_CON_HANDLE_INVALID;
242*4c517414SMilanka Ringwald             // Disconnect battery service
243*4c517414SMilanka Ringwald             battery_service_client_disconnect(battery_service_cid);
244*4c517414SMilanka Ringwald 
245*4c517414SMilanka Ringwald             /* LISTING_PAUSE */
246*4c517414SMilanka Ringwald             if (cmdline_addr_found){
247*4c517414SMilanka Ringwald                 printf("Disconnected %s\n", bd_addr_to_str(cmdline_addr));
248*4c517414SMilanka Ringwald                 return;
249*4c517414SMilanka Ringwald             }
250*4c517414SMilanka Ringwald 
251*4c517414SMilanka Ringwald             /* LISTING_RESUME */
252*4c517414SMilanka Ringwald             printf("Disconnected %s\n", bd_addr_to_str(report.address));
253*4c517414SMilanka Ringwald             printf("Restart scan.\n");
254*4c517414SMilanka Ringwald             app_state = APP_STATE_W4_SCAN_RESULT;
255*4c517414SMilanka Ringwald             gap_start_scan();
256*4c517414SMilanka Ringwald             break;
257*4c517414SMilanka Ringwald         default:
258*4c517414SMilanka Ringwald             break;
259*4c517414SMilanka Ringwald     }
260*4c517414SMilanka Ringwald }
261*4c517414SMilanka Ringwald /* LISTING_END */
262*4c517414SMilanka Ringwald 
263*4c517414SMilanka Ringwald /* LISTING_START(gatt_client_event_handler): GATT Client Event Handler */
264*4c517414SMilanka Ringwald // The gatt_client_event_handler receives following events from remote device:
265*4c517414SMilanka Ringwald //  - GATTSERVICE_SUBEVENT_BATTERY_SERVICE_CONNECTED
266*4c517414SMilanka Ringwald //  - GATTSERVICE_SUBEVENT_BATTERY_SERVICE_LEVEL
267*4c517414SMilanka Ringwald //
268*4c517414SMilanka Ringwald static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
269*4c517414SMilanka Ringwald     /* LISTING_PAUSE */
2709ec2630cSMatthias Ringwald     UNUSED(packet_type);
2719ec2630cSMatthias Ringwald     UNUSED(channel);
2729ec2630cSMatthias Ringwald     UNUSED(size);
2739ec2630cSMatthias Ringwald 
274*4c517414SMilanka Ringwald     /* LISTING_RESUME */
275f3d85318SMilanka Ringwald     uint8_t status;
276f3d85318SMilanka Ringwald     uint8_t att_status;
277bcf00d8fSMatthias Ringwald 
278174a0c1cSMilanka Ringwald     if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META){
279174a0c1cSMilanka Ringwald         return;
280174a0c1cSMilanka Ringwald     }
281174a0c1cSMilanka Ringwald 
282174a0c1cSMilanka Ringwald     switch (hci_event_gattservice_meta_get_subevent_code(packet)){
2837ec9a1bbSMilanka Ringwald         case GATTSERVICE_SUBEVENT_BATTERY_SERVICE_CONNECTED:
2847ec9a1bbSMilanka Ringwald             status = gattservice_subevent_battery_service_connected_get_status(packet);
285174a0c1cSMilanka Ringwald             switch (status){
286174a0c1cSMilanka Ringwald                 case ERROR_CODE_SUCCESS:
287f3d85318SMilanka Ringwald                     printf("Battery service client connected, found %d services, poll bitmap 0x%02x\n",
288f3d85318SMilanka Ringwald                         gattservice_subevent_battery_service_connected_get_num_instances(packet),
289f3d85318SMilanka Ringwald                         gattservice_subevent_battery_service_connected_get_poll_bitmap(packet));
290bcf00d8fSMatthias Ringwald                     break;
291174a0c1cSMilanka Ringwald                 default:
29289b171cfSMilanka Ringwald                     printf("Battery service client connection failed, err 0x%02x.\n", status);
2930f09bd96SMilanka Ringwald                     add_to_blacklist(report.address);
2940f09bd96SMilanka Ringwald                     gap_disconnect(connection_handle);
295bcf00d8fSMatthias Ringwald                     break;
296bcf00d8fSMatthias Ringwald             }
297bcf00d8fSMatthias Ringwald             break;
298174a0c1cSMilanka Ringwald 
29983b6788cSMilanka Ringwald         case GATTSERVICE_SUBEVENT_BATTERY_SERVICE_LEVEL:
300f3d85318SMilanka Ringwald             att_status = gattservice_subevent_battery_service_level_get_att_status(packet);
301f3d85318SMilanka Ringwald             if (att_status != ATT_ERROR_SUCCESS){
302f3d85318SMilanka Ringwald                 printf("Battery level read failed, ATT Error 0x%02x\n", att_status);
303f3d85318SMilanka Ringwald             } else {
30489b171cfSMilanka Ringwald                 printf("Service index: %d, Battery level: %d\n",
30583b6788cSMilanka Ringwald                     gattservice_subevent_battery_service_level_get_sevice_index(packet),
30683b6788cSMilanka Ringwald                     gattservice_subevent_battery_service_level_get_level(packet));
307f3d85318SMilanka Ringwald 
308f3d85318SMilanka Ringwald             }
3090f09bd96SMilanka Ringwald             break;
310bcf00d8fSMatthias Ringwald 
311bcf00d8fSMatthias Ringwald         default:
312bcf00d8fSMatthias Ringwald             break;
313bcf00d8fSMatthias Ringwald     }
314bcf00d8fSMatthias Ringwald }
315*4c517414SMilanka Ringwald  /* LISTING_END */
316bcf00d8fSMatthias Ringwald 
317bcf00d8fSMatthias Ringwald int btstack_main(int argc, const char * argv[]);
318bcf00d8fSMatthias Ringwald int btstack_main(int argc, const char * argv[]){
319bcf00d8fSMatthias Ringwald 
32083b6788cSMilanka Ringwald     // parse address if command line arguments are provided
321bcf00d8fSMatthias Ringwald     int arg = 1;
322bcf00d8fSMatthias Ringwald     cmdline_addr_found = 0;
323bcf00d8fSMatthias Ringwald 
324bcf00d8fSMatthias Ringwald     while (arg < argc) {
325bcf00d8fSMatthias Ringwald         if(!strcmp(argv[arg], "-a") || !strcmp(argv[arg], "--address")){
326bcf00d8fSMatthias Ringwald             arg++;
327a6efb919SMatthias Ringwald             cmdline_addr_found = sscanf_bd_addr(argv[arg], cmdline_addr);
328bcf00d8fSMatthias Ringwald             arg++;
3290f09bd96SMilanka Ringwald             if (!cmdline_addr_found) exit(1);
330bcf00d8fSMatthias Ringwald             continue;
331bcf00d8fSMatthias Ringwald         }
33283b6788cSMilanka Ringwald         fprintf(stderr, "\nUsage: %s [-a|--address aa:bb:cc:dd:ee:ff]\n", argv[0]);
33383b6788cSMilanka Ringwald         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");
334bcf00d8fSMatthias Ringwald         return 0;
335bcf00d8fSMatthias Ringwald     }
3366316c8edSMatthias Ringwald     (void)argv;
33783b6788cSMilanka Ringwald 
338*4c517414SMilanka Ringwald     battery_service_client_setup();
339a4fe6467SMatthias Ringwald 
34083b6788cSMilanka Ringwald     app_state = APP_STATE_IDLE;
341a4fe6467SMatthias Ringwald 
342bcf00d8fSMatthias Ringwald     // turn on!
343bcf00d8fSMatthias Ringwald     hci_power_control(HCI_POWER_ON);
344bcf00d8fSMatthias Ringwald 
345bcf00d8fSMatthias Ringwald     return 0;
346bcf00d8fSMatthias Ringwald }
347bcf00d8fSMatthias Ringwald 
348ec8ae085SMilanka Ringwald /* EXAMPLE_END */
349bcf00d8fSMatthias Ringwald 
350bcf00d8fSMatthias Ringwald 
351