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