summaryrefslogtreecommitdiff
path: root/drivers/media/sprd_scale/common/compat_img_scale.c
blob: f7b72a81aec0d7bcce1ad48b81e5495412699615 (plain)
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;
}