Ejemplo n.º 1
0
void btu_register_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout, tBTU_TIMER_CALLBACK timer_cb)
{
    UINT8 i = 0;
    INT8  first = -1;
    for (; i < BTU_MAX_REG_TIMER; i++)
    {
        if (btu_cb.timer_reg[i].p_tle == NULL && first < 0)
            first = i;
        if (btu_cb.timer_reg[i].p_tle == p_tle)
        {
            btu_cb.timer_reg[i].timer_cb = timer_cb;
            btu_start_timer(p_tle, type, timeout);
            first = -1;
            break;
        }
    }

    if (first >= 0 && first < BTU_MAX_REG_TIMER)
    {
        btu_cb.timer_reg[first].timer_cb = timer_cb;
        btu_cb.timer_reg[first].p_tle = p_tle;
        btu_start_timer(p_tle, type, timeout);
    }

}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         l2c_process_held_packets
**
** Description      This function processes any L2CAP packets that arrived before
**                  the HCI connection complete arrived. It is a work around for
**                  badly behaved controllers.
**
** Returns          void
**
*******************************************************************************/
void l2c_process_held_packets (BOOLEAN timed_out)
{
    BT_HDR      *p_buf, *p_buf1;
    BUFFER_Q    *p_rcv_hold_q = &l2cb.rcv_hold_q;

    if (!p_rcv_hold_q->count)
        return;

    if (!timed_out)
    {
        btu_stop_timer(&l2cb.rcv_hold_tle);
        L2CAP_TRACE_WARNING0("L2CAP HOLD CONTINUE");
    }
    else
    {
        L2CAP_TRACE_WARNING0("L2CAP HOLD TIMEOUT");
    }

    /* Update the timeouts in the hold queue */
    for (p_buf = (BT_HDR *)GKI_getfirst (p_rcv_hold_q); p_buf; p_buf = p_buf1)
    {
        p_buf1 = (BT_HDR *)GKI_getnext (p_buf);
        if (!timed_out || (!p_buf->layer_specific) || (--p_buf->layer_specific == 0))
        {
            GKI_remove_from_queue (p_rcv_hold_q, p_buf);
            p_buf->layer_specific = 0xFFFF;
            l2c_rcv_acl_data (p_buf);
        }
    }

    /* If anyone still in the queue, restart the timeout */
    if (p_rcv_hold_q->count)
        btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT);
}
Ejemplo n.º 3
0
/*******************************************************************************
**
** Function         l2c_process_held_packets
**
** Description      This function processes any L2CAP packets that arrived before
**                  the HCI connection complete arrived. It is a work around for
**                  badly behaved controllers.
**
** Returns          void
**
*******************************************************************************/
void l2c_process_held_packets(BOOLEAN timed_out)
{
    if (list_is_empty(l2cb.rcv_pending_q)) {
        return;
    }

    if (!timed_out) {
        btu_stop_timer(&l2cb.rcv_hold_tle);
        L2CAP_TRACE_WARNING("L2CAP HOLD CONTINUE");
    } else {
        L2CAP_TRACE_WARNING("L2CAP HOLD TIMEOUT");
    }

    for (const list_node_t *node = list_begin(l2cb.rcv_pending_q);
            node != list_end(l2cb.rcv_pending_q);)  {
        BT_HDR *p_buf = list_node(node);
        node = list_next(node);
        if (!timed_out || (!p_buf->layer_specific) || (--p_buf->layer_specific == 0)) {
            list_remove(l2cb.rcv_pending_q, p_buf);
            p_buf->layer_specific = 0xFFFF;
            l2c_rcv_acl_data(p_buf);
        }
    }

    /* If anyone still in the queue, restart the timeout */
    if (!list_is_empty(l2cb.rcv_pending_q)) {
        btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT);
    }
}
Ejemplo n.º 4
0
/*******************************************************************************
**
** Function         avdt_ccb_ret_cmd
**
** Description      This function is called to retransmit the currently
**                  pending command.  The retransmission count is incremented.
**                  If the count reaches the maximum number of retransmissions,
**                  the event is treated as a response timeout.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    UINT8   err_code = AVDT_ERR_TIMEOUT;
    BT_HDR  *p_msg;

    p_ccb->ret_count++;
    if (p_ccb->ret_count == AVDT_RET_MAX)
    {
        /* command failed */
        p_ccb->ret_count = 0;
        avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);

        /* go to next queued command */
        avdt_ccb_snd_cmd(p_ccb, p_data);
    }
    else
    {
        /* if command pending and we're not congested and not sending a fragment */
        if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
        {
            /* make copy of message in p_curr_cmd and send it */
            if ((p_msg = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
            {
                memcpy(p_msg, p_ccb->p_curr_cmd,
                       (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
                avdt_msg_send(p_ccb, p_msg);
            }
        }

        /* restart timer */
        btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
    }
}
/*******************************************************************************
**
** Function         mca_ccb_snd_req
**
** Description      This function builds a request and sends it to the peer.
**
** Returns          void.
**
*******************************************************************************/
void mca_ccb_snd_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
{
    tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data;
    BT_HDR  *p_pkt;
    UINT8   *p, *p_start;
    BOOLEAN is_abort = FALSE;
    tMCA_DCB *p_dcb;

    MCA_TRACE_DEBUG ("mca_ccb_snd_req cong=%d req=%d", p_ccb->cong, p_msg->op_code);
    /* check for abort request */
    if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (p_msg->op_code == MCA_OP_MDL_ABORT_REQ))
    {
        p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
        /* the Abort API does not have the associated mdl_id.
         * Get the mdl_id in dcb to compose the request */
        if (p_dcb)
        {
            p_msg->mdl_id = p_dcb->mdl_id;
            mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
        }
        mca_free_buf ((void **)&p_ccb->p_tx_req);
        p_ccb->status = MCA_CCB_STAT_NORM;
        is_abort = TRUE;
    }

    /* no pending outgoing messages or it's an abort request for a pending data channel */
    if ((!p_ccb->p_tx_req) || is_abort)
    {
        p_ccb->p_tx_req = p_msg;
        if (!p_ccb->cong)
        {
            p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
            if (p_pkt)
            {
                p_pkt->offset = L2CAP_MIN_OFFSET;
                p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
                *p++ = p_msg->op_code;
                UINT16_TO_BE_STREAM (p, p_msg->mdl_id);
                if (p_msg->op_code == MCA_OP_MDL_CREATE_REQ)
                {
                    *p++ = p_msg->mdep_id;
                    *p++ = p_msg->param;
                }
                p_msg->hdr.layer_specific = TRUE;   /* mark this message as sent */
                p_pkt->len = p - p_start;
                L2CA_DataWrite (p_ccb->lcid, p_pkt);
                p_ccb->timer_entry.param = (TIMER_PARAM_TYPE) p_ccb;
                btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_MCA_CCB_RSP, p_ccb->p_rcb->reg.rsp_tout);
            }
        }
        /* else the L2CAP channel is congested. keep the message to be sent later */
    }
    else
    {
        MCA_TRACE_WARNING ("dropping api req");
        GKI_freebuf (p_data);
    }
}
Ejemplo n.º 6
0
/*******************************************************************************
**
** Function         rfc_port_timer_start
**
** Description      Start RFC Timer
**
*******************************************************************************/
void rfc_port_timer_start (tPORT *p_port, UINT16 timeout)
{
    TIMER_LIST_ENT *p_tle = &p_port->rfc.tle;

    RFCOMM_TRACE_EVENT ("rfc_port_timer_start - timeout:%d", timeout);

    p_tle->param = (UINT32)p_port;

    btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_PORT, timeout);
}
Ejemplo n.º 7
0
/*******************************************************************************
**
** Function         rfc_timer_start
**
** Description      Start RFC Timer
**
*******************************************************************************/
void rfc_timer_start (tRFC_MCB *p_mcb, UINT16 timeout)
{
    TIMER_LIST_ENT *p_tle = &p_mcb->tle;

    RFCOMM_TRACE_EVENT ("rfc_timer_start - timeout:%d", timeout);

    p_tle->param = (UINT32)p_mcb;

    btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_MFC, timeout);
}
Ejemplo n.º 8
0
/*******************************************************************************
**
** Function         BNEP_Init
**
** Description      This function initializes the BNEP unit. It should be called
**                  before accessing any other APIs to initialize the control block
**
** Returns          void
**
*******************************************************************************/
void BNEP_Init (void)
{
    memset (&bnep_cb, 0, sizeof (tBNEP_CB));

#if defined(BNEP_INITIAL_TRACE_LEVEL)
    bnep_cb.trace_level = BNEP_INITIAL_TRACE_LEVEL;
#else
    bnep_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
#endif

    /* Start a timer to read our BD address */
    btu_start_timer (&bnep_cb.bnep_tle, BTU_TTYPE_BNEP, 2);
}
/*******************************************************************************
**
** Function         l2cble_init_direct_conn
**
** Description      This function is to initate a direct connection
**
** Returns          TRUE connection initiated, FALSE otherwise.
**
*******************************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
    tBTM_BLE_CB         *p_cb = &btm_cb.ble_ctr_cb;
    UINT16               scan_int, scan_win;
    BD_ADDR         init_addr;
    UINT8           init_addr_type = BLE_ADDR_PUBLIC,
                    own_addr_type = BLE_ADDR_PUBLIC;

    /* There can be only one BLE connection request outstanding at a time */
    if (p_dev_rec == NULL)
    {
        BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
        return(FALSE);
    }

    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    init_addr_type = p_lcb->ble_addr_type;
    memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);

    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                        scan_win, /* UINT16 scan_win      */
                                        FALSE,                   /* UINT8 white_list     */
                                        p_lcb->ble_addr_type,          /* UINT8 addr_type_peer */
                                        p_lcb->remote_bd_addr,         /* BD_ADDR bda_peer     */
                                        BLE_ADDR_PUBLIC,         /* UINT8 addr_type_own  */
                                        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_min  */
                                        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_max  */
                                        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency  */
                                        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_SUP_TOUT_DEF), /* UINT16 conn_timeout  */
                                        0,                       /* UINT16 min_len       */
                                        0))                      /* UINT16 max_len       */
    {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR0("initate direct connection fail, no resources");
        return (FALSE);
    }
    else
    {
        p_lcb->link_state = LST_CONNECTING;
        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
        //Assigning below variable which is checked at LE conn cancel
        l2cb.is_ble_connecting=TRUE;
        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
        btm_ble_set_conn_st (BLE_DIR_CONN);

        return (TRUE);
    }
}
Ejemplo n.º 10
0
/*******************************************************************************
**
** Function         BTM_ReadLocalDeviceNameFromController
**
** Description      Get local device name from controller. Do not use cached
**                  name (used to get chip-id prior to btm reset complete).
**
** Returns          BTM_CMD_STARTED if successful, otherwise an error
**
*******************************************************************************/
tBTM_STATUS BTM_ReadLocalDeviceNameFromController (tBTM_CMPL_CB *p_rln_cmpl_cback)
{
    /* Check if rln already in progress */
    if (btm_cb.devcb.p_rln_cmpl_cb)
        return(BTM_NO_RESOURCES);

    /* Save callback */
    btm_cb.devcb.p_rln_cmpl_cb = p_rln_cmpl_cback;

    btsnd_hcic_read_name();
    btu_start_timer (&btm_cb.devcb.rln_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);

    return BTM_CMD_STARTED;
}
Ejemplo n.º 11
0
/*******************************************************************************
**
** Function         smp_br_data_received
**
** Description      This function is called when data is received from L2CAP on
**                  SMP BR channel.
**
** Returns          void
**
*******************************************************************************/
static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
{
    tSMP_CB *p_cb = &smp_cb;
    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    UINT8   cmd ;
    SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);

    STREAM_TO_UINT8(cmd, p);

    /* sanity check */
    if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
    {
        SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
        GKI_freebuf(p_buf);
        return;
    }

    /* reject the pairing request if there is an on-going SMP pairing */
    if (SMP_OPCODE_PAIRING_REQ == cmd)
    {
        if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE))
        {
            p_cb->role = HCI_ROLE_SLAVE;
            p_cb->smp_over_br = TRUE;
            memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
        }
        else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
        {
            GKI_freebuf (p_buf);
            smp_reject_unexpected_pairing_command(bd_addr);
            return;
        }
        /* else, out of state pairing request received, passed into State Machine */
    }

    if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
    {
        btu_stop_timer (&p_cb->rsp_timer_ent);
        btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
                             SMP_WAIT_FOR_RSP_TOUT);

        p_cb->rcvd_cmd_code = cmd;
        p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
        smp_br_state_machine_event(p_cb, cmd, p);
    }

    GKI_freebuf (p_buf);
}
/*******************************************************************************
**
** Function         sdp_config_cfm
**
** Description      This function processes the L2CAP configuration confirmation
**                  event.
**
** Returns          void
**
*******************************************************************************/
static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
{
    tCONN_CB    *p_ccb;

    SDP_TRACE_EVENT2 ("SDP - Rcvd cfg cfm, CID: 0x%x  Result: %d", l2cap_cid, p_cfg->result);

    /* Find CCB based on CID */
    if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL)
    {
        SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
        return;
    }

    /* For now, always accept configuration from the other side */
    if (p_cfg->result == L2CAP_CFG_OK)
    {
        p_ccb->con_flags |= SDP_FLAGS_MY_CFG_DONE;

        if (p_ccb->con_flags & SDP_FLAGS_HIS_CFG_DONE)
        {
            p_ccb->con_state = SDP_STATE_CONNECTED;

            if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)
                sdp_disc_connected (p_ccb);
            else
                /* Start inactivity timer */
                btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
        }
    }
    else
    {
        /* If peer has rejected FCR and suggested basic then try basic */
        if (p_cfg->fcr_present)
        {
            tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg;
            cfg.fcr_present = FALSE;
            L2CA_ConfigReq (l2cap_cid, &cfg);

            /* Remain in configure state */
            return;
        }

#if SDP_CLIENT_ENABLED == TRUE
        sdp_disconnect(p_ccb, SDP_CFG_FAILED);
#endif
    }
}
Ejemplo n.º 13
0
/*******************************************************************************
**
** Function         avdt_ccb_chk_close
**
** Description      This function checks for active streams on this CCB.
**                  If there are none, it starts an idle timer.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_chk_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    int         i;
    tAVDT_SCB   *p_scb = &avdt_cb.scb[0];
    UNUSED(p_data);

    /* see if there are any active scbs associated with this ccb */
    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
        if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb)) {
            break;
        }
    }

    /* if no active scbs start idle timer */
    if (i == AVDT_NUM_SEPS) {
        btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_IDLE, avdt_cb.rcb.idle_tout);
    }
}
Ejemplo n.º 14
0
/*******************************************************************************
**
** Function         btm_ble_resume_bg_conn
**
** Description      This function is to resume a background auto connection
**                  procedure.
**
** Parameters       none.
**
** Returns          none.
**
*******************************************************************************/
BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param)
{
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    BOOLEAN ret = FALSE;

    if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE )
    {
        if (def_param)
        {
            p_cb->scan_int = BTM_BLE_CONN_PARAM_UNDEF;
            p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;

            /* start scan param idle timer */
            btu_start_timer(&p_cb->scan_param_idle_timer,
                            BTU_TTYPE_BLE_SCAN_PARAM_IDLE,
                            BTM_BLE_SCAN_PARAM_TOUT);
        }

        if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
            ret = btm_ble_start_auto_conn(TRUE);

        if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
        {
            /* terminate selective connection mode if all devices are connected */
            if (btm_ble_count_unconn_dev_in_whitelist() == 0)
            {
                btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_DISABLE);
                btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
                btm_cb.btm_inq_vars.inq_active = FALSE;
            }
            else if (!btm_cb.btm_inq_vars.inq_active)
                btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
        }

        if (ret)
            p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;

    }

    return ret;
}
Ejemplo n.º 15
0
/*******************************************************************************
**
** Function         l2cble_init_direct_conn
**
** Description      This function is to initate a direct connection
**
** Returns          TRUE connection initiated, FALSE otherwise.
**
*******************************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
    tBTM_BLE_CB         *p_cb = &btm_cb.ble_ctr_cb;
    UINT16               scan_int, scan_win;
    BD_ADDR         init_addr;
    UINT8           init_addr_type = BLE_ADDR_PUBLIC,
                    own_addr_type = BLE_ADDR_PUBLIC;

    /* There can be only one BLE connection request outstanding at a time */
    if (p_dev_rec == NULL)
    {
        L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
        return(FALSE);
    }

    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    init_addr_type = p_lcb->ble_addr_type;
    memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);

