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