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(®_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(®_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