V4L (0973): Another build fix for compat_ioctl32.c
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / compat_ioctl32.c
1 #include <linux/config.h>
2 #include <linux/compat.h>
3 #include <linux/videodev.h>
4 #include <linux/module.h>
5
6 #ifdef CONFIG_COMPAT
7 struct video_tuner32 {
8         compat_int_t tuner;
9         char name[32];
10         compat_ulong_t rangelow, rangehigh;
11         u32 flags;      /* It is really u32 in videodev.h */
12         u16 mode, signal;
13 };
14
15 static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
16 {
17         int i;
18
19         if(get_user(kp->tuner, &up->tuner))
20                 return -EFAULT;
21         for(i = 0; i < 32; i++)
22                 __get_user(kp->name[i], &up->name[i]);
23         __get_user(kp->rangelow, &up->rangelow);
24         __get_user(kp->rangehigh, &up->rangehigh);
25         __get_user(kp->flags, &up->flags);
26         __get_user(kp->mode, &up->mode);
27         __get_user(kp->signal, &up->signal);
28         return 0;
29 }
30
31 static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
32 {
33         int i;
34
35         if(put_user(kp->tuner, &up->tuner))
36                 return -EFAULT;
37         for(i = 0; i < 32; i++)
38                 __put_user(kp->name[i], &up->name[i]);
39         __put_user(kp->rangelow, &up->rangelow);
40         __put_user(kp->rangehigh, &up->rangehigh);
41         __put_user(kp->flags, &up->flags);
42         __put_user(kp->mode, &up->mode);
43         __put_user(kp->signal, &up->signal);
44         return 0;
45 }
46
47 struct video_buffer32 {
48         compat_caddr_t base;
49         compat_int_t height, width, depth, bytesperline;
50 };
51
52 static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
53 {
54         u32 tmp;
55
56         if (get_user(tmp, &up->base))
57                 return -EFAULT;
58
59         /* This is actually a physical address stored
60          * as a void pointer.
61          */
62         kp->base = (void *)(unsigned long) tmp;
63
64         __get_user(kp->height, &up->height);
65         __get_user(kp->width, &up->width);
66         __get_user(kp->depth, &up->depth);
67         __get_user(kp->bytesperline, &up->bytesperline);
68         return 0;
69 }
70
71 static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
72 {
73         u32 tmp = (u32)((unsigned long)kp->base);
74
75         if(put_user(tmp, &up->base))
76                 return -EFAULT;
77         __put_user(kp->height, &up->height);
78         __put_user(kp->width, &up->width);
79         __put_user(kp->depth, &up->depth);
80         __put_user(kp->bytesperline, &up->bytesperline);
81         return 0;
82 }
83
84 struct video_clip32 {
85         s32 x, y, width, height;        /* Its really s32 in videodev.h */
86         compat_caddr_t next;
87 };
88
89 struct video_window32 {
90         u32 x, y, width, height, chromakey, flags;
91         compat_caddr_t clips;
92         compat_int_t clipcount;
93 };
94
95 static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
96 {
97         int ret = -ENOIOCTLCMD;
98
99         if (file->f_ops->unlocked_ioctl)
100                 ret = file->f_ops->unlocked_ioctl(file, cmd, arg);
101         else if (file->f_ops->ioctl) {
102                 lock_kernel();
103                 ret = file->f_ops->ioctl(file->f_dentry->d_inode, file, cmd, arg);
104                 unlock_kernel();
105         }
106
107         return ret;
108 }
109
110
111 /* You get back everything except the clips... */
112 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
113 {
114         if(put_user(kp->x, &up->x))
115                 return -EFAULT;
116         __put_user(kp->y, &up->y);
117         __put_user(kp->width, &up->width);
118         __put_user(kp->height, &up->height);
119         __put_user(kp->chromakey, &up->chromakey);
120         __put_user(kp->flags, &up->flags);
121         __put_user(kp->clipcount, &up->clipcount);
122         return 0;
123 }
124
125 #define VIDIOCGTUNER32          _IOWR('v',4, struct video_tuner32)
126 #define VIDIOCSTUNER32          _IOW('v',5, struct video_tuner32)
127 #define VIDIOCGWIN32            _IOR('v',9, struct video_window32)
128 #define VIDIOCSWIN32            _IOW('v',10, struct video_window32)
129 #define VIDIOCGFBUF32           _IOR('v',11, struct video_buffer32)
130 #define VIDIOCSFBUF32           _IOW('v',12, struct video_buffer32)
131 #define VIDIOCGFREQ32           _IOR('v',14, u32)
132 #define VIDIOCSFREQ32           _IOW('v',15, u32)
133
134 enum {
135         MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
136 };
137
138 static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
139 {
140         struct video_window32 __user *up = compat_ptr(arg);
141         struct video_window __user *vw;
142         struct video_clip __user *p;
143         int nclips;
144         u32 n;
145
146         if (get_user(nclips, &up->clipcount))
147                 return -EFAULT;
148
149         /* Peculiar interface... */
150         if (nclips < 0)
151                 nclips = VIDEO_CLIPMAP_SIZE;
152
153         if (nclips > MaxClips)
154                 return -ENOMEM;
155
156         vw = compat_alloc_user_space(sizeof(struct video_window) +
157                                     nclips * sizeof(struct video_clip));
158
159         p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
160
161         if (get_user(n, &up->x) || put_user(n, &vw->x) ||
162             get_user(n, &up->y) || put_user(n, &vw->y) ||
163             get_user(n, &up->width) || put_user(n, &vw->width) ||
164             get_user(n, &up->height) || put_user(n, &vw->height) ||
165             get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
166             get_user(n, &up->flags) || put_user(n, &vw->flags) ||
167             get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
168             get_user(n, &up->clips) || put_user(p, &vw->clips))
169                 return -EFAULT;
170
171         if (nclips) {
172                 struct video_clip32 __user *u = compat_ptr(n);
173                 int i;
174                 if (!u)
175                         return -EINVAL;
176                 for (i = 0; i < nclips; i++, u++, p++) {
177                         s32 v;
178                         if (get_user(v, &u->x) ||
179                             put_user(v, &p->x) ||
180                             get_user(v, &u->y) ||
181                             put_user(v, &p->y) ||
182                             get_user(v, &u->width) ||
183                             put_user(v, &p->width) ||
184                             get_user(v, &u->height) ||
185                             put_user(v, &p->height) ||
186                             put_user(NULL, &p->next))
187                                 return -EFAULT;
188                 }
189         }
190
191         return native_ioctl(file, VIDIOCSWIN, (unsigned long)p);
192 }
193
194 static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
195 {
196         union {
197                 struct video_tuner vt;
198                 struct video_buffer vb;
199                 struct video_window vw;
200                 unsigned long vx;
201         } karg;
202         mm_segment_t old_fs = get_fs();
203         void __user *up = compat_ptr(arg);
204         int err = 0;
205
206         /* First, convert the command. */
207         switch(cmd) {
208         case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
209         case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
210         case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
211         case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
212         case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
213         case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
214         case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
215         };
216
217         switch(cmd) {
218         case VIDIOCSTUNER:
219         case VIDIOCGTUNER:
220                 err = get_video_tuner32(&karg.vt, up);
221                 break;
222
223         case VIDIOCSFBUF:
224                 err = get_video_buffer32(&karg.vb, up);
225                 break;
226
227         case VIDIOCSFREQ:
228                 err = get_user(karg.vx, (u32 __user *)up);
229                 break;
230         };
231         if(err)
232                 goto out;
233
234         set_fs(KERNEL_DS);
235         err = native_ioctl(file, cmd, (unsigned long)&karg);
236         set_fs(old_fs);
237
238         if(err == 0) {
239                 switch(cmd) {
240                 case VIDIOCGTUNER:
241                         err = put_video_tuner32(&karg.vt, up);
242                         break;
243
244                 case VIDIOCGWIN:
245                         err = put_video_window32(&karg.vw, up);
246                         break;
247
248                 case VIDIOCGFBUF:
249                         err = put_video_buffer32(&karg.vb, up);
250                         break;
251
252                 case VIDIOCGFREQ:
253                         err = put_user(((u32)karg.vx), (u32 __user *)up);
254                         break;
255                 };
256         }
257 out:
258         return err;
259 }
260
261 long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
262 {
263         int ret = -ENOIOCTLCMD;
264
265         if (!file->f_ops->ioctl)
266                 return ret;
267
268         switch (cmd) {
269         case VIDIOCSWIN32:
270                 ret = do_set_window(file, cmd, arg);
271                 break;
272         case VIDIOCGTUNER32:
273         case VIDIOCSTUNER32:
274         case VIDIOCGWIN32:
275         case VIDIOCGFBUF32:
276         case VIDIOCSFBUF32:
277         case VIDIOCGFREQ32:
278         case VIDIOCSFREQ32:
279                 ret = do_video_ioctl(file, cmd, arg);
280                 break;
281
282         /* Little v, the video4linux ioctls (conflict?) */
283         case VIDIOCGCAP:
284         case VIDIOCGCHAN:
285         case VIDIOCSCHAN:
286         case VIDIOCGPICT:
287         case VIDIOCSPICT:
288         case VIDIOCCAPTURE:
289         case VIDIOCKEY:
290         case VIDIOCGAUDIO:
291         case VIDIOCSAUDIO:
292         case VIDIOCSYNC:
293         case VIDIOCMCAPTURE:
294         case VIDIOCGMBUF:
295         case VIDIOCGUNIT:
296         case VIDIOCGCAPTURE:
297         case VIDIOCSCAPTURE:
298
299         /* BTTV specific... */
300         case _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]):
301         case _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]):
302         case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
303         case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
304         case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
305         case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
306         case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
307         case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
308                 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
309                 break;
310
311         return ret;
312         }
313 }
314 #else
315 long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
316 {
317         return -ENOIOCTLCMD;
318 }
319 #endif
320 EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
321
322 MODULE_LICENSE("GPL");