1/******************************************************************************
2 *
3 *  Copyright (C) 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
29extern fixed_queue_t* btu_general_alarm_queue;
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 ******************************************************************************/
42void 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 ******************************************************************************/
66tBNEP_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 ******************************************************************************/
98void 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 ******************************************************************************/
128tBNEP_RESULT BNEP_Connect(BD_ADDR p_rem_bda, tBT_UUID* src_uuid,
129                          tBT_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  BNEP_TRACE_API("BNEP_Connect()  BDA: %02x-%02x-%02x-%02x-%02x-%02x",
134                 p_rem_bda[0], p_rem_bda[1], p_rem_bda[2], p_rem_bda[3],
135                 p_rem_bda[4], p_rem_bda[5]);
136
137  if (!bnep_cb.profile_registered) return BNEP_WRONG_STATE;
138
139  /* Both source and destination UUID lengths should be same */
140  if (src_uuid->len != dst_uuid->len) return BNEP_CONN_FAILED_UUID_SIZE;
141
142  if (!p_bcb) {
143    p_bcb = bnepu_allocate_bcb(p_rem_bda);
144    if (p_bcb == NULL) return (BNEP_NO_RESOURCES);
145  } else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
146    return BNEP_WRONG_STATE;
147  else {
148    /* Backup current UUID values to restore if role change fails */
149    memcpy((uint8_t*)&(p_bcb->prv_src_uuid), (uint8_t*)&(p_bcb->src_uuid),
150           sizeof(tBT_UUID));
151    memcpy((uint8_t*)&(p_bcb->prv_dst_uuid), (uint8_t*)&(p_bcb->dst_uuid),
152           sizeof(tBT_UUID));
153  }
154
155  /* We are the originator of this connection */
156  p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;
157
158  memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)src_uuid, sizeof(tBT_UUID));
159  memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)dst_uuid, sizeof(tBT_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    BNEP_TRACE_API("BNEP initiating security procedures for src uuid 0x%x",
167                   p_bcb->src_uuid.uu.uuid16);
168
169#if (BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE)
170    btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, true,
171                              BTM_SEC_PROTO_BNEP, bnep_get_uuid32(src_uuid),
172                              &bnep_sec_check_complete, p_bcb);
173#else
174    bnep_sec_check_complete(p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
175#endif
176
177  } else {
178    /* Transition to the next appropriate state, waiting for connection confirm.
179     */
180    p_bcb->con_state = BNEP_STATE_CONN_START;
181
182    cid = L2CA_ConnectReq(BT_PSM_BNEP, p_bcb->rem_bda);
183    if (cid != 0) {
184      p_bcb->l2cap_cid = cid;
185
186    } else {
187      BNEP_TRACE_ERROR("BNEP - Originate failed");
188      if (bnep_cb.p_conn_state_cb)
189        (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda,
190                                   BNEP_CONN_FAILED, false);
191      bnepu_release_bcb(p_bcb);
192      return BNEP_CONN_FAILED;
193    }
194
195    /* Start timer waiting for connect */
196    alarm_set_on_queue(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS,
197                       bnep_conn_timer_timeout, p_bcb, btu_general_alarm_queue);
198  }
199
200  *p_handle = p_bcb->handle;
201  return (BNEP_SUCCESS);
202}
203
204/*******************************************************************************
205 *
206 * Function         BNEP_ConnectResp
207 *
208 * Description      This function is called in responce to connection indication
209 *
210 *
211 * Parameters:      handle  - handle given in the connection indication
212 *                  resp    - responce for the connection indication
213 *
214 * Returns          BNEP_SUCCESS                if connection started
215 *                  BNEP_WRONG_HANDLE           if the connection is not found
216 *                  BNEP_WRONG_STATE            if the responce is not expected
217 *
218 ******************************************************************************/
219tBNEP_RESULT BNEP_ConnectResp(uint16_t handle, tBNEP_RESULT resp) {
220  tBNEP_CONN* p_bcb;
221  uint16_t resp_code = BNEP_SETUP_CONN_OK;
222
223  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
224
225  p_bcb = &(bnep_cb.bcb[handle - 1]);
226
227  if (p_bcb->con_state != BNEP_STATE_CONN_SETUP ||
228      (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)))
229    return (BNEP_WRONG_STATE);
230
231  BNEP_TRACE_API("BNEP_ConnectResp()  for handle %d, responce %d", handle,
232                 resp);
233
234  /* Form appropriate responce based on profile responce */
235  if (resp == BNEP_CONN_FAILED_SRC_UUID)
236    resp_code = BNEP_SETUP_INVALID_SRC_UUID;
237  else if (resp == BNEP_CONN_FAILED_DST_UUID)
238    resp_code = BNEP_SETUP_INVALID_DEST_UUID;
239  else if (resp == BNEP_CONN_FAILED_UUID_SIZE)
240    resp_code = BNEP_SETUP_INVALID_UUID_SIZE;
241  else if (resp == BNEP_SUCCESS)
242    resp_code = BNEP_SETUP_CONN_OK;
243  else
244    resp_code = BNEP_SETUP_CONN_NOT_ALLOWED;
245
246  bnep_send_conn_responce(p_bcb, resp_code);
247  p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
248
249  if (resp == BNEP_SUCCESS)
250    bnep_connected(p_bcb);
251  else if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
252    /* Restore the original parameters */
253    p_bcb->con_state = BNEP_STATE_CONNECTED;
254    p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
255
256    memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)&(p_bcb->prv_src_uuid),
257           sizeof(tBT_UUID));
258    memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)&(p_bcb->prv_dst_uuid),
259           sizeof(tBT_UUID));
260  }
261
262  /* Process remaining part of the setup message (extension headers) */
263  if (p_bcb->p_pending_data) {
264    uint8_t extension_present = true, *p, ext_type;
265    uint16_t rem_len;
266
267    rem_len = p_bcb->p_pending_data->len;
268    p = (uint8_t*)(p_bcb->p_pending_data + 1) + p_bcb->p_pending_data->offset;
269    while (extension_present && p && rem_len) {
270      ext_type = *p++;
271      extension_present = ext_type >> 7;
272      ext_type &= 0x7F;
273
274      /* if unknown extension present stop processing */
275      if (ext_type) break;
276
277      p = bnep_process_control_packet(p_bcb, p, &rem_len, true);
278    }
279
280    osi_free_and_reset((void**)&p_bcb->p_pending_data);
281  }
282  return (BNEP_SUCCESS);
283}
284
285/*******************************************************************************
286 *
287 * Function         BNEP_Disconnect
288 *
289 * Description      This function is called to close the specified connection.
290 *
291 * Parameters:      handle   - handle of the connection
292 *
293 * Returns          BNEP_SUCCESS                if connection is disconnected
294 *                  BNEP_WRONG_HANDLE           if no connection is not found
295 *
296 ******************************************************************************/
297tBNEP_RESULT BNEP_Disconnect(uint16_t handle) {
298  tBNEP_CONN* p_bcb;
299
300  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
301
302  p_bcb = &(bnep_cb.bcb[handle - 1]);
303
304  if (p_bcb->con_state == BNEP_STATE_IDLE) return (BNEP_WRONG_HANDLE);
305
306  BNEP_TRACE_API("BNEP_Disconnect()  for handle %d", handle);
307
308  L2CA_DisconnectReq(p_bcb->l2cap_cid);
309
310  bnepu_release_bcb(p_bcb);
311
312  return (BNEP_SUCCESS);
313}
314
315/*******************************************************************************
316 *
317 * Function         BNEP_WriteBuf
318 *
319 * Description      This function sends data in a GKI buffer on BNEP connection
320 *
321 * Parameters:      handle       - handle of the connection to write
322 *                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
323 *                  p_buf        - pointer to address of buffer with data
324 *                  protocol     - protocol type of the packet
325 *                  p_src_addr   - (optional) BD_ADDR/ethernet address of the
326 *                                 source
327 *                                 (should be NULL if it is local BD Addr)
328 *                  fw_ext_present - forwarded extensions present
329 *
330 * Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
331 *                  BNEP_MTU_EXCEDED        - If the data length is greater than
332 *                                            the MTU
333 *                  BNEP_IGNORE_CMD         - If the packet is filtered out
334 *                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
335 *                  BNEP_SUCCESS            - If written successfully
336 *
337 ******************************************************************************/
338tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, uint8_t* p_dest_addr, BT_HDR* p_buf,
339                           uint16_t protocol, uint8_t* p_src_addr,
340                           bool fw_ext_present) {
341  tBNEP_CONN* p_bcb;
342  uint8_t* p_data;
343
344  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) {
345    osi_free(p_buf);
346    return (BNEP_WRONG_HANDLE);
347  }
348
349  p_bcb = &(bnep_cb.bcb[handle - 1]);
350  /* Check MTU size */
351  if (p_buf->len > BNEP_MTU_SIZE) {
352    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", p_buf->len,
353                     BNEP_MTU_SIZE);
354    osi_free(p_buf);
355    return (BNEP_MTU_EXCEDED);
356  }
357
358  /* Check if the packet should be filtered out */
359  p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
360  if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
361                             p_data) != BNEP_SUCCESS) {
362    /*
363    ** If packet is filtered and ext headers are present
364    ** drop the data and forward the ext headers
365    */
366    if (fw_ext_present) {
367      uint8_t ext, length;
368      uint16_t org_len, new_len;
369      /* parse the extension headers and findout the new packet len */
370      org_len = p_buf->len;
371      new_len = 0;
372      do {
373        ext = *p_data++;
374        length = *p_data++;
375        p_data += length;
376
377        new_len += (length + 2);
378
379        if (new_len > org_len) {
380          osi_free(p_buf);
381          return BNEP_IGNORE_CMD;
382        }
383
384      } while (ext & 0x80);
385
386      if (protocol != BNEP_802_1_P_PROTOCOL)
387        protocol = 0;
388      else {
389        new_len += 4;
390        p_data[2] = 0;
391        p_data[3] = 0;
392      }
393      p_buf->len = new_len;
394    } else {
395      osi_free(p_buf);
396      return BNEP_IGNORE_CMD;
397    }
398  }
399
400  /* Check transmit queue */
401  if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH) {
402    osi_free(p_buf);
403    return (BNEP_Q_SIZE_EXCEEDED);
404  }
405
406  /* Build the BNEP header */
407  bnepu_build_bnep_hdr(p_bcb, p_buf, protocol, p_src_addr, p_dest_addr,
408                       fw_ext_present);
409
410  /* Send the data or queue it up */
411  bnepu_check_send_packet(p_bcb, p_buf);
412
413  return (BNEP_SUCCESS);
414}
415
416/*******************************************************************************
417 *
418 * Function         BNEP_Write
419 *
420 * Description      This function sends data over a BNEP connection
421 *
422 * Parameters:      handle       - handle of the connection to write
423 *                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
424 *                  p_data       - pointer to data start
425 *                  protocol     - protocol type of the packet
426 *                  p_src_addr   - (optional) BD_ADDR/ethernet address of the
427 *                                 source
428 *                                 (should be NULL if it is local BD Addr)
429 *                  fw_ext_present - forwarded extensions present
430 *
431 * Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
432 *                  BNEP_MTU_EXCEDED        - If the data length is greater than
433 *                                            the MTU
434 *                  BNEP_IGNORE_CMD         - If the packet is filtered out
435 *                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
436 *                  BNEP_NO_RESOURCES       - If not able to allocate a buffer
437 *                  BNEP_SUCCESS            - If written successfully
438 *
439 ******************************************************************************/
440tBNEP_RESULT BNEP_Write(uint16_t handle, uint8_t* p_dest_addr, uint8_t* p_data,
441                        uint16_t len, uint16_t protocol, uint8_t* p_src_addr,
442                        bool fw_ext_present) {
443  tBNEP_CONN* p_bcb;
444  uint8_t* p;
445
446  /* Check MTU size. Consider the possibility of having extension headers */
447  if (len > BNEP_MTU_SIZE) {
448    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", len,
449                     BNEP_MTU_SIZE);
450    return (BNEP_MTU_EXCEDED);
451  }
452
453  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
454
455  p_bcb = &(bnep_cb.bcb[handle - 1]);
456
457  /* Check if the packet should be filtered out */
458  if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
459                             p_data) != BNEP_SUCCESS) {
460    /*
461    ** If packet is filtered and ext headers are present
462    ** drop the data and forward the ext headers
463    */
464    if (fw_ext_present) {
465      uint8_t ext, length;
466      uint16_t org_len, new_len;
467      /* parse the extension headers and findout the new packet len */
468      org_len = len;
469      new_len = 0;
470      p = p_data;
471      do {
472        ext = *p_data++;
473        length = *p_data++;
474        p_data += length;
475
476        new_len += (length + 2);
477
478        if (new_len > org_len) return BNEP_IGNORE_CMD;
479
480      } while (ext & 0x80);
481
482      if (protocol != BNEP_802_1_P_PROTOCOL)
483        protocol = 0;
484      else {
485        new_len += 4;
486        p_data[2] = 0;
487        p_data[3] = 0;
488      }
489      len = new_len;
490      p_data = p;
491    } else
492      return BNEP_IGNORE_CMD;
493  }
494
495  /* Check transmit queue */
496  if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
497    return (BNEP_Q_SIZE_EXCEEDED);
498
499  /* Get a buffer to copy the data into */
500  BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
501
502  p_buf->len = len;
503  p_buf->offset = BNEP_MINIMUM_OFFSET;
504  p = (uint8_t*)(p_buf + 1) + BNEP_MINIMUM_OFFSET;
505
506  memcpy(p, p_data, len);
507
508  /* Build the BNEP header */
509  bnepu_build_bnep_hdr(p_bcb, p_buf, protocol, p_src_addr, p_dest_addr,
510                       fw_ext_present);
511
512  /* Send the data or queue it up */
513  bnepu_check_send_packet(p_bcb, p_buf);
514
515  return (BNEP_SUCCESS);
516}
517
518/*******************************************************************************
519 *
520 * Function         BNEP_SetProtocolFilters
521 *
522 * Description      This function sets the protocol filters on peer device
523 *
524 * Parameters:      handle        - Handle for the connection
525 *                  num_filters   - total number of filter ranges
526 *                  p_start_array - Array of beginings of all protocol ranges
527 *                  p_end_array   - Array of ends of all protocol ranges
528 *
529 * Returns          BNEP_WRONG_HANDLE           - if the connection handle is
530 *                                                not valid
531 *                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong
532 *                                                state
533 *                  BNEP_TOO_MANY_FILTERS       - if too many filters
534 *                  BNEP_SUCCESS                - if request sent successfully
535 *
536 ******************************************************************************/
537tBNEP_RESULT BNEP_SetProtocolFilters(uint16_t handle, uint16_t num_filters,
538                                     uint16_t* p_start_array,
539                                     uint16_t* p_end_array) {
540  uint16_t xx;
541  tBNEP_CONN* p_bcb;
542
543  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
544
545  p_bcb = &(bnep_cb.bcb[handle - 1]);
546
547  /* Check the connection state */
548  if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
549      (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
550    return (BNEP_WRONG_STATE);
551
552  /* Validate the parameters */
553  if (num_filters && (!p_start_array || !p_end_array))
554    return (BNEP_SET_FILTER_FAIL);
555
556  if (num_filters > BNEP_MAX_PROT_FILTERS) return (BNEP_TOO_MANY_FILTERS);
557
558  /* Fill the filter values in connnection block */
559  for (xx = 0; xx < num_filters; xx++) {
560    p_bcb->sent_prot_filter_start[xx] = *p_start_array++;
561    p_bcb->sent_prot_filter_end[xx] = *p_end_array++;
562  }
563
564  p_bcb->sent_num_filters = num_filters;
565
566  bnepu_send_peer_our_filters(p_bcb);
567
568  return (BNEP_SUCCESS);
569}
570
571/*******************************************************************************
572 *
573 * Function         BNEP_SetMulticastFilters
574 *
575 * Description      This function sets the filters for multicast addresses for
576 *                  BNEP.
577 *
578 * Parameters:      handle        - Handle for the connection
579 *                  num_filters   - total number of filter ranges
580 *                  p_start_array - Pointer to sequence of beginings of all
581 *                                         multicast address ranges
582 *                  p_end_array   - Pointer to sequence of ends of all
583 *                                         multicast address ranges
584 *
585 * Returns          BNEP_WRONG_HANDLE           - if the connection handle is
586 *                                                not valid
587 *                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong
588 *                                                state
589 *                  BNEP_TOO_MANY_FILTERS       - if too many filters
590 *                  BNEP_SUCCESS                - if request sent successfully
591 *
592 ******************************************************************************/
593tBNEP_RESULT BNEP_SetMulticastFilters(uint16_t handle, uint16_t num_filters,
594                                      uint8_t* p_start_array,
595                                      uint8_t* p_end_array) {
596  uint16_t xx;
597  tBNEP_CONN* p_bcb;
598
599  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
600
601  p_bcb = &(bnep_cb.bcb[handle - 1]);
602
603  /* Check the connection state */
604  if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
605      (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
606    return (BNEP_WRONG_STATE);
607
608  /* Validate the parameters */
609  if (num_filters && (!p_start_array || !p_end_array))
610    return (BNEP_SET_FILTER_FAIL);
611
612  if (num_filters > BNEP_MAX_MULTI_FILTERS) return (BNEP_TOO_MANY_FILTERS);
613
614  /* Fill the multicast filter values in connnection block */
615  for (xx = 0; xx < num_filters; xx++) {
616    memcpy(p_bcb->sent_mcast_filter_start[xx], p_start_array, BD_ADDR_LEN);
617    memcpy(p_bcb->sent_mcast_filter_end[xx], 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 ******************************************************************************/
640uint8_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/*******************************************************************************
647 *
648 * Function         BNEP_GetStatus
649 *
650 * Description      This function gets the status information for BNEP
651 *                  connection
652 *
653 * Returns          BNEP_SUCCESS            - if the status is available
654 *                  BNEP_NO_RESOURCES       - if no structure is passed for
655 *                                            output
656 *                  BNEP_WRONG_HANDLE       - if the handle is invalid
657 *                  BNEP_WRONG_STATE        - if not in connected state
658 *
659 ******************************************************************************/
660tBNEP_RESULT BNEP_GetStatus(uint16_t handle, tBNEP_STATUS* p_status) {
661#if (BNEP_SUPPORTS_STATUS_API == TRUE)
662  tBNEP_CONN* p_bcb;
663
664  if (!p_status) return BNEP_NO_RESOURCES;
665
666  if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE);
667
668  p_bcb = &(bnep_cb.bcb[handle - 1]);
669
670  memset(p_status, 0, sizeof(tBNEP_STATUS));
671  if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
672      (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
673    return BNEP_WRONG_STATE;
674
675  /* Read the status parameters from the connection control block */
676  p_status->con_status = BNEP_STATUS_CONNECTED;
677  p_status->l2cap_cid = p_bcb->l2cap_cid;
678  p_status->rem_mtu_size = p_bcb->rem_mtu_size;
679  p_status->xmit_q_depth = fixed_queue_length(p_bcb->xmit_q);
680  p_status->sent_num_filters = p_bcb->sent_num_filters;
681  p_status->sent_mcast_filters = p_bcb->sent_mcast_filters;
682  p_status->rcvd_num_filters = p_bcb->rcvd_num_filters;
683  p_status->rcvd_mcast_filters = p_bcb->rcvd_mcast_filters;
684
685  memcpy(p_status->rem_bda, p_bcb->rem_bda, BD_ADDR_LEN);
686  memcpy(&(p_status->src_uuid), &(p_bcb->src_uuid), sizeof(tBT_UUID));
687  memcpy(&(p_status->dst_uuid), &(p_bcb->dst_uuid), sizeof(tBT_UUID));
688
689  return BNEP_SUCCESS;
690#else
691  return (BNEP_IGNORE_CMD);
692#endif
693}
694