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 "stack/include/pan_api.h"
29
30 #include <base/strings/stringprintf.h>
31 #include <bluetooth/log.h>
32
33 #include <cstdint>
34 #include <cstring>
35 #include <string>
36
37 #include "bta/sys/bta_sys.h"
38 #include "internal_include/bt_target.h"
39 #include "main/shim/dumpsys.h"
40 #include "os/logging/log_adapter.h"
41 #include "osi/include/allocator.h"
42 #include "stack/include/bnep_api.h"
43 #include "stack/include/bt_hdr.h"
44 #include "stack/include/bt_uuid16.h"
45 #include "stack/include/btm_log_history.h"
46 #include "stack/include/sdp_api.h"
47 #include "stack/pan/pan_int.h"
48 #include "types/bluetooth/uuid.h"
49 #include "types/raw_address.h"
50
51 using namespace bluetooth;
52 using namespace bluetooth::legacy::stack::sdp;
53
54 using bluetooth::Uuid;
55
56 namespace {
57 constexpr char kBtmLogTag[] = "PAN";
58 }
59
60 extern std::string user_service_name; /* Service name for PANU role */
61 extern std::string gn_service_name; /* Service name for GN role */
62 extern std::string nap_service_name; /* Service name for NAP role */
63
64 /*******************************************************************************
65 *
66 * Function PAN_Register
67 *
68 * Description This function is called by the application to register
69 * its callbacks with PAN profile. The application then
70 * should set the PAN role explicitly.
71 *
72 * Parameters: p_register - contains all callback function pointers
73 *
74 *
75 * Returns none
76 *
77 ******************************************************************************/
PAN_Register(tPAN_REGISTER * p_register)78 void PAN_Register(tPAN_REGISTER* p_register) {
79 if (!p_register) {
80 return;
81 }
82
83 pan_register_with_bnep();
84
85 pan_cb.pan_conn_state_cb = p_register->pan_conn_state_cb;
86 pan_cb.pan_bridge_req_cb = p_register->pan_bridge_req_cb;
87 pan_cb.pan_data_buf_ind_cb = p_register->pan_data_buf_ind_cb;
88 pan_cb.pan_data_ind_cb = p_register->pan_data_ind_cb;
89 pan_cb.pan_pfilt_ind_cb = p_register->pan_pfilt_ind_cb;
90 pan_cb.pan_mfilt_ind_cb = p_register->pan_mfilt_ind_cb;
91 pan_cb.pan_tx_data_flow_cb = p_register->pan_tx_data_flow_cb;
92
93 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Registered");
94 }
95
96 /*******************************************************************************
97 *
98 * Function PAN_Deregister
99 *
100 * Description This function is called by the application to de-register
101 * its callbacks with PAN profile. This will make the PAN to
102 * become inactive. This will deregister PAN services from SDP
103 * and close all active connections
104 *
105 * Parameters: none
106 *
107 *
108 * Returns none
109 *
110 ******************************************************************************/
PAN_Deregister(void)111 void PAN_Deregister(void) {
112 pan_cb.pan_bridge_req_cb = NULL;
113 pan_cb.pan_data_buf_ind_cb = NULL;
114 pan_cb.pan_data_ind_cb = NULL;
115 pan_cb.pan_conn_state_cb = NULL;
116 pan_cb.pan_pfilt_ind_cb = NULL;
117 pan_cb.pan_mfilt_ind_cb = NULL;
118
119 PAN_SetRole(PAN_ROLE_INACTIVE, std::string(), std::string());
120 BNEP_Deregister();
121
122 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Unregistered");
123 }
124
125 /*******************************************************************************
126 *
127 * Function PAN_SetRole
128 *
129 * Description This function is called by the application to set the PAN
130 * profile role. This should be called after PAN_Register.
131 * This can be called any time to change the PAN role
132 *
133 * Parameters: role - is bit map of roles to be active
134 * PAN_ROLE_CLIENT is for PANU role
135 * PAN_ROLE_NAP_SERVER is for NAP role
136 * p_user_name - Service name for PANU role
137 * p_nap_name - Service name for NAP role
138 * Can be NULL if user wants the default
139 *
140 * Returns PAN_SUCCESS - if the role is set successfully
141 * PAN_FAILURE - if the role is not valid
142 *
143 ******************************************************************************/
PAN_SetRole(uint8_t role,std::string p_user_name,std::string p_nap_name)144 tPAN_RESULT PAN_SetRole(uint8_t role, std::string p_user_name, std::string p_nap_name) {
145 /* Check if it is a shutdown request */
146 if (role == PAN_ROLE_INACTIVE) {
147 pan_close_all_connections();
148 pan_cb.role = role;
149 user_service_name.clear();
150 nap_service_name.clear();
151 return PAN_SUCCESS;
152 }
153
154 const char* p_desc;
155
156 /* If the role is not a valid combination reject it */
157 if ((!(role & (PAN_ROLE_CLIENT | PAN_ROLE_NAP_SERVER))) && role != PAN_ROLE_INACTIVE) {
158 log::error("PAN role {} is invalid", role);
159 return PAN_FAILURE;
160 }
161
162 /* If the current active role is same as the role being set do nothing */
163 if (pan_cb.role == role) {
164 log::verbose("PAN role already was set to: {}", role);
165 return PAN_SUCCESS;
166 }
167
168 /* Register all the roles with SDP */
169 log::verbose("PAN_SetRole() called with role 0x{:x}", role);
170 if (role & PAN_ROLE_NAP_SERVER) {
171 /* Check the service name */
172 if (p_nap_name.empty()) {
173 p_nap_name = std::string(PAN_NAP_DEFAULT_SERVICE_NAME);
174 }
175
176 /* Registering for NAP service with SDP */
177 p_desc = PAN_NAP_DEFAULT_DESCRIPTION;
178
179 if (pan_cb.pan_nap_sdp_handle != 0) {
180 if (!get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(pan_cb.pan_nap_sdp_handle)) {
181 log::warn("Unable to delete SDP record handle:{}", pan_cb.pan_nap_sdp_handle);
182 }
183 }
184
185 pan_cb.pan_nap_sdp_handle =
186 pan_register_with_sdp(UUID_SERVCLASS_NAP, p_nap_name.c_str(), p_desc);
187 bta_sys_add_uuid(UUID_SERVCLASS_NAP);
188 nap_service_name = p_nap_name;
189 } else if (pan_cb.role & PAN_ROLE_NAP_SERVER) {
190 /* If the NAP role is already active and now being cleared delete the record */
191 if (pan_cb.pan_nap_sdp_handle != 0) {
192 if (!get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(pan_cb.pan_nap_sdp_handle)) {
193 log::warn("Unable to delete SDP record handle:{}", pan_cb.pan_nap_sdp_handle);
194 }
195 pan_cb.pan_nap_sdp_handle = 0;
196 bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
197 nap_service_name.clear();
198 }
199 }
200
201 if (role & PAN_ROLE_CLIENT) {
202 /* Check the service name */
203 if (p_user_name.empty()) {
204 p_user_name = PAN_PANU_DEFAULT_SERVICE_NAME;
205 }
206
207 /* Registering for PANU service with SDP */
208 p_desc = PAN_PANU_DEFAULT_DESCRIPTION;
209 if (pan_cb.pan_user_sdp_handle != 0) {
210 if (!get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(pan_cb.pan_user_sdp_handle)) {
211 log::warn("Unable to delete SDP record handle:{}", pan_cb.pan_user_sdp_handle);
212 }
213 }
214
215 pan_cb.pan_user_sdp_handle =
216 pan_register_with_sdp(UUID_SERVCLASS_PANU, p_user_name.c_str(), p_desc);
217 bta_sys_add_uuid(UUID_SERVCLASS_PANU);
218 user_service_name = p_user_name;
219 } else if (pan_cb.role & PAN_ROLE_CLIENT) {
220 /* If the PANU role is already active and now being cleared delete the record */
221 if (pan_cb.pan_user_sdp_handle != 0) {
222 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(pan_cb.pan_user_sdp_handle)) {
223 log::warn("Unable to delete SDP record handle:{}", pan_cb.pan_user_sdp_handle);
224 }
225 pan_cb.pan_user_sdp_handle = 0;
226 bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
227 user_service_name.clear();
228 }
229 }
230
231 pan_cb.role = role;
232 log::verbose("PAN role set to: {}", role);
233
234 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Role change",
235 base::StringPrintf("role:0x%x", role));
236 return PAN_SUCCESS;
237 }
238
239 /*******************************************************************************
240 *
241 * Function PAN_Connect
242 *
243 * Description This function is called by the application to initiate a
244 * connection to the remote device
245 *
246 * Parameters: rem_bda - BD Addr of the remote device
247 * src_role - Role of the local device for the connection
248 * dst_role - Role of the remote device for the connection
249 * PAN_ROLE_CLIENT is for PANU role
250 * PAN_ROLE_NAP_SERVER is for NAP role
251 * *handle - Pointer for returning Handle to the connection
252 *
253 * Returns PAN_SUCCESS - if the connection is initiated
254 * successfully
255 * PAN_NO_RESOURCES - resources are not sufficient
256 * PAN_FAILURE - if the connection cannot be initiated
257 * this can be because of the combination of
258 * src and dst roles may not be valid or
259 * allowed at that point of time
260 *
261 ******************************************************************************/
PAN_Connect(const RawAddress & rem_bda,tPAN_ROLE src_role,tPAN_ROLE dst_role,uint16_t * handle)262 tPAN_RESULT PAN_Connect(const RawAddress& rem_bda, tPAN_ROLE src_role, tPAN_ROLE dst_role,
263 uint16_t* handle) {
264 uint32_t mx_chan_id;
265
266 /*
267 ** Initialize the handle so that in case of failure return values
268 ** the profile will not get confused
269 */
270 *handle = BNEP_INVALID_HANDLE;
271
272 /* Check if PAN is active or not */
273 if (!(pan_cb.role & src_role)) {
274 log::error("PAN is not active for the role {}", src_role);
275 return PAN_FAILURE;
276 }
277
278 /* Validate the parameters before proceeding */
279 if ((src_role != PAN_ROLE_CLIENT && src_role != PAN_ROLE_NAP_SERVER) ||
280 (dst_role != PAN_ROLE_CLIENT && dst_role != PAN_ROLE_NAP_SERVER)) {
281 log::error("Either source {} or destination role {} is invalid", src_role, dst_role);
282 return PAN_FAILURE;
283 }
284
285 /* Check if connection exists for this remote device */
286 tPAN_CONN* pcb = pan_get_pcb_by_addr(rem_bda);
287
288 uint16_t src_uuid, dst_uuid;
289 /* If we are PANU for this role validate destination role */
290 if (src_role == PAN_ROLE_CLIENT) {
291 if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb))) {
292 /*
293 ** If the request is not for existing connection reject it
294 ** because if there is already a connection we cannot accept
295 ** another connection in PANU role
296 */
297 log::error("Cannot make PANU connections when there are more than one connection");
298 return PAN_INVALID_SRC_ROLE;
299 }
300
301 src_uuid = UUID_SERVCLASS_PANU;
302 if (dst_role == PAN_ROLE_CLIENT) {
303 dst_uuid = UUID_SERVCLASS_PANU;
304 } else {
305 dst_uuid = UUID_SERVCLASS_NAP;
306 }
307 mx_chan_id = dst_uuid;
308 } else if (dst_role == PAN_ROLE_CLIENT) {
309 /* If destination is PANU role validate source role */
310 if (pan_cb.num_conns && pan_cb.active_role == PAN_ROLE_CLIENT && !pcb) {
311 log::error("Device already have a connection in PANU role");
312 return PAN_INVALID_SRC_ROLE;
313 }
314
315 dst_uuid = UUID_SERVCLASS_PANU;
316 src_uuid = UUID_SERVCLASS_NAP;
317 mx_chan_id = src_uuid;
318 } else {
319 /* The role combination is not valid */
320 log::error("Source {} and Destination roles {} are not valid combination", src_role, dst_role);
321 return PAN_FAILURE;
322 }
323
324 /* Allocate control block and initiate connection */
325 if (!pcb) {
326 pcb = pan_allocate_pcb(rem_bda, BNEP_INVALID_HANDLE);
327 }
328 if (!pcb) {
329 log::error("PAN Connection failed because of no resources");
330 return PAN_NO_RESOURCES;
331 }
332
333 log::verbose("for BD Addr: {}", rem_bda);
334 if (pcb->con_state == PAN_STATE_IDLE) {
335 pan_cb.num_conns++;
336 } else if (pcb->con_state == PAN_STATE_CONNECTED) {
337 pcb->con_flags |= PAN_FLAGS_CONN_COMPLETED;
338 } else {
339 /* PAN connection is still in progress */
340 return PAN_WRONG_STATE;
341 }
342
343 pcb->con_state = PAN_STATE_CONN_START;
344 pcb->prv_src_uuid = pcb->src_uuid;
345 pcb->prv_dst_uuid = pcb->dst_uuid;
346
347 pcb->src_uuid = src_uuid;
348 pcb->dst_uuid = dst_uuid;
349
350 tBNEP_RESULT ret = BNEP_Connect(rem_bda, Uuid::From16Bit(src_uuid), Uuid::From16Bit(dst_uuid),
351 &(pcb->handle), mx_chan_id);
352 if (ret != BNEP_SUCCESS) {
353 pan_release_pcb(pcb);
354 return (tPAN_RESULT)ret;
355 }
356
357 log::verbose("PAN_Connect() current active role set to {}", src_role);
358 pan_cb.prv_active_role = pan_cb.active_role;
359 pan_cb.active_role = src_role;
360 *handle = pcb->handle;
361
362 return PAN_SUCCESS;
363 }
364
365 /*******************************************************************************
366 *
367 * Function PAN_Disconnect
368 *
369 * Description This is used to disconnect the connection
370 *
371 * Parameters: handle - handle for the connection
372 *
373 * Returns PAN_SUCCESS - if the connection is closed successfully
374 * PAN_FAILURE - if the connection is not found or
375 * there is an error in disconnecting
376 *
377 ******************************************************************************/
PAN_Disconnect(uint16_t handle)378 tPAN_RESULT PAN_Disconnect(uint16_t handle) {
379 tPAN_CONN* pcb;
380 tBNEP_RESULT result;
381
382 /* Check if the connection exists */
383 pcb = pan_get_pcb_by_handle(handle);
384 if (!pcb) {
385 log::error("PAN connection not found for the handle {}", handle);
386 return PAN_FAILURE;
387 }
388
389 result = BNEP_Disconnect(pcb->handle);
390 if (pcb->con_state != PAN_STATE_IDLE) {
391 pan_cb.num_conns--;
392 }
393
394 if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP) {
395 (*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, false);
396 }
397
398 BTM_LogHistory(kBtmLogTag, pcb->rem_bda, "Disconnect");
399
400 pan_release_pcb(pcb);
401
402 if (result != BNEP_SUCCESS) {
403 log::verbose("Error in closing PAN connection");
404 return PAN_FAILURE;
405 }
406
407 log::verbose("PAN connection closed");
408 return PAN_SUCCESS;
409 }
410
411 /*******************************************************************************
412 *
413 * Function PAN_Write
414 *
415 * Description This sends data over the PAN connections. If this is called
416 * on GN or NAP side and the packet is multicast or broadcast
417 * it will be sent on all the links. Otherwise the correct link
418 * is found based on the destination address and forwarded on
419 * it.
420 *
421 * Parameters: handle - handle for the connection
422 * dst - MAC or BD Addr of the destination device
423 * src - MAC or BD Addr of the source who sent this packet
424 * protocol - protocol of the ethernet packet like IP or ARP
425 * p_data - pointer to the data
426 * len - length of the data
427 * ext - to indicate that extension headers present
428 *
429 * Returns PAN_SUCCESS - if the data is sent successfully
430 * PAN_FAILURE - if the connection is not found or
431 * there is an error in sending data
432 *
433 ******************************************************************************/
PAN_Write(uint16_t handle,const RawAddress & dst,const RawAddress & src,uint16_t protocol,uint8_t * p_data,uint16_t len,bool ext)434 tPAN_RESULT PAN_Write(uint16_t handle, const RawAddress& dst, const RawAddress& src,
435 uint16_t protocol, uint8_t* p_data, uint16_t len, bool ext) {
436 if (pan_cb.role == PAN_ROLE_INACTIVE || !pan_cb.num_conns) {
437 log::error("PAN is not active, data write failed.");
438 return PAN_FAILURE;
439 }
440
441 // If the packet is broadcast or multicast, we're going to have to create
442 // a copy of the packet for each connection. We can save one extra copy
443 // by fast-pathing here and calling BNEP_Write instead of placing the packet
444 // in a BT_HDR buffer, calling BNEP_Write, and then freeing the buffer.
445 if (dst.address[0] & 0x01) {
446 int i;
447 for (i = 0; i < MAX_PAN_CONNS; ++i) {
448 if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED) {
449 BNEP_Write(pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
450 }
451 }
452 return PAN_SUCCESS;
453 }
454
455 BT_HDR* buffer = reinterpret_cast<BT_HDR*>(osi_malloc(PAN_BUF_SIZE));
456 buffer->len = len;
457 buffer->offset = PAN_MINIMUM_OFFSET;
458 memcpy(reinterpret_cast<uint8_t*>(buffer) + sizeof(BT_HDR) + buffer->offset, p_data, buffer->len);
459
460 return PAN_WriteBuf(handle, dst, src, protocol, buffer, ext);
461 }
462
463 /*******************************************************************************
464 *
465 * Function PAN_WriteBuf
466 *
467 * Description This sends data over the PAN connections. If this is called
468 * on GN or NAP side and the packet is multicast or broadcast
469 * it will be sent on all the links. Otherwise the correct link
470 * is found based on the destination address and forwarded on
471 * it. If the return value is not PAN_SUCCESS, the application
472 * should take care of releasing the message buffer.
473 *
474 * Parameters: handle - handle for the connection
475 * dst - MAC or BD Addr of the destination device
476 * src - MAC or BD Addr of the source who sent this packet
477 * protocol - protocol of the ethernet packet like IP or ARP
478 * p_buf - pointer to the data buffer
479 * ext - to indicate that extension headers present
480 *
481 * Returns PAN_SUCCESS - if the data is sent successfully
482 * PAN_FAILURE - if the connection is not found or
483 * there is an error in sending data
484 *
485 ******************************************************************************/
PAN_WriteBuf(uint16_t handle,const RawAddress & dst,const RawAddress & src,uint16_t protocol,BT_HDR * p_buf,bool ext)486 tPAN_RESULT PAN_WriteBuf(uint16_t handle, const RawAddress& dst, const RawAddress& src,
487 uint16_t protocol, BT_HDR* p_buf, bool ext) {
488 tPAN_CONN* pcb;
489 uint16_t i;
490 tBNEP_RESULT result;
491
492 if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns))) {
493 log::error("PAN is not active Data write failed");
494 osi_free(p_buf);
495 return PAN_FAILURE;
496 }
497
498 /* Check if it is broadcast or multicast packet */
499 if (dst.address[0] & 0x01) {
500 uint8_t* data = reinterpret_cast<uint8_t*>(p_buf) + sizeof(BT_HDR) + p_buf->offset;
501 for (i = 0; i < MAX_PAN_CONNS; ++i) {
502 if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED) {
503 BNEP_Write(pan_cb.pcb[i].handle, dst, data, p_buf->len, protocol, src, ext);
504 }
505 }
506 osi_free(p_buf);
507 return PAN_SUCCESS;
508 }
509
510 /* Check if the data write is on PANU side */
511 if (pan_cb.active_role == PAN_ROLE_CLIENT) {
512 /* Data write is on PANU connection */
513 for (i = 0; i < MAX_PAN_CONNS; i++) {
514 if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
515 pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU) {
516 break;
517 }
518 }
519
520 if (i == MAX_PAN_CONNS) {
521 log::error("PAN Don't have any user connections");
522 osi_free(p_buf);
523 return PAN_FAILURE;
524 }
525
526 uint16_t len = p_buf->len;
527 result = BNEP_WriteBuf(pan_cb.pcb[i].handle, dst, p_buf, protocol, src, ext);
528 if (result == BNEP_IGNORE_CMD) {
529 log::verbose("PAN ignored data write for PANU connection");
530 return (tPAN_RESULT)result;
531 } else if (result != BNEP_SUCCESS) {
532 log::error("PAN failed to write data for the PANU connection");
533 return (tPAN_RESULT)result;
534 }
535
536 pan_cb.pcb[i].write.octets += len;
537 pan_cb.pcb[i].write.packets++;
538
539 log::verbose("PAN successfully wrote data for the PANU connection");
540 return PAN_SUCCESS;
541 }
542
543 /* findout to which connection the data is meant for */
544 pcb = pan_get_pcb_by_handle(handle);
545 if (!pcb) {
546 log::error("PAN Buf write for wrong handle");
547 osi_free(p_buf);
548 return PAN_FAILURE;
549 }
550
551 if (pcb->con_state != PAN_STATE_CONNECTED) {
552 log::error("PAN Buf write when conn is not active");
553 pcb->write.drops++;
554 osi_free(p_buf);
555 return PAN_FAILURE;
556 }
557
558 uint16_t len = p_buf->len;
559 result = BNEP_WriteBuf(pcb->handle, dst, p_buf, protocol, src, ext);
560 if (result == BNEP_IGNORE_CMD) {
561 log::verbose("PAN ignored data buf write to PANU");
562 pcb->write.errors++;
563 return PAN_IGNORE_CMD;
564 } else if (result != BNEP_SUCCESS) {
565 log::error("PAN failed to send data buf to the PANU");
566 pcb->write.errors++;
567 return (tPAN_RESULT)result;
568 }
569
570 pcb->write.octets += len;
571 pcb->write.packets++;
572
573 log::verbose("PAN successfully sent data buf to the PANU");
574
575 return PAN_SUCCESS;
576 }
577
578 /*******************************************************************************
579 *
580 * Function PAN_SetProtocolFilters
581 *
582 * Description This function is used to set protocol filters on the peer
583 *
584 * Parameters: handle - handle for the connection
585 * num_filters - number of protocol filter ranges
586 * start - array of starting protocol numbers
587 * end - array of ending protocol numbers
588 *
589 *
590 * Returns PAN_SUCCESS if protocol filters are set successfully
591 * PAN_FAILURE if connection not found or error in setting
592 *
593 ******************************************************************************/
PAN_SetProtocolFilters(uint16_t handle,uint16_t num_filters,uint16_t * p_start_array,uint16_t * p_end_array)594 tPAN_RESULT PAN_SetProtocolFilters(uint16_t handle, uint16_t num_filters, uint16_t* p_start_array,
595 uint16_t* p_end_array) {
596 tPAN_CONN* pcb;
597
598 /* Check if the connection exists */
599 pcb = pan_get_pcb_by_handle(handle);
600 if (!pcb) {
601 log::error("PAN connection not found for the handle {}", handle);
602 return PAN_FAILURE;
603 }
604
605 tBNEP_RESULT result =
606 BNEP_SetProtocolFilters(pcb->handle, num_filters, p_start_array, p_end_array);
607 if (result != BNEP_SUCCESS) {
608 log::error("PAN failed to set protocol filters for handle {}", handle);
609 return (tPAN_RESULT)result;
610 }
611
612 log::verbose("PAN successfully sent protocol filters for handle {}", handle);
613 return PAN_SUCCESS;
614 }
615
616 /*******************************************************************************
617 *
618 * Function PAN_SetMulticastFilters
619 *
620 * Description This function is used to set multicast filters on the peer
621 *
622 * Parameters: handle - handle for the connection
623 * num_filters - number of multicast filter ranges
624 * start - array of starting multicast filter addresses
625 * end - array of ending multicast filter addresses
626 *
627 *
628 * Returns PAN_SUCCESS if multicast filters are set successfully
629 * PAN_FAILURE if connection not found or error in setting
630 *
631 ******************************************************************************/
PAN_SetMulticastFilters(uint16_t handle,uint16_t num_mcast_filters,uint8_t * p_start_array,uint8_t * p_end_array)632 tPAN_RESULT PAN_SetMulticastFilters(uint16_t handle, uint16_t num_mcast_filters,
633 uint8_t* p_start_array, uint8_t* p_end_array) {
634 tPAN_CONN* pcb;
635
636 /* Check if the connection exists */
637 pcb = pan_get_pcb_by_handle(handle);
638 if (!pcb) {
639 log::error("PAN connection not found for the handle {}", handle);
640 return PAN_FAILURE;
641 }
642
643 tBNEP_RESULT result =
644 BNEP_SetMulticastFilters(pcb->handle, num_mcast_filters, p_start_array, p_end_array);
645 if (result != BNEP_SUCCESS) {
646 log::error("PAN failed to set multicast filters for handle {}", handle);
647 return (tPAN_RESULT)result;
648 }
649
650 log::verbose("PAN successfully sent multicast filters for handle {}", handle);
651 return PAN_SUCCESS;
652 }
653
654 /*******************************************************************************
655 *
656 * Function PAN_Init
657 *
658 * Description This function initializes the PAN module variables
659 *
660 * Parameters: none
661 *
662 * Returns none
663 *
664 ******************************************************************************/
PAN_Init(void)665 void PAN_Init(void) { memset(&pan_cb, 0, sizeof(tPAN_CB)); }
666
667 #define DUMPSYS_TAG "shim::legacy::pan"
PAN_Dumpsys(int fd)668 void PAN_Dumpsys(int fd) {
669 LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG);
670
671 LOG_DUMPSYS(fd, "Connections:%hhu roles configured:%s current:%s previous:%s", pan_cb.num_conns,
672 pan_role_to_text(pan_cb.role).c_str(), pan_role_to_text(pan_cb.active_role).c_str(),
673 pan_role_to_text(pan_cb.prv_active_role).c_str());
674
675 if (!user_service_name.empty()) {
676 LOG_DUMPSYS(fd, "service_name_user:\"%s\"", user_service_name.c_str());
677 }
678 if (!gn_service_name.empty()) {
679 LOG_DUMPSYS(fd, "service_name_gn:\"%s\"", gn_service_name.c_str());
680 }
681 if (!nap_service_name.empty()) {
682 LOG_DUMPSYS(fd, "service_name_nap:\"%s\"", nap_service_name.c_str());
683 }
684
685 const tPAN_CONN* pcb = &pan_cb.pcb[0];
686 for (int i = 0; i < MAX_PAN_CONNS; i++, pcb++) {
687 if (pcb->con_state == PAN_STATE_IDLE) {
688 continue;
689 }
690 LOG_DUMPSYS(fd, " Id:%d peer:%s", i, ADDRESS_TO_LOGGABLE_CSTR(pcb->rem_bda));
691 LOG_DUMPSYS(fd, " rx_packets:%-5lu rx_octets:%-8lu rx_errors:%-5lu rx_drops:%-5lu",
692 (unsigned long)pcb->read.packets, (unsigned long)pcb->read.octets,
693 (unsigned long)pcb->read.errors, (unsigned long)pcb->read.drops);
694 LOG_DUMPSYS(fd, " tx_packets:%-5lu tx_octets:%-8lu tx_errors:%-5lu tx_drops:%-5lu",
695 (unsigned long)pcb->write.packets, (unsigned long)pcb->write.octets,
696 (unsigned long)pcb->write.errors, (unsigned long)pcb->write.drops);
697 LOG_DUMPSYS(fd,
698 " src_uuid:0x%04x[prev:0x%04x] dst_uuid:0x%04x[prev:0x%04x] "
699 "bad_pkts:%hu",
700 pcb->src_uuid, pcb->dst_uuid, pcb->prv_src_uuid, pcb->prv_dst_uuid,
701 pcb->bad_pkts_rcvd);
702 }
703 }
704 #undef DUMPSYS_TAG
705