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)
{
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;
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_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;
- if (cmd == FE_SET_PROPERTY) {
+ 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);
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);
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);
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
(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;
}
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