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 extern fixed_queue_t *btu_general_alarm_queue;
     31 
     32 /*******************************************************************************
     33 **
     34 ** Function         BNEP_Init
     35 **
     36 ** Description      This function initializes the BNEP unit. It should be called
     37 **                  before accessing any other APIs to initialize the control block
     38 **
     39 ** Returns          void
     40 **
     41 *******************************************************************************/
     42 void BNEP_Init (void)
     43 {
     44     memset (&bnep_cb, 0, sizeof (tBNEP_CB));
     45 
     46 #if defined(BNEP_INITIAL_TRACE_LEVEL)
     47     bnep_cb.trace_level = BNEP_INITIAL_TRACE_LEVEL;
     48 #else
     49     bnep_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
     50 #endif
     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     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 *******************************************************************************/
    103 void 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 *******************************************************************************/
    134 tBNEP_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         alarm_set_on_queue(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS,
    212                            bnep_conn_timer_timeout, p_bcb,
    213                            btu_general_alarm_queue);
    214     }
    215 
    216     *p_handle = p_bcb->handle;
    217     return (BNEP_SUCCESS);
    218 }
    219 
    220 
    221 /*******************************************************************************
    222 **
    223 ** Function         BNEP_ConnectResp
    224 **
    225 ** Description      This function is called in responce to connection indication
    226 **
    227 **
    228 ** Parameters:      handle  - handle given in the connection indication
    229 **                  resp    - responce for the connection indication
    230 **
    231 ** Returns          BNEP_SUCCESS                if connection started
    232 **                  BNEP_WRONG_HANDLE           if the connection is not found
    233 **                  BNEP_WRONG_STATE            if the responce is not expected
    234 **
    235 *******************************************************************************/
    236 tBNEP_RESULT BNEP_ConnectResp (UINT16 handle, tBNEP_RESULT resp)
    237 {
    238     tBNEP_CONN      *p_bcb;
    239     UINT16          resp_code = BNEP_SETUP_CONN_OK;
    240 
    241     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    242         return (BNEP_WRONG_HANDLE);
    243 
    244     p_bcb = &(bnep_cb.bcb[handle - 1]);
    245 
    246     if (p_bcb->con_state != BNEP_STATE_CONN_SETUP ||
    247         (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)))
    248         return (BNEP_WRONG_STATE);
    249 
    250     BNEP_TRACE_API ("BNEP_ConnectResp()  for handle %d, responce %d", handle, resp);
    251 
    252     /* Form appropriate responce based on profile responce */
    253     if      (resp == BNEP_CONN_FAILED_SRC_UUID)   resp_code = BNEP_SETUP_INVALID_SRC_UUID;
    254     else if (resp == BNEP_CONN_FAILED_DST_UUID)   resp_code = BNEP_SETUP_INVALID_DEST_UUID;
    255     else if (resp == BNEP_CONN_FAILED_UUID_SIZE)  resp_code = BNEP_SETUP_INVALID_UUID_SIZE;
    256     else if (resp == BNEP_SUCCESS)                resp_code = BNEP_SETUP_CONN_OK;
    257     else                                          resp_code = BNEP_SETUP_CONN_NOT_ALLOWED;
    258 
    259     bnep_send_conn_responce (p_bcb, resp_code);
    260     p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
    261 
    262     if (resp == BNEP_SUCCESS)
    263         bnep_connected (p_bcb);
    264     else if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
    265     {
    266         /* Restore the original parameters */
    267         p_bcb->con_state = BNEP_STATE_CONNECTED;
    268         p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
    269 
    270         memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)&(p_bcb->prv_src_uuid), sizeof (tBT_UUID));
    271         memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)&(p_bcb->prv_dst_uuid), sizeof (tBT_UUID));
    272     }
    273 
    274     /* Process remaining part of the setup message (extension headers) */
    275     if (p_bcb->p_pending_data)
    276     {
    277         UINT8   extension_present = TRUE, *p, ext_type;
    278         UINT16  rem_len;
    279 
    280         rem_len = p_bcb->p_pending_data->len;
    281         p       = (UINT8 *)(p_bcb->p_pending_data + 1) + p_bcb->p_pending_data->offset;
    282         while (extension_present && p && rem_len)
    283         {
    284             ext_type = *p++;
    285             extension_present = ext_type >> 7;
    286             ext_type &= 0x7F;
    287 
    288             /* if unknown extension present stop processing */
    289             if (ext_type)
    290                 break;
    291 
    292             p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
    293         }
    294 
    295         osi_free_and_reset((void **)&p_bcb->p_pending_data);
    296     }
    297     return (BNEP_SUCCESS);
    298 }
    299 
    300 
    301 /*******************************************************************************
    302 **
    303 ** Function         BNEP_Disconnect
    304 **
    305 ** Description      This function is called to close the specified connection.
    306 **
    307 ** Parameters:      handle   - handle of the connection
    308 **
    309 ** Returns          BNEP_SUCCESS                if connection is disconnected
    310 **                  BNEP_WRONG_HANDLE           if no connection is not found
    311 **
    312 *******************************************************************************/
    313 tBNEP_RESULT BNEP_Disconnect (UINT16 handle)
    314 {
    315     tBNEP_CONN      *p_bcb;
    316 
    317     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    318         return (BNEP_WRONG_HANDLE);
    319 
    320     p_bcb = &(bnep_cb.bcb[handle - 1]);
    321 
    322     if (p_bcb->con_state == BNEP_STATE_IDLE)
    323         return (BNEP_WRONG_HANDLE);
    324 
    325     BNEP_TRACE_API ("BNEP_Disconnect()  for handle %d", handle);
    326 
    327     L2CA_DisconnectReq (p_bcb->l2cap_cid);
    328 
    329     bnepu_release_bcb (p_bcb);
    330 
    331     return (BNEP_SUCCESS);
    332 }
    333 
    334 
    335 /*******************************************************************************
    336 **
    337 ** Function         BNEP_WriteBuf
    338 **
    339 ** Description      This function sends data in a GKI buffer on BNEP connection
    340 **
    341 ** Parameters:      handle       - handle of the connection to write
    342 **                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
    343 **                  p_buf        - pointer to address of buffer with data
    344 **                  protocol     - protocol type of the packet
    345 **                  p_src_addr   - (optional) BD_ADDR/ethernet address of the source
    346 **                                 (should be NULL if it is local BD Addr)
    347 **                  fw_ext_present - forwarded extensions present
    348 **
    349 ** Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
    350 **                  BNEP_MTU_EXCEDED        - If the data length is greater than MTU
    351 **                  BNEP_IGNORE_CMD         - If the packet is filtered out
    352 **                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
    353 **                  BNEP_SUCCESS            - If written successfully
    354 **
    355 *******************************************************************************/
    356 tBNEP_RESULT BNEP_WriteBuf (UINT16 handle,
    357                             UINT8 *p_dest_addr,
    358                             BT_HDR *p_buf,
    359                             UINT16 protocol,
    360                             UINT8 *p_src_addr,
    361                             BOOLEAN fw_ext_present)
    362 {
    363     tBNEP_CONN      *p_bcb;
    364     UINT8           *p_data;
    365 
    366     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    367     {
    368         osi_free(p_buf);
    369         return (BNEP_WRONG_HANDLE);
    370     }
    371 
    372     p_bcb = &(bnep_cb.bcb[handle - 1]);
    373     /* Check MTU size */
    374     if (p_buf->len > BNEP_MTU_SIZE)
    375     {
    376         BNEP_TRACE_ERROR ("BNEP_Write() length %d exceeded MTU %d", p_buf->len, BNEP_MTU_SIZE);
    377         osi_free(p_buf);
    378         return (BNEP_MTU_EXCEDED);
    379     }
    380 
    381     /* Check if the packet should be filtered out */
    382     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
    383     if (bnep_is_packet_allowed (p_bcb, p_dest_addr, protocol, fw_ext_present, p_data) != BNEP_SUCCESS)
    384     {
    385         /*
    386         ** If packet is filtered and ext headers are present
    387         ** drop the data and forward the ext headers
    388         */
    389         if (fw_ext_present)
    390         {
    391             UINT8       ext, length;
    392             UINT16      org_len, new_len;
    393             /* parse the extension headers and findout the new packet len */
    394             org_len = p_buf->len;
    395             new_len = 0;
    396             do {
    397 
    398                 ext     = *p_data++;
    399                 length  = *p_data++;
    400                 p_data += length;
    401 
    402                 new_len += (length + 2);
    403 
    404                 if (new_len > org_len)
    405                 {
    406                     osi_free(p_buf);
    407                     return BNEP_IGNORE_CMD;
    408                 }
    409 
    410             } while (ext & 0x80);
    411 
    412             if (protocol != BNEP_802_1_P_PROTOCOL)
    413                 protocol = 0;
    414             else
    415             {
    416                 new_len += 4;
    417                 p_data[2] = 0;
    418                 p_data[3] = 0;
    419             }
    420             p_buf->len  = new_len;
    421         }
    422         else
    423         {
    424             osi_free(p_buf);
    425             return BNEP_IGNORE_CMD;
    426         }
    427     }
    428 
    429     /* Check transmit queue */
    430     if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
    431     {
    432         osi_free(p_buf);
    433         return (BNEP_Q_SIZE_EXCEEDED);
    434     }
    435 
    436     /* Build the BNEP header */
    437     bnepu_build_bnep_hdr (p_bcb, p_buf, protocol, p_src_addr, p_dest_addr, fw_ext_present);
    438 
    439     /* Send the data or queue it up */
    440     bnepu_check_send_packet (p_bcb, p_buf);
    441 
    442     return (BNEP_SUCCESS);
    443 }
    444 
    445 
    446 /*******************************************************************************
    447 **
    448 ** Function         BNEP_Write
    449 **
    450 ** Description      This function sends data over a BNEP connection
    451 **
    452 ** Parameters:      handle       - handle of the connection to write
    453 **                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
    454 **                  p_data       - pointer to data start
    455 **                  protocol     - protocol type of the packet
    456 **                  p_src_addr   - (optional) BD_ADDR/ethernet address of the source
    457 **                                 (should be NULL if it is local BD Addr)
    458 **                  fw_ext_present - forwarded extensions present
    459 **
    460 ** Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
    461 **                  BNEP_MTU_EXCEDED        - If the data length is greater than MTU
    462 **                  BNEP_IGNORE_CMD         - If the packet is filtered out
    463 **                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
    464 **                  BNEP_NO_RESOURCES       - If not able to allocate a buffer
    465 **                  BNEP_SUCCESS            - If written successfully
    466 **
    467 *******************************************************************************/
    468 tBNEP_RESULT  BNEP_Write (UINT16 handle,
    469                           UINT8 *p_dest_addr,
    470                           UINT8 *p_data,
    471                           UINT16 len,
    472                           UINT16 protocol,
    473                           UINT8 *p_src_addr,
    474                           BOOLEAN fw_ext_present)
    475 {
    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 (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
    536         return (BNEP_Q_SIZE_EXCEEDED);
    537 
    538     /* Get a buffer to copy the data into */
    539     BT_HDR *p_buf = (BT_HDR *)osi_malloc(BNEP_BUF_SIZE);
    540 
    541     p_buf->len = len;
    542     p_buf->offset = BNEP_MINIMUM_OFFSET;
    543     p = (UINT8 *)(p_buf + 1) + BNEP_MINIMUM_OFFSET;
    544 
    545     memcpy (p, p_data, len);
    546 
    547     /* Build the BNEP header */
    548     bnepu_build_bnep_hdr (p_bcb, p_buf, protocol, p_src_addr, p_dest_addr, fw_ext_present);
    549 
    550     /* Send the data or queue it up */
    551     bnepu_check_send_packet (p_bcb, p_buf);
    552 
    553     return (BNEP_SUCCESS);
    554 }
    555 
    556 
    557 /*******************************************************************************
    558 **
    559 ** Function         BNEP_SetProtocolFilters
    560 **
    561 ** Description      This function sets the protocol filters on peer device
    562 **
    563 ** Parameters:      handle        - Handle for the connection
    564 **                  num_filters   - total number of filter ranges
    565 **                  p_start_array - Array of beginings of all protocol ranges
    566 **                  p_end_array   - Array of ends of all protocol ranges
    567 **
    568 ** Returns          BNEP_WRONG_HANDLE           - if the connection handle is not valid
    569 **                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong state
    570 **                  BNEP_TOO_MANY_FILTERS       - if too many filters
    571 **                  BNEP_SUCCESS                - if request sent successfully
    572 **
    573 *******************************************************************************/
    574 tBNEP_RESULT BNEP_SetProtocolFilters (UINT16 handle,
    575                                       UINT16 num_filters,
    576                                       UINT16 *p_start_array,
    577                                       UINT16 *p_end_array)
    578 {
    579     UINT16          xx;
    580     tBNEP_CONN     *p_bcb;
    581 
    582     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    583         return (BNEP_WRONG_HANDLE);
    584 
    585     p_bcb = &(bnep_cb.bcb[handle - 1]);
    586 
    587     /* Check the connection state */
    588     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
    589         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
    590         return (BNEP_WRONG_STATE);
    591 
    592     /* Validate the parameters */
    593     if (num_filters && (!p_start_array || !p_end_array))
    594         return (BNEP_SET_FILTER_FAIL);
    595 
    596     if (num_filters > BNEP_MAX_PROT_FILTERS)
    597         return (BNEP_TOO_MANY_FILTERS);
    598 
    599     /* Fill the filter values in connnection block */
    600     for (xx = 0; xx < num_filters; xx++)
    601     {
    602         p_bcb->sent_prot_filter_start[xx] = *p_start_array++;
    603         p_bcb->sent_prot_filter_end[xx]   = *p_end_array++;
    604     }
    605 
    606     p_bcb->sent_num_filters = num_filters;
    607 
    608     bnepu_send_peer_our_filters (p_bcb);
    609 
    610     return (BNEP_SUCCESS);
    611 }
    612 
    613 
    614 /*******************************************************************************
    615 **
    616 ** Function         BNEP_SetMulticastFilters
    617 **
    618 ** Description      This function sets the filters for multicast addresses for BNEP.
    619 **
    620 ** Parameters:      handle        - Handle for the connection
    621 **                  num_filters   - total number of filter ranges
    622 **                  p_start_array - Pointer to sequence of beginings of all
    623 **                                         multicast address ranges
    624 **                  p_end_array   - Pointer to sequence of ends of all
    625 **                                         multicast address ranges
    626 **
    627 ** Returns          BNEP_WRONG_HANDLE           - if the connection handle is not valid
    628 **                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong state
    629 **                  BNEP_TOO_MANY_FILTERS       - if too many filters
    630 **                  BNEP_SUCCESS                - if request sent successfully
    631 **
    632 *******************************************************************************/
    633 tBNEP_RESULT BNEP_SetMulticastFilters (UINT16 handle,
    634                                        UINT16 num_filters,
    635                                        UINT8 *p_start_array,
    636                                        UINT8 *p_end_array)
    637 {
    638     UINT16          xx;
    639     tBNEP_CONN     *p_bcb;
    640 
    641     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    642         return (BNEP_WRONG_HANDLE);
    643 
    644     p_bcb = &(bnep_cb.bcb[handle - 1]);
    645 
    646     /* Check the connection state */
    647     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
    648         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
    649         return (BNEP_WRONG_STATE);
    650 
    651     /* Validate the parameters */
    652     if (num_filters && (!p_start_array || !p_end_array))
    653         return (BNEP_SET_FILTER_FAIL);
    654 
    655     if (num_filters > BNEP_MAX_MULTI_FILTERS)
    656         return (BNEP_TOO_MANY_FILTERS);
    657 
    658     /* Fill the multicast filter values in connnection block */
    659     for (xx = 0; xx < num_filters; xx++)
    660     {
    661         memcpy (p_bcb->sent_mcast_filter_start[xx], p_start_array, BD_ADDR_LEN);
    662         memcpy (p_bcb->sent_mcast_filter_end[xx], p_end_array, BD_ADDR_LEN);
    663 
    664         p_start_array += BD_ADDR_LEN;
    665         p_end_array   += BD_ADDR_LEN;
    666     }
    667 
    668     p_bcb->sent_mcast_filters = num_filters;
    669 
    670     bnepu_send_peer_our_multi_filters (p_bcb);
    671 
    672     return (BNEP_SUCCESS);
    673 }
    674 
    675 /*******************************************************************************
    676 **
    677 ** Function         BNEP_SetTraceLevel
    678 **
    679 ** Description      This function sets the trace level for BNEP. If called with
    680 **                  a value of 0xFF, it simply reads the current trace level.
    681 **
    682 ** Returns          the new (current) trace level
    683 **
    684 *******************************************************************************/
    685 UINT8 BNEP_SetTraceLevel (UINT8 new_level)
    686 {
    687     if (new_level != 0xFF)
    688         bnep_cb.trace_level = new_level;
    689 
    690     return (bnep_cb.trace_level);
    691 }
    692 
    693 
    694 /*******************************************************************************
    695 **
    696 ** Function         BNEP_GetStatus
    697 **
    698 ** Description      This function gets the status information for BNEP connection
    699 **
    700 ** Returns          BNEP_SUCCESS            - if the status is available
    701 **                  BNEP_NO_RESOURCES       - if no structure is passed for output
    702 **                  BNEP_WRONG_HANDLE       - if the handle is invalid
    703 **                  BNEP_WRONG_STATE        - if not in connected state
    704 **
    705 *******************************************************************************/
    706 tBNEP_RESULT BNEP_GetStatus (UINT16 handle, tBNEP_STATUS *p_status)
    707 {
    708 #if (defined (BNEP_SUPPORTS_STATUS_API) && BNEP_SUPPORTS_STATUS_API == TRUE)
    709     tBNEP_CONN     *p_bcb;
    710 
    711     if (!p_status)
    712         return BNEP_NO_RESOURCES;
    713 
    714     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
    715         return (BNEP_WRONG_HANDLE);
    716 
    717     p_bcb = &(bnep_cb.bcb[handle - 1]);
    718 
    719     memset (p_status, 0, sizeof (tBNEP_STATUS));
    720     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
    721         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
    722         return BNEP_WRONG_STATE;
    723 
    724     /* Read the status parameters from the connection control block */
    725     p_status->con_status            = BNEP_STATUS_CONNECTED;
    726     p_status->l2cap_cid             = p_bcb->l2cap_cid;
    727     p_status->rem_mtu_size          = p_bcb->rem_mtu_size;
    728     p_status->xmit_q_depth          = fixed_queue_length(p_bcb->xmit_q);
    729     p_status->sent_num_filters      = p_bcb->sent_num_filters;
    730     p_status->sent_mcast_filters    = p_bcb->sent_mcast_filters;
    731     p_status->rcvd_num_filters      = p_bcb->rcvd_num_filters;
    732     p_status->rcvd_mcast_filters    = p_bcb->rcvd_mcast_filters;
    733 
    734     memcpy (p_status->rem_bda, p_bcb->rem_bda, BD_ADDR_LEN);
    735     memcpy (&(p_status->src_uuid), &(p_bcb->src_uuid), sizeof (tBT_UUID));
    736     memcpy (&(p_status->dst_uuid), &(p_bcb->dst_uuid), sizeof (tBT_UUID));
    737 
    738     return BNEP_SUCCESS;
    739 #else
    740     return (BNEP_IGNORE_CMD);
    741 #endif
    742 }
    743 
    744 
    745