Loading CORE/HDD/inc/wlan_hdd_main.h +35 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -1791,6 +1795,8 @@ struct hdd_context_s v_BOOL_t btCoexModeSet; v_BOOL_t isPnoEnable; bool is_sco_enabled; bool is_bt_enabled; macAddrSpoof_t spoofMacAddr; /* flag to decide if driver need to scan DFS channels or not */ v_BOOL_t disable_dfs_flag; Loading Loading @@ -1863,6 +1869,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 */ Loading Loading @@ -2425,4 +2434,30 @@ static inline void hdd_fill_last_rx(hdd_adapter_t *adapter) #else void hdd_fill_last_rx(hdd_adapter_t *adapter); #endif #ifdef FEATURE_WLAN_SW_PTA /** * hdd_process_bt_sco_profile - process BT SCO profile * @hdd_ctx: pointer to HDD context * @bt_enabled: status of BT * @bt_sco: status of SCO * * Return: 0 on success, error on failure */ int hdd_process_bt_sco_profile(hdd_context_t *hdd_ctx, bool bt_enabled, bool bt_sco); /** * hdd_is_sw_pta_enabled - is sw pta enabled * @hdd_ctx: pointer to HDD context * * Return: bool */ bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx); #else static inline bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx) { return 0; } #endif #endif // end #if !defined( WLAN_HDD_MAIN_H ) CORE/HDD/src/wlan_hdd_cfg80211.c +37 −0 Original line number Diff line number Diff line Loading @@ -620,6 +620,13 @@ static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = }; #endif /* WLAN_NL80211_TESTMODE */ #ifdef FEATURE_WLAN_SW_PTA bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx) { return hdd_ctx->cfg_ini->is_sw_pta_enabled; } #endif #ifdef FEATURE_WLAN_CH_AVOID /* * FUNCTION: wlan_hdd_send_avoid_freq_event Loading Loading @@ -15805,6 +15812,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 (hdd_is_sw_pta_enabled(pHddCtx) && 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) Loading Loading @@ -16323,6 +16343,14 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, return -EINVAL; } /** * If sw pta is enabled, new connections should not allowed. */ if (hdd_is_sw_pta_enabled(pHddCtx) && pHddCtx->is_sco_enabled) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO operation in progress", __func__); return -EINVAL; } pRoamProfile = &pWextState->roamProfile; Loading Loading @@ -20078,6 +20106,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 (hdd_is_sw_pta_enabled(pHddCtx) && 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) CORE/HDD/src/wlan_hdd_main.c +155 −104 Original line number Diff line number Diff line Loading @@ -214,9 +214,6 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, //wait time for beacon miss rate. #define BCN_MISS_RATE_TIME 500 //max size for BT profile indication cmd #define MAX_USER_COMMAND_SIZE_BT_PROFILE_IND_CMD 24 /* * Android DRIVER command structures */ Loading Loading @@ -250,19 +247,6 @@ static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue, static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg); #endif /* WLAN_FEATURE_RMC */ #ifdef FEATURE_WLAN_SW_PTA /* BT profile sysfile entry obj */ static struct kobject *driver_kobject; static ssize_t hdd_sysfs_bt_profile_ind_cmd_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); static struct kobj_attribute bt_profile_attribute = __ATTR(bt_profile, 0220, NULL, hdd_sysfs_bt_profile_ind_cmd_store); #endif void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback); void hdd_set_wlan_suspend_mode(bool suspend); void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable); Loading Loading @@ -3909,130 +3893,198 @@ int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, } #ifdef FEATURE_WLAN_SW_PTA static void hdd_sysfs_bt_profile_create(hdd_context_t* hdd_ctx) static void hdd_sco_resp_callback(uint8_t sco_status) { if(!hdd_ctx->cfg_ini->is_sw_pta_enabled) return; hdd_context_t *hdd_ctx = NULL; v_CONTEXT_t vos_ctx = NULL; driver_kobject = kobject_create_and_add(WLAN_MODULE_NAME, kernel_kobj); if (!driver_kobject) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s:could not allocate driver kobject", __func__); 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; } if(sysfs_create_file(driver_kobject, &bt_profile_attribute.attr)) hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Failed to create BT profile sysfs entry", __func__); /* 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; } static void hdd_sysfs_bt_profile_destroy(hdd_context_t* hdd_ctx) { if(!hdd_ctx->cfg_ini->is_sw_pta_enabled) return; hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: Response status %d", __func__, sco_status); sysfs_remove_file(driver_kobject, &bt_profile_attribute.attr); if (driver_kobject) { kobject_put(driver_kobject); driver_kobject = NULL; if (sco_status) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid sco status %d", __func__, sco_status); return; } complete(&hdd_ctx->sw_pta_comp); } static int hdd_sysfs_validate_and_copy_buf(char *dest_buf, size_t dest_buf_size, char const *source_buf, size_t source_buf_size) int hdd_process_bt_sco_profile(hdd_context_t *hdd_ctx, bool bt_enabled, bool bt_sco) { if (source_buf_size > (dest_buf_size - 1)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Command length is larger than %zu bytes", __func__, dest_buf_size); tpAniSirGlobal mac_ctx = PMAC_STRUCT(hdd_ctx->hHal); uint8_t no_of_states_changed = 0; 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; } /* sysfs already provides kernel space buffer so copy from user * is not needed. Doing this extra copy operation just to ensure * the local buf is properly null-terminated. /** * At a time only one status can be changed compared to * previous command (BT_ENABLED/SCO) * If no.of states changed is greater than one it is * an invalid command. */ strlcpy(dest_buf, source_buf, dest_buf_size); if (bt_enabled != hdd_ctx->is_bt_enabled) no_of_states_changed++; /* default 'echo' cmd takes new line character to here */ if (dest_buf[source_buf_size - 1] == '\n') dest_buf[source_buf_size - 1] = '\0'; if (bt_sco != hdd_ctx->is_sco_enabled) no_of_states_changed++; return 0; if (no_of_states_changed > 1) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Multiple states changed", __func__); return -EINVAL; } static ssize_t __hdd_sysfs_bt_profile_ind_cmd_store(hdd_context_t *hdd_ctx, const char *buf, size_t count) { char buf_local[MAX_USER_COMMAND_SIZE_BT_PROFILE_IND_CMD + 1]; char *sptr, *token, *profile, *profile_mode; int ret; INIT_COMPLETION(hdd_ctx->sw_pta_comp); ENTER(); if (wlan_hdd_validate_context(hdd_ctx)) if (bt_enabled != hdd_ctx->is_bt_enabled) { hal_status = sme_bt_req(hdd_ctx->hHal, hdd_sco_resp_callback, adapter->sessionId, bt_enabled); if (!HAL_STATUS_SUCCESS(hal_status)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Error sending sme sco indication request", __func__); return -EINVAL; } ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), buf, count); if (ret) 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; } sptr = buf_local; /* Get BT profile */ token = strsep(&sptr, " "); hdd_ctx->is_bt_enabled = bt_enabled; return 0; } if (!token) return -EINVAL; profile = token; if (bt_sco) { 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 (!hdd_ctx->is_sco_enabled) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO is already disabled", __func__); return 0; } sco_status = false; } token = NULL; /* Get BT profile mode */ token = strsep(&sptr, " "); 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; } if (!token) 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; } profile_mode = token; if (!bt_sco) { hdd_ctx->is_sco_enabled = false; mac_ctx->isCoexScoIndSet = 0; return 0; } hddLog(VOS_TRACE_LEVEL_INFO, "%s:profile = %s, profile_mode = %s", __func__, profile, profile_mode); 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; } EXIT(); return count; 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; } static ssize_t hdd_sysfs_bt_profile_ind_cmd_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { hdd_context_t *pHddCtx = NULL; ssize_t err_size = 0; if (wlan_hdd_scan_abort(adapter)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Error aborting scan request", __func__); return -EINVAL; } pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_get_global_context(VOS_MODULE_ID_HDD, NULL)); hdd_ctx->is_sco_enabled = true; mac_ctx->isCoexScoIndSet = 1; if (!pHddCtx) { hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL"); 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; } } err_size = __hdd_sysfs_bt_profile_ind_cmd_store(pHddCtx, buf, count); return 0; } static void hdd_init_sw_pta(hdd_context_t *hdd_ctx) { init_completion(&hdd_ctx->sw_pta_comp); } return err_size; static void hdd_deinit_sw_pta(hdd_context_t *hdd_ctx) { complete(&hdd_ctx->sw_pta_comp); } #else static inline void hdd_sysfs_bt_profile_create(hdd_context_t* pHddCtx) static void hdd_init_sw_pta(hdd_context_t *hdd_ctx) { } static inline void hdd_sysfs_bt_profile_destroy(hdd_context_t* pHddCtx) static void hdd_deinit_sw_pta(hdd_context_t *hdd_ctx) { } #endif Loading Loading @@ -8277,8 +8329,6 @@ int __hdd_open(struct net_device *dev) "%s: session already exist for station mode", __func__); } hdd_sysfs_bt_profile_create(pHddCtx); set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { Loading Loading @@ -8456,8 +8506,6 @@ int __hdd_stop (struct net_device *dev) wlan_hdd_stop_mon(pHddCtx, true); } hdd_sysfs_bt_profile_destroy(pHddCtx); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); /* Disable TX on the interface, after this hard_start_xmit() will not Loading Loading @@ -12639,6 +12687,7 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) wlan_hdd_ftm_close(pHddCtx); goto free_hdd_ctx; } hdd_deinit_sw_pta(pHddCtx); /* DeRegister with platform driver as client for Suspend/Resume */ vosStatus = hddDeregisterPmOps(pHddCtx); Loading Loading @@ -14759,6 +14808,8 @@ int hdd_wlan_startup(struct device *dev ) hdd_assoc_registerFwdEapolCB(pVosContext); mutex_init(&pHddCtx->cache_channel_lock); hdd_init_sw_pta(pHddCtx); goto success; err_open_cesium_nl_sock: Loading CORE/MAC/inc/wniApi.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 }; Loading CORE/MAC/src/include/sirParams.h +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
CORE/HDD/inc/wlan_hdd_main.h +35 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -1791,6 +1795,8 @@ struct hdd_context_s v_BOOL_t btCoexModeSet; v_BOOL_t isPnoEnable; bool is_sco_enabled; bool is_bt_enabled; macAddrSpoof_t spoofMacAddr; /* flag to decide if driver need to scan DFS channels or not */ v_BOOL_t disable_dfs_flag; Loading Loading @@ -1863,6 +1869,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 */ Loading Loading @@ -2425,4 +2434,30 @@ static inline void hdd_fill_last_rx(hdd_adapter_t *adapter) #else void hdd_fill_last_rx(hdd_adapter_t *adapter); #endif #ifdef FEATURE_WLAN_SW_PTA /** * hdd_process_bt_sco_profile - process BT SCO profile * @hdd_ctx: pointer to HDD context * @bt_enabled: status of BT * @bt_sco: status of SCO * * Return: 0 on success, error on failure */ int hdd_process_bt_sco_profile(hdd_context_t *hdd_ctx, bool bt_enabled, bool bt_sco); /** * hdd_is_sw_pta_enabled - is sw pta enabled * @hdd_ctx: pointer to HDD context * * Return: bool */ bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx); #else static inline bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx) { return 0; } #endif #endif // end #if !defined( WLAN_HDD_MAIN_H )
CORE/HDD/src/wlan_hdd_cfg80211.c +37 −0 Original line number Diff line number Diff line Loading @@ -620,6 +620,13 @@ static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = }; #endif /* WLAN_NL80211_TESTMODE */ #ifdef FEATURE_WLAN_SW_PTA bool hdd_is_sw_pta_enabled(hdd_context_t *hdd_ctx) { return hdd_ctx->cfg_ini->is_sw_pta_enabled; } #endif #ifdef FEATURE_WLAN_CH_AVOID /* * FUNCTION: wlan_hdd_send_avoid_freq_event Loading Loading @@ -15805,6 +15812,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 (hdd_is_sw_pta_enabled(pHddCtx) && 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) Loading Loading @@ -16323,6 +16343,14 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, return -EINVAL; } /** * If sw pta is enabled, new connections should not allowed. */ if (hdd_is_sw_pta_enabled(pHddCtx) && pHddCtx->is_sco_enabled) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO operation in progress", __func__); return -EINVAL; } pRoamProfile = &pWextState->roamProfile; Loading Loading @@ -20078,6 +20106,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 (hdd_is_sw_pta_enabled(pHddCtx) && 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)
CORE/HDD/src/wlan_hdd_main.c +155 −104 Original line number Diff line number Diff line Loading @@ -214,9 +214,6 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, //wait time for beacon miss rate. #define BCN_MISS_RATE_TIME 500 //max size for BT profile indication cmd #define MAX_USER_COMMAND_SIZE_BT_PROFILE_IND_CMD 24 /* * Android DRIVER command structures */ Loading Loading @@ -250,19 +247,6 @@ static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue, static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg); #endif /* WLAN_FEATURE_RMC */ #ifdef FEATURE_WLAN_SW_PTA /* BT profile sysfile entry obj */ static struct kobject *driver_kobject; static ssize_t hdd_sysfs_bt_profile_ind_cmd_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); static struct kobj_attribute bt_profile_attribute = __ATTR(bt_profile, 0220, NULL, hdd_sysfs_bt_profile_ind_cmd_store); #endif void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback); void hdd_set_wlan_suspend_mode(bool suspend); void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable); Loading Loading @@ -3909,130 +3893,198 @@ int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, } #ifdef FEATURE_WLAN_SW_PTA static void hdd_sysfs_bt_profile_create(hdd_context_t* hdd_ctx) static void hdd_sco_resp_callback(uint8_t sco_status) { if(!hdd_ctx->cfg_ini->is_sw_pta_enabled) return; hdd_context_t *hdd_ctx = NULL; v_CONTEXT_t vos_ctx = NULL; driver_kobject = kobject_create_and_add(WLAN_MODULE_NAME, kernel_kobj); if (!driver_kobject) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s:could not allocate driver kobject", __func__); 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; } if(sysfs_create_file(driver_kobject, &bt_profile_attribute.attr)) hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Failed to create BT profile sysfs entry", __func__); /* 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; } static void hdd_sysfs_bt_profile_destroy(hdd_context_t* hdd_ctx) { if(!hdd_ctx->cfg_ini->is_sw_pta_enabled) return; hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: Response status %d", __func__, sco_status); sysfs_remove_file(driver_kobject, &bt_profile_attribute.attr); if (driver_kobject) { kobject_put(driver_kobject); driver_kobject = NULL; if (sco_status) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid sco status %d", __func__, sco_status); return; } complete(&hdd_ctx->sw_pta_comp); } static int hdd_sysfs_validate_and_copy_buf(char *dest_buf, size_t dest_buf_size, char const *source_buf, size_t source_buf_size) int hdd_process_bt_sco_profile(hdd_context_t *hdd_ctx, bool bt_enabled, bool bt_sco) { if (source_buf_size > (dest_buf_size - 1)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Command length is larger than %zu bytes", __func__, dest_buf_size); tpAniSirGlobal mac_ctx = PMAC_STRUCT(hdd_ctx->hHal); uint8_t no_of_states_changed = 0; 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; } /* sysfs already provides kernel space buffer so copy from user * is not needed. Doing this extra copy operation just to ensure * the local buf is properly null-terminated. /** * At a time only one status can be changed compared to * previous command (BT_ENABLED/SCO) * If no.of states changed is greater than one it is * an invalid command. */ strlcpy(dest_buf, source_buf, dest_buf_size); if (bt_enabled != hdd_ctx->is_bt_enabled) no_of_states_changed++; /* default 'echo' cmd takes new line character to here */ if (dest_buf[source_buf_size - 1] == '\n') dest_buf[source_buf_size - 1] = '\0'; if (bt_sco != hdd_ctx->is_sco_enabled) no_of_states_changed++; return 0; if (no_of_states_changed > 1) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Multiple states changed", __func__); return -EINVAL; } static ssize_t __hdd_sysfs_bt_profile_ind_cmd_store(hdd_context_t *hdd_ctx, const char *buf, size_t count) { char buf_local[MAX_USER_COMMAND_SIZE_BT_PROFILE_IND_CMD + 1]; char *sptr, *token, *profile, *profile_mode; int ret; INIT_COMPLETION(hdd_ctx->sw_pta_comp); ENTER(); if (wlan_hdd_validate_context(hdd_ctx)) if (bt_enabled != hdd_ctx->is_bt_enabled) { hal_status = sme_bt_req(hdd_ctx->hHal, hdd_sco_resp_callback, adapter->sessionId, bt_enabled); if (!HAL_STATUS_SUCCESS(hal_status)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Error sending sme sco indication request", __func__); return -EINVAL; } ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), buf, count); if (ret) 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; } sptr = buf_local; /* Get BT profile */ token = strsep(&sptr, " "); hdd_ctx->is_bt_enabled = bt_enabled; return 0; } if (!token) return -EINVAL; profile = token; if (bt_sco) { 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 (!hdd_ctx->is_sco_enabled) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: BT SCO is already disabled", __func__); return 0; } sco_status = false; } token = NULL; /* Get BT profile mode */ token = strsep(&sptr, " "); 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; } if (!token) 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; } profile_mode = token; if (!bt_sco) { hdd_ctx->is_sco_enabled = false; mac_ctx->isCoexScoIndSet = 0; return 0; } hddLog(VOS_TRACE_LEVEL_INFO, "%s:profile = %s, profile_mode = %s", __func__, profile, profile_mode); 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; } EXIT(); return count; 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; } static ssize_t hdd_sysfs_bt_profile_ind_cmd_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { hdd_context_t *pHddCtx = NULL; ssize_t err_size = 0; if (wlan_hdd_scan_abort(adapter)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Error aborting scan request", __func__); return -EINVAL; } pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_get_global_context(VOS_MODULE_ID_HDD, NULL)); hdd_ctx->is_sco_enabled = true; mac_ctx->isCoexScoIndSet = 1; if (!pHddCtx) { hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL"); 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; } } err_size = __hdd_sysfs_bt_profile_ind_cmd_store(pHddCtx, buf, count); return 0; } static void hdd_init_sw_pta(hdd_context_t *hdd_ctx) { init_completion(&hdd_ctx->sw_pta_comp); } return err_size; static void hdd_deinit_sw_pta(hdd_context_t *hdd_ctx) { complete(&hdd_ctx->sw_pta_comp); } #else static inline void hdd_sysfs_bt_profile_create(hdd_context_t* pHddCtx) static void hdd_init_sw_pta(hdd_context_t *hdd_ctx) { } static inline void hdd_sysfs_bt_profile_destroy(hdd_context_t* pHddCtx) static void hdd_deinit_sw_pta(hdd_context_t *hdd_ctx) { } #endif Loading Loading @@ -8277,8 +8329,6 @@ int __hdd_open(struct net_device *dev) "%s: session already exist for station mode", __func__); } hdd_sysfs_bt_profile_create(pHddCtx); set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { Loading Loading @@ -8456,8 +8506,6 @@ int __hdd_stop (struct net_device *dev) wlan_hdd_stop_mon(pHddCtx, true); } hdd_sysfs_bt_profile_destroy(pHddCtx); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); /* Disable TX on the interface, after this hard_start_xmit() will not Loading Loading @@ -12639,6 +12687,7 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) wlan_hdd_ftm_close(pHddCtx); goto free_hdd_ctx; } hdd_deinit_sw_pta(pHddCtx); /* DeRegister with platform driver as client for Suspend/Resume */ vosStatus = hddDeregisterPmOps(pHddCtx); Loading Loading @@ -14759,6 +14808,8 @@ int hdd_wlan_startup(struct device *dev ) hdd_assoc_registerFwdEapolCB(pVosContext); mutex_init(&pHddCtx->cache_channel_lock); hdd_init_sw_pta(pHddCtx); goto success; err_open_cesium_nl_sock: Loading
CORE/MAC/inc/wniApi.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 }; Loading
CORE/MAC/src/include/sirParams.h +12 −0 Original line number Diff line number Diff line Loading @@ -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