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