• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14 
15 #include <linux/uaccess.h>
16 #include <video/adf.h>
17 
18 #include "adf_fops.h"
19 #include "adf_fops32.h"
20 
adf_compat_post_config(struct file * file,struct adf_post_config32 __user * arg)21 long adf_compat_post_config(struct file *file,
22 		struct adf_post_config32 __user *arg)
23 {
24 	struct adf_post_config32 cfg32;
25 	struct adf_post_config __user *cfg;
26 	int ret;
27 
28 	if (copy_from_user(&cfg32, arg, sizeof(cfg32)))
29 		return -EFAULT;
30 
31 	cfg = compat_alloc_user_space(sizeof(*cfg));
32 	if (!access_ok(VERIFY_WRITE, cfg, sizeof(*cfg)))
33 		return -EFAULT;
34 
35 	if (put_user(cfg32.n_interfaces, &cfg->n_interfaces) ||
36 			put_user(compat_ptr(cfg32.interfaces),
37 					&cfg->interfaces) ||
38 			put_user(cfg32.n_bufs, &cfg->n_bufs) ||
39 			put_user(compat_ptr(cfg32.bufs), &cfg->bufs) ||
40 			put_user(cfg32.custom_data_size,
41 					&cfg->custom_data_size) ||
42 			put_user(compat_ptr(cfg32.custom_data),
43 					&cfg->custom_data))
44 		return -EFAULT;
45 
46 	ret = adf_file_ioctl(file, ADF_POST_CONFIG, (unsigned long)cfg);
47 	if (ret < 0)
48 		return ret;
49 
50 	if (copy_in_user(&arg->complete_fence, &cfg->complete_fence,
51 			sizeof(cfg->complete_fence)))
52 		return -EFAULT;
53 
54 	return 0;
55 }
56 
adf_compat_get_device_data(struct file * file,struct adf_device_data32 __user * arg)57 long adf_compat_get_device_data(struct file *file,
58 		struct adf_device_data32 __user *arg)
59 {
60 	struct adf_device_data32 data32;
61 	struct adf_device_data __user *data;
62 	int ret;
63 
64 	if (copy_from_user(&data32, arg, sizeof(data32)))
65 		return -EFAULT;
66 
67 	data = compat_alloc_user_space(sizeof(*data));
68 	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
69 		return -EFAULT;
70 
71 	if (put_user(data32.n_attachments, &data->n_attachments) ||
72 			put_user(compat_ptr(data32.attachments),
73 					&data->attachments) ||
74 			put_user(data32.n_allowed_attachments,
75 					&data->n_allowed_attachments) ||
76 			put_user(compat_ptr(data32.allowed_attachments),
77 					&data->allowed_attachments) ||
78 			put_user(data32.custom_data_size,
79 					&data->custom_data_size) ||
80 			put_user(compat_ptr(data32.custom_data),
81 					&data->custom_data))
82 		return -EFAULT;
83 
84 	ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data);
85 	if (ret < 0)
86 		return ret;
87 
88 	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
89 			copy_in_user(&arg->n_attachments, &data->n_attachments,
90 					sizeof(arg->n_attachments)) ||
91 			copy_in_user(&arg->n_allowed_attachments,
92 					&data->n_allowed_attachments,
93 					sizeof(arg->n_allowed_attachments)) ||
94 			copy_in_user(&arg->custom_data_size,
95 					&data->custom_data_size,
96 					sizeof(arg->custom_data_size)))
97 		return -EFAULT;
98 
99 	return 0;
100 }
101 
adf_compat_get_interface_data(struct file * file,struct adf_interface_data32 __user * arg)102 long adf_compat_get_interface_data(struct file *file,
103 		struct adf_interface_data32 __user *arg)
104 {
105 	struct adf_interface_data32 data32;
106 	struct adf_interface_data __user *data;
107 	int ret;
108 
109 	if (copy_from_user(&data32, arg, sizeof(data32)))
110 		return -EFAULT;
111 
112 	data = compat_alloc_user_space(sizeof(*data));
113 	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
114 		return -EFAULT;
115 
116 	if (put_user(data32.n_available_modes, &data->n_available_modes) ||
117 			put_user(compat_ptr(data32.available_modes),
118 					&data->available_modes) ||
119 			put_user(data32.custom_data_size,
120 					&data->custom_data_size) ||
121 			put_user(compat_ptr(data32.custom_data),
122 					&data->custom_data))
123 		return -EFAULT;
124 
125 	ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data);
126 	if (ret < 0)
127 		return ret;
128 
129 	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
130 			copy_in_user(&arg->type, &data->type,
131 					sizeof(arg->type)) ||
132 			copy_in_user(&arg->id, &data->id, sizeof(arg->id)) ||
133 			copy_in_user(&arg->flags, &data->flags,
134 					sizeof(arg->flags)) ||
135 			copy_in_user(&arg->dpms_state, &data->dpms_state,
136 					sizeof(arg->dpms_state)) ||
137 			copy_in_user(&arg->hotplug_detect,
138 					&data->hotplug_detect,
139 					sizeof(arg->hotplug_detect)) ||
140 			copy_in_user(&arg->width_mm, &data->width_mm,
141 					sizeof(arg->width_mm)) ||
142 			copy_in_user(&arg->height_mm, &data->height_mm,
143 					sizeof(arg->height_mm)) ||
144 			copy_in_user(&arg->current_mode, &data->current_mode,
145 					sizeof(arg->current_mode)) ||
146 			copy_in_user(&arg->n_available_modes,
147 					&data->n_available_modes,
148 					sizeof(arg->n_available_modes)) ||
149 			copy_in_user(&arg->custom_data_size,
150 					&data->custom_data_size,
151 					sizeof(arg->custom_data_size)))
152 		return -EFAULT;
153 
154 	return 0;
155 }
156 
adf_compat_get_overlay_engine_data(struct file * file,struct adf_overlay_engine_data32 __user * arg)157 long adf_compat_get_overlay_engine_data(struct file *file,
158 		struct adf_overlay_engine_data32 __user *arg)
159 {
160 	struct adf_overlay_engine_data32 data32;
161 	struct adf_overlay_engine_data __user *data;
162 	int ret;
163 
164 	if (copy_from_user(&data32, arg, sizeof(data32)))
165 		return -EFAULT;
166 
167 	data = compat_alloc_user_space(sizeof(*data));
168 	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
169 		return -EFAULT;
170 
171 	if (put_user(data32.n_supported_formats, &data->n_supported_formats) ||
172 			put_user(compat_ptr(data32.supported_formats),
173 					&data->supported_formats) ||
174 			put_user(data32.custom_data_size,
175 					&data->custom_data_size) ||
176 			put_user(compat_ptr(data32.custom_data),
177 					&data->custom_data))
178 		return -EFAULT;
179 
180 	ret = adf_file_ioctl(file, ADF_GET_OVERLAY_ENGINE_DATA,
181 			(unsigned long)data);
182 	if (ret < 0)
183 		return ret;
184 
185 	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
186 			copy_in_user(&arg->n_supported_formats,
187 					&data->n_supported_formats,
188 					sizeof(arg->n_supported_formats)) ||
189 			copy_in_user(&arg->custom_data_size,
190 					&data->custom_data_size,
191 					sizeof(arg->custom_data_size)))
192 		return -EFAULT;
193 
194 	return 0;
195 }
196 
adf_file_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)197 long adf_file_compat_ioctl(struct file *file, unsigned int cmd,
198 		unsigned long arg)
199 {
200 	switch (cmd) {
201 	case ADF_POST_CONFIG32:
202 		return adf_compat_post_config(file, compat_ptr(arg));
203 
204 	case ADF_GET_DEVICE_DATA32:
205 		return adf_compat_get_device_data(file, compat_ptr(arg));
206 
207 	case ADF_GET_INTERFACE_DATA32:
208 		return adf_compat_get_interface_data(file, compat_ptr(arg));
209 
210 	case ADF_GET_OVERLAY_ENGINE_DATA32:
211 		return adf_compat_get_overlay_engine_data(file,
212 				compat_ptr(arg));
213 
214 	default:
215 		return adf_file_ioctl(file, cmd, arg);
216 	}
217 }
218