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