• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4  *
5  * Copyright (c) 2017 by Allwinnertech Co., Ltd.  http://www.allwinnertech.com
6  *
7  * Authors:  Zhao Wei <zhaowei@allwinnertech.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 
14 #include <linux/compat.h>
15 #include <linux/module.h>
16 #include <linux/videodev2.h>
17 #include <linux/v4l2-subdev.h>
18 #include <media/v4l2-dev.h>
19 #include <media/v4l2-ioctl.h>
20 
21 #include "sensor_helper.h"
22 
23 #ifdef CONFIG_COMPAT
native_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)24 static long native_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
25 {
26 	return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
27 }
28 
29 struct sensor_config32 {
30 	int width;
31 	int height;
32 	unsigned int hoffset;	/*receive hoffset from sensor output*/
33 	unsigned int voffset;	/*receive voffset from sensor output*/
34 	unsigned int hts;	/*h size of timing, unit: pclk */
35 	unsigned int vts;	/*v size of timing, unit: line */
36 	unsigned int pclk;	/*pixel clock in Hz */
37 	unsigned int fps_fixed;	/*sensor fps */
38 	unsigned int bin_factor;/*binning factor */
39 	unsigned int intg_min;	/*integration min, unit: line, Q4 */
40 	unsigned int intg_max;	/*integration max, unit: line, Q4 */
41 	unsigned int gain_min;	/*sensor gain min, Q4 */
42 	unsigned int gain_max;	/*sensor gain max, Q4 */
43 	unsigned int mbus_code;	/*media bus code */
44 	unsigned int wdr_mode;	/*isp wdr mode */
45 };
46 
47 struct sensor_exp_gain32 {
48 	int exp_val;
49 	int gain_val;
50 	int r_gain;
51 	int b_gain;
52 };
53 
54 struct actuator_ctrl32 {
55 	unsigned int code;
56 };
57 
58 struct actuator_para32 {
59 	unsigned short code_min;
60 	unsigned short code_max;
61 };
62 
63 struct flash_para32 {
64    enum v4l2_flash_led_mode mode;
65 };
66 
67 #define VIDIOC_VIN_SENSOR_CFG_REQ32 \
68 	_IOWR('V', BASE_VIDIOC_PRIVATE + 60, struct sensor_config32)
69 
70 #define VIDIOC_VIN_SENSOR_EXP_GAIN32 \
71 	_IOWR('V', BASE_VIDIOC_PRIVATE + 61, struct sensor_exp_gain32)
72 #define VIDIOC_VIN_ACT_SET_CODE32 \
73 	_IOWR('V', BASE_VIDIOC_PRIVATE + 64, struct actuator_ctrl32)
74 #define VIDIOC_VIN_ACT_INIT32 \
75 	_IOWR('V', BASE_VIDIOC_PRIVATE + 65, struct actuator_para32)
76 #define VIDIOC_VIN_FLASH_EN32 \
77 	_IOWR('V', BASE_VIDIOC_PRIVATE + 66, struct flash_para32)
78 
get_sensor_config32(struct sensor_config * kp,struct sensor_config32 __user * up)79 static int get_sensor_config32(struct sensor_config *kp,
80 			      struct sensor_config32 __user *up)
81 {
82 	if (!access_ok(up, sizeof(struct sensor_config32)) ||
83 	    get_user(kp->width, &up->width) || get_user(kp->height, &up->height) ||
84 	    get_user(kp->hoffset, &up->hoffset) || get_user(kp->voffset, &up->voffset) ||
85 	    get_user(kp->hts, &up->hts) || get_user(kp->vts, &up->vts) ||
86 	    get_user(kp->pclk, &up->pclk) || get_user(kp->fps_fixed, &up->fps_fixed) ||
87 	    get_user(kp->bin_factor, &up->bin_factor) || get_user(kp->intg_min, &up->intg_min) ||
88 	    get_user(kp->intg_max, &up->intg_max) || get_user(kp->gain_min, &up->gain_min) ||
89 	    get_user(kp->gain_max, &up->gain_max) || get_user(kp->mbus_code, &up->mbus_code) ||
90 	    get_user(kp->wdr_mode, &up->wdr_mode))
91 		return -EFAULT;
92 	return 0;
93 }
94 
put_sensor_config32(struct sensor_config * kp,struct sensor_config32 __user * up)95 static int put_sensor_config32(struct sensor_config *kp,
96 			      struct sensor_config32 __user *up)
97 {
98 	if (!access_ok(up, sizeof(struct sensor_config32)) ||
99 	    put_user(kp->width, &up->width) || put_user(kp->height, &up->height) ||
100 	    put_user(kp->hoffset, &up->hoffset) || put_user(kp->voffset, &up->voffset) ||
101 	    put_user(kp->hts, &up->hts) || put_user(kp->vts, &up->vts) ||
102 	    put_user(kp->pclk, &up->pclk) || put_user(kp->fps_fixed, &up->fps_fixed) ||
103 	    put_user(kp->bin_factor, &up->bin_factor) || put_user(kp->intg_min, &up->intg_min) ||
104 	    put_user(kp->intg_max, &up->intg_max) || put_user(kp->gain_min, &up->gain_min) ||
105 	    put_user(kp->gain_max, &up->gain_max) || put_user(kp->mbus_code, &up->mbus_code) ||
106 	    put_user(kp->wdr_mode, &up->wdr_mode))
107 		return -EFAULT;
108 	return 0;
109 }
110 
get_sensor_exp_gain32(struct sensor_exp_gain * kp,struct sensor_exp_gain32 __user * up)111 static int get_sensor_exp_gain32(struct sensor_exp_gain *kp,
112 			      struct sensor_exp_gain32 __user *up)
113 {
114 	if (!access_ok(up, sizeof(struct sensor_exp_gain32)) ||
115 	    get_user(kp->exp_val, &up->exp_val) || get_user(kp->gain_val, &up->gain_val) ||
116 	    get_user(kp->r_gain, &up->r_gain) || get_user(kp->b_gain, &up->b_gain))
117 		return -EFAULT;
118 	return 0;
119 }
120 
put_sensor_exp_gain32(struct sensor_exp_gain * kp,struct sensor_exp_gain32 __user * up)121 static int put_sensor_exp_gain32(struct sensor_exp_gain *kp,
122 			      struct sensor_exp_gain32 __user *up)
123 {
124 	if (!access_ok(up, sizeof(struct sensor_exp_gain32)) ||
125 	    put_user(kp->exp_val, &up->exp_val) || put_user(kp->gain_val, &up->gain_val) ||
126 	    put_user(kp->r_gain, &up->r_gain) || put_user(kp->b_gain, &up->b_gain))
127 		return -EFAULT;
128 	return 0;
129 }
130 
get_act_init_config32(struct actuator_para * kp,struct actuator_para32 __user * up)131 static int get_act_init_config32(struct actuator_para *kp,
132 			      struct actuator_para32 __user *up)
133 {
134 	if (!access_ok(up, sizeof(struct actuator_para32)) ||
135 	    get_user(kp->code_min, &up->code_min) || get_user(kp->code_max, &up->code_max))
136 		return -EFAULT;
137 	return 0;
138 }
139 
put_act_init_config32(struct actuator_para * kp,struct actuator_para32 __user * up)140 static int put_act_init_config32(struct actuator_para *kp,
141 			      struct actuator_para32 __user *up)
142 {
143 	if (!access_ok(up, sizeof(struct actuator_para32)) ||/*VERIFY_WRITE, */
144 	    put_user(kp->code_min, &up->code_min) || put_user(kp->code_max, &up->code_max))
145 		return -EFAULT;
146 	return 0;
147 }
148 
get_act_code32(struct actuator_ctrl * kp,struct actuator_ctrl32 __user * up)149 static int get_act_code32(struct actuator_ctrl *kp,
150 			      struct actuator_ctrl32 __user *up)
151 {
152 	if (!access_ok(up, sizeof(struct actuator_ctrl32)) ||
153 	    get_user(kp->code, &up->code))
154 		return -EFAULT;
155 	return 0;
156 }
157 
put_act_code32(struct actuator_ctrl * kp,struct actuator_ctrl32 __user * up)158 static int put_act_code32(struct actuator_ctrl *kp,
159 			      struct actuator_ctrl32 __user *up)
160 {
161 	if (!access_ok(up, sizeof(struct actuator_ctrl32)) ||/*VERIFY_WRITE, */
162 	    put_user(kp->code, &up->code))
163 		return -EFAULT;
164 	return 0;
165 }
166 
get_flash_mode32(struct flash_para * kp,struct flash_para32 __user * up)167 static int get_flash_mode32(struct flash_para *kp,
168 			      struct flash_para32 __user *up)
169 {
170 	if (!access_ok(up, sizeof(struct flash_para32)) ||
171 	    get_user(kp->mode, &up->mode))
172 		return -EFAULT;
173 	return 0;
174 }
175 
put_flash_mode32(struct flash_para * kp,struct flash_para32 __user * up)176 static int put_flash_mode32(struct flash_para *kp,
177 			      struct flash_para32 __user *up)
178 {
179 	if (!access_ok(up, sizeof(struct flash_para32)) ||
180 	    put_user(kp->mode, &up->mode))
181 		return -EFAULT;
182 	return 0;
183 }
184 
sensor_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)185 long sensor_compat_ioctl32(struct v4l2_subdev *sd,
186 		unsigned int cmd, unsigned long arg)
187 {
188 	union {
189 		struct sensor_config sc;
190 		struct sensor_exp_gain seg;
191 		struct actuator_ctrl ctrl;
192 		struct actuator_para para;
193 		struct flash_para flash;
194 	} karg;
195 	void __user *up = compat_ptr(arg);
196 	int compatible_arg = 1;
197 	long err = 0;
198 
199 	vin_log(VIN_LOG_ISP, "%s cmd is 0x%x\n", __func__, cmd);
200 
201 	switch (cmd) {
202 	case VIDIOC_VIN_SENSOR_CFG_REQ32:
203 		cmd = VIDIOC_VIN_SENSOR_CFG_REQ;
204 		break;
205 	case VIDIOC_VIN_SENSOR_EXP_GAIN32:
206 		cmd = VIDIOC_VIN_SENSOR_EXP_GAIN;
207 		break;
208 	case VIDIOC_VIN_ACT_INIT32:
209 		cmd = VIDIOC_VIN_ACT_INIT;
210 		break;
211 	case VIDIOC_VIN_ACT_SET_CODE32:
212 		cmd = VIDIOC_VIN_ACT_SET_CODE;
213 		break;
214 	case VIDIOC_VIN_FLASH_EN32:
215 		cmd = VIDIOC_VIN_FLASH_EN;
216 		break;
217 	}
218 
219 	switch (cmd) {
220 	case VIDIOC_VIN_SENSOR_CFG_REQ:
221 		err = get_sensor_config32(&karg.sc, up);
222 		compatible_arg = 0;
223 		break;
224 	case VIDIOC_VIN_SENSOR_EXP_GAIN:
225 		err = get_sensor_exp_gain32(&karg.seg, up);
226 		compatible_arg = 0;
227 		break;
228 	case VIDIOC_VIN_ACT_INIT:
229 		err = get_act_init_config32(&karg.para, up);
230 		compatible_arg = 0;
231 		break;
232 	case VIDIOC_VIN_ACT_SET_CODE:
233 		err = get_act_code32(&karg.ctrl, up);
234 		compatible_arg = 0;
235 		break;
236 	case VIDIOC_VIN_FLASH_EN:
237 		err = get_flash_mode32(&karg.flash, up);
238 		compatible_arg = 0;
239 		break;
240 
241 	}
242 
243 	if (err)
244 		return err;
245 
246 	if (compatible_arg)
247 		err = native_ioctl(sd, cmd, up);
248 	else {
249 		mm_segment_t old_fs = get_fs();
250 
251 		set_fs(KERNEL_DS);
252 		err = native_ioctl(sd, cmd, &karg);
253 		set_fs(old_fs);
254 	}
255 
256 	switch (cmd) {
257 	case VIDIOC_VIN_SENSOR_CFG_REQ:
258 		err = put_sensor_config32(&karg.sc, up);
259 		break;
260 	case VIDIOC_VIN_SENSOR_EXP_GAIN:
261 		err = put_sensor_exp_gain32(&karg.seg, up);
262 		break;
263 	case VIDIOC_VIN_ACT_INIT:
264 		err = put_act_init_config32(&karg.para, up);
265 		compatible_arg = 0;
266 		break;
267 	case VIDIOC_VIN_ACT_SET_CODE:
268 		err = put_act_code32(&karg.ctrl, up);
269 		compatible_arg = 0;
270 		break;
271 	case VIDIOC_VIN_FLASH_EN:
272 		err = put_flash_mode32(&karg.flash, up);
273 		compatible_arg = 0;
274 		break;
275 	}
276 
277 	return err;
278 }
279 EXPORT_SYMBOL_GPL(sensor_compat_ioctl32);
280 
281 #endif
282