#if BLE_PRIVACY_SPT == TRUE
    /* if RPA offloading supported */
    if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
        btm_random_pseudo_to_public(init_addr, &init_addr_type);
    /* otherwise, if remote is RPA enabled, use latest RPA */
    else if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA)
    {
        init_addr_type = BLE_ADDR_RANDOM;
        memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
    }
    /* if privacy is on and current do not consider using reconnection address */
    if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */
        own_addr_type = BLE_ADDR_RANDOM;
#endif

    if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
    {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
        return FALSE;
    }

    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                        scan_win, /* UINT16 scan_win      */
                                        FALSE,                   /* UINT8 white_list     */
                                        init_addr_type,          /* UINT8 addr_type_peer */
                                        init_addr,               /* BD_ADDR bda_peer     */
                                        own_addr_type,         /* UINT8 addr_type_own  */
                                        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
                                        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
                                        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
                                        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
                                        0,                       /* UINT16 min_len       */
                                        0))                      /* UINT16 max_len       */
    {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
        return (FALSE);
    }
    else
    {
        p_lcb->link_state = LST_CONNECTING;
        l2cb.is_ble_connecting = TRUE;
        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
        btm_ble_set_conn_st (BLE_DIR_CONN);

        return (TRUE);
    }
}
Ejemplo n.º 16
0
/*******************************************************************************
**
** Function         l2c_ble_link_adjust_allocation
**
** Description      This function is called when a link is created or removed
**                  to calculate the amount of packets each link may send to
**                  the HCI without an ack coming back.
**
**                  Currently, this is a simple allocation, dividing the
**                  number of Controller Packets by the number of links. In
**                  the future, QOS configuration should be examined.
**
** Returns          void
**
*******************************************************************************/
void l2c_ble_link_adjust_allocation (void)
{
    UINT16      qq, yy, qq_remainder;
    tL2C_LCB    *p_lcb;
    UINT16      hi_quota, low_quota;
    UINT16      num_lowpri_links = 0;
    UINT16      num_hipri_links  = 0;
    UINT16      controller_xmit_quota = l2cb.num_lm_ble_bufs;
    UINT16      high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;

    /* If no links active, reset buffer quotas and controller buffers */
    if (l2cb.num_ble_links_active == 0)
    {
        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
        l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
        return;
    }

    /* First, count the links */
    for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
    {
        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
        {
            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
                num_hipri_links++;
            else
                num_lowpri_links++;
        }
    }

    /* now adjust high priority link quota */
    low_quota = num_lowpri_links ? 1 : 0;
    while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota )
        high_pri_link_quota--;


    /* Work out the xmit quota and buffer quota high and low priorities */
    hi_quota  = num_hipri_links * high_pri_link_quota;
    low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;

    /* Work out and save the HCI xmit quota for each low priority link */

    /* If each low priority link cannot have at least one buffer */
    if (num_lowpri_links > low_quota)
    {
        l2cb.ble_round_robin_quota = low_quota;
        qq = qq_remainder = 0;
    }
    /* If each low priority link can have at least one buffer */
    else if (num_lowpri_links > 0)
    {
        l2cb.ble_round_robin_quota = 0;
        l2cb.ble_round_robin_unacked = 0;
        qq = low_quota / num_lowpri_links;
        qq_remainder = low_quota % num_lowpri_links;
    }
    /* If no low priority link */
    else
    {
        l2cb.ble_round_robin_quota = 0;
        l2cb.ble_round_robin_unacked = 0;
        qq = qq_remainder = 0;
    }
    L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
                        num_hipri_links, num_lowpri_links, low_quota,
                        l2cb.ble_round_robin_quota, qq);

    /* Now, assign the quotas to each link */
    for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
    {
        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
        {
            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
            {
                p_lcb->link_xmit_quota   = high_pri_link_quota;
            }
            else
            {
                /* Safety check in case we switched to round-robin with something outstanding */
                /* if sent_not_acked is added into round_robin_unacked then don't add it again */
                /* l2cap keeps updating sent_not_acked for exiting from round robin */
                if (( p_lcb->link_xmit_quota > 0 )&&( qq == 0 ))
                    l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;

                p_lcb->link_xmit_quota   = qq;
                if (qq_remainder > 0)
                {
                    p_lcb->link_xmit_quota++;
                    qq_remainder--;
                }
            }

            L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation LCB %d   Priority: %d  XmitQuota: %d",
                                yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);

            L2CAP_TRACE_EVENT("        SentNotAcked: %d  RRUnacked: %d",
                                p_lcb->sent_not_acked, l2cb.round_robin_unacked);

            /* There is a special case where we have readjusted the link quotas and  */
            /* this link may have sent anything but some other link sent packets so  */
            /* so we may need a timer to kick off this link's transmissions.         */
            if ( (p_lcb->link_state == LST_CONNECTED)
              && (!list_is_empty(p_lcb->link_xmit_data_q))
              && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) )
                btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_FLOW_CONTROL_TOUT);
        }
    }
}
Ejemplo n.º 17
0
/*******************************************************************************
**
** Function         l2cble_init_direct_conn
**
** Description      This function is to initate a direct connection
**
** Returns          TRUE connection initiated, FALSE otherwise.
**
*******************************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    UINT16 scan_int;
    UINT16 scan_win;
    BD_ADDR peer_addr;
    UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
    UINT8 own_addr_type = BLE_ADDR_PUBLIC;

    /* There can be only one BLE connection request outstanding at a time */
    if (p_dev_rec == NULL)
    {
        L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
        return(FALSE);
    }

    scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    peer_addr_type = p_lcb->ble_addr_type;
    memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);

