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