1 /* 2 * V4L2 sub-device 3 * 4 * Copyright (C) 2010 Nokia Corporation 5 * 6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 7 * Sakari Ailus <sakari.ailus@iki.fi> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 #include <linux/ioctl.h> 24 #include <linux/slab.h> 25 #include <linux/types.h> 26 #include <linux/videodev2.h> 27 #include <linux/export.h> 28 29 #include <media/v4l2-ctrls.h> 30 #include <media/v4l2-device.h> 31 #include <media/v4l2-ioctl.h> 32 #include <media/v4l2-fh.h> 33 #include <media/v4l2-event.h> 34 35 static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) 36 { 37 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 38 fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL); 39 if (fh->pad == NULL) 40 return -ENOMEM; 41 #endif 42 return 0; 43 } 44 45 static void subdev_fh_free(struct v4l2_subdev_fh *fh) 46 { 47 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 48 kfree(fh->pad); 49 fh->pad = NULL; 50 #endif 51 } 52 53 static int subdev_open(struct file *file) 54 { 55 struct video_device *vdev = video_devdata(file); 56 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 57 struct v4l2_subdev_fh *subdev_fh; 58 #if defined(CONFIG_MEDIA_CONTROLLER) 59 struct media_entity *entity = NULL; 60 #endif 61 int ret; 62 63 subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL); 64 if (subdev_fh == NULL) 65 return -ENOMEM; 66 67 ret = subdev_fh_init(subdev_fh, sd); 68 if (ret) { 69 kfree(subdev_fh); 70 return ret; 71 } 72 73 v4l2_fh_init(&subdev_fh->vfh, vdev); 74 v4l2_fh_add(&subdev_fh->vfh); 75 file->private_data = &subdev_fh->vfh; 76 #if defined(CONFIG_MEDIA_CONTROLLER) 77 if (sd->v4l2_dev->mdev) { 78 entity = media_entity_get(&sd->entity); 79 if (!entity) { 80 ret = -EBUSY; 81 goto err; 82 } 83 } 84 #endif 85 86 if (sd->internal_ops && sd->internal_ops->open) { 87 ret = sd->internal_ops->open(sd, subdev_fh); 88 if (ret < 0) 89 goto err; 90 } 91 92 return 0; 93 94 err: 95 #if defined(CONFIG_MEDIA_CONTROLLER) 96 if (entity) 97 media_entity_put(entity); 98 #endif 99 v4l2_fh_del(&subdev_fh->vfh); 100 v4l2_fh_exit(&subdev_fh->vfh); 101 subdev_fh_free(subdev_fh); 102 kfree(subdev_fh); 103 104 return ret; 105 } 106 107 static int subdev_close(struct file *file) 108 { 109 struct video_device *vdev = video_devdata(file); 110 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 111 struct v4l2_fh *vfh = file->private_data; 112 struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); 113 114 if (sd->internal_ops && sd->internal_ops->close) 115 sd->internal_ops->close(sd, subdev_fh); 116 #if defined(CONFIG_MEDIA_CONTROLLER) 117 if (sd->v4l2_dev->mdev) 118 media_entity_put(&sd->entity); 119 #endif 120 v4l2_fh_del(vfh); 121 v4l2_fh_exit(vfh); 122 subdev_fh_free(subdev_fh); 123 kfree(subdev_fh); 124 file->private_data = NULL; 125 126 return 0; 127 } 128 129 static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) 130 { 131 struct video_device *vdev = video_devdata(file); 132 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 133 struct v4l2_fh *vfh = file->private_data; 134 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 135 struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); 136 #endif 137 138 switch (cmd) { 139 case VIDIOC_QUERYCTRL: 140 return v4l2_queryctrl(vfh->ctrl_handler, arg); 141 142 case VIDIOC_QUERYMENU: 143 return v4l2_querymenu(vfh->ctrl_handler, arg); 144 145 case VIDIOC_G_CTRL: 146 return v4l2_g_ctrl(vfh->ctrl_handler, arg); 147 148 case VIDIOC_S_CTRL: 149 return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg); 150 151 case VIDIOC_G_EXT_CTRLS: 152 return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg); 153 154 case VIDIOC_S_EXT_CTRLS: 155 return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg); 156 157 case VIDIOC_TRY_EXT_CTRLS: 158 return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg); 159 160 case VIDIOC_DQEVENT: 161 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) 162 return -ENOIOCTLCMD; 163 164 return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); 165 166 case VIDIOC_SUBSCRIBE_EVENT: 167 return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); 168 169 case VIDIOC_UNSUBSCRIBE_EVENT: 170 return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); 171 172 #ifdef CONFIG_VIDEO_ADV_DEBUG 173 case VIDIOC_DBG_G_REGISTER: 174 { 175 struct v4l2_dbg_register *p = arg; 176 177 if (!capable(CAP_SYS_ADMIN)) 178 return -EPERM; 179 return v4l2_subdev_call(sd, core, g_register, p); 180 } 181 case VIDIOC_DBG_S_REGISTER: 182 { 183 struct v4l2_dbg_register *p = arg; 184 185 if (!capable(CAP_SYS_ADMIN)) 186 return -EPERM; 187 return v4l2_subdev_call(sd, core, s_register, p); 188 } 189 #endif 190 191 case VIDIOC_LOG_STATUS: { 192 int ret; 193 194 pr_info("%s: ================= START STATUS =================\n", 195 sd->name); 196 ret = v4l2_subdev_call(sd, core, log_status); 197 pr_info("%s: ================== END STATUS ==================\n", 198 sd->name); 199 return ret; 200 } 201 202 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 203 case VIDIOC_SUBDEV_G_FMT: { 204 struct v4l2_subdev_format *format = arg; 205 206 if (format->which != V4L2_SUBDEV_FORMAT_TRY && 207 format->which != V4L2_SUBDEV_FORMAT_ACTIVE) 208 return -EINVAL; 209 210 if (format->pad >= sd->entity.num_pads) 211 return -EINVAL; 212 213 return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format); 214 } 215 216 case VIDIOC_SUBDEV_S_FMT: { 217 struct v4l2_subdev_format *format = arg; 218 219 if (format->which != V4L2_SUBDEV_FORMAT_TRY && 220 format->which != V4L2_SUBDEV_FORMAT_ACTIVE) 221 return -EINVAL; 222 223 if (format->pad >= sd->entity.num_pads) 224 return -EINVAL; 225 226 return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format); 227 } 228 229 case VIDIOC_SUBDEV_G_CROP: { 230 struct v4l2_subdev_crop *crop = arg; 231 struct v4l2_subdev_selection sel; 232 int rval; 233 234 if (crop->which != V4L2_SUBDEV_FORMAT_TRY && 235 crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) 236 return -EINVAL; 237 238 if (crop->pad >= sd->entity.num_pads) 239 return -EINVAL; 240 241 rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); 242 if (rval != -ENOIOCTLCMD) 243 return rval; 244 245 memset(&sel, 0, sizeof(sel)); 246 sel.which = crop->which; 247 sel.pad = crop->pad; 248 sel.target = V4L2_SEL_TGT_CROP; 249 250 rval = v4l2_subdev_call( 251 sd, pad, get_selection, subdev_fh, &sel); 252 253 crop->rect = sel.r; 254 255 return rval; 256 } 257 258 case VIDIOC_SUBDEV_S_CROP: { 259 struct v4l2_subdev_crop *crop = arg; 260 struct v4l2_subdev_selection sel; 261 int rval; 262 263 if (crop->which != V4L2_SUBDEV_FORMAT_TRY && 264 crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) 265 return -EINVAL; 266 267 if (crop->pad >= sd->entity.num_pads) 268 return -EINVAL; 269 270 rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); 271 if (rval != -ENOIOCTLCMD) 272 return rval; 273 274 memset(&sel, 0, sizeof(sel)); 275 sel.which = crop->which; 276 sel.pad = crop->pad; 277 sel.target = V4L2_SEL_TGT_CROP; 278 sel.r = crop->rect; 279 280 rval = v4l2_subdev_call( 281 sd, pad, set_selection, subdev_fh, &sel); 282 283 crop->rect = sel.r; 284 285 return rval; 286 } 287 288 case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { 289 struct v4l2_subdev_mbus_code_enum *code = arg; 290 291 if (code->pad >= sd->entity.num_pads) 292 return -EINVAL; 293 294 return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh, 295 code); 296 } 297 298 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: { 299 struct v4l2_subdev_frame_size_enum *fse = arg; 300 301 if (fse->pad >= sd->entity.num_pads) 302 return -EINVAL; 303 304 return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh, 305 fse); 306 } 307 308 case VIDIOC_SUBDEV_G_FRAME_INTERVAL: { 309 struct v4l2_subdev_frame_interval *fi = arg; 310 311 if (fi->pad >= sd->entity.num_pads) 312 return -EINVAL; 313 314 return v4l2_subdev_call(sd, video, g_frame_interval, arg); 315 } 316 317 case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { 318 struct v4l2_subdev_frame_interval *fi = arg; 319 320 if (fi->pad >= sd->entity.num_pads) 321 return -EINVAL; 322 323 return v4l2_subdev_call(sd, video, s_frame_interval, arg); 324 } 325 326 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { 327 struct v4l2_subdev_frame_interval_enum *fie = arg; 328 329 if (fie->pad >= sd->entity.num_pads) 330 return -EINVAL; 331 332 return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh, 333 fie); 334 } 335 336 case VIDIOC_SUBDEV_G_SELECTION: { 337 struct v4l2_subdev_selection *sel = arg; 338 339 if (sel->which != V4L2_SUBDEV_FORMAT_TRY && 340 sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) 341 return -EINVAL; 342 343 if (sel->pad >= sd->entity.num_pads) 344 return -EINVAL; 345 346 return v4l2_subdev_call( 347 sd, pad, get_selection, subdev_fh, sel); 348 } 349 350 case VIDIOC_SUBDEV_S_SELECTION: { 351 struct v4l2_subdev_selection *sel = arg; 352 353 if (sel->which != V4L2_SUBDEV_FORMAT_TRY && 354 sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) 355 return -EINVAL; 356 357 if (sel->pad >= sd->entity.num_pads) 358 return -EINVAL; 359 360 return v4l2_subdev_call( 361 sd, pad, set_selection, subdev_fh, sel); 362 } 363 364 case VIDIOC_G_EDID: { 365 struct v4l2_subdev_edid *edid = arg; 366 367 if (edid->pad >= sd->entity.num_pads) 368 return -EINVAL; 369 if (edid->blocks && edid->edid == NULL) 370 return -EINVAL; 371 372 return v4l2_subdev_call(sd, pad, get_edid, edid); 373 } 374 375 case VIDIOC_S_EDID: { 376 struct v4l2_subdev_edid *edid = arg; 377 378 if (edid->pad >= sd->entity.num_pads) 379 return -EINVAL; 380 if (edid->blocks && edid->edid == NULL) 381 return -EINVAL; 382 383 return v4l2_subdev_call(sd, pad, set_edid, edid); 384 } 385 386 case VIDIOC_SUBDEV_DV_TIMINGS_CAP: { 387 struct v4l2_dv_timings_cap *cap = arg; 388 389 if (cap->pad >= sd->entity.num_pads) 390 return -EINVAL; 391 392 return v4l2_subdev_call(sd, pad, dv_timings_cap, cap); 393 } 394 395 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: { 396 struct v4l2_enum_dv_timings *dvt = arg; 397 398 if (dvt->pad >= sd->entity.num_pads) 399 return -EINVAL; 400 401 return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt); 402 } 403 404 case VIDIOC_SUBDEV_QUERY_DV_TIMINGS: 405 return v4l2_subdev_call(sd, video, query_dv_timings, arg); 406 407 case VIDIOC_SUBDEV_G_DV_TIMINGS: 408 return v4l2_subdev_call(sd, video, g_dv_timings, arg); 409 410 case VIDIOC_SUBDEV_S_DV_TIMINGS: 411 return v4l2_subdev_call(sd, video, s_dv_timings, arg); 412 #endif 413 default: 414 return v4l2_subdev_call(sd, core, ioctl, cmd, arg); 415 } 416 417 return 0; 418 } 419 420 static long subdev_ioctl(struct file *file, unsigned int cmd, 421 unsigned long arg) 422 { 423 return video_usercopy(file, cmd, arg, subdev_do_ioctl); 424 } 425 426 #ifdef CONFIG_COMPAT 427 static long subdev_compat_ioctl32(struct file *file, unsigned int cmd, 428 unsigned long arg) 429 { 430 struct video_device *vdev = video_devdata(file); 431 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 432 433 return v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg); 434 } 435 #endif 436 437 static unsigned int subdev_poll(struct file *file, poll_table *wait) 438 { 439 struct video_device *vdev = video_devdata(file); 440 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 441 struct v4l2_fh *fh = file->private_data; 442 443 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) 444 return POLLERR; 445 446 poll_wait(file, &fh->wait, wait); 447 448 if (v4l2_event_pending(fh)) 449 return POLLPRI; 450 451 return 0; 452 } 453 454 const struct v4l2_file_operations v4l2_subdev_fops = { 455 .owner = THIS_MODULE, 456 .open = subdev_open, 457 .unlocked_ioctl = subdev_ioctl, 458 #ifdef CONFIG_COMPAT 459 .compat_ioctl32 = subdev_compat_ioctl32, 460 #endif 461 .release = subdev_close, 462 .poll = subdev_poll, 463 }; 464 465 #ifdef CONFIG_MEDIA_CONTROLLER 466 int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, 467 struct media_link *link, 468 struct v4l2_subdev_format *source_fmt, 469 struct v4l2_subdev_format *sink_fmt) 470 { 471 if (source_fmt->format.width != sink_fmt->format.width 472 || source_fmt->format.height != sink_fmt->format.height 473 || source_fmt->format.code != sink_fmt->format.code) 474 return -EINVAL; 475 476 return 0; 477 } 478 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default); 479 480 static int 481 v4l2_subdev_link_validate_get_format(struct media_pad *pad, 482 struct v4l2_subdev_format *fmt) 483 { 484 if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) { 485 struct v4l2_subdev *sd = 486 media_entity_to_v4l2_subdev(pad->entity); 487 488 fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; 489 fmt->pad = pad->index; 490 return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); 491 } 492 493 WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L, 494 "Driver bug! Wrong media entity type 0x%08x, entity %s\n", 495 pad->entity->type, pad->entity->name); 496 497 return -EINVAL; 498 } 499 500 int v4l2_subdev_link_validate(struct media_link *link) 501 { 502 struct v4l2_subdev *sink; 503 struct v4l2_subdev_format sink_fmt, source_fmt; 504 int rval; 505 506 rval = v4l2_subdev_link_validate_get_format( 507 link->source, &source_fmt); 508 if (rval < 0) 509 return 0; 510 511 rval = v4l2_subdev_link_validate_get_format( 512 link->sink, &sink_fmt); 513 if (rval < 0) 514 return 0; 515 516 sink = media_entity_to_v4l2_subdev(link->sink->entity); 517 518 rval = v4l2_subdev_call(sink, pad, link_validate, link, 519 &source_fmt, &sink_fmt); 520 if (rval != -ENOIOCTLCMD) 521 return rval; 522 523 return v4l2_subdev_link_validate_default( 524 sink, link, &source_fmt, &sink_fmt); 525 } 526 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); 527 #endif /* CONFIG_MEDIA_CONTROLLER */ 528 529 void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) 530 { 531 INIT_LIST_HEAD(&sd->list); 532 BUG_ON(!ops); 533 sd->ops = ops; 534 sd->v4l2_dev = NULL; 535 sd->flags = 0; 536 sd->name[0] = '\0'; 537 sd->grp_id = 0; 538 sd->dev_priv = NULL; 539 sd->host_priv = NULL; 540 #if defined(CONFIG_MEDIA_CONTROLLER) 541 sd->entity.name = sd->name; 542 sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; 543 #endif 544 } 545 EXPORT_SYMBOL(v4l2_subdev_init); 546