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 #define BTSTACK_FILE__ "sdp_rfcomm_query.c"
39
40 // *****************************************************************************
41 /* EXAMPLE_START(sdp_rfcomm_query): SDP Client - Query RFCOMM SDP record
42 *
43 * @text The example shows how the SDP Client is used to get all RFCOMM service
44 * records from a remote device. It extracts the remote RFCOMM Server Channel,
45 * which are needed to connect to a remote RFCOMM service.
46 */
47 // *****************************************************************************
48
49 #include "btstack_config.h"
50
51 #include <stdint.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56
57 #include "hci_cmd.h"
58 #include "btstack_run_loop.h"
59
60 #include "btstack.h"
61
62 #define NUM_SERVICES 10
63
64 static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
65
66 static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xD1, 0x15};
67
68 static struct {
69 uint8_t channel_nr;
70 char service_name[SDP_SERVICE_NAME_LEN+1];
71 } services[NUM_SERVICES];
72
73 static uint8_t service_index = 0;
74
75 static btstack_packet_callback_registration_t hci_event_callback_registration;
76 static btstack_context_callback_registration_t handle_sdp_client_query_request;
77
handle_start_sdp_client_query(void * context)78 static void handle_start_sdp_client_query(void * context){
79 UNUSED(context);
80 sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
81 }
82
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)83 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
84 UNUSED(channel);
85 UNUSED(size);
86
87 if (packet_type != HCI_EVENT_PACKET) return;
88 uint8_t event = hci_event_packet_get_type(packet);
89
90 switch (event) {
91 case BTSTACK_EVENT_STATE:
92 // BTstack activated, get started
93 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
94 handle_sdp_client_query_request.callback = &handle_start_sdp_client_query;
95 (void) sdp_client_register_query_callback(&handle_sdp_client_query_request);
96 }
97 break;
98 default:
99 break;
100 }
101 }
102
store_found_service(const char * name,uint8_t port)103 static void store_found_service(const char * name, uint8_t port){
104 printf("APP: Service name: '%s', RFCOMM port %u\n", name, port);
105 if (service_index < NUM_SERVICES){
106 services[service_index].channel_nr = port;
107 btstack_strcpy(services[service_index].service_name, SDP_SERVICE_NAME_LEN + 1, name);
108 service_index++;
109 } else {
110 printf("APP: list full - ignore\n");
111 return;
112 }
113 }
114
report_found_services(void)115 static void report_found_services(void){
116 printf("\n *** Client query response done. ");
117 if (service_index == 0){
118 printf("No service found.\n\n");
119 } else {
120 printf("Found following %d services:\n", service_index);
121 }
122 int i;
123 for (i=0; i<service_index; i++){
124 printf(" Service name %s, RFCOMM port %u\n", services[i].service_name, services[i].channel_nr);
125 }
126 printf(" ***\n\n");
127 }
128
handle_query_rfcomm_event(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)129 static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
130 UNUSED(packet_type);
131 UNUSED(channel);
132 UNUSED(size);
133
134 switch (hci_event_packet_get_type(packet)){
135 case SDP_EVENT_QUERY_RFCOMM_SERVICE:
136 store_found_service(sdp_event_query_rfcomm_service_get_name(packet),
137 sdp_event_query_rfcomm_service_get_rfcomm_channel(packet));
138 break;
139 case SDP_EVENT_QUERY_COMPLETE:
140 if (sdp_event_query_complete_get_status(packet)){
141 printf("SDP query failed, status 0x%02x\n", sdp_event_query_complete_get_status(packet));
142 break;
143 }
144 printf("SDP query done.\n");
145 report_found_services();
146 break;
147 default:
148 break;
149 }
150 }
151
152 int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])153 int btstack_main(int argc, const char * argv[]){
154 (void)argc;
155 (void)argv;
156
157 // init L2CAP
158 l2cap_init();
159
160 // register for HCI events
161 hci_event_callback_registration.callback = &packet_handler;
162 hci_add_event_handler(&hci_event_callback_registration);
163
164 // turn on!
165 hci_power_control(HCI_POWER_ON);
166
167 return 0;
168 }
169
170 /* EXAMPLE_END */