/******************************************************************************* ** ** Function SMP_SecurityGrant ** ** Description This function is called to grant security process. ** ** Parameters bd_addr - peer device bd address. ** res - result of the operation SMP_SUCCESS if success. ** Otherwise, SMP_REPEATED_ATTEMPTS is too many attempts. ** ** Returns None ** *******************************************************************************/ void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res) { SMP_TRACE_EVENT ("SMP_SecurityGrant "); if (smp_cb.smp_over_br) { if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP || smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) { return; } /* clear the SMP_SEC_REQUEST_EVT event after get grant */ /* avoid generating duplicate pair request */ smp_cb.cb_evt = 0; smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res); return; } if (smp_cb.state != SMP_STATE_WAIT_APP_RSP || smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) { return; } /* clear the SMP_SEC_REQUEST_EVT event after get grant */ /* avoid generate duplicate pair request */ smp_cb.cb_evt = 0; smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res); }
/******************************************************************************* ** ** Function SMP_BR_PairWith ** ** Description This function is called to start a SMP pairing over BR/EDR. ** Device support one SMP pairing at one time. ** ** Parameters bd_addr - peer device bd address. ** ** Returns SMP_STARTED if pairing started, otherwise reason for failure. ** *******************************************************************************/ tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr) { tSMP_CB *p_cb = &smp_cb; UINT8 status = SMP_PAIR_INTERNAL_ERR; SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ", __func__, p_cb->state, p_cb->br_state, p_cb->flags); if (p_cb->state != SMP_STATE_IDLE || p_cb->smp_over_br || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) { /* pending security on going, reject this one */ return SMP_BUSY; } p_cb->role = HCI_ROLE_MASTER; p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD; p_cb->smp_over_br = TRUE; memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN); if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE)) { SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__); smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status); return status; } return SMP_STARTED; }
/******************************************************************************* ** ** Function smp_br_connect_callback ** ** Description This callback function is called by L2CAP to indicate that ** SMP BR channel is ** connected (conn = TRUE)/disconnected (conn = FALSE). ** *******************************************************************************/ static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport) { tSMP_CB *p_cb = &smp_cb; tSMP_INT_DATA int_data; SMP_TRACE_EVENT ("%s", __func__); if (transport != BT_TRANSPORT_BR_EDR) { SMP_TRACE_WARNING("%s is called on unexpected transport %d", __func__, transport); return; } if (!(memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0)) return; SMP_TRACE_EVENT ("%s for pairing BDA: %08x%04x Event: %s", __func__, (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3], (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected"); if (connected) { if(!p_cb->connect_initialized) { p_cb->connect_initialized = TRUE; /* initialize local i/r key to be default keys */ p_cb->local_r_key = p_cb->local_i_key = SMP_BR_SEC_DEFAULT_KEY; p_cb->loc_auth_req = p_cb->peer_auth_req = 0; p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT; smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_CONN_EVT, NULL); } } else { int_data.reason = reason; /* Disconnected while doing security */ smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_DISCONN_EVT, &int_data); } }
/******************************************************************************* ** ** 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 smp_tx_complete_callback ** ** Description SMP channel tx complete callback ** *******************************************************************************/ static void smp_tx_complete_callback (UINT16 cid, UINT16 num_pkt) { tSMP_CB *p_cb = &smp_cb; if (p_cb->total_tx_unacked >= num_pkt) p_cb->total_tx_unacked -= num_pkt; else SMP_TRACE_ERROR("Unexpected %s: num_pkt = %d", __func__,num_pkt); UINT8 reason = SMP_SUCCESS; if (p_cb->total_tx_unacked == 0 && p_cb->wait_for_authorization_complete) { if (cid == L2CAP_SMP_CID) smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); else smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason); } }