brintos

brintos / linux-shallow public Read only

0
0
Text · 30.7 KiB · 8c07400 Raw
1211 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.4 *	Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>5 *6 * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)7 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)8 * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs9 * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)10 * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)11 * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>12 *13 * These routines maintain argument size conversion between 32bit and 64bit14 * ioctls.15 */16 17#include <linux/compat.h>18#include <linux/module.h>19#include <linux/videodev2.h>20#include <linux/v4l2-subdev.h>21#include <media/v4l2-dev.h>22#include <media/v4l2-fh.h>23#include <media/v4l2-ctrls.h>24#include <media/v4l2-ioctl.h>25 26/*27 * Per-ioctl data copy handlers.28 *29 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,30 * where "v4l2_foo" is the name of the V4L2 struct.31 *32 * They basically get two __user pointers, one with a 32-bits struct that33 * came from the userspace call and a 64-bits struct, also allocated as34 * userspace, but filled internally by do_video_ioctl().35 *36 * For ioctls that have pointers inside it, the functions will also37 * receive an ancillary buffer with extra space, used to pass extra38 * data to the routine.39 */40 41struct v4l2_window32 {42	struct v4l2_rect        w;43	__u32			field;	/* enum v4l2_field */44	__u32			chromakey;45	compat_caddr_t		clips; /* always NULL */46	__u32			clipcount; /* always 0 */47	compat_caddr_t		bitmap; /* always NULL */48	__u8                    global_alpha;49};50 51static int get_v4l2_window32(struct v4l2_window *p64,52			     struct v4l2_window32 __user *p32)53{54	struct v4l2_window32 w32;55 56	if (copy_from_user(&w32, p32, sizeof(w32)))57		return -EFAULT;58 59	*p64 = (struct v4l2_window) {60		.w		= w32.w,61		.field		= w32.field,62		.chromakey	= w32.chromakey,63		.clips		= NULL,64		.clipcount	= 0,65		.bitmap		= NULL,66		.global_alpha	= w32.global_alpha,67	};68 69	return 0;70}71 72static int put_v4l2_window32(struct v4l2_window *p64,73			     struct v4l2_window32 __user *p32)74{75	struct v4l2_window32 w32;76 77	memset(&w32, 0, sizeof(w32));78	w32 = (struct v4l2_window32) {79		.w		= p64->w,80		.field		= p64->field,81		.chromakey	= p64->chromakey,82		.clips		= 0,83		.clipcount	= 0,84		.bitmap		= 0,85		.global_alpha	= p64->global_alpha,86	};87 88	if (copy_to_user(p32, &w32, sizeof(w32)))89		return -EFAULT;90 91	return 0;92}93 94struct v4l2_format32 {95	__u32	type;	/* enum v4l2_buf_type */96	union {97		struct v4l2_pix_format	pix;98		struct v4l2_pix_format_mplane	pix_mp;99		struct v4l2_window32	win;100		struct v4l2_vbi_format	vbi;101		struct v4l2_sliced_vbi_format	sliced;102		struct v4l2_sdr_format	sdr;103		struct v4l2_meta_format	meta;104		__u8	raw_data[200];        /* user-defined */105	} fmt;106};107 108/**109 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument110 * @index:	on return, index of the first created buffer111 * @count:	entry: number of requested buffers,112 *		return: number of created buffers113 * @memory:	buffer memory type114 * @format:	frame format, for which buffers are requested115 * @capabilities: capabilities of this buffer type.116 * @flags:	additional buffer management attributes (ignored unless the117 *		queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and118 *		configured for MMAP streaming I/O).119 * @max_num_buffers: if V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set120 *		this field indicate the maximum possible number of buffers121 *		for this queue.122 * @reserved:	future extensions123 */124struct v4l2_create_buffers32 {125	__u32			index;126	__u32			count;127	__u32			memory;	/* enum v4l2_memory */128	struct v4l2_format32	format;129	__u32			capabilities;130	__u32			flags;131	__u32			max_num_buffers;132	__u32			reserved[5];133};134 135static int get_v4l2_format32(struct v4l2_format *p64,136			     struct v4l2_format32 __user *p32)137{138	if (get_user(p64->type, &p32->type))139		return -EFAULT;140 141	switch (p64->type) {142	case V4L2_BUF_TYPE_VIDEO_CAPTURE:143	case V4L2_BUF_TYPE_VIDEO_OUTPUT:144		return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,145				      sizeof(p64->fmt.pix)) ? -EFAULT : 0;146	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:147	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:148		return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,149				      sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;150	case V4L2_BUF_TYPE_VIDEO_OVERLAY:151	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:152		return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);153	case V4L2_BUF_TYPE_VBI_CAPTURE:154	case V4L2_BUF_TYPE_VBI_OUTPUT:155		return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,156				      sizeof(p64->fmt.vbi)) ? -EFAULT : 0;157	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:158	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:159		return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,160				      sizeof(p64->fmt.sliced)) ? -EFAULT : 0;161	case V4L2_BUF_TYPE_SDR_CAPTURE:162	case V4L2_BUF_TYPE_SDR_OUTPUT:163		return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,164				      sizeof(p64->fmt.sdr)) ? -EFAULT : 0;165	case V4L2_BUF_TYPE_META_CAPTURE:166	case V4L2_BUF_TYPE_META_OUTPUT:167		return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,168				      sizeof(p64->fmt.meta)) ? -EFAULT : 0;169	default:170		return -EINVAL;171	}172}173 174static int get_v4l2_create32(struct v4l2_create_buffers *p64,175			     struct v4l2_create_buffers32 __user *p32)176{177	if (copy_from_user(p64, p32,178			   offsetof(struct v4l2_create_buffers32, format)))179		return -EFAULT;180	if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))181		return -EFAULT;182	if (copy_from_user(&p64->max_num_buffers, &p32->max_num_buffers,183			   sizeof(p32->max_num_buffers)))184		return -EFAULT;185	return get_v4l2_format32(&p64->format, &p32->format);186}187 188static int put_v4l2_format32(struct v4l2_format *p64,189			     struct v4l2_format32 __user *p32)190{191	switch (p64->type) {192	case V4L2_BUF_TYPE_VIDEO_CAPTURE:193	case V4L2_BUF_TYPE_VIDEO_OUTPUT:194		return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,195				    sizeof(p64->fmt.pix)) ? -EFAULT : 0;196	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:197	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:198		return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,199				    sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;200	case V4L2_BUF_TYPE_VIDEO_OVERLAY:201	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:202		return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);203	case V4L2_BUF_TYPE_VBI_CAPTURE:204	case V4L2_BUF_TYPE_VBI_OUTPUT:205		return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,206				    sizeof(p64->fmt.vbi)) ? -EFAULT : 0;207	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:208	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:209		return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,210				    sizeof(p64->fmt.sliced)) ? -EFAULT : 0;211	case V4L2_BUF_TYPE_SDR_CAPTURE:212	case V4L2_BUF_TYPE_SDR_OUTPUT:213		return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,214				    sizeof(p64->fmt.sdr)) ? -EFAULT : 0;215	case V4L2_BUF_TYPE_META_CAPTURE:216	case V4L2_BUF_TYPE_META_OUTPUT:217		return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,218				    sizeof(p64->fmt.meta)) ? -EFAULT : 0;219	default:220		return -EINVAL;221	}222}223 224static int put_v4l2_create32(struct v4l2_create_buffers *p64,225			     struct v4l2_create_buffers32 __user *p32)226{227	if (copy_to_user(p32, p64,228			 offsetof(struct v4l2_create_buffers32, format)) ||229	    put_user(p64->capabilities, &p32->capabilities) ||230	    put_user(p64->flags, &p32->flags) ||231	    put_user(p64->max_num_buffers, &p32->max_num_buffers) ||232	    copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))233		return -EFAULT;234	return put_v4l2_format32(&p64->format, &p32->format);235}236 237struct v4l2_standard32 {238	__u32		     index;239	compat_u64	     id;240	__u8		     name[24];241	struct v4l2_fract    frameperiod; /* Frames, not fields */242	__u32		     framelines;243	__u32		     reserved[4];244};245 246static int get_v4l2_standard32(struct v4l2_standard *p64,247			       struct v4l2_standard32 __user *p32)248{249	/* other fields are not set by the user, nor used by the driver */250	return get_user(p64->index, &p32->index);251}252 253static int put_v4l2_standard32(struct v4l2_standard *p64,254			       struct v4l2_standard32 __user *p32)255{256	if (put_user(p64->index, &p32->index) ||257	    put_user(p64->id, &p32->id) ||258	    copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||259	    copy_to_user(&p32->frameperiod, &p64->frameperiod,260			 sizeof(p32->frameperiod)) ||261	    put_user(p64->framelines, &p32->framelines) ||262	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))263		return -EFAULT;264	return 0;265}266 267struct v4l2_plane32 {268	__u32			bytesused;269	__u32			length;270	union {271		__u32		mem_offset;272		compat_long_t	userptr;273		__s32		fd;274	} m;275	__u32			data_offset;276	__u32			reserved[11];277};278 279/*280 * This is correct for all architectures including i386, but not x32,281 * which has different alignment requirements for timestamp282 */283struct v4l2_buffer32 {284	__u32			index;285	__u32			type;	/* enum v4l2_buf_type */286	__u32			bytesused;287	__u32			flags;288	__u32			field;	/* enum v4l2_field */289	struct {290		compat_s64	tv_sec;291		compat_s64	tv_usec;292	}			timestamp;293	struct v4l2_timecode	timecode;294	__u32			sequence;295 296	/* memory location */297	__u32			memory;	/* enum v4l2_memory */298	union {299		__u32           offset;300		compat_long_t   userptr;301		compat_caddr_t  planes;302		__s32		fd;303	} m;304	__u32			length;305	__u32			reserved2;306	__s32			request_fd;307};308 309#ifdef CONFIG_COMPAT_32BIT_TIME310struct v4l2_buffer32_time32 {311	__u32			index;312	__u32			type;	/* enum v4l2_buf_type */313	__u32			bytesused;314	__u32			flags;315	__u32			field;	/* enum v4l2_field */316	struct old_timeval32	timestamp;317	struct v4l2_timecode	timecode;318	__u32			sequence;319 320	/* memory location */321	__u32			memory;	/* enum v4l2_memory */322	union {323		__u32           offset;324		compat_long_t   userptr;325		compat_caddr_t  planes;326		__s32		fd;327	} m;328	__u32			length;329	__u32			reserved2;330	__s32			request_fd;331};332#endif333 334static int get_v4l2_plane32(struct v4l2_plane *p64,335			    struct v4l2_plane32 __user *p32,336			    enum v4l2_memory memory)337{338	struct v4l2_plane32 plane32;339	typeof(p64->m) m = {};340 341	if (copy_from_user(&plane32, p32, sizeof(plane32)))342		return -EFAULT;343 344	switch (memory) {345	case V4L2_MEMORY_MMAP:346	case V4L2_MEMORY_OVERLAY:347		m.mem_offset = plane32.m.mem_offset;348		break;349	case V4L2_MEMORY_USERPTR:350		m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);351		break;352	case V4L2_MEMORY_DMABUF:353		m.fd = plane32.m.fd;354		break;355	}356 357	memset(p64, 0, sizeof(*p64));358	*p64 = (struct v4l2_plane) {359		.bytesused	= plane32.bytesused,360		.length		= plane32.length,361		.m		= m,362		.data_offset	= plane32.data_offset,363	};364 365	return 0;366}367 368static int put_v4l2_plane32(struct v4l2_plane *p64,369			    struct v4l2_plane32 __user *p32,370			    enum v4l2_memory memory)371{372	struct v4l2_plane32 plane32;373 374	memset(&plane32, 0, sizeof(plane32));375	plane32 = (struct v4l2_plane32) {376		.bytesused	= p64->bytesused,377		.length		= p64->length,378		.data_offset	= p64->data_offset,379	};380 381	switch (memory) {382	case V4L2_MEMORY_MMAP:383	case V4L2_MEMORY_OVERLAY:384		plane32.m.mem_offset = p64->m.mem_offset;385		break;386	case V4L2_MEMORY_USERPTR:387		plane32.m.userptr = (uintptr_t)(p64->m.userptr);388		break;389	case V4L2_MEMORY_DMABUF:390		plane32.m.fd = p64->m.fd;391		break;392	}393 394	if (copy_to_user(p32, &plane32, sizeof(plane32)))395		return -EFAULT;396 397	return 0;398}399 400static int get_v4l2_buffer32(struct v4l2_buffer *vb,401			     struct v4l2_buffer32 __user *arg)402{403	struct v4l2_buffer32 vb32;404 405	if (copy_from_user(&vb32, arg, sizeof(vb32)))406		return -EFAULT;407 408	memset(vb, 0, sizeof(*vb));409	*vb = (struct v4l2_buffer) {410		.index		= vb32.index,411		.type		= vb32.type,412		.bytesused	= vb32.bytesused,413		.flags		= vb32.flags,414		.field		= vb32.field,415		.timestamp.tv_sec	= vb32.timestamp.tv_sec,416		.timestamp.tv_usec	= vb32.timestamp.tv_usec,417		.timecode	= vb32.timecode,418		.sequence	= vb32.sequence,419		.memory		= vb32.memory,420		.m.offset	= vb32.m.offset,421		.length		= vb32.length,422		.request_fd	= vb32.request_fd,423	};424 425	switch (vb->memory) {426	case V4L2_MEMORY_MMAP:427	case V4L2_MEMORY_OVERLAY:428		vb->m.offset = vb32.m.offset;429		break;430	case V4L2_MEMORY_USERPTR:431		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);432		break;433	case V4L2_MEMORY_DMABUF:434		vb->m.fd = vb32.m.fd;435		break;436	}437 438	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))439		vb->m.planes = (void __force *)440				compat_ptr(vb32.m.planes);441 442	return 0;443}444 445#ifdef CONFIG_COMPAT_32BIT_TIME446static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,447				    struct v4l2_buffer32_time32 __user *arg)448{449	struct v4l2_buffer32_time32 vb32;450 451	if (copy_from_user(&vb32, arg, sizeof(vb32)))452		return -EFAULT;453 454	*vb = (struct v4l2_buffer) {455		.index		= vb32.index,456		.type		= vb32.type,457		.bytesused	= vb32.bytesused,458		.flags		= vb32.flags,459		.field		= vb32.field,460		.timestamp.tv_sec	= vb32.timestamp.tv_sec,461		.timestamp.tv_usec	= vb32.timestamp.tv_usec,462		.timecode	= vb32.timecode,463		.sequence	= vb32.sequence,464		.memory		= vb32.memory,465		.m.offset	= vb32.m.offset,466		.length		= vb32.length,467		.request_fd	= vb32.request_fd,468	};469	switch (vb->memory) {470	case V4L2_MEMORY_MMAP:471	case V4L2_MEMORY_OVERLAY:472		vb->m.offset = vb32.m.offset;473		break;474	case V4L2_MEMORY_USERPTR:475		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);476		break;477	case V4L2_MEMORY_DMABUF:478		vb->m.fd = vb32.m.fd;479		break;480	}481 482	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))483		vb->m.planes = (void __force *)484				compat_ptr(vb32.m.planes);485 486	return 0;487}488#endif489 490static int put_v4l2_buffer32(struct v4l2_buffer *vb,491			     struct v4l2_buffer32 __user *arg)492{493	struct v4l2_buffer32 vb32;494 495	memset(&vb32, 0, sizeof(vb32));496	vb32 = (struct v4l2_buffer32) {497		.index		= vb->index,498		.type		= vb->type,499		.bytesused	= vb->bytesused,500		.flags		= vb->flags,501		.field		= vb->field,502		.timestamp.tv_sec	= vb->timestamp.tv_sec,503		.timestamp.tv_usec	= vb->timestamp.tv_usec,504		.timecode	= vb->timecode,505		.sequence	= vb->sequence,506		.memory		= vb->memory,507		.m.offset	= vb->m.offset,508		.length		= vb->length,509		.request_fd	= vb->request_fd,510	};511 512	switch (vb->memory) {513	case V4L2_MEMORY_MMAP:514	case V4L2_MEMORY_OVERLAY:515		vb32.m.offset = vb->m.offset;516		break;517	case V4L2_MEMORY_USERPTR:518		vb32.m.userptr = (uintptr_t)(vb->m.userptr);519		break;520	case V4L2_MEMORY_DMABUF:521		vb32.m.fd = vb->m.fd;522		break;523	}524 525	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))526		vb32.m.planes = (uintptr_t)vb->m.planes;527 528	if (copy_to_user(arg, &vb32, sizeof(vb32)))529		return -EFAULT;530 531	return 0;532}533 534#ifdef CONFIG_COMPAT_32BIT_TIME535static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,536				    struct v4l2_buffer32_time32 __user *arg)537{538	struct v4l2_buffer32_time32 vb32;539 540	memset(&vb32, 0, sizeof(vb32));541	vb32 = (struct v4l2_buffer32_time32) {542		.index		= vb->index,543		.type		= vb->type,544		.bytesused	= vb->bytesused,545		.flags		= vb->flags,546		.field		= vb->field,547		.timestamp.tv_sec	= vb->timestamp.tv_sec,548		.timestamp.tv_usec	= vb->timestamp.tv_usec,549		.timecode	= vb->timecode,550		.sequence	= vb->sequence,551		.memory		= vb->memory,552		.m.offset	= vb->m.offset,553		.length		= vb->length,554		.request_fd	= vb->request_fd,555	};556	switch (vb->memory) {557	case V4L2_MEMORY_MMAP:558	case V4L2_MEMORY_OVERLAY:559		vb32.m.offset = vb->m.offset;560		break;561	case V4L2_MEMORY_USERPTR:562		vb32.m.userptr = (uintptr_t)(vb->m.userptr);563		break;564	case V4L2_MEMORY_DMABUF:565		vb32.m.fd = vb->m.fd;566		break;567	}568 569	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))570		vb32.m.planes = (uintptr_t)vb->m.planes;571 572	if (copy_to_user(arg, &vb32, sizeof(vb32)))573		return -EFAULT;574 575	return 0;576}577#endif578 579struct v4l2_framebuffer32 {580	__u32			capability;581	__u32			flags;582	compat_caddr_t		base;583	struct {584		__u32		width;585		__u32		height;586		__u32		pixelformat;587		__u32		field;588		__u32		bytesperline;589		__u32		sizeimage;590		__u32		colorspace;591		__u32		priv;592	} fmt;593};594 595static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,596				  struct v4l2_framebuffer32 __user *p32)597{598	if (get_user(p64->capability, &p32->capability) ||599	    get_user(p64->flags, &p32->flags) ||600	    copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))601		return -EFAULT;602	p64->base = NULL;603 604	return 0;605}606 607static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,608				  struct v4l2_framebuffer32 __user *p32)609{610	if (put_user((uintptr_t)p64->base, &p32->base) ||611	    put_user(p64->capability, &p32->capability) ||612	    put_user(p64->flags, &p32->flags) ||613	    copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))614		return -EFAULT;615 616	return 0;617}618 619struct v4l2_input32 {620	__u32	     index;		/*  Which input */621	__u8	     name[32];		/*  Label */622	__u32	     type;		/*  Type of input */623	__u32	     audioset;		/*  Associated audios (bitfield) */624	__u32        tuner;             /*  Associated tuner */625	compat_u64   std;626	__u32	     status;627	__u32	     capabilities;628	__u32	     reserved[3];629};630 631/*632 * The 64-bit v4l2_input struct has extra padding at the end of the struct.633 * Otherwise it is identical to the 32-bit version.634 */635static inline int get_v4l2_input32(struct v4l2_input *p64,636				   struct v4l2_input32 __user *p32)637{638	if (copy_from_user(p64, p32, sizeof(*p32)))639		return -EFAULT;640	return 0;641}642 643static inline int put_v4l2_input32(struct v4l2_input *p64,644				   struct v4l2_input32 __user *p32)645{646	if (copy_to_user(p32, p64, sizeof(*p32)))647		return -EFAULT;648	return 0;649}650 651struct v4l2_ext_controls32 {652	__u32 which;653	__u32 count;654	__u32 error_idx;655	__s32 request_fd;656	__u32 reserved[1];657	compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */658};659 660struct v4l2_ext_control32 {661	__u32 id;662	__u32 size;663	__u32 reserved2[1];664	union {665		__s32 value;666		__s64 value64;667		compat_caddr_t string; /* actually char * */668	};669} __attribute__ ((packed));670 671/* Return true if this control is a pointer type. */672static inline bool ctrl_is_pointer(struct file *file, u32 id)673{674	struct video_device *vdev = video_devdata(file);675	struct v4l2_fh *fh = NULL;676	struct v4l2_ctrl_handler *hdl = NULL;677	struct v4l2_query_ext_ctrl qec = { id };678	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;679 680	if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))681		fh = file->private_data;682 683	if (fh && fh->ctrl_handler)684		hdl = fh->ctrl_handler;685	else if (vdev->ctrl_handler)686		hdl = vdev->ctrl_handler;687 688	if (hdl) {689		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);690 691		return ctrl && ctrl->is_ptr;692	}693 694	if (!ops || !ops->vidioc_query_ext_ctrl)695		return false;696 697	return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&698		(qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);699}700 701static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,702				   struct v4l2_ext_controls32 __user *p32)703{704	struct v4l2_ext_controls32 ec32;705 706	if (copy_from_user(&ec32, p32, sizeof(ec32)))707		return -EFAULT;708 709	*p64 = (struct v4l2_ext_controls) {710		.which		= ec32.which,711		.count		= ec32.count,712		.error_idx	= ec32.error_idx,713		.request_fd	= ec32.request_fd,714		.reserved[0]	= ec32.reserved[0],715		.controls	= (void __force *)compat_ptr(ec32.controls),716	};717 718	return 0;719}720 721static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,722				   struct v4l2_ext_controls32 __user *p32)723{724	struct v4l2_ext_controls32 ec32;725 726	memset(&ec32, 0, sizeof(ec32));727	ec32 = (struct v4l2_ext_controls32) {728		.which		= p64->which,729		.count		= p64->count,730		.error_idx	= p64->error_idx,731		.request_fd	= p64->request_fd,732		.reserved[0]	= p64->reserved[0],733		.controls	= (uintptr_t)p64->controls,734	};735 736	if (copy_to_user(p32, &ec32, sizeof(ec32)))737		return -EFAULT;738 739	return 0;740}741 742#ifdef CONFIG_X86_64743/*744 * x86 is the only compat architecture with different struct alignment745 * between 32-bit and 64-bit tasks.746 */747struct v4l2_event32 {748	__u32				type;749	union {750		compat_s64		value64;751		__u8			data[64];752	} u;753	__u32				pending;754	__u32				sequence;755	struct {756		compat_s64		tv_sec;757		compat_s64		tv_nsec;758	} timestamp;759	__u32				id;760	__u32				reserved[8];761};762 763static int put_v4l2_event32(struct v4l2_event *p64,764			    struct v4l2_event32 __user *p32)765{766	if (put_user(p64->type, &p32->type) ||767	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||768	    put_user(p64->pending, &p32->pending) ||769	    put_user(p64->sequence, &p32->sequence) ||770	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||771	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||772	    put_user(p64->id, &p32->id) ||773	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))774		return -EFAULT;775	return 0;776}777 778#endif779 780#ifdef CONFIG_COMPAT_32BIT_TIME781struct v4l2_event32_time32 {782	__u32				type;783	union {784		compat_s64		value64;785		__u8			data[64];786	} u;787	__u32				pending;788	__u32				sequence;789	struct old_timespec32		timestamp;790	__u32				id;791	__u32				reserved[8];792};793 794static int put_v4l2_event32_time32(struct v4l2_event *p64,795				   struct v4l2_event32_time32 __user *p32)796{797	if (put_user(p64->type, &p32->type) ||798	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||799	    put_user(p64->pending, &p32->pending) ||800	    put_user(p64->sequence, &p32->sequence) ||801	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||802	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||803	    put_user(p64->id, &p32->id) ||804	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))805		return -EFAULT;806	return 0;807}808#endif809 810struct v4l2_edid32 {811	__u32 pad;812	__u32 start_block;813	__u32 blocks;814	__u32 reserved[5];815	compat_caddr_t edid;816};817 818static int get_v4l2_edid32(struct v4l2_edid *p64,819			   struct v4l2_edid32 __user *p32)820{821	compat_uptr_t edid;822 823	if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||824	    get_user(edid, &p32->edid))825		return -EFAULT;826 827	p64->edid = (void __force *)compat_ptr(edid);828	return 0;829}830 831static int put_v4l2_edid32(struct v4l2_edid *p64,832			   struct v4l2_edid32 __user *p32)833{834	if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))835		return -EFAULT;836	return 0;837}838 839/*840 * List of ioctls that require 32-bits/64-bits conversion841 *842 * The V4L2 ioctls that aren't listed there don't have pointer arguments843 * and the struct size is identical for both 32 and 64 bits versions, so844 * they don't need translations.845 */846 847#define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)848#define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)849#define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)850#define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)851#define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)852#define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)853#define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)854#define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)855#define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)856#define VIDIOC_G_EDID32		_IOWR('V', 40, struct v4l2_edid32)857#define VIDIOC_S_EDID32		_IOWR('V', 41, struct v4l2_edid32)858#define VIDIOC_TRY_FMT32	_IOWR('V', 64, struct v4l2_format32)859#define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)860#define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)861#define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)862#define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)863#define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)864#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)865 866#ifdef CONFIG_COMPAT_32BIT_TIME867#define VIDIOC_QUERYBUF32_TIME32	_IOWR('V',  9, struct v4l2_buffer32_time32)868#define VIDIOC_QBUF32_TIME32		_IOWR('V', 15, struct v4l2_buffer32_time32)869#define VIDIOC_DQBUF32_TIME32		_IOWR('V', 17, struct v4l2_buffer32_time32)870#define	VIDIOC_DQEVENT32_TIME32		_IOR ('V', 89, struct v4l2_event32_time32)871#define VIDIOC_PREPARE_BUF32_TIME32	_IOWR('V', 93, struct v4l2_buffer32_time32)872#endif873 874unsigned int v4l2_compat_translate_cmd(unsigned int cmd)875{876	switch (cmd) {877	case VIDIOC_G_FMT32:878		return VIDIOC_G_FMT;879	case VIDIOC_S_FMT32:880		return VIDIOC_S_FMT;881	case VIDIOC_TRY_FMT32:882		return VIDIOC_TRY_FMT;883	case VIDIOC_G_FBUF32:884		return VIDIOC_G_FBUF;885	case VIDIOC_S_FBUF32:886		return VIDIOC_S_FBUF;887#ifdef CONFIG_COMPAT_32BIT_TIME888	case VIDIOC_QUERYBUF32_TIME32:889		return VIDIOC_QUERYBUF;890	case VIDIOC_QBUF32_TIME32:891		return VIDIOC_QBUF;892	case VIDIOC_DQBUF32_TIME32:893		return VIDIOC_DQBUF;894	case VIDIOC_PREPARE_BUF32_TIME32:895		return VIDIOC_PREPARE_BUF;896#endif897	case VIDIOC_QUERYBUF32:898		return VIDIOC_QUERYBUF;899	case VIDIOC_QBUF32:900		return VIDIOC_QBUF;901	case VIDIOC_DQBUF32:902		return VIDIOC_DQBUF;903	case VIDIOC_CREATE_BUFS32:904		return VIDIOC_CREATE_BUFS;905	case VIDIOC_G_EXT_CTRLS32:906		return VIDIOC_G_EXT_CTRLS;907	case VIDIOC_S_EXT_CTRLS32:908		return VIDIOC_S_EXT_CTRLS;909	case VIDIOC_TRY_EXT_CTRLS32:910		return VIDIOC_TRY_EXT_CTRLS;911	case VIDIOC_PREPARE_BUF32:912		return VIDIOC_PREPARE_BUF;913	case VIDIOC_ENUMSTD32:914		return VIDIOC_ENUMSTD;915	case VIDIOC_ENUMINPUT32:916		return VIDIOC_ENUMINPUT;917	case VIDIOC_G_EDID32:918		return VIDIOC_G_EDID;919	case VIDIOC_S_EDID32:920		return VIDIOC_S_EDID;921#ifdef CONFIG_X86_64922	case VIDIOC_DQEVENT32:923		return VIDIOC_DQEVENT;924#endif925#ifdef CONFIG_COMPAT_32BIT_TIME926	case VIDIOC_DQEVENT32_TIME32:927		return VIDIOC_DQEVENT;928#endif929	}930	return cmd;931}932 933int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)934{935	switch (cmd) {936	case VIDIOC_G_FMT32:937	case VIDIOC_S_FMT32:938	case VIDIOC_TRY_FMT32:939		return get_v4l2_format32(parg, arg);940 941	case VIDIOC_S_FBUF32:942		return get_v4l2_framebuffer32(parg, arg);943#ifdef CONFIG_COMPAT_32BIT_TIME944	case VIDIOC_QUERYBUF32_TIME32:945	case VIDIOC_QBUF32_TIME32:946	case VIDIOC_DQBUF32_TIME32:947	case VIDIOC_PREPARE_BUF32_TIME32:948		return get_v4l2_buffer32_time32(parg, arg);949#endif950	case VIDIOC_QUERYBUF32:951	case VIDIOC_QBUF32:952	case VIDIOC_DQBUF32:953	case VIDIOC_PREPARE_BUF32:954		return get_v4l2_buffer32(parg, arg);955 956	case VIDIOC_G_EXT_CTRLS32:957	case VIDIOC_S_EXT_CTRLS32:958	case VIDIOC_TRY_EXT_CTRLS32:959		return get_v4l2_ext_controls32(parg, arg);960 961	case VIDIOC_CREATE_BUFS32:962		return get_v4l2_create32(parg, arg);963 964	case VIDIOC_ENUMSTD32:965		return get_v4l2_standard32(parg, arg);966 967	case VIDIOC_ENUMINPUT32:968		return get_v4l2_input32(parg, arg);969 970	case VIDIOC_G_EDID32:971	case VIDIOC_S_EDID32:972		return get_v4l2_edid32(parg, arg);973	}974	return 0;975}976 977int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)978{979	switch (cmd) {980	case VIDIOC_G_FMT32:981	case VIDIOC_S_FMT32:982	case VIDIOC_TRY_FMT32:983		return put_v4l2_format32(parg, arg);984 985	case VIDIOC_G_FBUF32:986		return put_v4l2_framebuffer32(parg, arg);987#ifdef CONFIG_COMPAT_32BIT_TIME988	case VIDIOC_QUERYBUF32_TIME32:989	case VIDIOC_QBUF32_TIME32:990	case VIDIOC_DQBUF32_TIME32:991	case VIDIOC_PREPARE_BUF32_TIME32:992		return put_v4l2_buffer32_time32(parg, arg);993#endif994	case VIDIOC_QUERYBUF32:995	case VIDIOC_QBUF32:996	case VIDIOC_DQBUF32:997	case VIDIOC_PREPARE_BUF32:998		return put_v4l2_buffer32(parg, arg);999 1000	case VIDIOC_G_EXT_CTRLS32:1001	case VIDIOC_S_EXT_CTRLS32:1002	case VIDIOC_TRY_EXT_CTRLS32:1003		return put_v4l2_ext_controls32(parg, arg);1004 1005	case VIDIOC_CREATE_BUFS32:1006		return put_v4l2_create32(parg, arg);1007 1008	case VIDIOC_ENUMSTD32:1009		return put_v4l2_standard32(parg, arg);1010 1011	case VIDIOC_ENUMINPUT32:1012		return put_v4l2_input32(parg, arg);1013 1014	case VIDIOC_G_EDID32:1015	case VIDIOC_S_EDID32:1016		return put_v4l2_edid32(parg, arg);1017#ifdef CONFIG_X86_641018	case VIDIOC_DQEVENT32:1019		return put_v4l2_event32(parg, arg);1020#endif1021#ifdef CONFIG_COMPAT_32BIT_TIME1022	case VIDIOC_DQEVENT32_TIME32:1023		return put_v4l2_event32_time32(parg, arg);1024#endif1025	}1026	return 0;1027}1028 1029int v4l2_compat_get_array_args(struct file *file, void *mbuf,1030			       void __user *user_ptr, size_t array_size,1031			       unsigned int cmd, void *arg)1032{1033	int err = 0;1034 1035	memset(mbuf, 0, array_size);1036 1037	switch (cmd) {1038#ifdef CONFIG_COMPAT_32BIT_TIME1039	case VIDIOC_QUERYBUF32_TIME32:1040	case VIDIOC_QBUF32_TIME32:1041	case VIDIOC_DQBUF32_TIME32:1042	case VIDIOC_PREPARE_BUF32_TIME32:1043#endif1044	case VIDIOC_QUERYBUF32:1045	case VIDIOC_QBUF32:1046	case VIDIOC_DQBUF32:1047	case VIDIOC_PREPARE_BUF32: {1048		struct v4l2_buffer *b64 = arg;1049		struct v4l2_plane *p64 = mbuf;1050		struct v4l2_plane32 __user *p32 = user_ptr;1051 1052		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {1053			u32 num_planes = b64->length;1054 1055			if (num_planes == 0)1056				return 0;1057 1058			while (num_planes--) {1059				err = get_v4l2_plane32(p64, p32, b64->memory);1060				if (err)1061					return err;1062				++p64;1063				++p32;1064			}1065		}1066		break;1067	}1068	case VIDIOC_G_EXT_CTRLS32:1069	case VIDIOC_S_EXT_CTRLS32:1070	case VIDIOC_TRY_EXT_CTRLS32: {1071		struct v4l2_ext_controls *ecs64 = arg;1072		struct v4l2_ext_control *ec64 = mbuf;1073		struct v4l2_ext_control32 __user *ec32 = user_ptr;1074		int n;1075 1076		for (n = 0; n < ecs64->count; n++) {1077			if (copy_from_user(ec64, ec32, sizeof(*ec32)))1078				return -EFAULT;1079 1080			if (ctrl_is_pointer(file, ec64->id)) {1081				compat_uptr_t p;1082 1083				if (get_user(p, &ec32->string))1084					return -EFAULT;1085				ec64->string = compat_ptr(p);1086			}1087			ec32++;1088			ec64++;1089		}1090		break;1091	}1092	default:1093		if (copy_from_user(mbuf, user_ptr, array_size))1094			err = -EFAULT;1095		break;1096	}1097 1098	return err;1099}1100 1101int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,1102			       void *mbuf, size_t array_size,1103			       unsigned int cmd, void *arg)1104{1105	int err = 0;1106 1107	switch (cmd) {1108#ifdef CONFIG_COMPAT_32BIT_TIME1109	case VIDIOC_QUERYBUF32_TIME32:1110	case VIDIOC_QBUF32_TIME32:1111	case VIDIOC_DQBUF32_TIME32:1112	case VIDIOC_PREPARE_BUF32_TIME32:1113#endif1114	case VIDIOC_QUERYBUF32:1115	case VIDIOC_QBUF32:1116	case VIDIOC_DQBUF32:1117	case VIDIOC_PREPARE_BUF32: {1118		struct v4l2_buffer *b64 = arg;1119		struct v4l2_plane *p64 = mbuf;1120		struct v4l2_plane32 __user *p32 = user_ptr;1121 1122		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {1123			u32 num_planes = b64->length;1124 1125			if (num_planes == 0)1126				return 0;1127 1128			while (num_planes--) {1129				err = put_v4l2_plane32(p64, p32, b64->memory);1130				if (err)1131					return err;1132				++p64;1133				++p32;1134			}1135		}1136		break;1137	}1138	case VIDIOC_G_EXT_CTRLS32:1139	case VIDIOC_S_EXT_CTRLS32:1140	case VIDIOC_TRY_EXT_CTRLS32: {1141		struct v4l2_ext_controls *ecs64 = arg;1142		struct v4l2_ext_control *ec64 = mbuf;1143		struct v4l2_ext_control32 __user *ec32 = user_ptr;1144		int n;1145 1146		for (n = 0; n < ecs64->count; n++) {1147			unsigned int size = sizeof(*ec32);1148			/*1149			 * Do not modify the pointer when copying a pointer1150			 * control.  The contents of the pointer was changed,1151			 * not the pointer itself.1152			 * The structures are otherwise compatible.1153			 */1154			if (ctrl_is_pointer(file, ec64->id))1155				size -= sizeof(ec32->value64);1156 1157			if (copy_to_user(ec32, ec64, size))1158				return -EFAULT;1159 1160			ec32++;1161			ec64++;1162		}1163		break;1164	}1165	default:1166		if (copy_to_user(user_ptr, mbuf, array_size))1167			err = -EFAULT;1168		break;1169	}1170 1171	return err;1172}1173 1174/**1175 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call1176 *1177 * @file: pointer to &struct file with the file handler1178 * @cmd: ioctl to be called1179 * @arg: arguments passed from/to the ioctl handler1180 *1181 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c1182 * in order to deal with 32-bit calls on a 64-bits Kernel.1183 *1184 * This function calls do_video_ioctl() for non-private V4L2 ioctls.1185 * If the function is a private one it calls vdev->fops->compat_ioctl321186 * instead.1187 */1188long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)1189{1190	struct video_device *vdev = video_devdata(file);1191	long ret = -ENOIOCTLCMD;1192 1193	if (!file->f_op->unlocked_ioctl)1194		return ret;1195 1196	if (!video_is_registered(vdev))1197		return -ENODEV;1198 1199	if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)1200		ret = file->f_op->unlocked_ioctl(file, cmd,1201					(unsigned long)compat_ptr(arg));1202	else if (vdev->fops->compat_ioctl32)1203		ret = vdev->fops->compat_ioctl32(file, cmd, arg);1204 1205	if (ret == -ENOIOCTLCMD)1206		pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",1207			 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);1208	return ret;1209}1210EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);1211