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