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