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