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 <cstddef>
31 #include <cstdint>
32 #include <cstring>
33
34 #include "bnep_api.h"
35 #include "internal_include/bt_target.h"
36 #include "stack/include/bt_types.h"
37 #include "stack/include/bt_uuid16.h"
38 #include "stack/include/sdp_api.h"
39 #include "stack/include/sdpdefs.h"
40 #include "stack/pan/pan_int.h"
41 #include "types/raw_address.h"
42
43 using namespace bluetooth;
44 using namespace bluetooth::legacy::stack::sdp;
45
46 static const uint8_t pan_proto_elem_data[] = {
47 0x35, 0x18, /* data element sequence of length 0x18 bytes */
48 0x35, 0x06, /* data element sequence for L2CAP descriptor */
49 0x19, 0x01,
50 0x00, /* UUID for L2CAP - 0x0100 */
51 0x09, 0x00,
52 0x0F, /* PSM for BNEP - 0x000F */
53 0x35, 0x0E, /* data element seqence for BNEP descriptor */
54 0x19, 0x00,
55 0x0F, /* UUID for BNEP - 0x000F */
56 0x09, 0x01,
57 0x00, /* BNEP specific parameter 0 -- Version of BNEP = version 1 = 0x0001
58 */
59 0x35, 0x06, /* BNEP specific parameter 1 -- Supported network packet type list */
60 0x09, 0x08,
61 0x00, /* network packet type IPv4 = 0x0800 */
62 0x09, 0x08,
63 0x06 /* network packet type ARP = 0x0806 */
64 };
65
66 /*******************************************************************************
67 *
68 * Function pan_register_with_sdp
69 *
70 * Description
71 *
72 * Returns
73 *
74 ******************************************************************************/
pan_register_with_sdp(uint16_t uuid,const char * p_name,const char * p_desc)75 uint32_t pan_register_with_sdp(uint16_t uuid, const char* p_name, const char* p_desc) {
76 uint32_t sdp_handle;
77 uint16_t browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
78 uint16_t security = 0;
79 uint32_t proto_len = (uint32_t)pan_proto_elem_data[1];
80
81 /* Create a record */
82 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
83
84 if (sdp_handle == 0) {
85 log::error("PAN_SetRole - could not create SDP record");
86 return 0;
87 }
88
89 /* Service Class ID List */
90 if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(sdp_handle, 1, &uuid)) {
91 log::warn("Unable to add SDP class id list handle:{}", sdp_handle);
92 }
93
94 /* Add protocol element sequence from the constant string */
95 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST,
96 DATA_ELE_SEQ_DESC_TYPE, proto_len,
97 (uint8_t*)(pan_proto_elem_data + 2))) {
98 log::warn("Unable to add SDP PAN profile attribute handle:{}", sdp_handle);
99 }
100
101 /* Language base */
102 if (!get_legacy_stack_sdp_api()->handle.SDP_AddLanguageBaseAttrIDList(
103 sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID)) {
104 log::warn("Unable to add SDP language base attribute");
105 }
106
107 /* Profile descriptor list */
108 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(sdp_handle, uuid,
109 PAN_PROFILE_VERSION)) {
110 log::warn("Unable to add SDP PAN profile version");
111 }
112
113 /* Service Name */
114 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
115 sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, (uint8_t)(strlen(p_name) + 1),
116 (uint8_t*)p_name)) {
117 log::warn("Unable to add SDP service name attribute handle:{}", sdp_handle);
118 }
119
120 /* Service description */
121 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
122 sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
123 (uint8_t)(strlen(p_desc) + 1), (uint8_t*)p_desc)) {
124 log::warn("Unable to add SDP service description attribute handle:{}", sdp_handle);
125 }
126
127 /* Security description */
128 // Only NAP and PANU has service level security; GN has no security
129 if (uuid == UUID_SERVCLASS_NAP || uuid == UUID_SERVCLASS_PANU) {
130 UINT16_TO_BE_FIELD(&security, 0x0001);
131 }
132 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
133 sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2, (uint8_t*)&security)) {
134 log::warn("Unable to add SDP security description attribute handle:{}", 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(sdp_handle, ATTR_ID_NET_ACCESS_TYPE,
146 UINT_DESC_TYPE, 2, array)) {
147 log::warn("Unable to add SDP attribute net access type handle:{}", sdp_handle);
148 }
149
150 /* Net access rate. */
151 p = array;
152 UINT32_TO_BE_STREAM(p, NetAccessRate);
153 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
154 sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4, array)) {
155 log::warn("Unable to add SDP attribute net access rate handle:{}", sdp_handle);
156 }
157 }
158
159 /* Make the service browsable */
160 if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
161 1, &browse_list)) {
162 log::warn("Unable to add SDP uuid sequence browse group list handle:{}", sdp_handle);
163 }
164
165 return sdp_handle;
166 }
167
168 /*******************************************************************************
169 *
170 * Function pan_allocate_pcb
171 *
172 * Description
173 *
174 * Returns
175 *
176 ******************************************************************************/
pan_allocate_pcb(const RawAddress & p_bda,uint16_t handle)177 tPAN_CONN* pan_allocate_pcb(const RawAddress& p_bda, uint16_t handle) {
178 uint16_t i;
179
180 for (i = 0; i < MAX_PAN_CONNS; i++) {
181 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].handle == handle) {
182 return NULL;
183 }
184 }
185
186 for (i = 0; i < MAX_PAN_CONNS; i++) {
187 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].rem_bda == p_bda) {
188 return NULL;
189 }
190 }
191
192 for (i = 0; i < MAX_PAN_CONNS; i++) {
193 if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
194 memset(&(pan_cb.pcb[i]), 0, sizeof(tPAN_CONN));
195 pan_cb.pcb[i].rem_bda = p_bda;
196 pan_cb.pcb[i].handle = handle;
197 return &(pan_cb.pcb[i]);
198 }
199 }
200 return NULL;
201 }
202
203 /*******************************************************************************
204 *
205 * Function pan_get_pcb_by_handle
206 *
207 * Description
208 *
209 * Returns
210 *
211 ******************************************************************************/
pan_get_pcb_by_handle(uint16_t handle)212 tPAN_CONN* pan_get_pcb_by_handle(uint16_t handle) {
213 uint16_t i;
214
215 for (i = 0; i < MAX_PAN_CONNS; i++) {
216 if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].handle == handle) {
217 return &(pan_cb.pcb[i]);
218 }
219 }
220
221 return NULL;
222 }
223
224 /*******************************************************************************
225 *
226 * Function pan_get_pcb_by_addr
227 *
228 * Description
229 *
230 * Returns
231 *
232 ******************************************************************************/
pan_get_pcb_by_addr(const RawAddress & p_bda)233 tPAN_CONN* pan_get_pcb_by_addr(const RawAddress& p_bda) {
234 uint16_t i;
235
236 for (i = 0; i < MAX_PAN_CONNS; i++) {
237 if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
238 continue;
239 }
240
241 if (pan_cb.pcb[i].rem_bda == p_bda) {
242 return &(pan_cb.pcb[i]);
243 }
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, pan_cb.active_role,
310 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, p_pcb->handle,
314 p_pcb->src_uuid, p_pcb->rem_bda);
315 }
316 #endif
317 }
318