dvb-core: compatile with 32bit in 64bit kernel [1/1]

PD#SWPL-3009

Problem:
32bit frontend app can't call ioctl in 64bit-kernel

Solution:
Add 32bit define in header and handle in dvb_frontend in 64bit-kernel

Verify:
Verify at android_p at R311

Change-Id: I63178803cfb1cf7d670e3c2b55f104e97f5afa63
Signed-off-by: Chuangcheng Peng <chuangcheng.peng@amlogic.com>
This commit is contained in:
Chuangcheng Peng
2018-12-07 18:16:13 +08:00
committed by Dongjin Kim
parent b682325e08
commit 3411f700d2
2 changed files with 188 additions and 40 deletions

View File

@@ -1965,7 +1965,63 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
return r;
}
static void dtv_property_32to64(struct dtv_property *dest,
struct dtv_property_32 *src)
{
int i = 0;
long tmp = 0;
dest->cmd = src->cmd;
// printk("%s cmd:%d\n",__func__,dest->cmd);
for (i = 0; i < 3; i++)
dest->reserved[i] = src->reserved[i];
dest->u.data = src->u.data;
dest->u.st.len = src->u.st.len;
for (i = 0; i < MAX_DTV_STATS; i++) {
dest->u.st.stat[i].scale = src->u.st.stat[i].scale;
dest->u.st.stat[i].uvalue = src->u.st.stat[i].uvalue;
dest->u.st.stat[i].svalue = src->u.st.stat[i].svalue;
}
for (i = 0; i < 32; i++)
dest->u.buffer.data[i] = src->u.buffer.data[i];
dest->u.buffer.len = src->u.buffer.len;
for (i = 0; i < 3; i++)
dest->u.buffer.reserved1[i] = src->u.buffer.reserved1[i];
tmp = (long)(src->u.buffer.reserved2);
dest->u.buffer.reserved2 = (void *)tmp;
dest->result = src->result;
}
static void dtv_property_64to32(struct dtv_property_32 *dest,
struct dtv_property *src)
{
int i = 0;
long tmp = 0;
dest->cmd = src->cmd;
// printk("%s cmd:%d\n",__func__,dest->cmd);
for (i = 0; i < 3; i++)
dest->reserved[i] = src->reserved[i];
dest->u.data = src->u.data;
// printk("%s data:%d\n",__func__,dest->u.data);
dest->u.st.len = src->u.st.len;
for (i = 0; i < MAX_DTV_STATS; i++) {
dest->u.st.stat[i].scale = src->u.st.stat[i].scale;
dest->u.st.stat[i].uvalue = src->u.st.stat[i].uvalue;
dest->u.st.stat[i].svalue = src->u.st.stat[i].svalue;
}
for (i = 0; i < 32; i++)
dest->u.buffer.data[i] = src->u.buffer.data[i];
dest->u.buffer.len = src->u.buffer.len;
for (i = 0; i < 3; i++)
dest->u.buffer.reserved1[i] = src->u.buffer.reserved1[i];
tmp = (long)(src->u.buffer.reserved2);
dest->u.buffer.reserved2 = (__u32)tmp;
dest->result = src->result;
}
static int dvb_frontend_ioctl(struct file *file,
unsigned int cmd, void *parg)
{
@@ -1991,7 +2047,9 @@ static int dvb_frontend_ioctl(struct file *file,
return -EPERM;
}
if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
if ((cmd == FE_SET_PROPERTY_32) || (cmd == FE_GET_PROPERTY_32)
|| (cmd == FE_SET_PROPERTY_64)
|| (cmd == FE_GET_PROPERTY_64))
err = dvb_frontend_ioctl_properties(file, cmd, parg);
else {
c->state = DTV_UNDEFINED;
@@ -2012,12 +2070,45 @@ static int dvb_frontend_ioctl_properties(struct file *file,
int err = 0;
struct dtv_properties *tvps = parg;
struct dtv_properties_32 *tvps_32_tmp = parg;
struct dtv_properties tvps_tmp;
struct dtv_property *tvp = NULL;
struct dtv_property_32 *tvp_32 = NULL;
int i;
int prop = 0;
int convert = 0;
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if ((cmd == FE_SET_PROPERTY_32) || (cmd == FE_SET_PROPERTY_64)
|| (cmd == FE_GET_PROPERTY_32)
|| (cmd == FE_GET_PROPERTY_64)) {
prop = 1;
if (cmd == FE_SET_PROPERTY) {
if ((cmd == FE_SET_PROPERTY_32) ||
(cmd == FE_GET_PROPERTY_32)) {
if (FE_SET_PROPERTY == FE_SET_PROPERTY_64)
convert = 1;
}
}
if (prop) {
if (convert) {
tvps_tmp.num = tvps_32_tmp->num;
tvps_tmp.props = (struct dtv_property *)(long)(tvps_32_tmp->props);
tvps = &tvps_tmp;
tvp_32 = memdup_user(tvps->props,
tvps->num * sizeof(struct dtv_property_32));
if (IS_ERR(tvp_32)) {
err = -EFAULT;
goto out;
}
}
}
#ifdef CONFIG_COMPAT
tvps->props = compat_ptr((unsigned long)tvps->props);
#endif
if ((cmd == FE_SET_PROPERTY_32) || (cmd == FE_SET_PROPERTY_64)) {
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
@@ -2026,9 +2117,22 @@ static int dvb_frontend_ioctl_properties(struct file *file,
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
if (convert) {
tvp = kmalloc_array(tvps->num,
sizeof(*tvp), GFP_KERNEL);
if (IS_ERR(tvp)) {
err = -EFAULT;
goto out;
}
for (i = 0; i < tvps->num; i++)
dtv_property_32to64(tvp + i, tvp_32+i);
} else {
tvp = memdup_user(tvps->props,
tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_set(fe, tvp + i, file);
@@ -2040,7 +2144,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
if (c->state == DTV_TUNE)
dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
} else if (cmd == FE_GET_PROPERTY) {
} else if ((cmd == FE_GET_PROPERTY_32) || (cmd == FE_GET_PROPERTY_64)) {
struct dtv_frontend_properties getp = fe->dtv_property_cache;
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
@@ -2051,9 +2155,20 @@ static int dvb_frontend_ioctl_properties(struct file *file,
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
if (convert) {
tvp = kmalloc_array(tvps->num,
sizeof(*tvp), GFP_KERNEL);
if (IS_ERR(tvp))
return PTR_ERR(tvp);
for (i = 0; i < tvps->num; i++)
dtv_property_32to64(tvp + i, tvp_32+i);
} else {
tvp = memdup_user(tvps->props,
tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
}
/*
* Let's use our own copy of property cache, in order to
@@ -2073,16 +2188,28 @@ static int dvb_frontend_ioctl_properties(struct file *file,
(tvp + i)->result = err;
}
if (copy_to_user((void __user *)tvps->props, tvp,
tvps->num * sizeof(struct dtv_property))) {
err = -EFAULT;
goto out;
}
if (convert) {
for (i = 0; i < tvps->num; i++)
dtv_property_64to32(tvp_32 + i,
(struct dtv_property *)(tvp+i));
if (copy_to_user((void __user *)tvps->props, tvp_32,
tvps->num * sizeof(struct dtv_property_32))) {
err = -EFAULT;
goto out;
}
} else {
if (copy_to_user((void __user *)tvps->props, tvp,
tvps->num * sizeof(struct dtv_property))) {
err = -EFAULT;
goto out;
}
}
} else
err = -EOPNOTSUPP;
out:
kfree(tvp_32);
kfree(tvp);
return err;
}
@@ -2663,24 +2790,14 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
static long dvb_frontend_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long args)
{
unsigned long ret;
struct dtv_properties tvps;
long ret;
#ifdef CONFIG_COMPAT
args = (unsigned long)compat_ptr(args);
#endif
if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) {
if (copy_from_user(&tvps, (void *)args,
sizeof(struct dtv_properties)))
return -EFAULT;
#ifdef CONFIG_COMPAT
tvps.props = compat_ptr((unsigned long)tvps.props);
#endif
if (copy_to_user((void *)args, (void *)&tvps,
sizeof(struct dtv_properties)))
return -EFAULT;
}
ret = dvb_generic_ioctl(filp, cmd, args);
return ret;
}
#endif

View File

@@ -541,16 +541,38 @@ struct dtv_property {
__u32 reserved1[3];
void *reserved2;
} buffer;
#if 0
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
} u;
int result;
} __attribute__ ((packed));
struct dtv_property_32 {
__u32 cmd;
__u32 reserved[3];
union {
__u32 data;
struct dtv_fe_stats st;
struct {
__u8 data[32];
__u32 len;
__u32 reserved1[3];
__u64 reserved;
} reserved;
#endif
#endif
__u32 reserved2;
} buffer;
} u;
int result;
} __attribute__ ((packed));
struct dtv_property_64 {
__u32 cmd;
__u32 reserved[3];
union {
__u32 data;
struct dtv_fe_stats st;
struct {
__u8 data[32];
__u32 len;
__u32 reserved1[3];
__u64 reserved2;
} buffer;
} u;
int result;
} __attribute__ ((packed));
@@ -560,14 +582,17 @@ struct dtv_property {
struct dtv_properties {
__u32 num;
#if 0 && defined(CONFIG_AMLOGIC_DVB_COMPAT)
union {
struct dtv_property *props;
__u64 reserved;
};
#else
struct dtv_property *props;
#endif
};
struct dtv_properties_32 {
__u32 num;
__u32 props;
};
struct dtv_properties_64 {
__u32 num;
__u64 props;
};
#if defined(__DVB_CORE__) || !defined (__KERNEL__)
@@ -722,6 +747,12 @@ struct dvbsx_blindscanevent {
#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
#define FE_SET_PROPERTY_32 _IOW('o', 82, struct dtv_properties_32)
#define FE_GET_PROPERTY_32 _IOR('o', 83, struct dtv_properties_32)
#define FE_SET_PROPERTY_64 _IOW('o', 82, struct dtv_properties_64)
#define FE_GET_PROPERTY_64 _IOR('o', 83, struct dtv_properties_64)
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
/*for atv*/
struct tuner_status_s {