Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e7cdeb2 authored by Dundi Raviteja's avatar Dundi Raviteja
Browse files

wlan: Add BTSCO handling for SWPTA BTC design

If BTSCO profile is enabled, abort any ongoing scan,
disable scan and disconnect STA if connected.

If BTSCO profile is disabled, enable scan and allow
connection.

Change-Id: Ib32176ee627d4b21d8bbade8a8fb7577452ba967
CRs-Fixed: 2792127
parent 2c9ea943
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1572,6 +1572,10 @@ struct hdd_cache_channels {
	struct hdd_cache_channel_info *channel_info;
};

#ifdef FEATURE_WLAN_SW_PTA
#define WLAN_WAIT_TIME_SW_PTA 1000
#endif

struct hdd_context_s
{
   /** Global VOS context  */
@@ -1791,6 +1795,7 @@ struct hdd_context_s

    v_BOOL_t btCoexModeSet;
    v_BOOL_t isPnoEnable;
    bool     is_sco_enabled;
    macAddrSpoof_t spoofMacAddr;
    /* flag to decide if driver need to scan DFS channels or not */
    v_BOOL_t  disable_dfs_flag;
@@ -1863,6 +1868,9 @@ struct hdd_context_s
    struct hdd_cache_channels *original_channels;
    struct mutex cache_channel_lock;
    bool force_rsne_override;
#ifdef FEATURE_WLAN_SW_PTA
    struct completion sw_pta_comp;
#endif
};

/* Use to notify the TDLS or BTCOEX is mode enable */
+30 −0
Original line number Diff line number Diff line
@@ -15804,6 +15804,19 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
    }
    mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
    /**
     * If sw pta is enabled, scan should not allowed.
     * Returning error makes framework to trigger scan continuously
     * for every second, so indicating framework that scan is aborted
     * and return success.
     */
    if (pHddCtx->cfg_ini->is_sw_pta_enabled && pHddCtx->is_sco_enabled) {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                  FL("BT SCO operation in progress"));
        hdd_cfg80211_scan_done(pAdapter, request, true);
        return 0;
    }
    /* Check if scan is allowed at this point of time.
     */
    if (TRUE == pHddCtx->btCoexModeSet)
@@ -16322,6 +16335,14 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
        return -EINVAL;
    }
    /**
     * If sw pta is enabled, new connections should not allowed.
     */
    if (pHddCtx->cfg_ini->is_sw_pta_enabled && pHddCtx->is_sco_enabled) {
        hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO operation in progress",
               __func__);
        return -EINVAL;
    }
    pRoamProfile = &pWextState->roamProfile;
@@ -20077,6 +20098,15 @@ void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
    }
    spin_unlock(&pHddCtx->schedScan_lock);
    /**
     * If sw pta is enabled, scan results should not send to framework.
     */
    if (pHddCtx->cfg_ini->is_sw_pta_enabled && pHddCtx->is_sco_enabled) {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                  FL("BT SCO operation in progress"));
        return;
    }
    ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
    if (0 > ret)
+159 −3
Original line number Diff line number Diff line
@@ -3922,9 +3922,15 @@ static void hdd_sysfs_bt_profile_create(hdd_context_t* hdd_ctx)
		return;
	}
	if(sysfs_create_file(driver_kobject, &bt_profile_attribute.attr))
	if (sysfs_create_file(driver_kobject, &bt_profile_attribute.attr)) {
		hddLog(VOS_TRACE_LEVEL_ERROR,
		       "%s:Failed to create BT profile sysfs entry", __func__);
		kobject_put(driver_kobject);
		driver_kobject = NULL;
		return;
	}
	init_completion(&hdd_ctx->sw_pta_comp);
}
static void hdd_sysfs_bt_profile_destroy(hdd_context_t* hdd_ctx)
@@ -3932,8 +3938,10 @@ static void hdd_sysfs_bt_profile_destroy(hdd_context_t* hdd_ctx)
	if(!hdd_ctx->cfg_ini->is_sw_pta_enabled)
		return;
	sysfs_remove_file(driver_kobject, &bt_profile_attribute.attr);
	complete(&hdd_ctx->sw_pta_comp);
	if (driver_kobject) {
		sysfs_remove_file(driver_kobject, &bt_profile_attribute.attr);
		kobject_put(driver_kobject);
		driver_kobject = NULL;
	}
