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