#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
    own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
    if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
    {
        if (btm_cb.ble_ctr_cb.privacy_mode >=  BTM_PRIVACY_1_2)
            own_addr_type |= BLE_ADDR_TYPE_ID_BIT;

        btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
        btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
    }
    else
        btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
#endif

    if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
    {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
        return FALSE;
    }

    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                        scan_win, /* UINT16 scan_win      */
                                        FALSE,                   /* UINT8 white_list     */
                                        peer_addr_type,          /* UINT8 addr_type_peer */
                                        peer_addr,               /* BD_ADDR bda_peer     */
                                        own_addr_type,         /* UINT8 addr_type_own  */
        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
        p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
        p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
        p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
        p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
                                        0,                       /* UINT16 min_len       */
                                        0))                      /* UINT16 max_len       */
    {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
        return (FALSE);
    }
    else
    {
        p_lcb->link_state = LST_CONNECTING;
        l2cb.is_ble_connecting = TRUE;
        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
        btm_ble_set_conn_st (BLE_DIR_CONN);

        return (TRUE);
    }
}
/*******************************************************************************
**
** Function         sdp_config_ind
**
** Description      This function processes the L2CAP configuration indication
**                  event.
**
** Returns          void
**
*******************************************************************************/
static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
{
    tCONN_CB    *p_ccb;

    /* Find CCB based on CID */
    if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL)
    {
        SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
        return;
    }

    /* Remember the remote MTU size */
    if (!p_cfg->mtu_present)
    {
        /* use min(L2CAP_DEFAULT_MTU,SDP_MTU_SIZE) for GKI buffer size reasons */
        p_ccb->rem_mtu_size = (L2CAP_DEFAULT_MTU > SDP_MTU_SIZE)?SDP_MTU_SIZE:L2CAP_DEFAULT_MTU;
    }
    else
    {
        if (p_cfg->mtu > SDP_MTU_SIZE)
            p_ccb->rem_mtu_size = SDP_MTU_SIZE;
        else
            p_ccb->rem_mtu_size = p_cfg->mtu;
    }

    /* For now, always accept configuration from the other side */
    p_cfg->flush_to_present = FALSE;
    p_cfg->mtu_present      = FALSE;
    p_cfg->result           = L2CAP_CFG_OK;

    /* Check peer config request against our rfcomm configuration */
    if (p_cfg->fcr_present)
    {
        /* Reject the window size if it is bigger than we want it to be */
        if (p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE)
        {
            if (sdp_cb.l2cap_my_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE
                    && p_cfg->fcr.tx_win_sz > sdp_cb.l2cap_my_cfg.fcr.tx_win_sz)
            {
                p_cfg->fcr.tx_win_sz = sdp_cb.l2cap_my_cfg.fcr.tx_win_sz;
                p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
                SDP_TRACE_DEBUG0("sdp_config_ind(CONFIG) -> Please try again with SMALLER TX WINDOW");
            }

            /* Reject if locally we want basic and they don't */
            if (sdp_cb.l2cap_my_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
            {
                /* Ask for a new setup */
                p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
                p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
                SDP_TRACE_DEBUG0("sdp_config_ind(CONFIG) -> Please try again with BASIC mode");
            }
            /* Remain in configure state and give the peer our desired configuration */
            if (p_cfg->result != L2CAP_CFG_OK)
            {
                SDP_TRACE_WARNING1 ("SDP - Rcvd cfg ind, Unacceptable Parameters sent cfg cfm, CID: 0x%x", l2cap_cid);
                L2CA_ConfigRsp (l2cap_cid, p_cfg);
                return;
            }
        }
        else    /* We agree with peer's request */
            p_cfg->fcr_present = FALSE;
    }

    L2CA_ConfigRsp (l2cap_cid, p_cfg);

    SDP_TRACE_EVENT1 ("SDP - Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid);

    p_ccb->con_flags |= SDP_FLAGS_HIS_CFG_DONE;

    if (p_ccb->con_flags & SDP_FLAGS_MY_CFG_DONE)
    {
        p_ccb->con_state = SDP_STATE_CONNECTED;

        if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)
            sdp_disc_connected (p_ccb);
        else
            /* Start inactivity timer */
            btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
    }

}
Ejemplo n.º 19
0
/*******************************************************************************
**
** Function         hidh_l2cif_disconnect_ind
**
** Description      This function handles a disconnect event from L2CAP. If
**                  requested to, we ack the disconnect before dropping the CCB
**
** Returns          void
**
*******************************************************************************/
static void hidh_l2cif_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
{
    UINT8 dhandle;
    tHID_CONN    *p_hcon = NULL;
    UINT16 disc_res = HCI_SUCCESS;
    UINT16 hid_close_evt_reason;

    /* Find CCB based on CID */
    if( (dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES )
        p_hcon = &hh_cb.devices[dhandle].conn;

    if (p_hcon == NULL)
    {
        HIDH_TRACE_WARNING ("HID-Host Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
        return;
    }

    if (ack_needed)
        L2CA_DisconnectRsp (l2cap_cid);

    HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);

    p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;

    if (l2cap_cid == p_hcon->ctrl_cid)
        p_hcon->ctrl_cid = 0;
    else
        p_hcon->intr_cid = 0;

    if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0))
    {
        hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
        p_hcon->conn_state = HID_CONN_STATE_UNUSED;

        if( !ack_needed )
            disc_res = btm_get_acl_disc_reason_code();

        HIDH_TRACE_EVENT ("HID-Host: acl disconnect reason %d", disc_res);

#if (HID_HOST_MAX_CONN_RETRY > 0)
        if( (disc_res == HCI_ERR_CONNECTION_TOUT || disc_res == HCI_ERR_UNSPECIFIED) &&
            (!(hh_cb.devices[dhandle].attr_mask & HID_RECONN_INIT)) &&
            (hh_cb.devices[dhandle].attr_mask & HID_NORMALLY_CONNECTABLE))
        {
            hh_cb.devices[dhandle].conn_tries = 0;
            hh_cb.devices[dhandle].conn.timer_entry.param = (UINT32) dhandle;
            HIDH_TRACE_EVENT ("HID-Host: starting timer for reconnection");
            btu_start_timer (&(hh_cb.devices[dhandle].conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
            hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, disc_res, NULL);
        }
        else
#endif
        {
            /* Set reason code for HID_HDEV_EVT_CLOSE */
            hid_close_evt_reason = p_hcon->disc_reason;

            /* If we got baseband sent HCI_DISCONNECT_COMPLETE_EVT due to security failure, then set reason to HID_ERR_AUTH_FAILED */
            if ((disc_res == HCI_ERR_AUTH_FAILURE)                        ||
                (disc_res == HCI_ERR_KEY_MISSING)                         ||
                (disc_res == HCI_ERR_HOST_REJECT_SECURITY)                ||
                (disc_res == HCI_ERR_PAIRING_NOT_ALLOWED)                 ||
                (disc_res == HCI_ERR_UNIT_KEY_USED)                       ||
                (disc_res == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
                (disc_res == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)           ||
                (disc_res == HCI_ERR_REPEATED_ATTEMPTS))
            {
                hid_close_evt_reason = HID_ERR_AUTH_FAILED;
            }
            HIDH_TRACE_EVENT ("HID-Host: disconnect ind, reason = %d", hid_close_evt_reason);
            hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, hid_close_evt_reason, NULL ) ;
        }
    }
}
Ejemplo n.º 20
0
/*******************************************************************************
**
** Function         l2c_rcv_acl_data
**
** Description      This function is called from the HCI Interface when an ACL
**                  data packet is received.
**
** Returns          void
**
*******************************************************************************/
void l2c_rcv_acl_data (BT_HDR *p_msg)
{
    UINT8       *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
    UINT16      handle, hci_len;
    UINT8       pkt_type;
    tL2C_LCB    *p_lcb;
    tL2C_CCB    *p_ccb = NULL;
    UINT16      l2cap_len, rcv_cid, psm;

    /* Extract the handle */
    STREAM_TO_UINT16 (handle, p);
    pkt_type = HCID_GET_EVENT (handle);
    handle   = HCID_GET_HANDLE (handle);

    /* Since the HCI Transport is putting segmented packets back together, we */
    /* should never get a valid packet with the type set to "continuation"    */
    if (pkt_type != L2CAP_PKT_CONTINUE) {
        /* Find the LCB based on the handle */
        if ((p_lcb = l2cu_find_lcb_by_handle (handle)) == NULL) {
            UINT8       cmd_code;

            /* There is a slight possibility (specifically with USB) that we get an */
            /* L2CAP connection request before we get the HCI connection complete.  */
            /* So for these types of messages, hold them for up to 2 seconds.       */
            STREAM_TO_UINT16 (hci_len, p);
            STREAM_TO_UINT16 (l2cap_len, p);
            STREAM_TO_UINT16 (rcv_cid, p);
            STREAM_TO_UINT8  (cmd_code, p);

            if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID)
                    && (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ)) {
                L2CAP_TRACE_WARNING ("L2CAP - holding ACL for unknown handle:%d ls:%d"
                                     "  cid:%d opcode:%d cur count:%d", handle, p_msg->layer_specific,
                                     rcv_cid, cmd_code, list_length(l2cb.rcv_pending_q));
                p_msg->layer_specific = 2;
                list_append(l2cb.rcv_pending_q, p_msg);

                if (list_length(l2cb.rcv_pending_q) == 1) {
                    btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT);
                }

                return;
            } else {
                L2CAP_TRACE_ERROR ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d"
                                   " opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid,
                                   cmd_code, list_length(l2cb.rcv_pending_q));
            }
            GKI_freebuf (p_msg);
            return;
        }
    } else {
        L2CAP_TRACE_WARNING ("L2CAP - expected pkt start or complete, got: %d", pkt_type);
        GKI_freebuf (p_msg);
        return;
    }

    /* Extract the length and update the buffer header */
    STREAM_TO_UINT16 (hci_len, p);
    p_msg->offset += 4;

    /* Extract the length and CID */
    STREAM_TO_UINT16 (l2cap_len, p);
    STREAM_TO_UINT16 (rcv_cid, p);