@@ -3963,6 +3971,146 @@ static int hdd_sysfs_validate_and_copy_buf(char *dest_buf, size_t dest_buf_size,
	return 0;
}
static void hdd_sco_resp_callback(uint8_t sco_status)
{
	hdd_context_t *hdd_ctx = NULL;
	v_CONTEXT_t vos_ctx = NULL;
	vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
	if (!vos_ctx) {
		hddLog(VOS_TRACE_LEVEL_FATAL,
		       "%s: Global VOS context is Null", __func__);
		return;
	}
	/* Get the HDD context. */
	hdd_ctx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
	if (!hdd_ctx) {
		hddLog(VOS_TRACE_LEVEL_FATAL,
		       "%s: HDD context is Null",__func__);
		return;
	}
	hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: Response status %d",
	       __func__, sco_status);
	if (sco_status) {
		hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid sco status %d",
		       __func__, sco_status);
		return;
	}
	complete(&hdd_ctx->sw_pta_comp);
}
static ssize_t __hdd_process_bt_sco_profile(hdd_context_t *hdd_ctx,
					    char *profile_mode)
{
	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hdd_ctx->hHal);
	hdd_station_ctx_t *hdd_sta_ctx;
	eConnectionState conn_state;
	hdd_adapter_t *adapter;
	eHalStatus hal_status;
	bool sco_status;
	int rc;
	if (!mac_ctx) {
		hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mac_ctx got NULL", __func__);
		return -EINVAL;
	}
	if (!strcmp(profile_mode, "ENABLE")) {
		if (hdd_ctx->is_sco_enabled) {
			hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO is already enabled",
			       __func__);
			return 0;
		}
		sco_status = true;
	} else if (!strcmp(profile_mode, "DISABLE")) {
		if (!hdd_ctx->is_sco_enabled) {
			hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO is already disabled",
			       __func__);
			return 0;
		}
		sco_status = false;
	} else {
		hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid profile mode %s",
		       __func__, profile_mode);
		return -EINVAL;
	}
	INIT_COMPLETION(hdd_ctx->sw_pta_comp);
	hal_status = sme_sco_req(hdd_ctx->hHal,
				 hdd_sco_resp_callback,
				 adapter->sessionId, sco_status);
	if (!HAL_STATUS_SUCCESS(hal_status)) {
		hddLog(VOS_TRACE_LEVEL_ERROR,
		       "%s: Error sending sme sco indication request",
		       __func__);
		return -EINVAL;
	}
	rc = wait_for_completion_timeout(&hdd_ctx->sw_pta_comp,
			msecs_to_jiffies(WLAN_WAIT_TIME_SW_PTA));
	if (!rc) {
		hddLog(VOS_TRACE_LEVEL_ERROR,
		       FL("Target response timed out for sw_pta_comp"));
		return -EINVAL;
	}
	if (!strcmp(profile_mode, "DISABLE")) {
		hdd_ctx->is_sco_enabled = false;
		mac_ctx->isCoexScoIndSet = 0;
		return 0;
	}
	adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
	if (!adapter) {
		hddLog(VOS_TRACE_LEVEL_ERROR,
		       "%s: No station adapter to enable bt sco", __func__);
		return -EINVAL;
	}
	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
	if (!hdd_sta_ctx) {
		hddLog(VOS_TRACE_LEVEL_ERROR,
		       "%s: No station context to enable bt sco", __func__);
		return -EINVAL;
	}
	if (wlan_hdd_scan_abort(adapter)) {
		hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Error aborting scan request",
		       __func__);
		return -EINVAL;
	}
	hdd_ctx->is_sco_enabled = true;
	mac_ctx->isCoexScoIndSet = 1;
	conn_state = hdd_sta_ctx->conn_info.connState;
	if (eConnectionState_Connecting == conn_state ||
	    smeNeighborMiddleOfRoaming(hdd_sta_ctx) ||
	    (eConnectionState_Associated == conn_state &&
	      sme_is_sta_key_exchange_in_progress(hdd_ctx->hHal,
						  adapter->sessionId)))
		sme_abortConnection(hdd_ctx->hHal,
				    adapter->sessionId);
	if (hdd_connIsConnected(hdd_sta_ctx)) {
		hal_status = sme_teardown_link_with_ap(mac_ctx,
						       adapter->sessionId);
		if (!HAL_STATUS_SUCCESS(hal_status)) {
			hddLog(VOS_TRACE_LEVEL_ERROR,
			       "%s: Error while Teardown link wih AP",
			       __func__);
			return -EINVAL;
		}
	}
	return 0;
}
static ssize_t __hdd_sysfs_bt_profile_ind_cmd_store(hdd_context_t *hdd_ctx,
						    const char *buf,
						    size_t count)
@@ -3973,8 +4121,11 @@ static ssize_t __hdd_sysfs_bt_profile_ind_cmd_store(hdd_context_t *hdd_ctx,
	ENTER();
	if (wlan_hdd_validate_context(hdd_ctx))
	if (wlan_hdd_validate_context(hdd_ctx)) {
		if (hdd_ctx && hdd_ctx->isLogpInProgress)
			return -EAGAIN;
		return -EINVAL;
	}
	ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
					      buf, count);
@@ -4001,7 +4152,12 @@ static ssize_t __hdd_sysfs_bt_profile_ind_cmd_store(hdd_context_t *hdd_ctx,
	hddLog(VOS_TRACE_LEVEL_INFO, "%s:profile = %s, profile_mode = %s",
	       __func__, profile, profile_mode);
	if (!strcmp(profile, "BT_PROFILE_SCO"))
		if (__hdd_process_bt_sco_profile(hdd_ctx, profile_mode))
			return -EINVAL;
	EXIT();
	return count;
}
+1 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ enum eWniMsgTypes
    eWNI_SME_SEND_SAE_MSG,
#ifdef FEATURE_WLAN_SW_PTA
    eWNI_SME_SW_PTA_RESP,
    eWNI_SME_TEARDOWN_LINK_WITH_AP,
#endif
    eWNI_SME_MSG_TYPES_END
};
+12 −0
Original line number Diff line number Diff line
@@ -283,6 +283,18 @@ struct sir_mgmt_msg {
    uint8_t *data;
};

#ifdef FEATURE_WLAN_SW_PTA
/**
 * struct sir_teardown_link - Struct used to tear down link with AP
 * @type: Message type
 * @session_id: session id
 */
struct sir_teardown_link {
    uint16_t type;
    uint8_t session_id;
};
#endif

/// Message queue definitions
//  msgtype(2bytes) reserved(2bytes) bodyptr(4bytes) bodyval(4bytes)
//  NOTE tSirMsgQ should be always multiples of WORD(4Bytes)
Loading