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