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