1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /*****************************************************************************
20 *
21 * This file contains main functions to support PAN profile
22 * commands and events.
23 *
24 *****************************************************************************/
25
26 #define LOG_TAG "pan"
27
28 #include <bluetooth/log.h>
29
30 #include <cstdint>
31
32 #include "internal_include/bt_target.h"
33 #include "os/log.h"
34 #include "stack/include/bt_types.h"
35 #include "stack/include/bt_uuid16.h"
36 #include "stack/include/sdp_api.h"
37 #include "stack/include/sdpdefs.h"
38 #include "stack/pan/pan_int.h"
39 #include "types/raw_address.h"
40
41 using namespace bluetooth;
42 using namespace bluetooth::legacy::stack::sdp;
43
44 static const uint8_t pan_proto_elem_data[] = {
45 0x35, 0x18, /* data element sequence of length 0x18 bytes */
46 0x35, 0x06, /* data element sequence for L2CAP descriptor */
47 0x19, 0x01, 0x00, /* UUID for L2CAP - 0x0100 */
48 0x09, 0x00, 0x0F, /* PSM for BNEP - 0x000F */
49 0x35, 0x0E, /* data element seqence for BNEP descriptor */
50 0x19, 0x00, 0x0F, /* UUID for BNEP - 0x000F */
51 0x09, 0x01,
52 0x00, /* BNEP specific parameter 0 -- Version of BNEP = version 1 = 0x0001
53 */
54 0x35,
55 0x06, /* BNEP specific parameter 1 -- Supported network packet type list */
56 0x09, 0x08, 0x00, /* network packet type IPv4 = 0x0800 */
57 0x09, 0x08, 0x06 /* network packet type ARP = 0x0806 */
58 };
59
60 /*******************************************************************************
61 *
62 * Function pan_register_with_sdp
63 *
64 * Description
65 *
66 * Returns
67 *
68 ******************************************************************************/
pan_register_with_sdp(uint16_t uuid,const char * p_name,const char * p_desc)69 uint32_t pan_register_with_sdp(uint16_t uuid, const char* p_name,
70 const char* p_desc) {
71 uint32_t sdp_handle;
72 uint16_t browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
73 uint16_t security = 0;
74 uint32_t proto_len = (uint32_t)pan_proto_elem_data[1];
75
76 /* Create a record */
77 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
78
79 if (sdp_handle == 0) {
80 log::error("PAN_SetRole - could not create SDP record");
81 return 0;
82 }
83
84 /* Service Class ID List */
85 if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(sdp_handle,
86 1, &uuid)) {
87 log::warn("Unable to add SDP class id list handle:{}", sdp_handle);
88 }
89
90 /* Add protocol element sequence from the constant string */
91 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
92 sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST, DATA_ELE_SEQ_DESC_TYPE,
93 proto_len, (uint8_t*)(pan_proto_elem_data + 2))) {
94 log::warn("Unable to add SDP PAN profile attribute handle:{}", sdp_handle);
95 }
96
97 /* Language base */
98 if (!get_legacy_stack_sdp_api()->handle.SDP_AddLanguageBaseAttrIDList(
99 sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8,
100 LANGUAGE_BASE_ID)) {
101 log::warn("Unable to add SDP language base attribute");
102 }
103
104 /* Profile descriptor list */
105 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
106 sdp_handle, uuid, PAN_PROFILE_VERSION)) {
107 log::warn("Unable to add SDP PAN profile version");
108 }
109
110 /* Service Name */
111 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
112 sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
113 (uint8_t)(strlen(p_name) + 1), (uint8_t*)p_name)) {
114 log::warn("Unable to add SDP service name attribute handle:{}", sdp_handle);
115 }
116
117 /* Service description */
118 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
119 sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
120 (uint8_t)(strlen(p_desc) + 1), (uint8_t*)p_desc)) {
121 log::warn("Unable to add SDP service description attribute handle:{}",
122 sdp_handle);
123 }
124
125 /* Security description */
126 // Only NAP and PANU has service level security; GN has no security
127 if (uuid == UUID_SERVCLASS_NAP || uuid == UUID_SERVCLASS_PANU) {
128 UINT16_TO_BE_FIELD(&security, 0x0001);
129 }
130 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
131 sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2,
132 (uint8_t*)&security)) {
133 log::warn("Unable to add SDP security description attribute handle:{}",
134 sdp_handle);
135 }
136
137 if (uuid == UUID_SERVCLASS_NAP) {
138 uint16_t NetAccessType = 0x0005; /* Ethernet */
139 uint32_t NetAccessRate = 0x0001312D0; /* 10Mb/sec */
140 uint8_t array[10], *p;
141
142 /* Net access type. */
143 p = array;
144 UINT16_TO_BE_STREAM(p, NetAccessType);
145 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
146 sdp_handle, ATTR_ID_NET_ACCESS_TYPE, UINT_DESC_TYPE, 2, array)) {
147 log::warn("Unable to add SDP attribute net access type handle:{}",
148 sdp_handle);
149 }
150
151 /* Net access rate. */
152 p = array;
153 UINT32_TO_BE_STREAM(p, NetAccessRate);
154 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
155 sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4,
156 array)) {
157 log::warn("Unable to add SDP attribute net access rate handle:{}",
158 sdp_handle);
159 }
160 }
161
162 /* Make the service browsable */
163 if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
164 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_list)) {
165 log::warn("Unable to add SDP uuid sequence browse group list handle:{}",
166 sdp_handle);
167 }
168
169 return sdp_handle;
170 }
171
172 /*******************************************************************************
173 *
174 * Function pan_allocate_pcb
175 *
176 * Description
177 *
178 * Returns
179 *
180 ******************************************************************************/
pan_allocate_pcb(const RawAddress & p_bda,uint16_t handle)181 tPAN_CONN* pan_allocate_pcb(const RawAddress& p_bda, uint16_t handle) {
182 uint16_t i;
183
184 for (i = 0; i < MAX_PAN_CONNS; i++) {
185 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
186 pan_cb.pcb[i].handle == handle)
187 return NULL;
188 }
189
190 for (i = 0; i < MAX_PAN_CONNS; i++) {
191 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
192 pan_cb.pcb[i].rem_bda == p_bda)
193 return NULL;
194 }
195
196 for (i = 0; i < MAX_PAN_CONNS; i++) {
197 if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
198 memset(&(pan_cb.pcb[i]), 0, sizeof(tPAN_CONN));
199 pan_cb.pcb[i].rem_bda = p_bda;
200 pan_cb.pcb[i].handle = handle;
201 return &(pan_cb.pcb[i]);
202 }
203 }
204 return NULL;
205 }
206
207 /*******************************************************************************
208 *
209 * Function pan_get_pcb_by_handle
210 *
211 * Description
212 *
213 * Returns
214 *
215 ******************************************************************************/
pan_get_pcb_by_handle(uint16_t handle)216 tPAN_CONN* pan_get_pcb_by_handle(uint16_t handle) {
217 uint16_t i;
218
219 for (i = 0; i < MAX_PAN_CONNS; i++) {
220 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
221 pan_cb.pcb[i].handle == handle)
222 return &(pan_cb.pcb[i]);
223 }
224
225 return NULL;
226 }
227
228 /*******************************************************************************
229 *
230 * Function pan_get_pcb_by_addr
231 *
232 * Description
233 *
234 * Returns
235 *
236 ******************************************************************************/
pan_get_pcb_by_addr(const RawAddress & p_bda)237 tPAN_CONN* pan_get_pcb_by_addr(const RawAddress& p_bda) {
238 uint16_t i;
239
240 for (i = 0; i < MAX_PAN_CONNS; i++) {
241 if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) continue;
242
243 if (pan_cb.pcb[i].rem_bda == p_bda) return &(pan_cb.pcb[i]);
244
245 /*
246 if (pan_cb.pcb[i].mfilter_present &&
247 p_bda == pan_cb.pcb[i].multi_cast_bridge)
248 return &(pan_cb.pcb[i]);
249 */
250 }
251
252 return NULL;
253 }
254
255 /*******************************************************************************
256 *
257 * Function pan_close_all_connections
258 *
259 * Description
260 *
261 * Returns void
262 *
263 ******************************************************************************/
pan_close_all_connections(void)264 void pan_close_all_connections(void) {
265 uint16_t i;
266
267 for (i = 0; i < MAX_PAN_CONNS; i++) {
268 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE) {
269 BNEP_Disconnect(pan_cb.pcb[i].handle);
270 pan_cb.pcb[i].con_state = PAN_STATE_IDLE;
271 }
272 }
273
274 pan_cb.active_role = PAN_ROLE_INACTIVE;
275 pan_cb.num_conns = 0;
276 return;
277 }
278
279 /*******************************************************************************
280 *
281 * Function pan_release_pcb
282 *
283 * Description This function releases a PCB.
284 *
285 * Returns void
286 *
287 ******************************************************************************/
pan_release_pcb(tPAN_CONN * p_pcb)288 void pan_release_pcb(tPAN_CONN* p_pcb) {
289 /* Drop any response pointer we may be holding */
290 memset(p_pcb, 0, sizeof(tPAN_CONN));
291 p_pcb->con_state = PAN_STATE_IDLE;
292 }
293
294 /*******************************************************************************
295 *
296 * Function pan_dump_status
297 *
298 * Description This function dumps the pan control block and connection
299 * blocks information
300 *
301 * Returns none
302 *
303 ******************************************************************************/
pan_dump_status(void)304 void pan_dump_status(void) {
305 #if (PAN_SUPPORTS_DEBUG_DUMP == TRUE)
306 uint16_t i;
307 tPAN_CONN* p_pcb;
308
309 log::verbose("PAN role {:x}, active role {}, num_conns {}", pan_cb.role,
310 pan_cb.active_role, pan_cb.num_conns);
311
312 for (i = 0, p_pcb = pan_cb.pcb; i < MAX_PAN_CONNS; i++, p_pcb++) {
313 log::verbose("{} state:{}, handle:{}, src{}, BD:{}", i, p_pcb->con_state,
314 p_pcb->handle, p_pcb->src_uuid, p_pcb->rem_bda);
315 }
316 #endif
317 }
318