#if BLE_INCLUDED == TRUE
    /* for BLE channel, always notify connection when ACL data received on the link */
    if (p_lcb && p_lcb->transport == BT_TRANSPORT_LE && p_lcb->link_state != LST_DISCONNECTING)
        /* only process fixed channel data as channel open indication when link is not in disconnecting mode */
    {
        l2cble_notify_le_connection(p_lcb->remote_bd_addr);
    }
#endif
    L2CAP_TRACE_DEBUG ("L2CAP - rcv_cid CID: 0x%04x\n", rcv_cid);
    /* Find the CCB for this CID */
    if (rcv_cid >= L2CAP_BASE_APPL_CID) {
        if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, rcv_cid)) == NULL) {
            L2CAP_TRACE_WARNING ("L2CAP - unknown CID: 0x%04x", rcv_cid);
            GKI_freebuf (p_msg);
            return;
        }
    }

    if (hci_len >= L2CAP_PKT_OVERHEAD) { /* Must receive at least the L2CAP length and CID.*/
        p_msg->len    = hci_len - L2CAP_PKT_OVERHEAD;
        p_msg->offset += L2CAP_PKT_OVERHEAD;
    } else {
        L2CAP_TRACE_WARNING ("L2CAP - got incorrect hci header" );
        GKI_freebuf (p_msg);
        return;
    }

    if (l2cap_len != p_msg->len) {
        L2CAP_TRACE_WARNING ("L2CAP - bad length in pkt. Exp: %d  Act: %d",
                             l2cap_len, p_msg->len);

        GKI_freebuf (p_msg);
        return;
    }

    /* Send the data through the channel state machine */
    if (rcv_cid == L2CAP_SIGNALLING_CID) {
        //counter_add("l2cap.sig.rx.bytes", l2cap_len);
        //counter_add("l2cap.sig.rx.pkts", 1);
#if (CLASSIC_BT_INCLUDED == TRUE)
        process_l2cap_cmd (p_lcb, p, l2cap_len);
#endif  ///CLASSIC_BT_INCLUDED == TRUE
        GKI_freebuf (p_msg);
    } else if (rcv_cid == L2CAP_CONNECTIONLESS_CID) {
        //counter_add("l2cap.ch2.rx.bytes", l2cap_len);
        //counter_add("l2cap.ch2.rx.pkts", 1);
        /* process_connectionless_data (p_lcb); */
        STREAM_TO_UINT16 (psm, p);
        L2CAP_TRACE_DEBUG( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ;

#if (L2CAP_UCD_INCLUDED == TRUE)
        /* if it is not broadcast, check UCD registration */
        if ( l2c_ucd_check_rx_pkts( p_lcb, p_msg ) ) {
            /* nothing to do */
        } else
#endif
            GKI_freebuf (p_msg);
    }
#if (BLE_INCLUDED == TRUE)
    else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) {
        //counter_add("l2cap.ble.rx.bytes", l2cap_len);
        //counter_add("l2cap.ble.rx.pkts", 1);
        l2cble_process_sig_cmd (p_lcb, p, l2cap_len);
        GKI_freebuf (p_msg);
    }
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0)
    else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) && (rcv_cid <= L2CAP_LAST_FIXED_CHNL) &&
             (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) ) {
        //counter_add("l2cap.fix.rx.bytes", l2cap_len);
        //counter_add("l2cap.fix.rx.pkts", 1);
        /* If no CCB for this channel, allocate one */
        if (p_lcb &&
                /* only process fixed channel data when link is open or wait for data indication */
                (p_lcb->link_state != LST_DISCONNECTING) &&
                l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) {
            p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];

            if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
#if (CLASSIC_BT_INCLUDED == TRUE)
                l2c_fcr_proc_pdu (p_ccb, p_msg);
#endif  ///CLASSIC_BT_INCLUDED == TRUE
            } else
                (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
                (rcv_cid, p_lcb->remote_bd_addr, p_msg);
        } else {
            GKI_freebuf (p_msg);
        }
    }
