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 ******************************************************************************/
53void 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 ******************************************************************************/
87void 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 ******************************************************************************/
126tPAN_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 ******************************************************************************/
266tPAN_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 ******************************************************************************/
399tPAN_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 ******************************************************************************/
450tPAN_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 ******************************************************************************/
503tPAN_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 ******************************************************************************/
599tPAN_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 ******************************************************************************/
639tBNEP_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 ******************************************************************************/
676uint8_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 ******************************************************************************/
696void 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