diff options
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r-- | drivers/media/video/v4l2-dev.c | 115 |
1 files changed, 64 insertions, 51 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index cb77197d480e..0ca7978654b5 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -81,7 +81,7 @@ static inline unsigned long *devnode_bits(int vfl_type) | |||
81 | /* Any types not assigned to fixed minor ranges must be mapped to | 81 | /* Any types not assigned to fixed minor ranges must be mapped to |
82 | one single bitmap for the purposes of finding a free node number | 82 | one single bitmap for the purposes of finding a free node number |
83 | since all those unassigned types use the same minor range. */ | 83 | since all those unassigned types use the same minor range. */ |
84 | int idx = (vfl_type > VFL_TYPE_VTX) ? VFL_TYPE_MAX - 1 : vfl_type; | 84 | int idx = (vfl_type > VFL_TYPE_RADIO) ? VFL_TYPE_MAX - 1 : vfl_type; |
85 | 85 | ||
86 | return devnode_nums[idx]; | 86 | return devnode_nums[idx]; |
87 | } | 87 | } |
@@ -187,48 +187,69 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, | |||
187 | size_t sz, loff_t *off) | 187 | size_t sz, loff_t *off) |
188 | { | 188 | { |
189 | struct video_device *vdev = video_devdata(filp); | 189 | struct video_device *vdev = video_devdata(filp); |
190 | int ret = -EIO; | ||
190 | 191 | ||
191 | if (!vdev->fops->read) | 192 | if (!vdev->fops->read) |
192 | return -EINVAL; | 193 | return -EINVAL; |
193 | if (!video_is_registered(vdev)) | 194 | if (vdev->lock) |
194 | return -EIO; | 195 | mutex_lock(vdev->lock); |
195 | return vdev->fops->read(filp, buf, sz, off); | 196 | if (video_is_registered(vdev)) |
197 | ret = vdev->fops->read(filp, buf, sz, off); | ||
198 | if (vdev->lock) | ||
199 | mutex_unlock(vdev->lock); | ||
200 | return ret; | ||
196 | } | 201 | } |
197 | 202 | ||
198 | static ssize_t v4l2_write(struct file *filp, const char __user *buf, | 203 | static ssize_t v4l2_write(struct file *filp, const char __user *buf, |
199 | size_t sz, loff_t *off) | 204 | size_t sz, loff_t *off) |
200 | { | 205 | { |
201 | struct video_device *vdev = video_devdata(filp); | 206 | struct video_device *vdev = video_devdata(filp); |
207 | int ret = -EIO; | ||
202 | 208 | ||
203 | if (!vdev->fops->write) | 209 | if (!vdev->fops->write) |
204 | return -EINVAL; | 210 | return -EINVAL; |
205 | if (!video_is_registered(vdev)) | 211 | if (vdev->lock) |
206 | return -EIO; | 212 | mutex_lock(vdev->lock); |
207 | return vdev->fops->write(filp, buf, sz, off); | 213 | if (video_is_registered(vdev)) |
214 | ret = vdev->fops->write(filp, buf, sz, off); | ||
215 | if (vdev->lock) | ||
216 | mutex_unlock(vdev->lock); | ||
217 | return ret; | ||
208 | } | 218 | } |
209 | 219 | ||
210 | static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) | 220 | static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) |
211 | { | 221 | { |
212 | struct video_device *vdev = video_devdata(filp); | 222 | struct video_device *vdev = video_devdata(filp); |
223 | int ret = DEFAULT_POLLMASK; | ||
213 | 224 | ||
214 | if (!vdev->fops->poll || !video_is_registered(vdev)) | 225 | if (!vdev->fops->poll) |
215 | return DEFAULT_POLLMASK; | 226 | return ret; |
216 | return vdev->fops->poll(filp, poll); | 227 | if (vdev->lock) |
228 | mutex_lock(vdev->lock); | ||
229 | if (video_is_registered(vdev)) | ||
230 | ret = vdev->fops->poll(filp, poll); | ||
231 | if (vdev->lock) | ||
232 | mutex_unlock(vdev->lock); | ||
233 | return ret; | ||
217 | } | 234 | } |
218 | 235 | ||
219 | static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 236 | static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
220 | { | 237 | { |
221 | struct video_device *vdev = video_devdata(filp); | 238 | struct video_device *vdev = video_devdata(filp); |
222 | int ret; | 239 | int ret = -ENODEV; |
223 | 240 | ||
224 | /* Allow ioctl to continue even if the device was unregistered. | ||
225 | Things like dequeueing buffers might still be useful. */ | ||
226 | if (vdev->fops->unlocked_ioctl) { | 241 | if (vdev->fops->unlocked_ioctl) { |
227 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); | 242 | if (vdev->lock) |
243 | mutex_lock(vdev->lock); | ||
244 | if (video_is_registered(vdev)) | ||
245 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); | ||
246 | if (vdev->lock) | ||
247 | mutex_unlock(vdev->lock); | ||
228 | } else if (vdev->fops->ioctl) { | 248 | } else if (vdev->fops->ioctl) { |
229 | /* TODO: convert all drivers to unlocked_ioctl */ | 249 | /* TODO: convert all drivers to unlocked_ioctl */ |
230 | lock_kernel(); | 250 | lock_kernel(); |
231 | ret = vdev->fops->ioctl(filp, cmd, arg); | 251 | if (video_is_registered(vdev)) |
252 | ret = vdev->fops->ioctl(filp, cmd, arg); | ||
232 | unlock_kernel(); | 253 | unlock_kernel(); |
233 | } else | 254 | } else |
234 | ret = -ENOTTY; | 255 | ret = -ENOTTY; |
@@ -236,30 +257,20 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
236 | return ret; | 257 | return ret; |
237 | } | 258 | } |
238 | 259 | ||
239 | #ifdef CONFIG_MMU | ||
240 | #define v4l2_get_unmapped_area NULL | ||
241 | #else | ||
242 | static unsigned long v4l2_get_unmapped_area(struct file *filp, | ||
243 | unsigned long addr, unsigned long len, unsigned long pgoff, | ||
244 | unsigned long flags) | ||
245 | { | ||
246 | struct video_device *vdev = video_devdata(filp); | ||
247 | |||
248 | if (!vdev->fops->get_unmapped_area) | ||
249 | return -ENOSYS; | ||
250 | if (!video_is_registered(vdev)) | ||
251 | return -ENODEV; | ||
252 | return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); | ||
253 | } | ||
254 | #endif | ||
255 | |||
256 | static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) | 260 | static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) |
257 | { | 261 | { |
258 | struct video_device *vdev = video_devdata(filp); | 262 | struct video_device *vdev = video_devdata(filp); |
263 | int ret = -ENODEV; | ||
259 | 264 | ||
260 | if (!vdev->fops->mmap || !video_is_registered(vdev)) | 265 | if (!vdev->fops->mmap) |
261 | return -ENODEV; | 266 | return ret; |
262 | return vdev->fops->mmap(filp, vm); | 267 | if (vdev->lock) |
268 | mutex_lock(vdev->lock); | ||
269 | if (video_is_registered(vdev)) | ||
270 | ret = vdev->fops->mmap(filp, vm); | ||
271 | if (vdev->lock) | ||
272 | mutex_unlock(vdev->lock); | ||
273 | return ret; | ||
263 | } | 274 | } |
264 | 275 | ||
265 | /* Override for the open function */ | 276 | /* Override for the open function */ |
@@ -271,17 +282,24 @@ static int v4l2_open(struct inode *inode, struct file *filp) | |||
271 | /* Check if the video device is available */ | 282 | /* Check if the video device is available */ |
272 | mutex_lock(&videodev_lock); | 283 | mutex_lock(&videodev_lock); |
273 | vdev = video_devdata(filp); | 284 | vdev = video_devdata(filp); |
274 | /* return ENODEV if the video device has been removed | 285 | /* return ENODEV if the video device has already been removed. */ |
275 | already or if it is not registered anymore. */ | 286 | if (vdev == NULL) { |
276 | if (vdev == NULL || !video_is_registered(vdev)) { | ||
277 | mutex_unlock(&videodev_lock); | 287 | mutex_unlock(&videodev_lock); |
278 | return -ENODEV; | 288 | return -ENODEV; |
279 | } | 289 | } |
280 | /* and increase the device refcount */ | 290 | /* and increase the device refcount */ |
281 | video_get(vdev); | 291 | video_get(vdev); |
282 | mutex_unlock(&videodev_lock); | 292 | mutex_unlock(&videodev_lock); |
283 | if (vdev->fops->open) | 293 | if (vdev->fops->open) { |
284 | ret = vdev->fops->open(filp); | 294 | if (vdev->lock) |
295 | mutex_lock(vdev->lock); | ||
296 | if (video_is_registered(vdev)) | ||
297 | ret = vdev->fops->open(filp); | ||
298 | else | ||
299 | ret = -ENODEV; | ||
300 | if (vdev->lock) | ||
301 | mutex_unlock(vdev->lock); | ||
302 | } | ||
285 | 303 | ||
286 | /* decrease the refcount in case of an error */ | 304 | /* decrease the refcount in case of an error */ |
287 | if (ret) | 305 | if (ret) |
@@ -295,8 +313,13 @@ static int v4l2_release(struct inode *inode, struct file *filp) | |||
295 | struct video_device *vdev = video_devdata(filp); | 313 | struct video_device *vdev = video_devdata(filp); |
296 | int ret = 0; | 314 | int ret = 0; |
297 | 315 | ||
298 | if (vdev->fops->release) | 316 | if (vdev->fops->release) { |
317 | if (vdev->lock) | ||
318 | mutex_lock(vdev->lock); | ||
299 | vdev->fops->release(filp); | 319 | vdev->fops->release(filp); |
320 | if (vdev->lock) | ||
321 | mutex_unlock(vdev->lock); | ||
322 | } | ||
300 | 323 | ||
301 | /* decrease the refcount unconditionally since the release() | 324 | /* decrease the refcount unconditionally since the release() |
302 | return value is ignored. */ | 325 | return value is ignored. */ |
@@ -309,7 +332,6 @@ static const struct file_operations v4l2_fops = { | |||
309 | .read = v4l2_read, | 332 | .read = v4l2_read, |
310 | .write = v4l2_write, | 333 | .write = v4l2_write, |
311 | .open = v4l2_open, | 334 | .open = v4l2_open, |
312 | .get_unmapped_area = v4l2_get_unmapped_area, | ||
313 | .mmap = v4l2_mmap, | 335 | .mmap = v4l2_mmap, |
314 | .unlocked_ioctl = v4l2_ioctl, | 336 | .unlocked_ioctl = v4l2_ioctl, |
315 | #ifdef CONFIG_COMPAT | 337 | #ifdef CONFIG_COMPAT |
@@ -377,8 +399,6 @@ static int get_index(struct video_device *vdev) | |||
377 | * | 399 | * |
378 | * %VFL_TYPE_GRABBER - A frame grabber | 400 | * %VFL_TYPE_GRABBER - A frame grabber |
379 | * | 401 | * |
380 | * %VFL_TYPE_VTX - A teletext device | ||
381 | * | ||
382 | * %VFL_TYPE_VBI - Vertical blank data (undecoded) | 402 | * %VFL_TYPE_VBI - Vertical blank data (undecoded) |
383 | * | 403 | * |
384 | * %VFL_TYPE_RADIO - A radio card | 404 | * %VFL_TYPE_RADIO - A radio card |
@@ -411,9 +431,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
411 | case VFL_TYPE_GRABBER: | 431 | case VFL_TYPE_GRABBER: |
412 | name_base = "video"; | 432 | name_base = "video"; |
413 | break; | 433 | break; |
414 | case VFL_TYPE_VTX: | ||
415 | name_base = "vtx"; | ||
416 | break; | ||
417 | case VFL_TYPE_VBI: | 434 | case VFL_TYPE_VBI: |
418 | name_base = "vbi"; | 435 | name_base = "vbi"; |
419 | break; | 436 | break; |
@@ -451,10 +468,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
451 | minor_offset = 64; | 468 | minor_offset = 64; |
452 | minor_cnt = 64; | 469 | minor_cnt = 64; |
453 | break; | 470 | break; |
454 | case VFL_TYPE_VTX: | ||
455 | minor_offset = 192; | ||
456 | minor_cnt = 32; | ||
457 | break; | ||
458 | case VFL_TYPE_VBI: | 471 | case VFL_TYPE_VBI: |
459 | minor_offset = 224; | 472 | minor_offset = 224; |
460 | minor_cnt = 32; | 473 | minor_cnt = 32; |