#endif

    else {
        //counter_add("l2cap.dyn.rx.bytes", l2cap_len);
        //counter_add("l2cap.dyn.rx.pkts", 1);
        if (p_ccb == NULL) {
            GKI_freebuf (p_msg);
        } else {
            /* Basic mode packets go straight to the state machine */
            if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
#if (CLASSIC_BT_INCLUDED == TRUE)
                l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg);
#endif  ///CLASSIC_BT_INCLUDED == TRUE
            } else {
                /* eRTM or streaming mode, so we need to validate states first */
                if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)) {
#if (CLASSIC_BT_INCLUDED == TRUE)
                    l2c_fcr_proc_pdu (p_ccb, p_msg);
#endif  ///CLASSIC_BT_INCLUDED == TRUE
                } else {
                    GKI_freebuf (p_msg);
                }
            }
        }
    }
}
Ejemplo n.º 21
0
/*******************************************************************************
**
** Function         smp_data_received
**
** Description      This function is called when data is received from L2CAP on
**                  SMP channel.
**
**
** Returns          void
**
*******************************************************************************/
static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
{
    tSMP_CB *p_cb = &smp_cb;
    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    UINT8   cmd ;
    SMP_TRACE_EVENT ("SMDBG l2c %s", __FUNCTION__);

    STREAM_TO_UINT8(cmd, p);

    /* sanity check */
    if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
    {
        SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
        GKI_freebuf (p_buf);
        return;
    }

    /* reject the pairing request if there is an on-going SMP pairing */
    if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd)
    {
        if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE) &&
            !(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
        {
            p_cb->role = L2CA_GetBleConnRole(bd_addr);
            memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
        }
        else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
        {
            GKI_freebuf (p_buf);
            smp_reject_unexpected_pairing_command(bd_addr);
            return;
        }
        /* else, out of state pairing request/security request received, passed into SM */
    }

    if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
    {
        btu_stop_timer (&p_cb->rsp_timer_ent);
        btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
                             SMP_WAIT_FOR_RSP_TOUT);

        if (cmd == SMP_OPCODE_CONFIRM)
        {
            SMP_TRACE_DEBUG ("in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
                              "loc_auth_req = 0x%02x",
                              __FUNCTION__, cmd, p_cb->peer_auth_req, p_cb->loc_auth_req);

            if ((p_cb->peer_auth_req  & SMP_SC_SUPPORT_BIT) &&
                (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
            {
                cmd = SMP_OPCODE_PAIR_COMMITM;
            }
        }

        p_cb->rcvd_cmd_code = cmd;
        p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
        smp_sm_event(p_cb, cmd, p);
    }

    GKI_freebuf (p_buf);
}
Ejemplo n.º 22
0
/*******************************************************************************
**
** Function         BNEP_Connect
**
** Description      This function creates a BNEP connection to a remote
**                  device.
**
** Parameters:      p_rem_addr  - BD_ADDR of the peer
**                  src_uuid    - source uuid for the connection
**                  dst_uuid    - destination uuid for the connection
**                  p_handle    - pointer to return the handle for the connection
**
** Returns          BNEP_SUCCESS                if connection started
**                  BNEP_NO_RESOURCES           if no resources
**
*******************************************************************************/
tBNEP_RESULT BNEP_Connect (BD_ADDR p_rem_bda,
                           tBT_UUID *src_uuid,
                           tBT_UUID *dst_uuid,
                           UINT16 *p_handle)
{
    UINT16          cid;
    tBNEP_CONN      *p_bcb = bnepu_find_bcb_by_bd_addr (p_rem_bda);

    BNEP_TRACE_API ("BNEP_Connect()  BDA: %02x-%02x-%02x-%02x-%02x-%02x",
                     p_rem_bda[0], p_rem_bda[1], p_rem_bda[2],
                     p_rem_bda[3], p_rem_bda[4], p_rem_bda[5]);

    if (!bnep_cb.profile_registered)
        return BNEP_WRONG_STATE;

    /* Both source and destination UUID lengths should be same */
    if (src_uuid->len != dst_uuid->len)
        return BNEP_CONN_FAILED_UUID_SIZE;

#if (!defined (BNEP_SUPPORTS_ALL_UUID_LENGTHS) || BNEP_SUPPORTS_ALL_UUID_LENGTHS == FALSE)
    if (src_uuid->len != 2)
        return BNEP_CONN_FAILED_UUID_SIZE;
#endif

    if (!p_bcb)
    {
        if ((p_bcb = bnepu_allocate_bcb (p_rem_bda)) == NULL)
            return (BNEP_NO_RESOURCES);
    }
    else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
            return BNEP_WRONG_STATE;
    else
    {
        /* Backup current UUID values to restore if role change fails */
        memcpy ((UINT8 *)&(p_bcb->prv_src_uuid), (UINT8 *)&(p_bcb->src_uuid), sizeof (tBT_UUID));
        memcpy ((UINT8 *)&(p_bcb->prv_dst_uuid), (UINT8 *)&(p_bcb->dst_uuid), sizeof (tBT_UUID));
    }

    /* We are the originator of this connection */
    p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;

    memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)src_uuid, sizeof (tBT_UUID));
    memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)dst_uuid, sizeof (tBT_UUID));

    if (p_bcb->con_state == BNEP_STATE_CONNECTED)
    {
        /* Transition to the next appropriate state, waiting for connection confirm. */
        p_bcb->con_state = BNEP_STATE_SEC_CHECKING;

        BNEP_TRACE_API ("BNEP initiating security procedures for src uuid 0x%x",
            p_bcb->src_uuid.uu.uuid16);

#if (defined (BNEP_DO_AUTH_FOR_ROLE_SWITCH) && BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE)
        btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
                                   BTM_SEC_PROTO_BNEP,
                                   bnep_get_uuid32(src_uuid),
                                   &bnep_sec_check_complete, p_bcb);
