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