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