#else
        bnep_sec_check_complete (p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
#endif

    }
    else
    {
        /* Transition to the next appropriate state, waiting for connection confirm. */
        p_bcb->con_state = BNEP_STATE_CONN_START;

        if ((cid = L2CA_ConnectReq (BT_PSM_BNEP, p_bcb->rem_bda)) != 0)
        {
            p_bcb->l2cap_cid = cid;

        }
        else
        {
            BNEP_TRACE_ERROR ("BNEP - Originate failed");
            if (bnep_cb.p_conn_state_cb)
                (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
            bnepu_release_bcb (p_bcb);
            return BNEP_CONN_FAILED;
        }

        /* Start timer waiting for connect */
        btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
    }

    *p_handle = p_bcb->handle;
    return (BNEP_SUCCESS);
}
Ejemplo n.º 23
0
/*******************************************************************************
**
** Function         l2c_rcv_acl_data
**
** Description      This function is called from the HCI Interface when an ACL
**                  data packet is received.
**
** Returns          void
**
*******************************************************************************/
void l2c_rcv_acl_data (BT_HDR *p_msg)
{
    UINT8       *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
    UINT16      handle, hci_len;
    UINT8       pkt_type;
    tL2C_LCB    *p_lcb;
    tL2C_CCB    *p_ccb = NULL;
    UINT16      l2cap_len, rcv_cid, psm;

    /* Extract the handle */
    STREAM_TO_UINT16 (handle, p);
    pkt_type = HCID_GET_EVENT (handle);
    handle   = HCID_GET_HANDLE (handle);

    /* Since the HCI Transport is putting segmented packets back together, we */
    /* should never get a valid packet with the type set to "continuation"    */
    if (pkt_type != L2CAP_PKT_CONTINUE)
    {
        /* Find the LCB based on the handle */
        if ((p_lcb = l2cu_find_lcb_by_handle (handle)) == NULL)
        {
            UINT8       cmd_code;

            /* There is a slight possibility (specifically with USB) that we get an */
            /* L2CAP connection request before we get the HCI connection complete.  */
            /* So for these types of messages, hold them for up to 2 seconds.       */
            STREAM_TO_UINT16 (hci_len, p);
            STREAM_TO_UINT16 (l2cap_len, p);
            STREAM_TO_UINT16 (rcv_cid, p);
            STREAM_TO_UINT8  (cmd_code, p);

            if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID)
                && (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ))
            {
                L2CAP_TRACE_WARNING5 ("L2CAP - holding ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d",
                                    handle, p_msg->layer_specific, rcv_cid, cmd_code,
                                    l2cb.rcv_hold_q.count);
                p_msg->layer_specific = 2;
                GKI_enqueue (&l2cb.rcv_hold_q, p_msg);

                if (l2cb.rcv_hold_q.count == 1)
                    btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT);

                return;
            }
            else
            {
                L2CAP_TRACE_ERROR5 ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d",
                                    handle, p_msg->layer_specific, rcv_cid, cmd_code, l2cb.rcv_hold_q.count);
            }
            GKI_freebuf (p_msg);
            return;
        }
    }
    else
    {
        L2CAP_TRACE_WARNING1 ("L2CAP - expected pkt start or complete, got: %d", pkt_type);
        GKI_freebuf (p_msg);
        return;
    }

    /* Extract the length and update the buffer header */
    STREAM_TO_UINT16 (hci_len, p);
    p_msg->offset += 4;

