wlan: Add sysfs entry for BT profile indication
Add the sysfs entry for the BT profile indication with two
parameters profile and profile mode.
--> echo <BT_PROFILE> <PROFILE_MODE> > /sys/kernel/wlan/bt_profile
where BT_PROFILE: BT_PROFILE_MAX, BT_PRPFILE_SCO etc
MODE : ENABLE/DISABLE
f.e: echo BT_PROFILE_MAX ENABLE > /sys/kernel/wlan/bt_profile
Change-Id: Ieb7f24035a552438fe90896e26e3c92e70325d6c
CRs-Fixed: 2762531
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 6a92340..49b3ead 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -214,6 +214,9 @@
//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
*/
@@ -247,6 +250,19 @@
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);
@@ -3892,6 +3908,135 @@
return len;
}
+#ifdef FEATURE_WLAN_SW_PTA
+static void hdd_sysfs_bt_profile_create(hdd_context_t* hdd_ctx)
+{
+ if(!hdd_ctx->cfg_ini->is_sw_pta_enabled)
+ return;
+
+ 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__);
+ 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__);
+}
+
+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);
+ if (driver_kobject) {
+ kobject_put(driver_kobject);
+ driver_kobject = NULL;
+ }
+}
+
+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)
+{
+ 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);
+ 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.
+ */
+ strlcpy(dest_buf, source_buf, dest_buf_size);
+
+ /* default 'echo' cmd takes new line character to here */
+ if (dest_buf[source_buf_size - 1] == '\n')
+ dest_buf[source_buf_size - 1] = '\0';
+
+ return 0;
+}
+
+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;
+
+ ENTER();
+
+ if (wlan_hdd_validate_context(hdd_ctx))
+ return -EINVAL;
+
+ ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
+ buf, count);
+ if (ret)
+ return -EINVAL;
+
+ sptr = buf_local;
+ /* Get BT profile */
+ token = strsep(&sptr, " ");
+
+ if (!token)
+ return -EINVAL;
+ profile = token;
+
+ token = NULL;
+ /* Get BT profile mode */
+ token = strsep(&sptr, " ");
+
+ if (!token)
+ return -EINVAL;
+
+ profile_mode = token;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s:profile = %s, profile_mode = %s",
+ __func__, profile, profile_mode);
+
+ EXIT();
+ return count;
+}
+
+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;
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD,
+ vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
+
+ if (!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL");
+ return -EINVAL;
+ }
+
+ err_size = __hdd_sysfs_bt_profile_ind_cmd_store(pHddCtx, buf, count);
+
+ return err_size;
+}
+#else
+static inline
+void hdd_sysfs_bt_profile_create(hdd_context_t* pHddCtx)
+{
+}
+
+static inline
+void hdd_sysfs_bt_profile_destroy(hdd_context_t* pHddCtx)
+{
+}
+#endif
+
static int hdd_driver_command(hdd_adapter_t *pAdapter,
hdd_priv_data_t *ppriv_data)
{
@@ -8126,6 +8271,8 @@
return -EINVAL;
}
+ hdd_sysfs_bt_profile_create(pHddCtx);
+
set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
{
@@ -8303,6 +8450,8 @@
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