• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
40 tPAN_CB  pan_cb;
41 #endif
42 
43 #define UUID_CONSTANT_PART  12
44 UINT8 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 *******************************************************************************/
pan_register_with_bnep(void)58 void 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 *******************************************************************************/
pan_conn_ind_cb(UINT16 handle,BD_ADDR p_bda,tBT_UUID * remote_uuid,tBT_UUID * local_uuid,BOOLEAN is_role_change)94 void 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 *******************************************************************************/
pan_connect_state_cb(UINT16 handle,BD_ADDR rem_bda,tBNEP_RESULT result,BOOLEAN is_role_change)333 void 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 *******************************************************************************/
pan_data_ind_cb(UINT16 handle,UINT8 * src,UINT8 * dst,UINT16 protocol,UINT8 * p_data,UINT16 len,BOOLEAN ext)435 void 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 *******************************************************************************/
pan_data_buf_ind_cb(UINT16 handle,UINT8 * src,UINT8 * dst,UINT16 protocol,BT_HDR * p_buf,BOOLEAN ext)540 void 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 *******************************************************************************/
pan_tx_data_flow_cb(UINT16 handle,tBNEP_RESULT event)648 void 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 *******************************************************************************/
pan_proto_filt_ind_cb(UINT16 handle,BOOLEAN indication,tBNEP_RESULT result,UINT16 num_filters,UINT8 * p_filters)678 void 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 *******************************************************************************/
pan_mcast_filt_ind_cb(UINT16 handle,BOOLEAN indication,tBNEP_RESULT result,UINT16 num_filters,UINT8 * p_filters)716 void 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