Home | History | Annotate | Download | only in bnep
      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 *******************************************************************************/
     39 void 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 *******************************************************************************/
     68 tBNEP_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 *******************************************************************************/
    104 void 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 *******************************************************************************/
    135 tBNEP_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_API ("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_API ("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_ERROR ("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 *******************************************************************************/
    240 tBNEP_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_API ("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 *******************************************************************************/
    318 tBNEP_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_API ("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 *******************************************************************************/
    361 tBNEP_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_ERROR ("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 *******************************************************************************/
    473 tBNEP_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_ERROR ("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_ERROR ("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 *******************************************************************************/
    584 tBNEP_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 *******************************************************************************/
    647 tBNEP_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 *******************************************************************************/
    704 UINT8 *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 *******************************************************************************/
    722 UINT8 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 *******************************************************************************/
    743 tBNEP_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