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 "bt_common.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    /* Check for valid interactions between the three PAN profile roles */
226    /*
227     * For reference, see Table 1 in PAN Profile v1.0 spec.
228     * Note: the remote is the initiator.
229     */
230    BOOLEAN is_valid_interaction = FALSE;
231    switch (remote_uuid->uu.uuid16) {
232    case UUID_SERVCLASS_NAP:
233    case UUID_SERVCLASS_GN:
234        if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
235            is_valid_interaction = TRUE;
236        break;
237    case UUID_SERVCLASS_PANU:
238        is_valid_interaction = TRUE;
239        break;
240    }
241    /*
242     * Explicitly disable connections to the local PANU if the remote is
243     * not PANU.
244     */
245    if ((local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) &&
246        (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU)) {
247        is_valid_interaction = FALSE;
248    }
249    if (!is_valid_interaction) {
250        PAN_TRACE_ERROR(
251          "PAN Connection failed because of invalid PAN profile roles "
252          "interaction: Remote UUID 0x%x Local UUID 0x%x",
253          remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
254        BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
255        return;
256    }
257
258    /* Requested destination role is */
259    if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
260        req_role = PAN_ROLE_CLIENT;
261    else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN)
262        req_role = PAN_ROLE_GN_SERVER;
263    else
264        req_role = PAN_ROLE_NAP_SERVER;
265
266    /* If the connection indication is for the existing connection
267    ** Check if the new destination role is acceptable
268    */
269    pcb = pan_get_pcb_by_handle (handle);
270    if (pcb)
271    {
272        if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
273        {
274            /* There are connections other than this one
275            ** so we cann't accept PANU role. Reject
276            */
277            PAN_TRACE_ERROR ("Dst UUID should be either GN or NAP only because there are other connections");
278            BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
279            return;
280        }
281
282        /* If it is already in connected state check for bridging status */
283        if (pcb->con_state == PAN_STATE_CONNECTED)
284        {
285            PAN_TRACE_EVENT ("PAN Role changing New Src 0x%x Dst 0x%x",
286                remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
287
288            pcb->prv_src_uuid = pcb->src_uuid;
289            pcb->prv_dst_uuid = pcb->dst_uuid;
290
291            if (pcb->src_uuid == UUID_SERVCLASS_NAP &&
292                local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP)
293            {
294                /* Remove bridging */
295                if (pan_cb.pan_bridge_req_cb)
296                    (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
297            }
298        }
299        /* Set the latest active PAN role */
300        pan_cb.active_role = req_role;
301        pcb->src_uuid = local_uuid->uu.uuid16;
302        pcb->dst_uuid = remote_uuid->uu.uuid16;
303        BNEP_ConnectResp (handle, BNEP_SUCCESS);
304        return;
305    }
306    else
307    {
308        /* If this a new connection and destination is PANU role and
309        ** we already have a connection then reject the request.
310        ** If we have a connection in PANU role then reject it
311        */
312        if (pan_cb.num_conns &&
313            (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU ||
314            pan_cb.active_role == PAN_ROLE_CLIENT))
315        {
316            PAN_TRACE_ERROR ("PAN already have a connection and can't be user");
317            BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
318            return;
319        }
320    }
321
322    /* This is a new connection */
323    PAN_TRACE_DEBUG ("New connection indication for handle %d", handle);
324    pcb = pan_allocate_pcb (p_bda, handle);
325    if (!pcb)
326    {
327        PAN_TRACE_ERROR ("PAN no control block for new connection");
328        BNEP_ConnectResp (handle, BNEP_CONN_FAILED);
329        return;
330    }
331
332    PAN_TRACE_EVENT ("PAN connection destination UUID is 0x%x", local_uuid->uu.uuid16);
333    /* Set the latest active PAN role */
334    pan_cb.active_role = req_role;
335    pcb->src_uuid = local_uuid->uu.uuid16;
336    pcb->dst_uuid = remote_uuid->uu.uuid16;
337    pcb->con_state = PAN_STATE_CONN_START;
338    pan_cb.num_conns++;
339
340    BNEP_ConnectResp (handle, BNEP_SUCCESS);
341    return;
342}
343
344
345/*******************************************************************************
346**
347** Function         pan_connect_state_cb
348**
349** Description      This function is registered with BNEP as connection state
350**                  change callback. BNEP will call this when the connection
351**                  is established successfully or terminated
352**
353** Parameters:      handle      - handle for the connection given in the connection
354**                                      indication callback
355**                  rem_bda     - remote device bd addr
356**                  result      - indicates whether the connection is up or down
357**                                      BNEP_SUCCESS if the connection is up
358**                                      all other values indicates appropriate errors
359**                  is_role_change - flag to indicate that it is a role change
360**
361** Returns          none
362**
363*******************************************************************************/
364void pan_connect_state_cb (UINT16 handle, BD_ADDR rem_bda, tBNEP_RESULT result, BOOLEAN is_role_change)
365{
366    tPAN_CONN       *pcb;
367    UINT8            peer_role;
368    UNUSED(rem_bda);
369
370    PAN_TRACE_EVENT ("pan_connect_state_cb - for handle %d, result %d", handle, result);
371    pcb = pan_get_pcb_by_handle (handle);
372    if (!pcb)
373    {
374        PAN_TRACE_ERROR ("PAN State change indication for wrong handle %d", handle);
375        return;
376    }
377
378    /* If the connection is getting terminated remove bridging */
379    if (result != BNEP_SUCCESS)
380    {
381        /* Inform the application that connection is down */
382        if (pan_cb.pan_conn_state_cb)
383            (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, result, is_role_change, PAN_ROLE_INACTIVE, PAN_ROLE_INACTIVE);
384
385        /* Check if this failure is for role change only */
386        if (pcb->con_state != PAN_STATE_CONNECTED &&
387            (pcb->con_flags & PAN_FLAGS_CONN_COMPLETED))
388        {
389            /* restore the original values */
390            PAN_TRACE_EVENT ("restoring the connection state to active");
391            pcb->con_state = PAN_STATE_CONNECTED;
392            pcb->con_flags &= (~PAN_FLAGS_CONN_COMPLETED);
393
394            pcb->src_uuid = pcb->prv_src_uuid;
395            pcb->dst_uuid = pcb->prv_dst_uuid;
396            pan_cb.active_role = pan_cb.prv_active_role;
397
398            if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
399                (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE);
400
401            return;
402        }
403
404        if (pcb->con_state == PAN_STATE_CONNECTED)
405        {
406            /* If the connections destination role is NAP remove bridging */
407            if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
408                (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
409        }
410
411        pan_cb.num_conns--;
412        pan_release_pcb (pcb);
413        return;
414    }
415
416    /* Requested destination role is */
417    if (pcb->src_uuid == UUID_SERVCLASS_PANU)
418        pan_cb.active_role = PAN_ROLE_CLIENT;
419    else if (pcb->src_uuid == UUID_SERVCLASS_GN)
420        pan_cb.active_role = PAN_ROLE_GN_SERVER;
421    else
422        pan_cb.active_role = PAN_ROLE_NAP_SERVER;
423
424    if (pcb->dst_uuid == UUID_SERVCLASS_PANU)
425        peer_role = PAN_ROLE_CLIENT;
426    else if (pcb->dst_uuid == UUID_SERVCLASS_GN)
427        peer_role = PAN_ROLE_GN_SERVER;
428    else
429        peer_role = PAN_ROLE_NAP_SERVER;
430
431    pcb->con_state = PAN_STATE_CONNECTED;
432
433    /* Inform the application that connection is down */
434    if (pan_cb.pan_conn_state_cb)
435        (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, PAN_SUCCESS, is_role_change, pan_cb.active_role, peer_role);
436
437    /* Create bridge if the destination role is NAP */
438    if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
439    {
440        PAN_TRACE_EVENT ("PAN requesting for bridge");
441        (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE);
442    }
443}
444
445
446/*******************************************************************************
447**
448** Function         pan_data_ind_cb
449**
450** Description      This function is registered with BNEP as data indication
451**                  callback. BNEP will call this when the peer sends any data
452**                  on this connection
453**
454** Parameters:      handle      - handle for the connection
455**                  src         - source BD Addr
456**                  dst         - destination BD Addr
457**                  protocol    - Network protocol of the Eth packet
458**                  p_data      - pointer to the data
459**                  len         - length of the data
460**                  fw_ext_present - to indicate whether the data contains any
461**                                         extension headers before the payload
462**
463** Returns          none
464**
465*******************************************************************************/
466void pan_data_ind_cb (UINT16 handle,
467                      UINT8 *src,
468                      UINT8 *dst,
469                      UINT16 protocol,
470                      UINT8 *p_data,
471                      UINT16 len,
472                      BOOLEAN ext)
473{
474    tPAN_CONN       *pcb;
475    UINT16          i;
476    BOOLEAN         forward;
477
478    /*
479    ** Check the connection status
480    ** If the destination address is MAC broadcast send on all links
481    ** except on the one received
482    ** If the destination uuid is for NAP send to host system also
483    ** If the destination address is one of the devices connected
484    ** send the packet to over that link
485    ** If the destination address is unknown and destination uuid is NAP
486    ** send it to the host system
487    */
488
489    PAN_TRACE_EVENT ("pan_data_ind_cb - for handle %d", handle);
490    pcb = pan_get_pcb_by_handle (handle);
491    if (!pcb)
492    {
493        PAN_TRACE_ERROR ("PAN Data indication for wrong handle %d", handle);
494        return;
495    }
496
497    if (pcb->con_state != PAN_STATE_CONNECTED)
498    {
499        PAN_TRACE_ERROR ("PAN Data indication in wrong state %d for handle %d",
500            pcb->con_state, handle);
501        return;
502    }
503
504    /* Check if it is broadcast packet */
505    if (dst[0] & 0x01)
506    {
507        PAN_TRACE_DEBUG ("PAN received broadcast packet on handle %d, src uuid 0x%x",
508            handle, pcb->src_uuid);
509        for (i=0; i<MAX_PAN_CONNS; i++)
510        {
511            if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
512                pan_cb.pcb[i].handle != handle &&
513                pcb->src_uuid == pan_cb.pcb[i].src_uuid)
514            {
515                BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
516            }
517        }
518
519        if (pan_cb.pan_data_ind_cb)
520            (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, TRUE);
521
522        return;
523    }
524
525    /* Check if it is for any other PAN connection */
526    for (i=0; i<MAX_PAN_CONNS; i++)
527    {
528        if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
529            pcb->src_uuid == pan_cb.pcb[i].src_uuid)
530        {
531            if (memcmp (pan_cb.pcb[i].rem_bda, dst, BD_ADDR_LEN) == 0)
532            {
533                BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
534                return;
535            }
536        }
537    }
538
539   if (pcb->src_uuid == UUID_SERVCLASS_NAP)
540       forward = TRUE;
541   else
542       forward = FALSE;
543
544    /* Send it over the LAN or give it to host software */
545    if (pan_cb.pan_data_ind_cb)
546        (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
547
548    return;
549}
550
551
552/*******************************************************************************
553**
554** Function         pan_data_buf_ind_cb
555**
556** Description      This function is registered with BNEP as data buffer indication
557**                  callback. BNEP will call this when the peer sends any data
558**                  on this connection. PAN is responsible to release the buffer
559**
560** Parameters:      handle      - handle for the connection
561**                  src         - source BD Addr
562**                  dst         - destination BD Addr
563**                  protocol    - Network protocol of the Eth packet
564**                  p_buf       - pointer to the data buffer
565**                  ext         - to indicate whether the data contains any
566**                                         extension headers before the payload
567**
568** Returns          none
569**
570*******************************************************************************/
571void pan_data_buf_ind_cb (UINT16 handle,
572                          UINT8 *src,
573                          UINT8 *dst,
574                          UINT16 protocol,
575                          BT_HDR *p_buf,
576                          BOOLEAN ext)
577{
578    tPAN_CONN       *pcb, *dst_pcb;
579    tBNEP_RESULT    result;
580    UINT16          i, len;
581    UINT8           *p_data;
582    BOOLEAN         forward = FALSE;
583
584    /* Check if the connection is in right state */
585    pcb = pan_get_pcb_by_handle (handle);
586    if (!pcb)
587    {
588        PAN_TRACE_ERROR ("PAN Data buffer indication for wrong handle %d", handle);
589        osi_free(p_buf);
590        return;
591    }
592
593    if (pcb->con_state != PAN_STATE_CONNECTED)
594    {
595        PAN_TRACE_ERROR ("PAN Data indication in wrong state %d for handle %d",
596            pcb->con_state, handle);
597        osi_free(p_buf);
598        return;
599    }
600
601    p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
602    len    = p_buf->len;
603
604    PAN_TRACE_EVENT ("pan_data_buf_ind_cb - for handle %d, protocol 0x%x, length %d, ext %d",
605        handle, protocol, len, ext);
606
607   if (pcb->src_uuid == UUID_SERVCLASS_NAP)
608       forward = TRUE;
609   else
610       forward = FALSE;
611
612    /* Check if it is broadcast or multicast packet */
613    if (pcb->src_uuid != UUID_SERVCLASS_PANU)
614    {
615        if (dst[0] & 0x01)
616        {
617            PAN_TRACE_DEBUG ("PAN received broadcast packet on handle %d, src uuid 0x%x",
618                handle, pcb->src_uuid);
619            for (i=0; i<MAX_PAN_CONNS; i++)
620            {
621                if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
622                    pan_cb.pcb[i].handle != handle &&
623                    pcb->src_uuid == pan_cb.pcb[i].src_uuid)
624                {
625                    BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
626                }
627            }
628
629            if (pan_cb.pan_data_buf_ind_cb)
630                (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward);
631            else if (pan_cb.pan_data_ind_cb)
632            {
633                (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
634                osi_free(p_buf);
635            }
636
637            return;
638        }
639
640        /* Check if it is for any other PAN connection */
641        dst_pcb = pan_get_pcb_by_addr (dst);
642        if (dst_pcb)
643        {
644            PAN_TRACE_EVENT ("%s - destination PANU found on handle %d and sending data, len: %d",
645                __func__, dst_pcb->handle, len);
646
647            result = BNEP_Write (dst_pcb->handle, dst, p_data, len, protocol, src, ext);
648            if (result != BNEP_SUCCESS && result != BNEP_IGNORE_CMD)
649                PAN_TRACE_ERROR ("Failed to write data for PAN connection handle %d", dst_pcb->handle);
650            osi_free(p_buf);
651            return;
652        }
653    }
654
655    /* Send it over the LAN or give it to host software */
656    if (pan_cb.pan_data_buf_ind_cb)
657        (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward);
658    else if (pan_cb.pan_data_ind_cb)
659    {
660        (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
661        osi_free(p_buf);
662    }
663    else
664        osi_free(p_buf);
665
666    return;
667}
668
669/*******************************************************************************
670**
671** Function         pan_proto_filt_ind_cb
672**
673** Description      This function is registered with BNEP to receive tx data
674**					flow status
675**
676** Parameters:      handle      - handle for the connection
677**					event       - flow status
678**
679** Returns          none
680**
681*******************************************************************************/
682void pan_tx_data_flow_cb (UINT16 handle,
683                            tBNEP_RESULT  event)
684{
685
686    if (pan_cb.pan_tx_data_flow_cb)
687        (*pan_cb.pan_tx_data_flow_cb) (handle, event);
688
689    return;
690}
691
692/*******************************************************************************
693**
694** Function         pan_proto_filt_ind_cb
695**
696** Description      This function is registered with BNEP as proto filter indication
697**                  callback. BNEP will call this when the peer sends any protocol
698**                  filter set for the connection or to indicate the result of the
699**                  protocol filter set by the local device
700**
701** Parameters:      handle      - handle for the connection
702**                  indication  - TRUE if this is indication
703**                                FALSE if it is called to give the result of local
704**                                      device protocol filter set
705**                  result      - This gives the result of the filter set operation
706**                  num_filters - number of filters set by the peer device
707**                  p_filters   - pointer to the filters set by the peer device
708**
709** Returns          none
710**
711*******************************************************************************/
712void pan_proto_filt_ind_cb (UINT16 handle,
713                            BOOLEAN indication,
714                            tBNEP_RESULT result,
715                            UINT16 num_filters,
716                            UINT8 *p_filters)
717{
718    PAN_TRACE_EVENT ("pan_proto_filt_ind_cb - called for handle %d with ind %d, result %d, num %d",
719                            handle, indication, result, num_filters);
720
721    if (pan_cb.pan_pfilt_ind_cb)
722        (*pan_cb.pan_pfilt_ind_cb) (handle, indication, result, num_filters, p_filters);
723}
724
725
726/*******************************************************************************
727**
728** Function         pan_mcast_filt_ind_cb
729**
730** Description      This function is registered with BNEP as mcast filter indication
731**                  callback. BNEP will call this when the peer sends any multicast
732**                  filter set for the connection or to indicate the result of the
733**                  multicast filter set by the local device
734**
735** Parameters:      handle      - handle for the connection
736**                  indication  - TRUE if this is indication
737**                                FALSE if it is called to give the result of local
738**                                      device multicast filter set
739**                  result      - This gives the result of the filter set operation
740**                  num_filters - number of filters set by the peer device
741**                  p_filters   - pointer to the filters set by the peer device
742**
743** Returns          none
744**
745*******************************************************************************/
746void pan_mcast_filt_ind_cb (UINT16 handle,
747                            BOOLEAN indication,
748                            tBNEP_RESULT result,
749                            UINT16 num_filters,
750                            UINT8 *p_filters)
751{
752    PAN_TRACE_EVENT ("pan_mcast_filt_ind_cb - called for handle %d with ind %d, result %d, num %d",
753                            handle, indication, result, num_filters);
754
755    if (pan_cb.pan_mfilt_ind_cb)
756        (*pan_cb.pan_mfilt_ind_cb) (handle, indication, result, num_filters, p_filters);
757}
758