techpack: audio: aw88261: Load calibration file through firmware class

Direct access to filesystem is insane and hits a neverallow, load it
through the firmware class instead.

Co-authored-by: Michael Bestas <mkbestas@lineageos.org>
Change-Id: Ic522644c73d63a36430526736257d635deb08f6a
This commit is contained in:
dianlujitaoandMichael Bestas authored and Michael Bestas committed 2024-01-07 15:54:48 +02:00
1 parent fd2f1845d4
commit b25b68201f
3 files changed
+35 -59

No files matched your search

+33 -55
View File
@@ -20,6 +20,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/firmware.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h> #include <linux/of.h>
#include <sound/core.h> #include <sound/core.h>
@@ -47,20 +48,12 @@ static unsigned int g_cali_status = false;
static struct miscdevice *g_misc_dev = NULL; static struct miscdevice *g_misc_dev = NULL;
static DEFINE_MUTEX(g_cali_lock); static DEFINE_MUTEX(g_cali_lock);
#ifdef AW_CALI_STORE_EXAMPLE #define AWINIC_CALI_FILE "aw_cali.bin"
/*write cali to persist file example*/
#define AWINIC_CALI_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
#define AW_INT_DEC_DIGIT 10 #define AW_INT_DEC_DIGIT 10
static void aw_fs_read(struct file *file, char *buf, size_t count, loff_t *pos) #ifdef AW_CALI_STORE_EXAMPLE
{ /*write cali to persist file example*/
#ifdef AW_KERNEL_VER_OVER_5_4_0 #define AWINIC_CALI_PERSIST_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
kernel_read(file, buf, count, pos);
#else
vfs_read(file, buf, count, pos);
#endif
}
static void aw_fs_write(struct file *file, char *buf, size_t count, loff_t *pos) static void aw_fs_write(struct file *file, char *buf, size_t count, loff_t *pos)
{ {
#ifdef AW_KERNEL_VER_OVER_5_4_0 #ifdef AW_KERNEL_VER_OVER_5_4_0
@@ -77,7 +70,7 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
loff_t pos = 0; loff_t pos = 0;
mm_segment_t fs; mm_segment_t fs;
fp = filp_open(AWINIC_CALI_FILE, O_RDWR | O_CREAT, 0644); fp = filp_open(AWINIC_CALI_PERSIST_FILE, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("%s:channel:%d open %s failed!\n", pr_err("%s:channel:%d open %s failed!\n",
__func__, channel, AWINIC_CALI_FILE); __func__, channel, AWINIC_CALI_FILE);
@@ -101,60 +94,49 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
filp_close(fp, NULL); filp_close(fp, NULL);
return 0; return 0;
} }
#endif
static int aw_cali_get_read_cali_re(int32_t *cali_re, int channel) static int aw_cali_get_read_cali_re(struct aw_device *aw_dev, int32_t *cali_re, int channel)
{ {
struct file *fp = NULL; int rc = -EINVAL;
/*struct inode *node;*/
int f_size;
char *buf = NULL;
int32_t int_cali_re = 0; int32_t int_cali_re = 0;
loff_t pos = 0; loff_t pos = 0;
mm_segment_t fs; const struct firmware *fw = NULL;
fp = filp_open(AWINIC_CALI_FILE, O_RDONLY, 0); /* open cali file */
if (IS_ERR(fp)) { if (request_firmware(&fw, AWINIC_CALI_FILE, aw_dev->dev)) {
pr_err("%s:channel:%d open %s failed!\n", pr_err("%s:channel:%d open %s failed!\n",
__func__, channel, AWINIC_CALI_FILE); __func__, channel, AWINIC_CALI_FILE);
return -EINVAL; return rc;
}
if (!fw || !fw->data || !fw->size) {
pr_err("%s: invalid firmware", __func__);
goto error;
}
if (fw->size < AW_INT_DEC_DIGIT || fw->size > AW_INT_DEC_DIGIT * 2) {
pr_err("%s: invalid firmware size\n", __func__);
goto error;
} }
pos = AW_INT_DEC_DIGIT * channel; pos = AW_INT_DEC_DIGIT * channel;
/*node = fp->f_dentry->d_inode;*/ if (sscanf(fw->data + pos, "%d", &int_cali_re) == 1)
/*f_size = node->i_size;*/
f_size = AW_INT_DEC_DIGIT;
buf = kzalloc(f_size + 1, GFP_ATOMIC);
if (!buf) {
pr_err("%s: channel:%d malloc mem %d failed!\n",
__func__, channel, f_size);
filp_close(fp, NULL);
return -EINVAL;
}
fs = get_fs();
set_fs(KERNEL_DS);
aw_fs_read(fp, buf, f_size, &pos);
set_fs(fs);
if (sscanf(buf, "%d", &int_cali_re) == 1)
*cali_re = int_cali_re; *cali_re = int_cali_re;
else else
*cali_re = AW_ERRO_CALI_VALUE; *cali_re = AW_ERRO_CALI_VALUE;
pr_info("%s: channel:%d buf:%s int_cali_re: %d\n", pr_info("%s: channel:%d int_cali_re: %d\n",
__func__, channel, buf, int_cali_re); __func__, channel, int_cali_re);
kfree(buf); rc = 0;
buf = NULL;
filp_close(fp, NULL);
return 0; error:
/* close file */
release_firmware(fw);
return rc;
} }
#endif
/*custom need add to set/get cali_re form/to nv*/ /*custom need add to set/get cali_re form/to nv*/
int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel) int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
@@ -170,18 +152,14 @@ int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
#endif #endif
} }
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t channel) int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t channel)
{ {
/*custom add, if success return value is 0 , else -1*/ /*custom add, if success return value is 0 , else -1*/
#ifdef AW_CALI_STORE_EXAMPLE
if (channel >= AW_DEV_CH_MAX) { if (channel >= AW_DEV_CH_MAX) {
pr_err("%s: unsupported channel [%d] \n", __func__, channel); pr_err("%s: unsupported channel [%d] \n", __func__, channel);
return -EINVAL; return -EINVAL;
} }
return aw_cali_get_read_cali_re(cali_re, channel); return aw_cali_get_read_cali_re(aw_dev, cali_re, channel);
#else
return 0;
#endif
} }
int aw_cali_store_cali_re(struct aw_device *aw_dev, int32_t re) int aw_cali_store_cali_re(struct aw_device *aw_dev, int32_t re)
@@ -1,8 +1,6 @@
#ifndef __AWINIC_CALIBRATION_H__ #ifndef __AWINIC_CALIBRATION_H__
#define __AWINIC_CALIBRATION_H__ #define __AWINIC_CALIBRATION_H__
#define AW_CALI_STORE_EXAMPLE
#define AW_CALI_READ_TIMES (3) #define AW_CALI_READ_TIMES (3)
#define AW_ERRO_CALI_VALUE (0) #define AW_ERRO_CALI_VALUE (0)
#define AW_CALI_RE_DEFAULT_TIMER (3000) #define AW_CALI_RE_DEFAULT_TIMER (3000)
@@ -136,7 +134,7 @@ struct aw_cali_desc {
int aw_cali_init(struct aw_cali_desc *cali_desc); int aw_cali_init(struct aw_cali_desc *cali_desc);
void aw_cali_deinit(struct aw_cali_desc *cali_desc); void aw_cali_deinit(struct aw_cali_desc *cali_desc);
int aw_cali_svc_get_cali_status(void); int aw_cali_svc_get_cali_status(void);
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t ch_index); int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t ch_index);
#endif #endif
@@ -1509,7 +1509,7 @@ int aw_dev_init_cali_re(struct aw_device *aw_dev)
if (aw_dev->cali_desc.mode) { if (aw_dev->cali_desc.mode) {
if (aw_dev->cali_desc.cali_re == AW_ERRO_CALI_VALUE) { if (aw_dev->cali_desc.cali_re == AW_ERRO_CALI_VALUE) {
ret = aw_cali_read_re_from_nvram(&aw_dev->cali_desc.cali_re, aw_dev->channel); ret = aw_cali_read_re_from_nvram(aw_dev, &aw_dev->cali_desc.cali_re, aw_dev->channel);
if (ret) { if (ret) {
aw_dev_info(aw_dev->dev, "read nvram cali failed, use default Re"); aw_dev_info(aw_dev->dev, "read nvram cali failed, use default Re");
aw_dev->cali_desc.cali_re = AW_ERRO_CALI_VALUE; aw_dev->cali_desc.cali_re = AW_ERRO_CALI_VALUE;