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 (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_ERROR ("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_ERROR ("PAN Connection failed because of wrong local UUID ");
178        BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
179        return;
180    }
181
182    PAN_TRACE_EVENT ("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_ERROR ("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
192    /* Check if the source UUID is a valid one */
193    if (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
194        remote_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
195        remote_uuid->uu.uuid16 != UUID_SERVCLASS_GN)
196    {
197        PAN_TRACE_ERROR ("Src UUID 0x%x is not valid", remote_uuid->uu.uuid16);
198        BNEP_ConnectResp (handle, BNEP_CONN_FAILED_SRC_UUID);
199        return;
200    }
201
202    /* Check if the destination UUID is a valid one */
203    if (local_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
204        local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
205        local_uuid->uu.uuid16 != UUID_SERVCLASS_GN)
206    {
207        PAN_TRACE_ERROR ("Dst UUID 0x%x is not valid", remote_uuid->uu.uuid16);
208        BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
209        return;
210    }
211
212    /* Check if currently we support the destination role requested */
213    if (((!(pan_cb.role & UUID_SERVCLASS_PANU))
214        && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) ||
215        ((!(pan_cb.role & UUID_SERVCLASS_GN))
216        && local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) ||
217        ((!(pan_cb.role & UUID_SERVCLASS_NAP))
218        && local_uuid->uu.uuid16 == UUID_SERVCLASS_NAP))
219    {
220        PAN_TRACE_ERROR ("PAN Connection failed because of unsupported destination UUID 0x%x", local_uuid->uu.uuid16);
221        BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
222        return;
223    }
224
225    /* Requested destination role is */
226    if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
227        req_role = PAN_ROLE_CLIENT;
228    else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN)
229        req_role = PAN_ROLE_GN_SERVER;
230    else
231        req_role = PAN_ROLE_NAP_SERVER;
232
233    /* If the connection indication is for the existing connection
234    ** Check if the new destination role is acceptable
235    */
236    pcb = pan_get_pcb_by_handle (handle);
237    if (pcb)
238    {
239        if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
240        {
241            /* There are connections other than this one
242            ** so we cann't accept PANU role. Reject
243            */
244            PAN_TRACE_ERROR ("Dst UUID should be either GN or NAP only because there are other connections");
245            BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
246            return;
247        }
248
249        /* If it is already in connected state check for bridging status */
250        if (pcb->con_state == PAN_STATE_CONNECTED)
251        {
252            PAN_TRACE_EVENT ("PAN Role changing New Src 0x%x Dst 0x%x",
253                remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
254
255            pcb->prv_src_uuid = pcb->src_uuid;
256            pcb->prv_dst_uuid = pcb->dst_uuid;
257
258            if (pcb->src_uuid == UUID_SERVCLASS_NAP &&
259                local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP)
260            {
261                /* Remove bridging */
262                if (pan_cb.pan_bridge_req_cb)
263                    (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
264            }
265        }
266        /* Set the latest active PAN role */
267        pan_cb.active_role = req_role;
268        pcb->src_uuid = local_uuid->uu.uuid16;
269        pcb->dst_uuid = remote_uuid->uu.uuid16;
270        BNEP_ConnectResp (handle, BNEP_SUCCESS);
271        return;
272    }
273    else
274    {
275        /* If this a new connection and destination is PANU role and
276        ** we already have a connection then reject the request.
277        ** If we have a connection in PANU role then reject it
278        */
279        if (pan_cb.num_conns &&
280            (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU ||
281            pan_cb.active_role == PAN_ROLE_CLIENT))
282        {
283            PAN_TRACE_ERROR ("PAN already have a connection and can't be user");
284            BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
285            return;
286        }
287    }
288
289    /* This is a new connection */
290    PAN_TRACE_DEBUG ("New connection indication for handle %d", handle);
291    pcb = pan_allocate_pcb (p_bda, handle);
292    if (!pcb)
293    {
294        PAN_TRACE_ERROR ("PAN no control block for new connection");
295        BNEP_ConnectResp (handle, BNEP_CONN_FAILED);
296        return;
297    }
298
299    PAN_TRACE_EVENT ("PAN connection destination UUID is 0x%x", local_uuid->uu.uuid16);
300    /* Set the latest active PAN role */
301    pan_cb.active_role = req_role;
302    pcb->src_uuid = local_uuid->uu.uuid16;
303    pcb->dst_uuid = remote_uuid->uu.uuid16;
304    pcb->con_state = PAN_STATE_CONN_START;
305    pan_cb.num_conns++;
306
307    BNEP_ConnectResp (handle, BNEP_SUCCESS);
308    return;
309}
310
311
312/*******************************************************************************
313**
314** Function         pan_connect_state_cb
315**
316** Description      This function is registered with BNEP as connection state
317**                  change callback. BNEP will call this when the connection
318**                  is established successfully or terminated
319**
320** Parameters:      handle      - handle for the connection given in the connection
321**                                      indication callback
322**                  rem_bda     - remote device bd addr
323**                  result      - indicates whether the connection is up or down
324**                                      BNEP_SUCCESS if the connection is up
325**                                      all other values indicates appropriate errors
326**                  is_role_change - flag to indicate that it is a role change
327**
328** Returns          none
329**
330*******************************************************************************/
331void pan_connect_state_cb (UINT16 handle, BD_ADDR rem_bda, tBNEP_RESULT result, BOOLEAN is_role_change)
332{
333    tPAN_CONN       *pcb;
334    UINT8            peer_role;
335    UNUSED(rem_bda);
336
337    PAN_TRACE_EVENT ("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_ERROR ("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_EVENT ("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_EVENT ("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_EVENT ("pan_data_ind_cb - for handle %d", handle);
457    pcb = pan_get_pcb_by_handle (handle);
458    if (!pcb)
459    {
460        PAN_TRACE_ERROR ("PAN Data indication for wrong handle %d", handle);
461        return;
462    }
463
464    if (pcb->con_state != PAN_STATE_CONNECTED)
465    {
466        PAN_TRACE_ERROR ("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_DEBUG ("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_ERROR ("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_ERROR ("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_EVENT ("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_DEBUG ("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_EVENT ("%s - destination PANU found on handle %d and sending data, len: %d",
612                __func__, dst_pcb->handle, len);
613
614            result = BNEP_Write (dst_pcb->handle, dst, p_data, len, 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            GKI_freebuf (p_buf);
618            return;
619        }
620    }
621
622    /* Send it over the LAN or give it to host software */
623    if (pan_cb.pan_data_buf_ind_cb)
624        (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward);
625    else if (pan_cb.pan_data_ind_cb)
626    {
627        (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
628        GKI_freebuf (p_buf);
629    }
630    else
631        GKI_freebuf (p_buf);
632
633    return;
634}
635
636/*******************************************************************************
637**
638** Function         pan_proto_filt_ind_cb
639**
640** Description      This function is registered with BNEP to receive tx data
641**					flow status
642**
643** Parameters:      handle      - handle for the connection
644**					event       - flow status
645**
646** Returns          none
647**
648*******************************************************************************/
649void pan_tx_data_flow_cb (UINT16 handle,
650                            tBNEP_RESULT  event)
651{
652
653    if (pan_cb.pan_tx_data_flow_cb)
654        (*pan_cb.pan_tx_data_flow_cb) (handle, event);
655
656    return;
657}
658
659/*******************************************************************************
660**
661** Function         pan_proto_filt_ind_cb
662**
663** Description      This function is registered with BNEP as proto filter indication
664**                  callback. BNEP will call this when the peer sends any protocol
665**                  filter set for the connection or to indicate the result of the
666**                  protocol filter set by the local device
667**
668** Parameters:      handle      - handle for the connection
669**                  indication  - TRUE if this is indication
670**                                FALSE if it is called to give the result of local
671**                                      device protocol filter set
672**                  result      - This gives the result of the filter set operation
673**                  num_filters - number of filters set by the peer device
674**                  p_filters   - pointer to the filters set by the peer device
675**
676** Returns          none
677**
678*******************************************************************************/
679void pan_proto_filt_ind_cb (UINT16 handle,
680                            BOOLEAN indication,
681                            tBNEP_RESULT result,
682                            UINT16 num_filters,
683                            UINT8 *p_filters)
684{
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}
691
692
693/*******************************************************************************
694**
695** Function         pan_mcast_filt_ind_cb
696**
697** Description      This function is registered with BNEP as mcast filter indication
698**                  callback. BNEP will call this when the peer sends any multicast
699**                  filter set for the connection or to indicate the result of the
700**                  multicast filter set by the local device
701**
702** Parameters:      handle      - handle for the connection
703**                  indication  - TRUE if this is indication
704**                                FALSE if it is called to give the result of local
705**                                      device multicast filter set
706**                  result      - This gives the result of the filter set operation
707**                  num_filters - number of filters set by the peer device
708**                  p_filters   - pointer to the filters set by the peer device
709**
710** Returns          none
711**
712*******************************************************************************/
713void pan_mcast_filt_ind_cb (UINT16 handle,
714                            BOOLEAN indication,
715                            tBNEP_RESULT result,
716                            UINT16 num_filters,
717                            UINT8 *p_filters)
718{
719    PAN_TRACE_EVENT ("pan_mcast_filt_ind_cb - called for handle %d with ind %d, result %d, num %d",
720                            handle, indication, result, num_filters);
721
722    if (pan_cb.pan_mfilt_ind_cb)
723        (*pan_cb.pan_mfilt_ind_cb) (handle, indication, result, num_filters, p_filters);
724}
725