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 <string.h>
27#include "bnep_api.h"
28#include "bt_common.h"
29#include "bt_types.h"
30#include "bt_utils.h"
31#include "hcidefs.h"
32#include "l2c_api.h"
33#include "osi/include/osi.h"
34#include "pan_api.h"
35#include "pan_int.h"
36#include "sdp_api.h"
37#include "sdpdefs.h"
38
39tPAN_CB pan_cb;
40
41#define UUID_CONSTANT_PART 12
42uint8_t constant_pan_uuid[UUID_CONSTANT_PART] = {
43    0, 0, 0x10, 0, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
44
45/*******************************************************************************
46 *
47 * Function         pan_register_with_bnep
48 *
49 * Description      This function registers PAN profile with BNEP
50 *
51 * Parameters:      none
52 *
53 * Returns          none
54 *
55 ******************************************************************************/
56void pan_register_with_bnep(void) {
57  tBNEP_REGISTER reg_info;
58
59  memset(&reg_info, 0, sizeof(tBNEP_REGISTER));
60
61  reg_info.p_conn_ind_cb = pan_conn_ind_cb;
62  reg_info.p_conn_state_cb = pan_connect_state_cb;
63  reg_info.p_data_buf_cb = pan_data_buf_ind_cb;
64  reg_info.p_data_ind_cb = NULL;
65  reg_info.p_tx_data_flow_cb = pan_tx_data_flow_cb;
66  reg_info.p_filter_ind_cb = pan_proto_filt_ind_cb;
67  reg_info.p_mfilter_ind_cb = pan_mcast_filt_ind_cb;
68
69  BNEP_Register(&reg_info);
70}
71
72/*******************************************************************************
73 *
74 * Function         pan_conn_ind_cb
75 *
76 * Description      This function is registered with BNEP as connection
77 *                  indication callback. BNEP will call this when there is
78 *                  connection request from the peer. PAN should call
79 *                  BNEP_ConnectResp to indicate whether to accept the
80 *                  connection or reject
81 *
82 * Parameters:      handle      - handle for the connection
83 *                  p_bda       - BD Addr of the peer requesting the connection
84 *                  remote_uuid     - UUID of the source role (peer device role)
85 *                  local_uuid      - UUID of the destination role (local device
86 *                                                                  role)
87 *                  is_role_change  - Flag to indicate that it is a role change
88 *
89 * Returns          none
90 *
91 ******************************************************************************/
92void pan_conn_ind_cb(uint16_t handle, BD_ADDR p_bda, tBT_UUID* remote_uuid,
93                     tBT_UUID* local_uuid, bool is_role_change) {
94  tPAN_CONN* pcb;
95  uint8_t req_role;
96  bool wrong_uuid;
97
98  /*
99  ** If we are in GN or NAP role and have one or more
100  ** active connections and the received connection is
101  ** for user role reject it.
102  ** If we are in user role with one connection active
103  ** reject the connection.
104  ** Allocate PCB and store the parameters
105  ** Make bridge request to the host system if connection
106  ** is for NAP
107  */
108  wrong_uuid = false;
109  if (remote_uuid->len == 16) {
110    /*
111    ** If the UUID is 16 bytes forst two bytes should be zeros
112    ** and last 12 bytes should match the spec defined constant value
113    */
114    if (memcmp(constant_pan_uuid, remote_uuid->uu.uuid128 + 4,
115               UUID_CONSTANT_PART))
116      wrong_uuid = true;
117
118    if (remote_uuid->uu.uuid128[0] || remote_uuid->uu.uuid128[1])
119      wrong_uuid = true;
120
121    /* Extract the 16 bit equivalent of the UUID */
122    remote_uuid->uu.uuid16 = (uint16_t)((remote_uuid->uu.uuid128[2] << 8) |
123                                        remote_uuid->uu.uuid128[3]);
124    remote_uuid->len = 2;
125  }
126  if (remote_uuid->len == 4) {
127    /* First two bytes should be zeros */
128    if (remote_uuid->uu.uuid32 & 0xFFFF0000) wrong_uuid = true;
129
130    remote_uuid->uu.uuid16 = (uint16_t)remote_uuid->uu.uuid32;
131    remote_uuid->len = 2;
132  }
133
134  if (wrong_uuid) {
135    PAN_TRACE_ERROR("PAN Connection failed because of wrong remote UUID ");
136    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
137    return;
138  }
139
140  wrong_uuid = false;
141  if (local_uuid->len == 16) {
142    /*
143    ** If the UUID is 16 bytes forst two bytes should be zeros
144    ** and last 12 bytes should match the spec defined constant value
145    */
146    if (memcmp(constant_pan_uuid, local_uuid->uu.uuid128 + 4,
147               UUID_CONSTANT_PART))
148      wrong_uuid = true;
149
150    if (local_uuid->uu.uuid128[0] || local_uuid->uu.uuid128[1])
151      wrong_uuid = true;
152
153    /* Extract the 16 bit equivalent of the UUID */
154    local_uuid->uu.uuid16 = (uint16_t)((local_uuid->uu.uuid128[2] << 8) |
155                                       local_uuid->uu.uuid128[3]);
156    local_uuid->len = 2;
157  }
158  if (local_uuid->len == 4) {
159    /* First two bytes should be zeros */
160    if (local_uuid->uu.uuid32 & 0xFFFF0000) wrong_uuid = true;
161
162    local_uuid->uu.uuid16 = (uint16_t)local_uuid->uu.uuid32;
163    local_uuid->len = 2;
164  }
165
166  if (wrong_uuid) {
167    PAN_TRACE_ERROR("PAN Connection failed because of wrong local UUID ");
168    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
169    return;
170  }
171
172  PAN_TRACE_EVENT(
173      "pan_conn_ind_cb - for handle %d, current role %d, dst uuid 0x%x, src "
174      "uuid 0x%x, role change %s",
175      handle, pan_cb.role, local_uuid->uu.uuid16, remote_uuid->uu.uuid16,
176      is_role_change ? "YES" : "NO");
177  /* The acceptable UUID size is only 2 */
178  if (remote_uuid->len != 2) {
179    PAN_TRACE_ERROR("PAN Connection failed because of wrong UUID size %d",
180                    remote_uuid->len);
181    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_UUID_SIZE);
182    return;
183  }
184
185  /* Check if the source UUID is a valid one */
186  if (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
187      remote_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
188      remote_uuid->uu.uuid16 != UUID_SERVCLASS_GN) {
189    PAN_TRACE_ERROR("Src UUID 0x%x is not valid", remote_uuid->uu.uuid16);
190    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
191    return;
192  }
193
194  /* Check if the destination UUID is a valid one */
195  if (local_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
196      local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
197      local_uuid->uu.uuid16 != UUID_SERVCLASS_GN) {
198    PAN_TRACE_ERROR("Dst UUID 0x%x is not valid", remote_uuid->uu.uuid16);
199    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
200    return;
201  }
202
203  /* Check if currently we support the destination role requested */
204  if (((!(pan_cb.role & UUID_SERVCLASS_PANU)) &&
205       local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) ||
206      ((!(pan_cb.role & UUID_SERVCLASS_GN)) &&
207       local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) ||
208      ((!(pan_cb.role & UUID_SERVCLASS_NAP)) &&
209       local_uuid->uu.uuid16 == UUID_SERVCLASS_NAP)) {
210    PAN_TRACE_ERROR(
211        "PAN Connection failed because of unsupported destination UUID 0x%x",
212        local_uuid->uu.uuid16);
213    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
214    return;
215  }
216
217  /* Requested destination role is */
218  if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
219    req_role = PAN_ROLE_CLIENT;
220  else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN)
221    req_role = PAN_ROLE_GN_SERVER;
222  else
223    req_role = PAN_ROLE_NAP_SERVER;
224
225  /* If the connection indication is for the existing connection
226  ** Check if the new destination role is acceptable
227  */
228  pcb = pan_get_pcb_by_handle(handle);
229  if (pcb) {
230    if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) {
231      /* There are connections other than this one
232      ** so we cann't accept PANU role. Reject
233      */
234      PAN_TRACE_ERROR(
235          "Dst UUID should be either GN or NAP only because there are other "
236          "connections");
237      BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
238      return;
239    }
240
241    /* If it is already in connected state check for bridging status */
242    if (pcb->con_state == PAN_STATE_CONNECTED) {
243      PAN_TRACE_EVENT("PAN Role changing New Src 0x%x Dst 0x%x",
244                      remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
245
246      pcb->prv_src_uuid = pcb->src_uuid;
247      pcb->prv_dst_uuid = pcb->dst_uuid;
248
249      if (pcb->src_uuid == UUID_SERVCLASS_NAP &&
250          local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP) {
251        /* Remove bridging */
252        if (pan_cb.pan_bridge_req_cb)
253          (*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, false);
254      }
255    }
256    /* Set the latest active PAN role */
257    pan_cb.active_role = req_role;
258    pcb->src_uuid = local_uuid->uu.uuid16;
259    pcb->dst_uuid = remote_uuid->uu.uuid16;
260    BNEP_ConnectResp(handle, BNEP_SUCCESS);
261    return;
262  } else {
263    /* If this a new connection and destination is PANU role and
264    ** we already have a connection then reject the request.
265    ** If we have a connection in PANU role then reject it
266    */
267    if (pan_cb.num_conns && (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU ||
268                             pan_cb.active_role == PAN_ROLE_CLIENT)) {
269      PAN_TRACE_ERROR("PAN already have a connection and can't be user");
270      BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
271      return;
272    }
273  }
274
275  /* This is a new connection */
276  PAN_TRACE_DEBUG("New connection indication for handle %d", handle);
277  pcb = pan_allocate_pcb(p_bda, handle);
278  if (!pcb) {
279    PAN_TRACE_ERROR("PAN no control block for new connection");
280    BNEP_ConnectResp(handle, BNEP_CONN_FAILED);
281    return;
282  }
283
284  PAN_TRACE_EVENT("PAN connection destination UUID is 0x%x",
285                  local_uuid->uu.uuid16);
286  /* Set the latest active PAN role */
287  pan_cb.active_role = req_role;
288  pcb->src_uuid = local_uuid->uu.uuid16;
289  pcb->dst_uuid = remote_uuid->uu.uuid16;
290  pcb->con_state = PAN_STATE_CONN_START;
291  pan_cb.num_conns++;
292
293  BNEP_ConnectResp(handle, BNEP_SUCCESS);
294  return;
295}
296
297/*******************************************************************************
298 *
299 * Function         pan_connect_state_cb
300 *
301 * Description      This function is registered with BNEP as connection state
302 *                  change callback. BNEP will call this when the connection
303 *                  is established successfully or terminated
304 *
305 * Parameters:      handle  - handle for the connection given in the connection
306 *                            indication callback
307 *                  rem_bda - remote device bd addr
308 *                  result  - indicates whether the connection is up or down
309 *                            BNEP_SUCCESS if the connection is up all other
310 *                            values indicate appropriate errors.
311 *                  is_role_change - flag to indicate that it is a role change
312 *
313 * Returns          none
314 *
315 ******************************************************************************/
316void pan_connect_state_cb(uint16_t handle, UNUSED_ATTR BD_ADDR rem_bda,
317                          tBNEP_RESULT result, bool is_role_change) {
318  tPAN_CONN* pcb;
319  uint8_t peer_role;
320
321  PAN_TRACE_EVENT("pan_connect_state_cb - for handle %d, result %d", handle,
322                  result);
323  pcb = pan_get_pcb_by_handle(handle);
324  if (!pcb) {
325    PAN_TRACE_ERROR("PAN State change indication for wrong handle %d", handle);
326    return;
327  }
328
329  /* If the connection is getting terminated remove bridging */
330  if (result != BNEP_SUCCESS) {
331    /* Inform the application that connection is down */
332    if (pan_cb.pan_conn_state_cb)
333      (*pan_cb.pan_conn_state_cb)(pcb->handle, pcb->rem_bda, result,
334                                  is_role_change, PAN_ROLE_INACTIVE,
335                                  PAN_ROLE_INACTIVE);
336
337    /* Check if this failure is for role change only */
338    if (pcb->con_state != PAN_STATE_CONNECTED &&
339        (pcb->con_flags & PAN_FLAGS_CONN_COMPLETED)) {
340      /* restore the original values */
341      PAN_TRACE_EVENT("restoring the connection state to active");
342      pcb->con_state = PAN_STATE_CONNECTED;
343      pcb->con_flags &= (~PAN_FLAGS_CONN_COMPLETED);
344
345      pcb->src_uuid = pcb->prv_src_uuid;
346      pcb->dst_uuid = pcb->prv_dst_uuid;
347      pan_cb.active_role = pan_cb.prv_active_role;
348
349      if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
350        (*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, true);
351
352      return;
353    }
354
355    if (pcb->con_state == PAN_STATE_CONNECTED) {
356      /* If the connections destination role is NAP remove bridging */
357      if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
358        (*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, false);
359    }
360
361    pan_cb.num_conns--;
362    pan_release_pcb(pcb);
363    return;
364  }
365
366  /* Requested destination role is */
367  if (pcb->src_uuid == UUID_SERVCLASS_PANU)
368    pan_cb.active_role = PAN_ROLE_CLIENT;
369  else if (pcb->src_uuid == UUID_SERVCLASS_GN)
370    pan_cb.active_role = PAN_ROLE_GN_SERVER;
371  else
372    pan_cb.active_role = PAN_ROLE_NAP_SERVER;
373
374  if (pcb->dst_uuid == UUID_SERVCLASS_PANU)
375    peer_role = PAN_ROLE_CLIENT;
376  else if (pcb->dst_uuid == UUID_SERVCLASS_GN)
377    peer_role = PAN_ROLE_GN_SERVER;
378  else
379    peer_role = PAN_ROLE_NAP_SERVER;
380
381  pcb->con_state = PAN_STATE_CONNECTED;
382
383  /* Inform the application that connection is down */
384  if (pan_cb.pan_conn_state_cb)
385    (*pan_cb.pan_conn_state_cb)(pcb->handle, pcb->rem_bda, PAN_SUCCESS,
386                                is_role_change, pan_cb.active_role, peer_role);
387
388  /* Create bridge if the destination role is NAP */
389  if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP) {
390    PAN_TRACE_EVENT("PAN requesting for bridge");
391    (*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, true);
392  }
393}
394
395/*******************************************************************************
396 *
397 * Function         pan_data_ind_cb
398 *
399 * Description      This function is registered with BNEP as data indication
400 *                  callback. BNEP will call this when the peer sends any data
401 *                  on this connection
402 *
403 * Parameters:      handle      - handle for the connection
404 *                  src         - source BD Addr
405 *                  dst         - destination BD Addr
406 *                  protocol    - Network protocol of the Eth packet
407 *                  p_data      - pointer to the data
408 *                  len         - length of the data
409 *                  fw_ext_present - to indicate whether the data contains any
410 *                                         extension headers before the payload
411 *
412 * Returns          none
413 *
414 ******************************************************************************/
415void pan_data_ind_cb(uint16_t handle, uint8_t* src, uint8_t* dst,
416                     uint16_t protocol, uint8_t* p_data, uint16_t len,
417                     bool ext) {
418  tPAN_CONN* pcb;
419  uint16_t i;
420  bool forward;
421
422  /*
423  ** Check the connection status
424  ** If the destination address is MAC broadcast send on all links
425  ** except on the one received
426  ** If the destination uuid is for NAP send to host system also
427  ** If the destination address is one of the devices connected
428  ** send the packet to over that link
429  ** If the destination address is unknown and destination uuid is NAP
430  ** send it to the host system
431  */
432
433  PAN_TRACE_EVENT("pan_data_ind_cb - for handle %d", handle);
434  pcb = pan_get_pcb_by_handle(handle);
435  if (!pcb) {
436    PAN_TRACE_ERROR("PAN Data indication for wrong handle %d", handle);
437    return;
438  }
439
440  if (pcb->con_state != PAN_STATE_CONNECTED) {
441    PAN_TRACE_ERROR("PAN Data indication in wrong state %d for handle %d",
442                    pcb->con_state, handle);
443    return;
444  }
445
446  /* Check if it is broadcast packet */
447  if (dst[0] & 0x01) {
448    PAN_TRACE_DEBUG("PAN received broadcast packet on handle %d, src uuid 0x%x",
449                    handle, pcb->src_uuid);
450    for (i = 0; i < MAX_PAN_CONNS; i++) {
451      if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
452          pan_cb.pcb[i].handle != handle &&
453          pcb->src_uuid == pan_cb.pcb[i].src_uuid) {
454        BNEP_Write(pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
455      }
456    }
457
458    if (pan_cb.pan_data_ind_cb)
459      (*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len,
460                                ext, true);
461
462    return;
463  }
464
465  /* Check if it is for any other PAN connection */
466  for (i = 0; i < MAX_PAN_CONNS; i++) {
467    if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
468        pcb->src_uuid == pan_cb.pcb[i].src_uuid) {
469      if (memcmp(pan_cb.pcb[i].rem_bda, dst, BD_ADDR_LEN) == 0) {
470        BNEP_Write(pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
471        return;
472      }
473    }
474  }
475
476  if (pcb->src_uuid == UUID_SERVCLASS_NAP)
477    forward = true;
478  else
479    forward = false;
480
481  /* Send it over the LAN or give it to host software */
482  if (pan_cb.pan_data_ind_cb)
483    (*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len, ext,
484                              forward);
485
486  return;
487}
488
489/*******************************************************************************
490 *
491 * Function         pan_data_buf_ind_cb
492 *
493 * Description      This function is registered with BNEP as data buffer
494 *                  indication callback. BNEP will call this when the peer sends
495 *                  any data on this connection. PAN is responsible to release
496 *                  the buffer
497 *
498 * Parameters:      handle      - handle for the connection
499 *                  src         - source BD Addr
500 *                  dst         - destination BD Addr
501 *                  protocol    - Network protocol of the Eth packet
502 *                  p_buf       - pointer to the data buffer
503 *                  ext         - to indicate whether the data contains any
504 *                                         extension headers before the payload
505 *
506 * Returns          none
507 *
508 ******************************************************************************/
509void pan_data_buf_ind_cb(uint16_t handle, uint8_t* src, uint8_t* dst,
510                         uint16_t protocol, BT_HDR* p_buf, bool ext) {
511  tPAN_CONN *pcb, *dst_pcb;
512  tBNEP_RESULT result;
513  uint16_t i, len;
514  uint8_t* p_data;
515  bool forward = false;
516
517  /* Check if the connection is in right state */
518  pcb = pan_get_pcb_by_handle(handle);
519  if (!pcb) {
520    PAN_TRACE_ERROR("PAN Data buffer indication for wrong handle %d", handle);
521    osi_free(p_buf);
522    return;
523  }
524
525  if (pcb->con_state != PAN_STATE_CONNECTED) {
526    PAN_TRACE_ERROR("PAN Data indication in wrong state %d for handle %d",
527                    pcb->con_state, handle);
528    osi_free(p_buf);
529    return;
530  }
531
532  p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
533  len = p_buf->len;
534
535  PAN_TRACE_EVENT(
536      "pan_data_buf_ind_cb - for handle %d, protocol 0x%x, length %d, ext %d",
537      handle, protocol, len, ext);
538
539  if (pcb->src_uuid == UUID_SERVCLASS_NAP)
540    forward = true;
541  else
542    forward = false;
543
544  /* Check if it is broadcast or multicast packet */
545  if (pcb->src_uuid != UUID_SERVCLASS_PANU) {
546    if (dst[0] & 0x01) {
547      PAN_TRACE_DEBUG(
548          "PAN received broadcast packet on handle %d, src uuid 0x%x", handle,
549          pcb->src_uuid);
550      for (i = 0; i < MAX_PAN_CONNS; i++) {
551        if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
552            pan_cb.pcb[i].handle != handle &&
553            pcb->src_uuid == pan_cb.pcb[i].src_uuid) {
554          BNEP_Write(pan_cb.pcb[i].handle, dst, p_data, len, protocol, src,
555                     ext);
556        }
557      }
558
559      if (pan_cb.pan_data_buf_ind_cb)
560        (*pan_cb.pan_data_buf_ind_cb)(pcb->handle, src, dst, protocol, p_buf,
561                                      ext, forward);
562      else if (pan_cb.pan_data_ind_cb) {
563        (*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len,
564                                  ext, forward);
565        osi_free(p_buf);
566      }
567
568      return;
569    }
570
571    /* Check if it is for any other PAN connection */
572    dst_pcb = pan_get_pcb_by_addr(dst);
573    if (dst_pcb) {
574      PAN_TRACE_EVENT(
575          "%s - destination PANU found on handle %d and sending data, len: %d",
576          __func__, dst_pcb->handle, len);
577
578      result =
579          BNEP_Write(dst_pcb->handle, dst, p_data, len, protocol, src, ext);
580      if (result != BNEP_SUCCESS && result != BNEP_IGNORE_CMD)
581        PAN_TRACE_ERROR("Failed to write data for PAN connection handle %d",
582                        dst_pcb->handle);
583      osi_free(p_buf);
584      return;
585    }
586  }
587
588  /* Send it over the LAN or give it to host software */
589  if (pan_cb.pan_data_buf_ind_cb)
590    (*pan_cb.pan_data_buf_ind_cb)(pcb->handle, src, dst, protocol, p_buf, ext,
591                                  forward);
592  else if (pan_cb.pan_data_ind_cb) {
593    (*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len, ext,
594                              forward);
595    osi_free(p_buf);
596  } else
597    osi_free(p_buf);
598
599  return;
600}
601
602/*******************************************************************************
603 *
604 * Function         pan_proto_filt_ind_cb
605 *
606 * Description      This function is registered with BNEP to receive tx data
607 *					flow status
608 *
609 * Parameters:      handle      - handle for the connection
610 *					event       - flow status
611 *
612 * Returns          none
613 *
614 ******************************************************************************/
615void pan_tx_data_flow_cb(uint16_t handle, tBNEP_RESULT event) {
616  if (pan_cb.pan_tx_data_flow_cb) (*pan_cb.pan_tx_data_flow_cb)(handle, event);
617
618  return;
619}
620
621/*******************************************************************************
622 *
623 * Function         pan_proto_filt_ind_cb
624 *
625 * Description      This function is registered with BNEP as proto filter
626 *                  indication callback. BNEP will call this when the peer sends
627 *                  any protocol filter set for the connection or to indicate
628 *                  the result of the protocol filter set by the local device
629 *
630 * Parameters:      handle      - handle for the connection
631 *                  indication  - true if this is indication
632 *                                false if it is called to give the result of
633 *                                      local device protocol filter set
634 *                  result      - This gives the result of the filter set
635 *                                      operation
636 *                  num_filters - number of filters set by the peer device
637 *                  p_filters   - pointer to the filters set by the peer device
638 *
639 * Returns          none
640 *
641 ******************************************************************************/
642void pan_proto_filt_ind_cb(uint16_t handle, bool indication,
643                           tBNEP_RESULT result, uint16_t num_filters,
644                           uint8_t* p_filters) {
645  PAN_TRACE_EVENT(
646      "pan_proto_filt_ind_cb - called for handle %d with ind %d, result %d, "
647      "num %d",
648      handle, indication, result, num_filters);
649
650  if (pan_cb.pan_pfilt_ind_cb)
651    (*pan_cb.pan_pfilt_ind_cb)(handle, indication, result, num_filters,
652                               p_filters);
653}
654
655/*******************************************************************************
656 *
657 * Function         pan_mcast_filt_ind_cb
658 *
659 * Description      This function is registered with BNEP as mcast filter
660 *                  indication callback. BNEP will call this when the peer sends
661 *                  any multicast filter set for the connection or to indicate
662 *                  the result of the multicast filter set by the local device
663 *
664 * Parameters:      handle      - handle for the connection
665 *                  indication  - true if this is indication
666 *                                false if it is called to give the result of
667 *                                      local device multicast filter set
668 *                  result      - This gives the result of the filter set
669 *                                operation
670 *                  num_filters - number of filters set by the peer device
671 *                  p_filters   - pointer to the filters set by the peer device
672 *
673 * Returns          none
674 *
675 ******************************************************************************/
676void pan_mcast_filt_ind_cb(uint16_t handle, bool indication,
677                           tBNEP_RESULT result, uint16_t num_filters,
678                           uint8_t* p_filters) {
679  PAN_TRACE_EVENT(
680      "pan_mcast_filt_ind_cb - called for handle %d with ind %d, result %d, "
681      "num %d",
682      handle, indication, result, num_filters);
683
684  if (pan_cb.pan_mfilt_ind_cb)
685    (*pan_cb.pan_mfilt_ind_cb)(handle, indication, result, num_filters,
686                               p_filters);
687}
688