1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/*! 18 * \file exynos_v4l2.c 19 * \brief source file for libv4l2 20 * \author Jinsung Yang (jsgood.yang@samsung.com) 21 * \author Sangwoo Park (sw5771.park@samsung.com) 22 * \date 2012/01/17 23 * 24 * <b>Revision History: </b> 25 * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n 26 * Initial version 27 * 28 */ 29 30#include <stdio.h> 31#include <errno.h> 32#include <stdarg.h> 33#include <fcntl.h> 34#include <string.h> 35#include <sys/types.h> 36#include <sys/ioctl.h> 37#include <sys/stat.h> 38 39#include "exynos_v4l2.h" 40 41//#define LOG_NDEBUG 0 42#define LOG_TAG "libexynosv4l2" 43#include <utils/Log.h> 44#include "Exynos_log.h" 45 46#define VIDEODEV_MINOR_MAX 63 47 48//#define EXYNOS_V4L2_TRACE 0 49#ifdef EXYNOS_V4L2_TRACE 50#define Exynos_v4l2_In() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__) 51#define Exynos_v4l2_Out() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__) 52#else 53#define Exynos_v4l2_In() ((void *)0) 54#define Exynos_v4l2_Out() ((void *)0) 55#endif 56 57static bool __v4l2_check_buf_type(enum v4l2_buf_type type) 58{ 59 bool supported; 60 61 switch (type) { 62 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 63 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 64 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 65 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 66 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 67 supported = true; 68 break; 69 70 default: 71 supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false; 72 break; 73 } 74 75 return supported; 76} 77 78static int __v4l2_open(const char *filename, int oflag, va_list ap) 79{ 80 mode_t mode = 0; 81 int fd; 82 83 if (oflag & O_CREAT) 84 mode = va_arg(ap, int); 85 86 fd = open(filename, oflag, mode); 87 88 return fd; 89} 90 91int exynos_v4l2_open(const char *filename, int oflag, ...) 92{ 93 va_list ap; 94 int fd; 95 96 Exynos_v4l2_In(); 97 98 va_start(ap, oflag); 99 fd = __v4l2_open(filename, oflag, ap); 100 va_end(ap); 101 102 Exynos_v4l2_Out(); 103 104 return fd; 105} 106 107int exynos_v4l2_open_devname(const char *devname, int oflag, ...) 108{ 109 bool found = false; 110 int fd = -1; 111 struct stat s; 112 va_list ap; 113 FILE *stream_fd; 114 char filename[64], name[64]; 115 int minor, size, i = 0; 116 117 Exynos_v4l2_In(); 118 119 do { 120 if (i > VIDEODEV_MINOR_MAX) 121 break; 122 123 /* video device node */ 124 sprintf(filename, "/dev/video%d", i++); 125 126 /* if the node is video device */ 127 if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) && 128 ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) { 129 minor = (int)((unsigned short)(s.st_rdev & 0x3f)); 130 ALOGD("try node: %s, minor: %d", filename, minor); 131 /* open sysfs entry */ 132 sprintf(filename, "/sys/class/video4linux/video%d/name", minor); 133 stream_fd = fopen(filename, "r"); 134 if (stream_fd == NULL) { 135 ALOGE("failed to open sysfs entry for videodev"); 136 continue; /* try next */ 137 } 138 139 /* read sysfs entry for device name */ 140 size = (int)fgets(name, sizeof(name), stream_fd); 141 fclose(stream_fd); 142 143 /* check read size */ 144 if (size == 0) { 145 ALOGE("failed to read sysfs entry for videodev"); 146 } else { 147 /* matched */ 148 if (strncmp(name, devname, strlen(devname)) == 0) { 149 ALOGI("node found for device %s: /dev/video%d", devname, minor); 150 found = true; 151 } 152 } 153 } 154 } while (found == false); 155 156 if (found) { 157 sprintf(filename, "/dev/video%d", minor); 158 va_start(ap, oflag); 159 fd = __v4l2_open(filename, oflag, ap); 160 va_end(ap); 161 162 if (fd > 0) 163 ALOGI("open video device %s", filename); 164 else 165 ALOGE("failed to open video device %s", filename); 166 } else { 167 ALOGE("no video device found"); 168 } 169 170 Exynos_v4l2_Out(); 171 172 return fd; 173} 174 175int exynos_v4l2_close(int fd) 176{ 177 int ret = -1; 178 179 Exynos_v4l2_In(); 180 181 if (fd < 0) 182 ALOGE("%s: invalid fd: %d", __func__, fd); 183 else 184 ret = close(fd); 185 186 Exynos_v4l2_Out(); 187 188 return ret; 189} 190 191bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf) 192{ 193 int ret = -1; 194 struct v4l2_input input; 195 196 Exynos_v4l2_In(); 197 198 if (fd < 0) { 199 ALOGE("%s: invalid fd: %d", __func__, fd); 200 return NULL; 201 } 202 203 input.index = index; 204 ret = ioctl(fd, VIDIOC_ENUMINPUT, &input); 205 if (ret) { 206 ALOGE("%s: no matching index founds", __func__); 207 return false; 208 } 209 210 ALOGI("Name of input channel[%d] is %s", input.index, input.name); 211 212 strcpy(input_name_buf, (const char *)input.name); 213 214 Exynos_v4l2_Out(); 215 216 return true; 217} 218 219int exynos_v4l2_s_input(int fd, int index) 220{ 221 int ret = -1; 222 struct v4l2_input input; 223 224 Exynos_v4l2_In(); 225 226 if (fd < 0) { 227 ALOGE("%s: invalid fd: %d", __func__, fd); 228 return ret; 229 } 230 231 input.index = index; 232 233 ret = ioctl(fd, VIDIOC_S_INPUT, &input); 234 if (ret){ 235 ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno)); 236 return ret; 237 } 238 239 Exynos_v4l2_Out(); 240 241 return ret; 242} 243 244bool exynos_v4l2_querycap(int fd, unsigned int need_caps) 245{ 246 struct v4l2_capability cap; 247 int ret; 248 249 Exynos_v4l2_In(); 250 251 if (fd < 0) { 252 ALOGE("%s: invalid fd: %d", __func__, fd); 253 return false; 254 } 255 256 if (!(need_caps & V4L2_CAP_VIDEO_CAPTURE) && 257 !(need_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) && 258 !(need_caps & V4L2_CAP_VIDEO_OUTPUT) && 259 !(need_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) && 260 !(need_caps & V4L2_CAP_VIDEO_OVERLAY)) { 261 ALOGE("%s: unsupported capabilities", __func__); 262 return false; 263 } 264 265 memset(&cap, 0, sizeof(cap)); 266 267 ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); 268 if (ret) { 269 ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno)); 270 return false; 271 } 272 273 if ((need_caps & cap.capabilities) != need_caps) { 274 ALOGE("%s: unsupported capabilities", __func__); 275 return false; 276 } 277 278 Exynos_v4l2_Out(); 279 280 return true; 281} 282 283bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt) 284{ 285 struct v4l2_fmtdesc fmtdesc; 286 int found = 0; 287 288 Exynos_v4l2_In(); 289 290 fmtdesc.type = type; 291 fmtdesc.index = 0; 292 293 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { 294 if (fmtdesc.pixelformat == fmt) { 295 ALOGE("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description); 296 found = 1; 297 break; 298 } 299 300 fmtdesc.index++; 301 } 302 303 if (!found) { 304 ALOGE("%s: unsupported pixel format", __func__); 305 return false; 306 } 307 308 Exynos_v4l2_Out(); 309 310 return true; 311} 312 313int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt) 314{ 315 int ret = -1; 316 317 Exynos_v4l2_In(); 318 319 if (fd < 0) { 320 ALOGE("%s: invalid fd: %d", __func__, fd); 321 return ret; 322 } 323 324 if (!fmt) { 325 ALOGE("%s: fmt is NULL", __func__); 326 return ret; 327 } 328 329 if (__v4l2_check_buf_type(fmt->type) == false) { 330 ALOGE("%s: unsupported buffer type", __func__); 331 return ret; 332 } 333 334 ret = ioctl(fd, VIDIOC_G_FMT, fmt); 335 if (ret) { 336 ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno)); 337 return ret; 338 } 339 340 Exynos_v4l2_Out(); 341 342 return ret; 343} 344 345static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt) 346{ 347 int ret = -1; 348 349 Exynos_v4l2_In(); 350 351 if (fd < 0) { 352 ALOGE("%s: invalid fd: %d", __func__, fd); 353 return ret; 354 } 355 356 if (!fmt) { 357 ALOGE("%s: fmt is NULL", __func__); 358 return ret; 359 } 360 361 if (__v4l2_check_buf_type(fmt->type) == false) { 362 ALOGE("%s: unsupported buffer type", __func__); 363 return ret; 364 } else { 365 ret = ioctl(fd, request, fmt); 366 if (ret) { 367 if (request == VIDIOC_TRY_FMT) 368 ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno)); 369 else 370 ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno)); 371 372 return ret; 373 } 374 } 375 376 Exynos_v4l2_Out(); 377 378 return ret; 379} 380 381int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt) 382{ 383 return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt); 384} 385 386int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt) 387{ 388 return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt); 389} 390 391int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req) 392{ 393 int ret = -1; 394 unsigned int count; 395 396 Exynos_v4l2_In(); 397 398 if (fd < 0) { 399 ALOGE("%s: invalid fd: %d", __func__, fd); 400 return ret; 401 } 402 403 if (!req) { 404 ALOGE("%s: req is NULL", __func__); 405 return ret; 406 } 407 408 if ((req->memory != V4L2_MEMORY_MMAP) && 409 (req->memory != V4L2_MEMORY_USERPTR) && 410 (req->memory != V4L2_MEMORY_DMABUF)) { 411 ALOGE("%s: unsupported memory type", __func__); 412 return ret; 413 } 414 415 if (__v4l2_check_buf_type(req->type) == false) { 416 ALOGE("%s: unsupported buffer type", __func__); 417 return ret; 418 } 419 420 count = req->count; 421 422 ret = ioctl(fd, VIDIOC_REQBUFS, req); 423 if (ret) { 424 ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno)); 425 return ret; 426 } 427 428 if (count != req->count) { 429 ALOGW("number of buffers had been changed: %d => %d", count, req->count); 430 } 431 432 Exynos_v4l2_Out(); 433 434 return ret; 435} 436 437int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf) 438{ 439 int ret = -1; 440 441 Exynos_v4l2_In(); 442 443 if (fd < 0) { 444 ALOGE("%s: invalid fd: %d", __func__, fd); 445 return ret; 446 } 447 448 if (!buf) { 449 ALOGE("%s: buf is NULL", __func__); 450 return ret; 451 } 452 453 if ((buf->memory != V4L2_MEMORY_MMAP) && 454 (buf->memory != V4L2_MEMORY_DMABUF)) { 455 ALOGE("%s: unsupported memory type", __func__); 456 return ret; 457 } 458 459 if (__v4l2_check_buf_type(buf->type) == false) { 460 ALOGE("%s: unsupported buffer type", __func__); 461 return ret; 462 } 463 464 ret = ioctl(fd, VIDIOC_QUERYBUF, buf); 465 if (ret) { 466 ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno)); 467 return ret; 468 } 469 470 Exynos_v4l2_Out(); 471 472 return ret; 473} 474 475int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf) 476{ 477 int ret = -1; 478 479 Exynos_v4l2_In(); 480 481 if (fd < 0) { 482 ALOGE("%s: invalid fd: %d", __func__, fd); 483 return ret; 484 } 485 486 if (!buf) { 487 ALOGE("%s: buf is NULL", __func__); 488 return ret; 489 } 490 491 if ((buf->memory != V4L2_MEMORY_MMAP) && 492 (buf->memory != V4L2_MEMORY_USERPTR) && 493 (buf->memory != V4L2_MEMORY_DMABUF)) { 494 ALOGE("%s: unsupported memory type", __func__); 495 return ret; 496 } 497 498 if (__v4l2_check_buf_type(buf->type) == false) { 499 ALOGE("%s: unsupported buffer type", __func__); 500 return ret; 501 } 502 503 ret = ioctl(fd, VIDIOC_QBUF, buf); 504 if (ret) { 505 ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno)); 506 return ret; 507 } 508 509 Exynos_v4l2_Out(); 510 511 return ret; 512} 513 514int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf) 515{ 516 int ret = -1; 517 518 Exynos_v4l2_In(); 519 520 if (fd < 0) { 521 ALOGE("%s: invalid fd: %d", __func__, fd); 522 return ret; 523 } 524 525 if (!buf) { 526 ALOGE("%s: buf is NULL", __func__); 527 return ret; 528 } 529 530 if ((buf->memory != V4L2_MEMORY_MMAP) && 531 (buf->memory != V4L2_MEMORY_USERPTR) && 532 (buf->memory != V4L2_MEMORY_DMABUF)) { 533 ALOGE("%s: unsupported memory type", __func__); 534 return ret; 535 } 536 537 if (__v4l2_check_buf_type(buf->type) == false) { 538 ALOGE("%s: unsupported buffer type", __func__); 539 return ret; 540 } 541 542 ret = ioctl(fd, VIDIOC_DQBUF, buf); 543 if (ret) { 544 ALOGE("failed to ioctl: VIDIOC_DQBUF (%d - %s)", errno, strerror(errno)); 545 return ret; 546 } 547 548 Exynos_v4l2_Out(); 549 550 return ret; 551} 552 553int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type) 554{ 555 int ret = -1; 556 557 Exynos_v4l2_In(); 558 559 if (fd < 0) { 560 ALOGE("%s: invalid fd: %d", __func__, fd); 561 return ret; 562 } 563 564 if (__v4l2_check_buf_type(type) == false) { 565 ALOGE("%s: unsupported buffer type", __func__); 566 return ret; 567 } 568 569 ret = ioctl(fd, VIDIOC_STREAMON, &type); 570 if (ret) { 571 ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno)); 572 return ret; 573 } 574 575 Exynos_v4l2_Out(); 576 577 return ret; 578} 579 580int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type) 581{ 582 int ret = -1; 583 584 Exynos_v4l2_In(); 585 586 if (fd < 0) { 587 ALOGE("%s: invalid fd: %d", __func__, fd); 588 return ret; 589 } 590 591 if (__v4l2_check_buf_type(type) == false) { 592 ALOGE("%s: unsupported buffer type", __func__); 593 return ret; 594 } 595 596 ret = ioctl(fd, VIDIOC_STREAMOFF, &type); 597 if (ret) { 598 ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno)); 599 return ret; 600 } 601 602 Exynos_v4l2_Out(); 603 604 return ret; 605} 606 607int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop) 608{ 609 int ret = -1; 610 611 Exynos_v4l2_In(); 612 613 if (fd < 0) { 614 ALOGE("%s: invalid fd: %d", __func__, fd); 615 return ret; 616 } 617 618 if (!crop) { 619 ALOGE("%s: crop is NULL", __func__); 620 return ret; 621 } 622 623 if (__v4l2_check_buf_type(crop->type) == false) { 624 ALOGE("%s: unsupported buffer type", __func__); 625 return ret; 626 } 627 628 ret = ioctl(fd, VIDIOC_CROPCAP, crop); 629 if (ret) { 630 ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno)); 631 return ret; 632 } 633 634 Exynos_v4l2_Out(); 635 636 return ret; 637} 638 639int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop) 640{ 641 int ret = -1; 642 643 Exynos_v4l2_In(); 644 645 if (fd < 0) { 646 ALOGE("%s: invalid fd: %d", __func__, fd); 647 return ret; 648 } 649 650 if (!crop) { 651 ALOGE("%s: crop is NULL", __func__); 652 return ret; 653 } 654 655 if (__v4l2_check_buf_type(crop->type) == false) { 656 ALOGE("%s: unsupported buffer type", __func__); 657 return ret; 658 } 659 660 ret = ioctl(fd, VIDIOC_G_CROP, crop); 661 if (ret) { 662 ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno)); 663 return ret; 664 } 665 666 Exynos_v4l2_Out(); 667 668 return ret; 669} 670 671int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop) 672{ 673 int ret = -1; 674 675 Exynos_v4l2_In(); 676 677 if (fd < 0) { 678 ALOGE("%s: invalid fd: %d", __func__, fd); 679 return ret; 680 } 681 682 if (!crop) { 683 ALOGE("%s: crop is NULL", __func__); 684 return ret; 685 } 686 687 if (__v4l2_check_buf_type(crop->type) == false) { 688 ALOGE("%s: unsupported buffer type", __func__); 689 return ret; 690 } 691 692 ret = ioctl(fd, VIDIOC_S_CROP, crop); 693 if (ret) { 694 ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno)); 695 return ret; 696 } 697 698 Exynos_v4l2_Out(); 699 700 return ret; 701} 702 703int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value) 704{ 705 int ret = -1; 706 struct v4l2_control ctrl; 707 708 Exynos_v4l2_In(); 709 710 ctrl.id = id; 711 712 if (fd < 0) { 713 ALOGE("%s: invalid fd: %d", __func__, fd); 714 return ret; 715 } 716 717 ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl); 718 if (ret) { 719 ALOGE("failed to ioctl: VIDIOC_G_CTRL (%d - %s)", errno, strerror(errno)); 720 return ret; 721 } 722 723 *value = ctrl.value; 724 725 Exynos_v4l2_Out(); 726 727 return ret; 728} 729 730int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value) 731{ 732 int ret = -1; 733 struct v4l2_control ctrl; 734 735 Exynos_v4l2_In(); 736 737 ctrl.id = id; 738 ctrl.value = value; 739 740 if (fd < 0) { 741 ALOGE("%s: invalid fd: %d", __func__, fd); 742 return ret; 743 } 744 745 ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl); 746 if (ret) { 747 ALOGE("failed to ioctl: VIDIOC_S_CTRL (%d)", errno); 748 return ret; 749 } 750 751 Exynos_v4l2_Out(); 752 753 return ret; 754} 755 756int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm) 757{ 758 int ret = -1; 759 760 Exynos_v4l2_In(); 761 762 if (fd < 0) { 763 ALOGE("%s: invalid fd: %d", __func__, fd); 764 return ret; 765 } 766 767 if (__v4l2_check_buf_type(streamparm->type) == false) { 768 ALOGE("%s: unsupported buffer type", __func__); 769 return ret; 770 } 771 772 ret = ioctl(fd, VIDIOC_G_PARM, streamparm); 773 if (ret) { 774 ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno)); 775 return ret; 776 } 777 778 Exynos_v4l2_Out(); 779 780 return ret; 781} 782 783int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm) 784{ 785 int ret = -1; 786 787 Exynos_v4l2_In(); 788 789 if (fd < 0) { 790 ALOGE("%s: invalid fd: %d", __func__, fd); 791 return ret; 792 } 793 794 if (__v4l2_check_buf_type(streamparm->type) == false) { 795 ALOGE("%s: unsupported buffer type", __func__); 796 return ret; 797 } 798 799 ret = ioctl(fd, VIDIOC_S_PARM, streamparm); 800 if (ret) { 801 ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno)); 802 return ret; 803 } 804 805 Exynos_v4l2_Out(); 806 807 return ret; 808} 809 810int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl) 811{ 812 int ret = -1; 813 814 Exynos_v4l2_In(); 815 816 if (fd < 0) { 817 ALOGE("%s: invalid fd: %d", __func__, fd); 818 return ret; 819 } 820 821 if (ctrl == NULL) { 822 ALOGE("%s: ctrl is NULL", __func__); 823 return ret; 824 } 825 826 ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl); 827 if (ret) 828 ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno)); 829 830 Exynos_v4l2_Out(); 831 832 return ret; 833} 834 835int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl) 836{ 837 int ret = -1; 838 839 Exynos_v4l2_In(); 840 841 if (fd < 0) { 842 ALOGE("%s: invalid fd: %d", __func__, fd); 843 return ret; 844 } 845 846 if (ctrl == NULL) { 847 ALOGE("%s: ctrl is NULL", __func__); 848 return ret; 849 } 850 851 ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl); 852 if (ret) 853 ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno)); 854 855 Exynos_v4l2_Out(); 856 857 return ret; 858} 859