diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c index 6fa2d22fe8fc..344b6c413cbb 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -19,18 +19,198 @@ */ #include "wlan_cm_main_api.h" +#include "wlan_cm_bss_score_param.h" +#include "wlan_scan_api.h" +#include "wlan_cm_sm.h" +#ifdef WLAN_POLICY_MGR_ENABLE +#include "wlan_policy_mgr_api.h" +#endif -QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx, struct cm_connect_req *req) +#ifdef WLAN_POLICY_MGR_ENABLE +static void +cm_get_pcl_chan_weigtage_for_sta(struct wlan_objmgr_pdev *pdev, + struct pcl_freq_weight_list *pcl_lst) { - /* - * TODO: Interface event, get candidate list, do hw mode change and - * serialize. Also move to scan state from here if required. - * If candidate found and all are blacklisted or serialization fails - * post WLAN_CM_SM_EV_CONNECT_REQ_FAIL. - */ + enum QDF_OPMODE opmode = QDF_STA_MODE; + enum policy_mgr_con_mode pm_mode; + uint32_t num_entries = 0; + QDF_STATUS status; + + if (!pcl_lst) + return; + + if (policy_mgr_map_concurrency_mode(&opmode, &pm_mode)) { + status = policy_mgr_get_pcl(wlan_pdev_get_psoc(pdev), pm_mode, + pcl_lst->pcl_freq_list, + &num_entries, + pcl_lst->pcl_weight_list, + NUM_CHANNELS); + if (QDF_IS_STATUS_ERROR(status)) + return; + pcl_lst->num_of_pcl_channels = num_entries; + } +} + +static void cm_calculate_scores(struct wlan_objmgr_pdev *pdev, + struct scan_filter *filter, qdf_list_t *list) +{ + struct pcl_freq_weight_list *pcl_lst = NULL; + + if (!filter->num_of_bssid) { + pcl_lst = qdf_mem_malloc(sizeof(*pcl_lst)); + cm_get_pcl_chan_weigtage_for_sta(pdev, pcl_lst); + if (pcl_lst && !pcl_lst->num_of_pcl_channels) { + qdf_mem_free(pcl_lst); + pcl_lst = NULL; + } + } + wlan_cm_calculate_bss_score(pdev, pcl_lst, list, &filter->bssid_hint); + if (pcl_lst) + qdf_mem_free(pcl_lst); +} +#else +static inline +void cm_calculate_scores(struct wlan_objmgr_pdev *pdev, + struct scan_filter *filter, qdf_list_t *list) +{ + wlan_cm_calculate_bss_score(pdev, NULL, list, &filter->bssid_hint); +} +#endif + +#ifdef WLAN_FEATURE_11W +static inline void +cm_set_pmf_caps(struct cm_connect_req *cm_req, struct scan_filter *filter) +{ + filter->pmf_cap = cm_req->req.crypto.pmf_cap; +} +#else +static inline void +cm_set_pmf_caps(struct cm_connect_req *cm_req, struct scan_filter *filter) +{} +#endif + +static void cm_connect_prepare_scan_fliter(struct cnx_mgr *cm_ctx, + struct cm_connect_req *cm_req, + struct scan_filter *filter) +{ + if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) { + filter->num_of_bssid = 1; + qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid); + } + + qdf_copy_macaddr(&filter->bssid_hint, &cm_req->req.bssid_hint); + filter->num_of_ssid = 1; + qdf_mem_copy(&filter->ssid_list[0], &cm_req->req.ssid, + sizeof(struct wlan_ssid)); + + if (cm_req->req.chan_freq) { + filter->num_of_channels = 1; + filter->chan_freq_list[0] = cm_req->req.chan_freq; + } + + /* TODO: Fill band (STA+STA) */ + /* TODO: RSN OVERRIDE */ + + filter->authmodeset = cm_req->req.crypto.auth_type; + filter->ucastcipherset = cm_req->req.crypto.ciphers_pairwise; + filter->key_mgmt = cm_req->req.crypto.akm_suites; + filter->mcastcipherset = cm_req->req.crypto.group_cipher; + filter->mgmtcipherset = cm_req->req.crypto.mgmt_ciphers; + + cm_set_pmf_caps(cm_req, filter); + + /* TODO: FOR WPS/OSEN set ignore auth */ + /* TODO: SET mobility domain */ + /* TODO: fill fils info */ +} + +static QDF_STATUS +cm_send_connect_start_fail(struct cnx_mgr *cm_ctx, + struct cm_connect_req *cm_req, + enum wlan_cm_connect_fail_reason reason) +{ + struct wlan_cm_connect_rsp *resp; + + resp = qdf_mem_malloc(sizeof(*resp)); + if (!resp) + return QDF_STATUS_E_NOMEM; + + return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, + sizeof(*resp), resp); + qdf_mem_free(resp); +} + +static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev, + struct cnx_mgr *cm_ctx, + struct cm_connect_req *cm_req) +{ + struct scan_filter *filter; + uint32_t num_bss = 0; + enum QDF_OPMODE op_mode; + qdf_list_t *candidate_list; + + filter = qdf_mem_malloc(sizeof(*filter)); + if (!filter) + return QDF_STATUS_E_NOMEM; + + cm_connect_prepare_scan_fliter(cm_ctx, cm_req, filter); + + candidate_list = wlan_scan_get_result(pdev, filter); + if (candidate_list) { + num_bss = qdf_list_size(candidate_list); + mlme_debug("num_entries found %d", num_bss); + } + + op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); + if (num_bss && op_mode == QDF_STA_MODE) + cm_calculate_scores(pdev, filter, candidate_list); + qdf_mem_free(filter); + + if (!candidate_list || + (candidate_list && !qdf_list_size(candidate_list))) { + if (candidate_list) + wlan_scan_purge_results(candidate_list); + mlme_info("No valid candidate found num_bss %d", num_bss); + /* + * Do connect scan only of no candidates were found + * if candidates were found and were removed due to invalid + * return failure + */ + if (!num_bss) + return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_SCAN, + sizeof(*cm_req), cm_req); + + return QDF_STATUS_E_EMPTY; + } + cm_req->candidate_list = candidate_list; + return QDF_STATUS_SUCCESS; } +QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx, + struct cm_connect_req *cm_req) +{ + struct wlan_objmgr_pdev *pdev; + enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE; + QDF_STATUS status; + + /* TODO: Interface event */ + pdev = wlan_vdev_get_pdev(cm_ctx->vdev); + if (!pdev) + return QDF_STATUS_E_INVAL; + status = cm_connect_get_candidates(pdev, cm_ctx, cm_req); + if (QDF_IS_STATUS_ERROR(status)) { + reason = CM_NO_CANDIDATE_FOUND; + goto connect_err; + } + + /* TODO: Do HW mode change */ + /* TODO: serialize */ + return QDF_STATUS_SUCCESS; +connect_err: + return cm_send_connect_start_fail(cm_ctx, cm_req, reason); +} + QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) { /* @@ -72,3 +252,19 @@ QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, */ return QDF_STATUS_SUCCESS; } + +QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_connect_req *req) +{ + struct cnx_mgr *cm_ctx = NULL; + struct cm_connect_req *cm_req = NULL; + + /* + * TODO: Get WAPI/WPA/RSN IE and refill crypto params of req. + * Prepare cm_connect_req cm_req, get cm id and inform it to OSIF. + * store connect req to the cm ctx req_list + */ + + return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_REQ, + sizeof(*cm_req), cm_req); +} diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c index ed177c621ba9..9ee6e9851d79 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c @@ -18,6 +18,7 @@ * DOC: Implements disconnect specific apis of connection manager */ #include "wlan_cm_main_api.h" +#include "wlan_cm_sm.h" QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx, struct cm_disconnect_req *req) @@ -48,3 +49,17 @@ QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx, return QDF_STATUS_SUCCESS; } +QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_disconnect_req *req) +{ + struct cnx_mgr *cm_ctx = NULL; + struct cm_disconnect_req *cm_req = NULL; + + /* + * TODO: Prepare cm_disconnect_req cm_req, get cm id and inform it to + * OSIF. store disconnect req to the cm ctx req_list + */ + + return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_REQ, + sizeof(*cm_req), cm_req); +} diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main.h index 16ac62a6d019..f28662492fd1 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_main.h @@ -71,63 +71,6 @@ enum wlan_cm_sm_state { WLAN_CM_SS_MAX = 14, }; -/** - * enum wlan_cm_sm_evt - connection manager related events - * @WLAN_CM_SM_EV_CONNECT_REQ: Connect request event from requester - * @WLAN_CM_SM_EV_SCAN: Event to start connect scan - * @WLAN_CM_SM_EV_SCAN_SUCCESS: Connect scan success event - * @WLAN_CM_SM_EV_SCAN_FAILURE: Connect scan fail event - * @WLAN_CM_SM_EV_CONNECT_START: Connect start process initiate - * @WLAN_CM_SM_EV_CONNECT_ACTIVE: Connect request is activated - * @WLAN_CM_SM_EV_CONNECT_SUCCESS: Connect success - * @WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: Get next candidate for connection - * @WLAN_CM_SM_EV_CONNECT_FAILURE: Connect failed for all candidate - * @WLAN_CM_SM_EV_DISCONNECT_REQ: Disconnect request event from - * requester - * @WLAN_CM_SM_EV_DISCONNECT_START: Start disconnect sequence - * @WLAN_CM_SM_EV_DISCONNECT_ACTIVE: Process disconnect after in active cmd - * @WLAN_CM_SM_EV_DISCONNECT_DONE: Disconnect done event - * @WLAN_CM_SM_EV_ROAM_START: Roam start event - * @WLAN_CM_SM_EV_ROAM_SYNC: Roam sync event - * @WLAN_CM_SM_EV_ROAM_INVOKE_FAIL: Roam invoke fail event - * @WLAN_CM_SM_EV_ROAM_HO_FAIL: Hand off failed event - * @WLAN_CM_SM_EV_PREAUTH_DONE: Preauth is completed - * @WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP: Get next candidate as preauth failed - * @WLAN_CM_SM_EV_PREAUTH_FAIL: Preauth failed for all candidate - * @WLAN_CM_SM_EV_START_REASSOC: Start reassoc after preauth done - * @WLAN_CM_SM_EV_REASSOC_DONE: Reassoc completed - * @WLAN_CM_SM_EV_REASSOC_FAILURE: Reassoc failed - * @WLAN_CM_SM_EV_ROAM_COMPLETE: Roaming completed - * @WLAN_CM_SM_EV_MAX: Max event - */ -enum wlan_cm_sm_evt { - WLAN_CM_SM_EV_CONNECT_REQ = 0, - WLAN_CM_SM_EV_SCAN = 1, - WLAN_CM_SM_EV_SCAN_SUCCESS = 2, - WLAN_CM_SM_EV_SCAN_FAILURE = 3, - WLAN_CM_SM_EV_CONNECT_START = 4, - WLAN_CM_SM_EV_CONNECT_ACTIVE = 5, - WLAN_CM_SM_EV_CONNECT_SUCCESS = 6, - WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 7, - WLAN_CM_SM_EV_CONNECT_FAILURE = 8, - WLAN_CM_SM_EV_DISCONNECT_REQ = 9, - WLAN_CM_SM_EV_DISCONNECT_START = 10, - WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 11, - WLAN_CM_SM_EV_DISCONNECT_DONE = 12, - WLAN_CM_SM_EV_ROAM_START = 13, - WLAN_CM_SM_EV_ROAM_SYNC = 14, - WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 15, - WLAN_CM_SM_EV_ROAM_HO_FAIL = 16, - WLAN_CM_SM_EV_PREAUTH_DONE = 17, - WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 18, - WLAN_CM_SM_EV_PREAUTH_FAIL = 19, - WLAN_CM_SM_EV_START_REASSOC = 20, - WLAN_CM_SM_EV_REASSOC_DONE = 21, - WLAN_CM_SM_EV_REASSOC_FAILURE = 22, - WLAN_CM_SM_EV_ROAM_COMPLETE = 23, - WLAN_CM_SM_EV_MAX, -}; - /** * struct cm_state_sm - connection manager sm * @cm_sm_lock: sm lock @@ -164,7 +107,7 @@ struct cm_connect_req { qdf_timer_t hw_mode_timer; struct wlan_cm_connect_req req; struct element_info rsn_ie; - qdf_list_t candidate_list; + qdf_list_t *candidate_list; struct scan_cache_node *cur_candidate; }; diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h index b0184a356f5e..6c9594fa47a3 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h @@ -102,6 +102,16 @@ QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id); QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, struct wlan_cm_connect_rsp *resp); +/** + * cm_connect_start_req() - Connect start req from the requester + * @vdev: vdev on which connect is received + * @req: Connection req provided + * + * Return: QDF status + */ +QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_connect_req *req); + /*************** DISCONNECT APIs ****************/ /** @@ -125,7 +135,7 @@ QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx, QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id); /** - * cm_connect_complete() - This API would be called after connect complete + * cm_disconnect_complete() - This API would be called after disconnect complete * request from the serialization. * @cm_ctx: connection manager context * @resp: disconnection complete resp. @@ -137,4 +147,14 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id); QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx, struct wlan_cm_discon_rsp *resp); +/** + * cm_disconnect_start_req() - Disconnect start req from the requester + * @vdev: vdev on which connect is received + * @req: disconnection req provided + * + * Return: QDF status + */ +QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev, + struct wlan_cm_disconnect_req *req); + #endif /* __WLAN_CM_MAIN_API_H__ */ diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h index 3d5579e0ca25..2d9177d67cb0 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h @@ -26,6 +26,63 @@ #ifdef FEATURE_CM_ENABLE #include +/** + * enum wlan_cm_sm_evt - connection manager related events + * @WLAN_CM_SM_EV_CONNECT_REQ: Connect request event from requester + * @WLAN_CM_SM_EV_SCAN: Event to start connect scan + * @WLAN_CM_SM_EV_SCAN_SUCCESS: Connect scan success event + * @WLAN_CM_SM_EV_SCAN_FAILURE: Connect scan fail event + * @WLAN_CM_SM_EV_CONNECT_START: Connect start process initiate + * @WLAN_CM_SM_EV_CONNECT_ACTIVE: Connect request is activated + * @WLAN_CM_SM_EV_CONNECT_SUCCESS: Connect success + * @WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: Get next candidate for connection + * @WLAN_CM_SM_EV_CONNECT_FAILURE: Connect failed for all candidate + * @WLAN_CM_SM_EV_DISCONNECT_REQ: Disconnect request event from + * requester + * @WLAN_CM_SM_EV_DISCONNECT_START: Start disconnect sequence + * @WLAN_CM_SM_EV_DISCONNECT_ACTIVE: Process disconnect after in active cmd + * @WLAN_CM_SM_EV_DISCONNECT_DONE: Disconnect done event + * @WLAN_CM_SM_EV_ROAM_START: Roam start event + * @WLAN_CM_SM_EV_ROAM_SYNC: Roam sync event + * @WLAN_CM_SM_EV_ROAM_INVOKE_FAIL: Roam invoke fail event + * @WLAN_CM_SM_EV_ROAM_HO_FAIL: Hand off failed event + * @WLAN_CM_SM_EV_PREAUTH_DONE: Preauth is completed + * @WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP: Get next candidate as preauth failed + * @WLAN_CM_SM_EV_PREAUTH_FAIL: Preauth failed for all candidate + * @WLAN_CM_SM_EV_START_REASSOC: Start reassoc after preauth done + * @WLAN_CM_SM_EV_REASSOC_DONE: Reassoc completed + * @WLAN_CM_SM_EV_REASSOC_FAILURE: Reassoc failed + * @WLAN_CM_SM_EV_ROAM_COMPLETE: Roaming completed + * @WLAN_CM_SM_EV_MAX: Max event + */ +enum wlan_cm_sm_evt { + WLAN_CM_SM_EV_CONNECT_REQ = 0, + WLAN_CM_SM_EV_SCAN = 1, + WLAN_CM_SM_EV_SCAN_SUCCESS = 2, + WLAN_CM_SM_EV_SCAN_FAILURE = 3, + WLAN_CM_SM_EV_CONNECT_START = 4, + WLAN_CM_SM_EV_CONNECT_ACTIVE = 5, + WLAN_CM_SM_EV_CONNECT_SUCCESS = 6, + WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 7, + WLAN_CM_SM_EV_CONNECT_FAILURE = 8, + WLAN_CM_SM_EV_DISCONNECT_REQ = 9, + WLAN_CM_SM_EV_DISCONNECT_START = 10, + WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 11, + WLAN_CM_SM_EV_DISCONNECT_DONE = 12, + WLAN_CM_SM_EV_ROAM_START = 13, + WLAN_CM_SM_EV_ROAM_SYNC = 14, + WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 15, + WLAN_CM_SM_EV_ROAM_HO_FAIL = 16, + WLAN_CM_SM_EV_PREAUTH_DONE = 17, + WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 18, + WLAN_CM_SM_EV_PREAUTH_FAIL = 19, + WLAN_CM_SM_EV_START_REASSOC = 20, + WLAN_CM_SM_EV_REASSOC_DONE = 21, + WLAN_CM_SM_EV_REASSOC_FAILURE = 22, + WLAN_CM_SM_EV_ROAM_COMPLETE = 23, + WLAN_CM_SM_EV_MAX, +}; + /** * cm_sm_create() - Invoke SM creation for connection manager * @cm_ctx: connection manager ctx diff --git a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c index 71bc74d7eb06..0e10d2f25a92 100644 --- a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c +++ b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c @@ -21,16 +21,17 @@ */ #include +#include "connection_mgr/core/src/wlan_cm_main_api.h" QDF_STATUS wlan_cm_start_connect(struct wlan_objmgr_vdev *vdev, struct wlan_cm_connect_req *req) { - return QDF_STATUS_SUCCESS; + return cm_connect_start_req(vdev, req); } QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev, struct wlan_cm_disconnect_req *req) { - return QDF_STATUS_SUCCESS; + return cm_disconnect_start_req(vdev, req); } diff --git a/umac/scan/dispatcher/inc/wlan_scan_api.h b/umac/scan/dispatcher/inc/wlan_scan_api.h index 8b0669112a9c..50b95593fce6 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_api.h @@ -223,4 +223,19 @@ static inline QDF_STATUS wlan_scan_purge_results(qdf_list_t *scan_list) return scm_purge_scan_results(scan_list); } +/** + * wlan_scan_get_result() - The Public API to get scan results + * @pdev: pdev info + * @filter: Filters + * + * This function fetches scan result + * + * Return: scan list pointer + */ +static inline qdf_list_t *wlan_scan_get_result(struct wlan_objmgr_pdev *pdev, + struct scan_filter *filter) +{ + return scm_get_scan_result(pdev, filter); +} + #endif