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