#if (L2CAP_HOST_FLOW_CTRL == TRUE)
    /* Send ack if we hit the threshold */
    if (++p_lcb->link_pkts_unacked >= p_lcb->link_ack_thresh)
        btu_hcif_send_host_rdy_for_data();
#endif

    /* Extract the length and CID */
    STREAM_TO_UINT16 (l2cap_len, p);
    STREAM_TO_UINT16 (rcv_cid, p);

    /* Find the CCB for this CID */
    if (rcv_cid >= L2CAP_BASE_APPL_CID)
    {
        if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, rcv_cid)) == NULL)
        {
            L2CAP_TRACE_WARNING1 ("L2CAP - unknown CID: 0x%04x", rcv_cid);
            GKI_freebuf (p_msg);
            return;
        }
    }

    if (hci_len >= L2CAP_PKT_OVERHEAD)  /* Must receive at least the L2CAP length and CID.*/
    {
        p_msg->len    = hci_len - L2CAP_PKT_OVERHEAD;
        p_msg->offset += L2CAP_PKT_OVERHEAD;
    }
    else
    {
        L2CAP_TRACE_WARNING0 ("L2CAP - got incorrect hci header" );
        GKI_freebuf (p_msg);
        return;
    }

    if (l2cap_len != p_msg->len)
    {
        L2CAP_TRACE_WARNING2 ("L2CAP - bad length in pkt. Exp: %d  Act: %d",
                              l2cap_len, p_msg->len);

        GKI_freebuf (p_msg);
        return;
    }

    /* Send the data through the channel state machine */
    if (rcv_cid == L2CAP_SIGNALLING_CID)
    {
        process_l2cap_cmd (p_lcb, p, l2cap_len);
        GKI_freebuf (p_msg);
    }
    else if (rcv_cid == L2CAP_CONNECTIONLESS_CID)
    {
        /* process_connectionless_data (p_lcb); */
        STREAM_TO_UINT16 (psm, p);
        L2CAP_TRACE_DEBUG1( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ;
#if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
        if (psm == TCS_PSM_INTERCOM || psm == TCS_PSM_CORDLESS)
        {
            p_msg->offset += L2CAP_BCST_OVERHEAD;
            p_msg->len -= L2CAP_BCST_OVERHEAD;
            tcs_proc_bcst_msg( p_lcb->remote_bd_addr, p_msg ) ;
            GKI_freebuf (p_msg);
        }
        else
#endif

#if (L2CAP_UCD_INCLUDED == TRUE)
        /* if it is not broadcast, check UCD registration */
        if ( l2c_ucd_check_rx_pkts( p_lcb, p_msg ) )
        {
            /* nothing to do */
        }
        else
#endif
            GKI_freebuf (p_msg);
    }
#if (BLE_INCLUDED == TRUE)
    else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID)
    {
        l2cble_process_sig_cmd (p_lcb, p, l2cap_len);
        GKI_freebuf (p_msg);
    }
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0)
    else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) && (rcv_cid <= L2CAP_LAST_FIXED_CHNL) &&
             (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) )
    {
        /* If no CCB for this channel, allocate one */
        if (l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
        {
            p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];

            if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
                l2c_fcr_proc_pdu (p_ccb, p_msg);
            else
                (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_lcb->remote_bd_addr, p_msg);
        }
        else
            GKI_freebuf (p_msg);
    }
#endif

    else
    {
        if (p_ccb == NULL)
            GKI_freebuf (p_msg);
        else
        {
            /* Basic mode packets go straight to the state machine */
            if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
                l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg);
            else
            {
                /* eRTM or streaming mode, so we need to validate states first */
                if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG))
                    l2c_fcr_proc_pdu (p_ccb, p_msg);
                else
                    GKI_freebuf (p_msg);
            }
        }
    }
}