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 if (sd->entity.num_pads) { 39 fh->pad = v4l2_subdev_alloc_pad_config(sd); 40 if (fh->pad == NULL) 41 return -ENOMEM; 42 } 43 #endif 44 return 0; 45 } 46 47 static void subdev_fh_free(struct v4l2_subdev_fh *fh) 48 { 49 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 50 v4l2_subdev_free_pad_config(fh->pad); 51 fh->pad = NULL; 52 #endif 53 } 54 55 static int subdev_open(struct file *file) 56 { 57 struct video_device *vdev = video_devdata(file); 58 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 59 struct v4l2_subdev_fh *subdev_fh; 60 #if defined(CONFIG_MEDIA_CONTROLLER) 61 struct media_entity *entity = NULL; 62 #endif 63 int ret; 64 65 subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL); 66 if (subdev_fh == NULL) 67 return -ENOMEM; 68 69 ret = subdev_fh_init(subdev_fh, sd); 70 if (ret) { 71 kfree(subdev_fh); 72 return ret; 73 } 74 75 v4l2_fh_init(&subdev_fh->vfh, vdev); 76 v4l2_fh_add(&subdev_fh->vfh); 77 file->private_data = &subdev_fh->vfh; 78 #if defined(CONFIG_MEDIA_CONTROLLER) 79 if (sd->v4l2_dev->mdev) { 80 entity = media_entity_get(&sd->entity); 81 if (!entity) { 82 ret = -EBUSY; 83 goto err; 84 } 85 } 86 #endif 87 88 if (sd->internal_ops && sd->internal_ops->open) { 89 ret = sd->internal_ops->open(sd, subdev_fh); 90 if (ret < 0) 91 goto err; 92 } 93 94 return 0; 95 96 err: 97 #if defined(CONFIG_MEDIA_CONTROLLER) 98 media_entity_put(entity); 99 #endif 100 v4l2_fh_del(&subdev_fh->vfh); 101 v4l2_fh_exit(&subdev_fh->vfh); 102 subdev_fh_free(subdev_fh); 103 kfree(subdev_fh); 104 105 return ret; 106 } 107 108 static int subdev_close(struct file *file) 109 { 110 struct video_device *vdev = video_devdata(file); 111 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 112 struct v4l2_fh *vfh = file->private_data; 113 struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); 114 115 if (sd->internal_ops && sd->internal_ops->close) 116 sd->internal_ops->close(sd, subdev_fh); 117 #if defined(CONFIG_MEDIA_CONTROLLER) 118 if (sd->v4l2_dev->mdev) 119 media_entity_put(&sd->entity); 120 #endif 121 v4l2_fh_del(vfh); 122 v4l2_fh_exit(vfh); 123 subdev_fh_free(subdev_fh); 124 kfree(subdev_fh); 125 file->private_data = NULL; 126 127 return 0; 128 } 129 130 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 131 static int check_format(struct v4l2_subdev *sd, 132 struct v4l2_subdev_format *format) 133 { 134 if (format->which != V4L2_SUBDEV_FORMAT_TRY && 135 format->which != V4L2_SUBDEV_FORMAT_ACTIVE) 136 return -EINVAL; 137 138 if (format->pad >= sd->entity.num_pads) 139 return -EINVAL; 140 141 return 0; 142 } 143 144 static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop) 145 { 146 if (crop->which != V4L2_SUBDEV_FORMAT_TRY && 147 crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) 148 return -EINVAL; 149 150 if (crop->pad >= sd->entity.num_pads) 151 return -EINVAL; 152 153 return 0; 154 } 155 156 static int check_selection(struct v4l2_subdev *sd, 157 struct v4l2_subdev_selection *sel) 158 { 159 if (sel->which != V4L2_SUBDEV_FORMAT_TRY && 160 sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) 161 return -EINVAL; 162 163 if (sel->pad >= sd->entity.num_pads) 164 return -EINVAL; 165 166 return 0; 167 } 168 169 static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) 170 { 171 if (edid->pad >= sd->entity.num_pads) 172 return -EINVAL; 173 174 if (edid->blocks && edid->edid == NULL) 175 return -EINVAL; 176 177 return 0; 178 } 179 #endif 180 181 static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) 182 { 183 struct video_device *vdev = video_devdata(file); 184 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 185 struct v4l2_fh *vfh = file->private_data; 186 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 187 struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); 188 int rval; 189 #endif 190 191 switch (cmd) { 192 case VIDIOC_QUERYCTRL: 193 return v4l2_queryctrl(vfh->ctrl_handler, arg); 194 195 case VIDIOC_QUERY_EXT_CTRL: 196 return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg); 197 198 case VIDIOC_QUERYMENU: 199 return v4l2_querymenu(vfh->ctrl_handler, arg); 200 201 case VIDIOC_G_CTRL: 202 return v4l2_g_ctrl(vfh->ctrl_handler, arg); 203 204 case VIDIOC_S_CTRL: 205 return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg); 206 207 case VIDIOC_G_EXT_CTRLS: 208 return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg); 209 210 case VIDIOC_S_EXT_CTRLS: 211 return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg); 212 213 case VIDIOC_TRY_EXT_CTRLS: 214 return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg); 215 216 case VIDIOC_DQEVENT: 217 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) 218 return -ENOIOCTLCMD; 219 220 return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); 221 222 case VIDIOC_SUBSCRIBE_EVENT: 223 return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); 224 225 case VIDIOC_UNSUBSCRIBE_EVENT: 226 return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); 227 228 #ifdef CONFIG_VIDEO_ADV_DEBUG 229 case VIDIOC_DBG_G_REGISTER: 230 { 231 struct v4l2_dbg_register *p = arg; 232 233 if (!capable(CAP_SYS_ADMIN)) 234 return -EPERM; 235 return v4l2_subdev_call(sd, core, g_register, p); 236 } 237 case VIDIOC_DBG_S_REGISTER: 238 { 239 struct v4l2_dbg_register *p = arg; 240 241 if (!capable(CAP_SYS_ADMIN)) 242 return -EPERM; 243 return v4l2_subdev_call(sd, core, s_register, p); 244 } 245 #endif 246 247 case VIDIOC_LOG_STATUS: { 248 int ret; 249 250 pr_info("%s: ================= START STATUS =================\n", 251 sd->name); 252 ret = v4l2_subdev_call(sd, core, log_status); 253 pr_info("%s: ================== END STATUS ==================\n", 254 sd->name); 255 return ret; 256 } 257 258 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 259 case VIDIOC_SUBDEV_G_FMT: { 260 struct v4l2_subdev_format *format = arg; 261 262 rval = check_format(sd, format); 263 if (rval) 264 return rval; 265 266 return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->pad, format); 267 } 268 269 case VIDIOC_SUBDEV_S_FMT: { 270 struct v4l2_subdev_format *format = arg; 271 272 rval = check_format(sd, format); 273 if (rval) 274 return rval; 275 276 return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->pad, format); 277 } 278 279 case VIDIOC_SUBDEV_G_CROP: { 280 struct v4l2_subdev_crop *crop = arg; 281 struct v4l2_subdev_selection sel; 282 283 rval = check_crop(sd, crop); 284 if (rval) 285 return rval; 286 287 memset(&sel, 0, sizeof(sel)); 288 sel.which = crop->which; 289 sel.pad = crop->pad; 290 sel.target = V4L2_SEL_TGT_CROP; 291 292 rval = v4l2_subdev_call( 293 sd, pad, get_selection, subdev_fh->pad, &sel); 294 295 crop->rect = sel.r; 296 297 return rval; 298 } 299 300 case VIDIOC_SUBDEV_S_CROP: { 301 struct v4l2_subdev_crop *crop = arg; 302 struct v4l2_subdev_selection sel; 303 304 rval = check_crop(sd, crop); 305 if (rval) 306 return rval; 307 308 memset(&sel, 0, sizeof(sel)); 309 sel.which = crop->which; 310 sel.pad = crop->pad; 311 sel.target = V4L2_SEL_TGT_CROP; 312 sel.r = crop->rect; 313 314 rval = v4l2_subdev_call( 315 sd, pad, set_selection, subdev_fh->pad, &sel); 316 317 crop->rect = sel.r; 318 319 return rval; 320 } 321 322 case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { 323 struct v4l2_subdev_mbus_code_enum *code = arg; 324 325 if (code->which != V4L2_SUBDEV_FORMAT_TRY && 326 code->which != V4L2_SUBDEV_FORMAT_ACTIVE) 327 return -EINVAL; 328 329 if (code->pad >= sd->entity.num_pads) 330 return -EINVAL; 331 332 return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->pad, 333 code); 334 } 335 336 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: { 337 struct v4l2_subdev_frame_size_enum *fse = arg; 338 339 if (fse->which != V4L2_SUBDEV_FORMAT_TRY && 340 fse->which != V4L2_SUBDEV_FORMAT_ACTIVE) 341 return -EINVAL; 342 343 if (fse->pad >= sd->entity.num_pads) 344 return -EINVAL; 345 346 return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->pad, 347 fse); 348 } 349 350 case VIDIOC_SUBDEV_G_FRAME_INTERVAL: { 351 struct v4l2_subdev_frame_interval *fi = arg; 352 353 if (fi->pad >= sd->entity.num_pads) 354 return -EINVAL; 355 356 return v4l2_subdev_call(sd, video, g_frame_interval, arg); 357 } 358 359 case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { 360 struct v4l2_subdev_frame_interval *fi = arg; 361 362 if (fi->pad >= sd->entity.num_pads) 363 return -EINVAL; 364 365 return v4l2_subdev_call(sd, video, s_frame_interval, arg); 366 } 367 368 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { 369 struct v4l2_subdev_frame_interval_enum *fie = arg; 370 371 if (fie->which != V4L2_SUBDEV_FORMAT_TRY && 372 fie->which != V4L2_SUBDEV_FORMAT_ACTIVE) 373 return -EINVAL; 374 375 if (fie->pad >= sd->entity.num_pads) 376 return -EINVAL; 377 378 return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->pad, 379 fie); 380 } 381 382 case VIDIOC_SUBDEV_G_SELECTION: { 383 struct v4l2_subdev_selection *sel = arg; 384 385 rval = check_selection(sd, sel); 386 if (rval) 387 return rval; 388 389 return v4l2_subdev_call( 390 sd, pad, get_selection, subdev_fh->pad, sel); 391 } 392 393 case VIDIOC_SUBDEV_S_SELECTION: { 394 struct v4l2_subdev_selection *sel = arg; 395 396 rval = check_selection(sd, sel); 397 if (rval) 398 return rval; 399 400 return v4l2_subdev_call( 401 sd, pad, set_selection, subdev_fh->pad, sel); 402 } 403 404 case VIDIOC_G_EDID: { 405 struct v4l2_subdev_edid *edid = arg; 406 407 rval = check_edid(sd, edid); 408 if (rval) 409 return rval; 410 411 return v4l2_subdev_call(sd, pad, get_edid, edid); 412 } 413 414 case VIDIOC_S_EDID: { 415 struct v4l2_subdev_edid *edid = arg; 416 417 rval = check_edid(sd, edid); 418 if (rval) 419 return rval; 420 421 return v4l2_subdev_call(sd, pad, set_edid, edid); 422 } 423 424 case VIDIOC_SUBDEV_DV_TIMINGS_CAP: { 425 struct v4l2_dv_timings_cap *cap = arg; 426 427 if (cap->pad >= sd->entity.num_pads) 428 return -EINVAL; 429 430 return v4l2_subdev_call(sd, pad, dv_timings_cap, cap); 431 } 432 433 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: { 434 struct v4l2_enum_dv_timings *dvt = arg; 435 436 if (dvt->pad >= sd->entity.num_pads) 437 return -EINVAL; 438 439 return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt); 440 } 441 442 case VIDIOC_SUBDEV_QUERY_DV_TIMINGS: 443 return v4l2_subdev_call(sd, video, query_dv_timings, arg); 444 445 case VIDIOC_SUBDEV_G_DV_TIMINGS: 446 return v4l2_subdev_call(sd, video, g_dv_timings, arg); 447 448 case VIDIOC_SUBDEV_S_DV_TIMINGS: 449 return v4l2_subdev_call(sd, video, s_dv_timings, arg); 450 #endif 451 default: 452 return v4l2_subdev_call(sd, core, ioctl, cmd, arg); 453 } 454 455 return 0; 456 } 457 458 static long subdev_ioctl(struct file *file, unsigned int cmd, 459 unsigned long arg) 460 { 461 return video_usercopy(file, cmd, arg, subdev_do_ioctl); 462 } 463 464 #ifdef CONFIG_COMPAT 465 static long subdev_compat_ioctl32(struct file *file, unsigned int cmd, 466 unsigned long arg) 467 { 468 struct video_device *vdev = video_devdata(file); 469 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 470 471 return v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg); 472 } 473 #endif 474 475 static unsigned int subdev_poll(struct file *file, poll_table *wait) 476 { 477 struct video_device *vdev = video_devdata(file); 478 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 479 struct v4l2_fh *fh = file->private_data; 480 481 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) 482 return POLLERR; 483 484 poll_wait(file, &fh->wait, wait); 485 486 if (v4l2_event_pending(fh)) 487 return POLLPRI; 488 489 return 0; 490 } 491 492 const struct v4l2_file_operations v4l2_subdev_fops = { 493 .owner = THIS_MODULE, 494 .open = subdev_open, 495 .unlocked_ioctl = subdev_ioctl, 496 #ifdef CONFIG_COMPAT 497 .compat_ioctl32 = subdev_compat_ioctl32, 498 #endif 499 .release = subdev_close, 500 .poll = subdev_poll, 501 }; 502 503 #ifdef CONFIG_MEDIA_CONTROLLER 504 int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, 505 struct media_link *link, 506 struct v4l2_subdev_format *source_fmt, 507 struct v4l2_subdev_format *sink_fmt) 508 { 509 /* The width, height and code must match. */ 510 if (source_fmt->format.width != sink_fmt->format.width 511 || source_fmt->format.height != sink_fmt->format.height 512 || source_fmt->format.code != sink_fmt->format.code) 513 return -EPIPE; 514 515 /* The field order must match, or the sink field order must be NONE 516 * to support interlaced hardware connected to bridges that support 517 * progressive formats only. 518 */ 519 if (source_fmt->format.field != sink_fmt->format.field && 520 sink_fmt->format.field != V4L2_FIELD_NONE) 521 return -EPIPE; 522 523 return 0; 524 } 525 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default); 526 527 static int 528 v4l2_subdev_link_validate_get_format(struct media_pad *pad, 529 struct v4l2_subdev_format *fmt) 530 { 531 if (is_media_entity_v4l2_subdev(pad->entity)) { 532 struct v4l2_subdev *sd = 533 media_entity_to_v4l2_subdev(pad->entity); 534 535 fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; 536 fmt->pad = pad->index; 537 return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); 538 } 539 540 WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L, 541 "Driver bug! Wrong media entity type 0x%08x, entity %s\n", 542 pad->entity->function, pad->entity->name); 543 544 return -EINVAL; 545 } 546 547 int v4l2_subdev_link_validate(struct media_link *link) 548 { 549 struct v4l2_subdev *sink; 550 struct v4l2_subdev_format sink_fmt, source_fmt; 551 int rval; 552 553 rval = v4l2_subdev_link_validate_get_format( 554 link->source, &source_fmt); 555 if (rval < 0) 556 return 0; 557 558 rval = v4l2_subdev_link_validate_get_format( 559 link->sink, &sink_fmt); 560 if (rval < 0) 561 return 0; 562 563 sink = media_entity_to_v4l2_subdev(link->sink->entity); 564 565 rval = v4l2_subdev_call(sink, pad, link_validate, link, 566 &source_fmt, &sink_fmt); 567 if (rval != -ENOIOCTLCMD) 568 return rval; 569 570 return v4l2_subdev_link_validate_default( 571 sink, link, &source_fmt, &sink_fmt); 572 } 573 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); 574 575 struct v4l2_subdev_pad_config * 576 v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd) 577 { 578 struct v4l2_subdev_pad_config *cfg; 579 int ret; 580 581 if (!sd->entity.num_pads) 582 return NULL; 583 584 cfg = kcalloc(sd->entity.num_pads, sizeof(*cfg), GFP_KERNEL); 585 if (!cfg) 586 return NULL; 587 588 ret = v4l2_subdev_call(sd, pad, init_cfg, cfg); 589 if (ret < 0 && ret != -ENOIOCTLCMD) { 590 kfree(cfg); 591 return NULL; 592 } 593 594 return cfg; 595 } 596 EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config); 597 598 void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg) 599 { 600 kfree(cfg); 601 } 602 EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config); 603 #endif /* CONFIG_MEDIA_CONTROLLER */ 604 605 void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) 606 { 607 INIT_LIST_HEAD(&sd->list); 608 BUG_ON(!ops); 609 sd->ops = ops; 610 sd->v4l2_dev = NULL; 611 sd->flags = 0; 612 sd->name[0] = '\0'; 613 sd->grp_id = 0; 614 sd->dev_priv = NULL; 615 sd->host_priv = NULL; 616 #if defined(CONFIG_MEDIA_CONTROLLER) 617 sd->entity.name = sd->name; 618 sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV; 619 sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; 620 #endif 621 } 622 EXPORT_SYMBOL(v4l2_subdev_init); 623 624 void v4l2_subdev_notify_event(struct v4l2_subdev *sd, 625 const struct v4l2_event *ev) 626 { 627 v4l2_event_queue(sd->devnode, ev); 628 v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, (void *)ev); 629 } 630 EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event); 631