1 /******************************************************************************
2 *
3 * Copyright 2001-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 the BNEP API code
22 *
23 ******************************************************************************/
24
25 #include "bnep_api.h"
26 #include <string.h>
27 #include "bnep_int.h"
28 #include "bta/include/bta_api.h"
29 #include "stack/btm/btm_sec.h"
30
31 using bluetooth::Uuid;
32
33 /*******************************************************************************
34 *
35 * Function BNEP_Init
36 *
37 * Description This function initializes the BNEP unit. It should be called
38 * before accessing any other APIs to initialize the control
39 * block.
40 *
41 * Returns void
42 *
43 ******************************************************************************/
BNEP_Init(void)44 void BNEP_Init(void) {
45 memset(&bnep_cb, 0, sizeof(tBNEP_CB));
46
47 #if defined(BNEP_INITIAL_TRACE_LEVEL)
48 bnep_cb.trace_level = BNEP_INITIAL_TRACE_LEVEL;
49 #else
50 bnep_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
51 #endif
52 }
53
54 /*******************************************************************************
55 *
56 * Function BNEP_Register
57 *
58 * Description This function is called by the upper layer to register
59 * its callbacks with BNEP
60 *
61 * Parameters: p_reg_info - contains all callback function pointers
62 *
63 *
64 * Returns BNEP_SUCCESS if registered successfully
65 * BNEP_FAILURE if connection state callback is missing
66 *
67 ******************************************************************************/
BNEP_Register(tBNEP_REGISTER * p_reg_info)68 tBNEP_RESULT BNEP_Register(tBNEP_REGISTER* p_reg_info) {
69 /* There should be connection state call back registered */
70 if ((!p_reg_info) || (!(p_reg_info->p_conn_state_cb)))
71 return BNEP_SECURITY_FAIL;
72
73 bnep_cb.p_conn_ind_cb = p_reg_info->p_conn_ind_cb;
74 bnep_cb.p_conn_state_cb = p_reg_info->p_conn_state_cb;
75 bnep_cb.p_data_ind_cb = p_reg_info->p_data_ind_cb;
76 bnep_cb.p_data_buf_cb = p_reg_info->p_data_buf_cb;
77 bnep_cb.p_filter_ind_cb = p_reg_info->p_filter_ind_cb;
78 bnep_cb.p_mfilter_ind_cb = p_reg_info->p_mfilter_ind_cb;
79 bnep_cb.p_tx_data_flow_cb = p_reg_info->p_tx_data_flow_cb;
80
81 if (bnep_register_with_l2cap()) return BNEP_SECURITY_FAIL;
82
83 bnep_cb.profile_registered = true;
84 return BNEP_SUCCESS;
85 }
86
87 /*******************************************************************************
88 *
89 * Function BNEP_Deregister
90 *
91 * Description This function is called by the upper layer to de-register
92 * its callbacks.
93 *
94 * Parameters: void
95 *
96 *
97 * Returns void
98 *
99 ******************************************************************************/
BNEP_Deregister(void)100 void BNEP_Deregister(void) {
101 /* Clear all the call backs registered */
102 bnep_cb.p_conn_ind_cb = NULL;
103 bnep_cb.p_conn_state_cb = NULL;
104 bnep_cb.p_data_ind_cb = NULL;
105 bnep_cb.p_data_buf_cb = NULL;
106 bnep_cb.p_filter_ind_cb = NULL;
107 bnep_cb.p_mfilter_ind_cb = NULL;
108
109 bnep_cb.profile_registered = false;
110 L2CA_Deregister(BT_PSM_BNEP);
111 }
112
113 /*******************************************************************************
114 *
115 * Function BNEP_Connect
116 *
117 * Description This function creates a BNEP connection to a remote
118 * device.
119 *
120 * Parameters: p_rem_addr - BD_ADDR of the peer
121 * src_uuid - source uuid for the connection
122 * dst_uuid - destination uuid for the connection
123 * p_handle - pointer to return the handle for the
124 * connection
125 *
126 * Returns BNEP_SUCCESS if connection started
127 * BNEP_NO_RESOURCES if no resources
128 *
129 ******************************************************************************/
BNEP_Connect(const RawAddress & p_rem_bda,const Uuid & src_uuid,const Uuid & dst_uuid,uint16_t * p_handle,uint32_t mx_chan_id)130 tBNEP_RESULT BNEP_Connect(const RawAddress& p_rem_bda, const Uuid& src_uuid,
131 const Uuid& dst_uuid, uint16_t* p_handle,
132 uint32_t mx_chan_id) {
133 uint16_t cid;
134 tBNEP_CONN* p_bcb = bnepu_find_bcb_by_bd_addr(p_rem_bda);
135
136 VLOG(0) << __func__ << " BDA:" << p_rem_bda;
137
138 if (!bnep_cb.profile_registered) return BNEP_WRONG_STATE;
139
140 if (!p_bcb) {
141 p_bcb = bnepu_allocate_bcb(p_rem_bda);
142 if (p_bcb == NULL) return (BNEP_NO_RESOURCES);
143 } else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
144 return BNEP_WRONG_STATE;
145 else {
146 /* Backup current UUID values to restore if role change fails */
147 p_bcb->prv_src_uuid = p_bcb->src_uuid;
148 p_bcb->prv_dst_uuid = p_bcb->dst_uuid;
149 }
150
151 /* We are the originator of this connection */
152 p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;
153
154 p_bcb->src_uuid = src_uuid;
155 p_bcb->dst_uuid = dst_uuid;
156
157 if (p_bcb->con_state == BNEP_STATE_CONNECTED) {
158 /* Transition to the next appropriate state, waiting for connection confirm.
159 */
160 p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
161
162 BNEP_TRACE_API("BNEP initiating security procedures for src uuid %s",
163 p_bcb->src_uuid.ToString().c_str());
164
165 bnep_sec_check_complete(&p_bcb->rem_bda, BT_TRANSPORT_BR_EDR, p_bcb);
166 } else {
167 /* Transition to the next appropriate state, waiting for connection confirm.
168 */
169 p_bcb->con_state = BNEP_STATE_CONN_START;
170
171 cid = L2CA_ConnectReq2(BT_PSM_BNEP, p_bcb->rem_bda,
172 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
173 if (cid != 0) {
174 p_bcb->l2cap_cid = cid;
175
176 } else {
177 BNEP_TRACE_ERROR("BNEP - Originate failed");
178 if (bnep_cb.p_conn_state_cb)
179 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda,
180 BNEP_CONN_FAILED, false);
181 bnepu_release_bcb(p_bcb);
182 return BNEP_CONN_FAILED;
183 }
184
185 /* Start timer waiting for connect */
186 alarm_set_on_mloop(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS,
187 bnep_conn_timer_timeout, p_bcb);
188 }
189
190 *p_handle = p_bcb->handle;
191 return (BNEP_SUCCESS);
192 }
193
194 /*******************************************************************************
195 *
196 * Function BNEP_ConnectResp
197 *
198 * Description This function is called in responce to connection indication
199 *
200 *
201 * Parameters: handle - handle given in the connection indication
202 * resp - responce for the connection indication
203 *
204 * Returns BNEP_SUCCESS if connection started
205 * BNEP_WRONG_HANDLE if the connection is not found
206 * BNEP_WRONG_STATE if the responce is not expected
207 *
208 ******************************************************************************/
BNEP_ConnectResp(uint16_t handle,tBNEP_RESULT resp)209 tBNEP_RESULT BNEP_ConnectResp(uint16_t handle, tBNEP_RESULT resp) {
210 tBNEP_CONN* p_bcb;
211 uint16_t resp_code = BNEP_SETUP_CONN_OK;
212
213 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
214
215 p_bcb = &(bnep_cb.bcb[handle - 1]);
216
217 if (p_bcb->con_state != BNEP_STATE_CONN_SETUP ||
218 (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)))
219 return (BNEP_WRONG_STATE);
220
221 BNEP_TRACE_API("BNEP_ConnectResp() for handle %d, responce %d", handle,
222 resp);
223
224 /* Form appropriate responce based on profile responce */
225 if (resp == BNEP_CONN_FAILED_SRC_UUID)
226 resp_code = BNEP_SETUP_INVALID_SRC_UUID;
227 else if (resp == BNEP_CONN_FAILED_DST_UUID)
228 resp_code = BNEP_SETUP_INVALID_DEST_UUID;
229 else if (resp == BNEP_CONN_FAILED_UUID_SIZE)
230 resp_code = BNEP_SETUP_INVALID_UUID_SIZE;
231 else if (resp == BNEP_SUCCESS)
232 resp_code = BNEP_SETUP_CONN_OK;
233 else
234 resp_code = BNEP_SETUP_CONN_NOT_ALLOWED;
235
236 bnep_send_conn_responce(p_bcb, resp_code);
237 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
238
239 if (resp == BNEP_SUCCESS)
240 bnep_connected(p_bcb);
241 else if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
242 /* Restore the original parameters */
243 p_bcb->con_state = BNEP_STATE_CONNECTED;
244 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
245
246 p_bcb->src_uuid = p_bcb->prv_src_uuid;
247 p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
248 }
249
250 /* Process remaining part of the setup message (extension headers) */
251 if (p_bcb->p_pending_data) {
252 uint8_t extension_present = true, *p, ext_type;
253 uint16_t rem_len;
254
255 rem_len = p_bcb->p_pending_data->len;
256 p = (uint8_t*)(p_bcb->p_pending_data + 1) + p_bcb->p_pending_data->offset;
257 while (extension_present && p && rem_len) {
258 ext_type = *p++;
259 extension_present = ext_type >> 7;
260 ext_type &= 0x7F;
261
262 /* if unknown extension present stop processing */
263 if (ext_type) break;
264
265 p = bnep_process_control_packet(p_bcb, p, &rem_len, true);
266 }
267
268 osi_free_and_reset((void**)&p_bcb->p_pending_data);
269 }
270 return (BNEP_SUCCESS);
271 }
272
273 /*******************************************************************************
274 *
275 * Function BNEP_Disconnect
276 *
277 * Description This function is called to close the specified connection.
278 *
279 * Parameters: handle - handle of the connection
280 *
281 * Returns BNEP_SUCCESS if connection is disconnected
282 * BNEP_WRONG_HANDLE if no connection is not found
283 *
284 ******************************************************************************/
BNEP_Disconnect(uint16_t handle)285 tBNEP_RESULT BNEP_Disconnect(uint16_t handle) {
286 tBNEP_CONN* p_bcb;
287
288 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
289
290 p_bcb = &(bnep_cb.bcb[handle - 1]);
291
292 if (p_bcb->con_state == BNEP_STATE_IDLE) return (BNEP_WRONG_HANDLE);
293
294 BNEP_TRACE_API("BNEP_Disconnect() for handle %d", handle);
295
296 L2CA_DisconnectReq(p_bcb->l2cap_cid);
297
298 bnepu_release_bcb(p_bcb);
299
300 return (BNEP_SUCCESS);
301 }
302
303 /*******************************************************************************
304 *
305 * Function BNEP_WriteBuf
306 *
307 * Description This function sends data in a GKI buffer on BNEP connection
308 *
309 * Parameters: handle - handle of the connection to write
310 * p_dest_addr - BD_ADDR/Ethernet addr of the destination
311 * p_buf - pointer to address of buffer with data
312 * protocol - protocol type of the packet
313 * p_src_addr - (optional) BD_ADDR/ethernet address of the
314 * source
315 * (should be NULL if it is local BD Addr)
316 * fw_ext_present - forwarded extensions present
317 *
318 * Returns: BNEP_WRONG_HANDLE - if passed handle is not valid
319 * BNEP_MTU_EXCEDED - If the data length is greater than
320 * the MTU
321 * BNEP_IGNORE_CMD - If the packet is filtered out
322 * BNEP_Q_SIZE_EXCEEDED - If the Tx Q is full
323 * BNEP_SUCCESS - If written successfully
324 *
325 ******************************************************************************/
BNEP_WriteBuf(uint16_t handle,const RawAddress & p_dest_addr,BT_HDR * p_buf,uint16_t protocol,const RawAddress * p_src_addr,bool fw_ext_present)326 tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, const RawAddress& p_dest_addr,
327 BT_HDR* p_buf, uint16_t protocol,
328 const RawAddress* p_src_addr, bool fw_ext_present) {
329 tBNEP_CONN* p_bcb;
330 uint8_t* p_data;
331
332 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) {
333 osi_free(p_buf);
334 return (BNEP_WRONG_HANDLE);
335 }
336
337 p_bcb = &(bnep_cb.bcb[handle - 1]);
338 /* Check MTU size */
339 if (p_buf->len > BNEP_MTU_SIZE) {
340 BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, p_buf->len,
341 BNEP_MTU_SIZE);
342 osi_free(p_buf);
343 return (BNEP_MTU_EXCEDED);
344 }
345
346 /* Check if the packet should be filtered out */
347 p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
348 if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
349 p_data, p_buf->len) != BNEP_SUCCESS) {
350 /*
351 ** If packet is filtered and ext headers are present
352 ** drop the data and forward the ext headers
353 */
354 if (fw_ext_present) {
355 uint8_t ext, length;
356 uint16_t org_len, new_len;
357 /* parse the extension headers and findout the new packet len */
358 org_len = p_buf->len;
359 new_len = 0;
360 do {
361 if ((new_len + 2) > org_len) {
362 osi_free(p_buf);
363 return BNEP_IGNORE_CMD;
364 }
365
366 ext = *p_data++;
367 length = *p_data++;
368 p_data += length;
369
370 new_len += (length + 2);
371
372 if (new_len > org_len) {
373 osi_free(p_buf);
374 return BNEP_IGNORE_CMD;
375 }
376
377 } while (ext & 0x80);
378
379 if (protocol != BNEP_802_1_P_PROTOCOL)
380 protocol = 0;
381 else {
382 new_len += 4;
383 if (new_len > org_len) return BNEP_IGNORE_CMD;
384 p_data[2] = 0;
385 p_data[3] = 0;
386 }
387 p_buf->len = new_len;
388 } else {
389 osi_free(p_buf);
390 return BNEP_IGNORE_CMD;
391 }
392 }
393
394 /* Check transmit queue */
395 if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH) {
396 osi_free(p_buf);
397 return (BNEP_Q_SIZE_EXCEEDED);
398 }
399
400 /* Build the BNEP header */
401 bnepu_build_bnep_hdr(p_bcb, p_buf, protocol, p_src_addr, &p_dest_addr,
402 fw_ext_present);
403
404 /* Send the data or queue it up */
405 bnepu_check_send_packet(p_bcb, p_buf);
406
407 return (BNEP_SUCCESS);
408 }
409
410 /*******************************************************************************
411 *
412 * Function BNEP_Write
413 *
414 * Description This function sends data over a BNEP connection
415 *
416 * Parameters: handle - handle of the connection to write
417 * p_dest_addr - BD_ADDR/Ethernet addr of the destination
418 * p_data - pointer to data start
419 * protocol - protocol type of the packet
420 * p_src_addr - (optional) BD_ADDR/ethernet address of the
421 * source
422 * (should be NULL if it is local BD Addr)
423 * fw_ext_present - forwarded extensions present
424 *
425 * Returns: BNEP_WRONG_HANDLE - if passed handle is not valid
426 * BNEP_MTU_EXCEDED - If the data length is greater than
427 * the MTU
428 * BNEP_IGNORE_CMD - If the packet is filtered out
429 * BNEP_Q_SIZE_EXCEEDED - If the Tx Q is full
430 * BNEP_NO_RESOURCES - If not able to allocate a buffer
431 * BNEP_SUCCESS - If written successfully
432 *
433 ******************************************************************************/
BNEP_Write(uint16_t handle,const RawAddress & p_dest_addr,uint8_t * p_data,uint16_t len,uint16_t protocol,const RawAddress * p_src_addr,bool fw_ext_present)434 tBNEP_RESULT BNEP_Write(uint16_t handle, const RawAddress& p_dest_addr,
435 uint8_t* p_data, uint16_t len, uint16_t protocol,
436 const RawAddress* p_src_addr, bool fw_ext_present) {
437 tBNEP_CONN* p_bcb;
438 uint8_t* p;
439
440 /* Check MTU size. Consider the possibility of having extension headers */
441 if (len > BNEP_MTU_SIZE) {
442 BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, len,
443 BNEP_MTU_SIZE);
444 return (BNEP_MTU_EXCEDED);
445 }
446
447 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
448
449 p_bcb = &(bnep_cb.bcb[handle - 1]);
450
451 /* Check if the packet should be filtered out */
452 if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
453 p_data, len) != BNEP_SUCCESS) {
454 /*
455 ** If packet is filtered and ext headers are present
456 ** drop the data and forward the ext headers
457 */
458 if (fw_ext_present) {
459 uint8_t ext, length;
460 uint16_t org_len, new_len;
461 /* parse the extension headers and findout the new packet len */
462 org_len = len;
463 new_len = 0;
464 p = p_data;
465 do {
466 if ((new_len + 2) > org_len) {
467 return BNEP_IGNORE_CMD;
468 }
469
470 ext = *p_data++;
471 length = *p_data++;
472 p_data += length;
473
474 new_len += (length + 2);
475
476 if (new_len > org_len) return BNEP_IGNORE_CMD;
477
478 } while (ext & 0x80);
479
480 if (protocol != BNEP_802_1_P_PROTOCOL)
481 protocol = 0;
482 else {
483 new_len += 4;
484 if (new_len > org_len) return BNEP_IGNORE_CMD;
485 p_data[2] = 0;
486 p_data[3] = 0;
487 }
488 len = new_len;
489 p_data = p;
490 } else
491 return BNEP_IGNORE_CMD;
492 }
493
494 /* Check transmit queue */
495 if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
496 return (BNEP_Q_SIZE_EXCEEDED);
497
498 /* Get a buffer to copy the data into */
499 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
500
501 p_buf->len = len;
502 p_buf->offset = BNEP_MINIMUM_OFFSET;
503 p = (uint8_t*)(p_buf + 1) + BNEP_MINIMUM_OFFSET;
504
505 memcpy(p, p_data, len);
506
507 /* Build the BNEP header */
508 bnepu_build_bnep_hdr(p_bcb, p_buf, protocol, p_src_addr, &p_dest_addr,
509 fw_ext_present);
510
511 /* Send the data or queue it up */
512 bnepu_check_send_packet(p_bcb, p_buf);
513
514 return (BNEP_SUCCESS);
515 }
516
517 /*******************************************************************************
518 *
519 * Function BNEP_SetProtocolFilters
520 *
521 * Description This function sets the protocol filters on peer device
522 *
523 * Parameters: handle - Handle for the connection
524 * num_filters - total number of filter ranges
525 * p_start_array - Array of beginings of all protocol ranges
526 * p_end_array - Array of ends of all protocol ranges
527 *
528 * Returns BNEP_WRONG_HANDLE - if the connection handle is
529 * not valid
530 * BNEP_SET_FILTER_FAIL - if the connection is in wrong
531 * state
532 * BNEP_TOO_MANY_FILTERS - if too many filters
533 * BNEP_SUCCESS - if request sent successfully
534 *
535 ******************************************************************************/
BNEP_SetProtocolFilters(uint16_t handle,uint16_t num_filters,uint16_t * p_start_array,uint16_t * p_end_array)536 tBNEP_RESULT BNEP_SetProtocolFilters(uint16_t handle, uint16_t num_filters,
537 uint16_t* p_start_array,
538 uint16_t* p_end_array) {
539 uint16_t xx;
540 tBNEP_CONN* p_bcb;
541
542 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
543
544 p_bcb = &(bnep_cb.bcb[handle - 1]);
545
546 /* Check the connection state */
547 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
548 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
549 return (BNEP_WRONG_STATE);
550
551 /* Validate the parameters */
552 if (num_filters && (!p_start_array || !p_end_array))
553 return (BNEP_SET_FILTER_FAIL);
554
555 if (num_filters > BNEP_MAX_PROT_FILTERS) return (BNEP_TOO_MANY_FILTERS);
556
557 /* Fill the filter values in connnection block */
558 for (xx = 0; xx < num_filters; xx++) {
559 p_bcb->sent_prot_filter_start[xx] = *p_start_array++;
560 p_bcb->sent_prot_filter_end[xx] = *p_end_array++;
561 }
562
563 p_bcb->sent_num_filters = num_filters;
564
565 bnepu_send_peer_our_filters(p_bcb);
566
567 return (BNEP_SUCCESS);
568 }
569
570 /*******************************************************************************
571 *
572 * Function BNEP_SetMulticastFilters
573 *
574 * Description This function sets the filters for multicast addresses for
575 * BNEP.
576 *
577 * Parameters: handle - Handle for the connection
578 * num_filters - total number of filter ranges
579 * p_start_array - Pointer to sequence of beginings of all
580 * multicast address ranges
581 * p_end_array - Pointer to sequence of ends of all
582 * multicast address ranges
583 *
584 * Returns BNEP_WRONG_HANDLE - if the connection handle is
585 * not valid
586 * BNEP_SET_FILTER_FAIL - if the connection is in wrong
587 * state
588 * BNEP_TOO_MANY_FILTERS - if too many filters
589 * BNEP_SUCCESS - if request sent successfully
590 *
591 ******************************************************************************/
BNEP_SetMulticastFilters(uint16_t handle,uint16_t num_filters,uint8_t * p_start_array,uint8_t * p_end_array)592 tBNEP_RESULT BNEP_SetMulticastFilters(uint16_t handle, uint16_t num_filters,
593 uint8_t* p_start_array,
594 uint8_t* p_end_array) {
595 uint16_t xx;
596 tBNEP_CONN* p_bcb;
597
598 if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
599
600 p_bcb = &(bnep_cb.bcb[handle - 1]);
601
602 /* Check the connection state */
603 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
604 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
605 return (BNEP_WRONG_STATE);
606
607 /* Validate the parameters */
608 if (num_filters && (!p_start_array || !p_end_array))
609 return (BNEP_SET_FILTER_FAIL);
610
611 if (num_filters > BNEP_MAX_MULTI_FILTERS) return (BNEP_TOO_MANY_FILTERS);
612
613 /* Fill the multicast filter values in connnection block */
614 for (xx = 0; xx < num_filters; xx++) {
615 memcpy(p_bcb->sent_mcast_filter_start[xx].address, p_start_array,
616 BD_ADDR_LEN);
617 memcpy(p_bcb->sent_mcast_filter_end[xx].address, p_end_array, BD_ADDR_LEN);
618
619 p_start_array += BD_ADDR_LEN;
620 p_end_array += BD_ADDR_LEN;
621 }
622
623 p_bcb->sent_mcast_filters = num_filters;
624
625 bnepu_send_peer_our_multi_filters(p_bcb);
626
627 return (BNEP_SUCCESS);
628 }
629
630 /*******************************************************************************
631 *
632 * Function BNEP_SetTraceLevel
633 *
634 * Description This function sets the trace level for BNEP. If called with
635 * a value of 0xFF, it simply reads the current trace level.
636 *
637 * Returns the new (current) trace level
638 *
639 ******************************************************************************/
BNEP_SetTraceLevel(uint8_t new_level)640 uint8_t BNEP_SetTraceLevel(uint8_t new_level) {
641 if (new_level != 0xFF) bnep_cb.trace_level = new_level;
642
643 return (bnep_cb.trace_level);
644 }
645
646