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