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