1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/*
* Copyright (C) 2012 Spreadtrum Communications Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/compat.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <video/sprd_scale_k.h>
#include "img_scale.h"
#include "compat_img_scale.h"
struct compat_scale_frame_param_t {
struct scale_size_t input_size;
struct scale_rect_t input_rect;
enum scale_fmt_e input_format;
struct scale_addr_t input_addr;
struct scale_endian_sel_t input_endian;
struct scale_size_t output_size;
enum scale_fmt_e output_format;
struct scale_addr_t output_addr;
struct scale_endian_sel_t output_endian;
enum scale_mode_e scale_mode;
uint32_t slice_height;
compat_caddr_t coeff_addr;
};
#define COMPAT_SCALE_IO_START _IOW(SCALE_IO_MAGIC, 0, struct compat_scale_frame_param_t)
static long compat_get_scale_frame_param(
struct scale_frame_param_t *kp,
struct compat_scale_frame_param_t __user *up)
{
compat_caddr_t tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct compat_scale_frame_param_t)) ||
copy_from_user(&kp->input_size, &up->input_size, sizeof(struct scale_size_t)) ||
copy_from_user(&kp->input_rect, &up->input_rect, sizeof(struct scale_rect_t)) ||
get_user(kp->input_format, &up->input_format) ||
copy_from_user(&kp->input_addr, &up->input_addr, sizeof(struct scale_addr_t)) ||
copy_from_user(&kp->input_endian, &up->input_endian, sizeof(struct scale_endian_sel_t)) ||
copy_from_user(&kp->output_size, &up->output_size, sizeof(struct scale_size_t)) ||
get_user(kp->output_format, &up->output_format) ||
copy_from_user(&kp->output_addr, &up->output_addr, sizeof(struct scale_addr_t)) ||
copy_from_user(&kp->output_endian, &up->output_endian, sizeof(struct scale_endian_sel_t)) ||
get_user(kp->scale_mode, &up->scale_mode) ||
get_user(kp->slice_height, &up->slice_height) ||
get_user(tmp, &up->coeff_addr))
return -EFAULT;
kp->coeff_addr = compat_ptr(tmp);
return 0;
}
long compat_scale_k_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct scale_frame_param_t karg;
void __user *up = compat_ptr(arg);
int compatible_arg = 1;
long err = 0;
if (!filp->f_op || !filp->f_op->unlocked_ioctl)
return -ENOTTY;
switch (cmd) {
case COMPAT_SCALE_IO_START:
err = compat_get_scale_frame_param(&karg, up);
cmd = SCALE_IO_START;
compatible_arg = 0;
break;
default:
break;
}
if (err)
return err;
if (compatible_arg)
err = filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)up);
else {
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
err = filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)&karg);
set_fs(old_fs);
}
return err;
}
|