| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Video capture interface for Linux version 2 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * A generic framework to process V4L2 ioctl commands. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public License |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 10 | 6 | * |
|---|
| 11 | 7 | * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1) |
|---|
| 12 | 8 | * Mauro Carvalho Chehab <mchehab@kernel.org> (version 2) |
|---|
| .. | .. |
|---|
| 32 | 28 | #include <media/v4l2-mem2mem.h> |
|---|
| 33 | 29 | |
|---|
| 34 | 30 | #include <trace/events/v4l2.h> |
|---|
| 31 | +#include <trace/hooks/v4l2core.h> |
|---|
| 32 | + |
|---|
| 35 | 33 | |
|---|
| 36 | 34 | /* Zero out the end of the struct pointed to by p. Everything after, but |
|---|
| 37 | 35 | * not including, the specified field is cleared. */ |
|---|
| .. | .. |
|---|
| 80 | 78 | { 0, "Unknown" } |
|---|
| 81 | 79 | }; |
|---|
| 82 | 80 | |
|---|
| 81 | +static void clear_reserved(struct v4l2_format *p) |
|---|
| 82 | +{ |
|---|
| 83 | + int ret = 0; |
|---|
| 84 | + |
|---|
| 85 | + trace_android_vh_clear_reserved_fmt_fields(p, &ret); |
|---|
| 86 | + if (!ret) |
|---|
| 87 | + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); |
|---|
| 88 | +} |
|---|
| 89 | + |
|---|
| 83 | 90 | /* video4linux standard ID conversion to standard name |
|---|
| 84 | 91 | */ |
|---|
| 85 | 92 | const char *v4l2_norm_to_name(v4l2_std_id id) |
|---|
| .. | .. |
|---|
| 88 | 95 | int i; |
|---|
| 89 | 96 | |
|---|
| 90 | 97 | /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle |
|---|
| 91 | | - 64 bit comparations. So, on that architecture, with some gcc |
|---|
| 98 | + 64 bit comparisons. So, on that architecture, with some gcc |
|---|
| 92 | 99 | variants, compilation fails. Currently, the max value is 30bit wide. |
|---|
| 93 | 100 | */ |
|---|
| 94 | 101 | BUG_ON(myid != id); |
|---|
| .. | .. |
|---|
| 121 | 128 | vs->id = id; |
|---|
| 122 | 129 | v4l2_video_std_frame_period(id, &vs->frameperiod); |
|---|
| 123 | 130 | vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625; |
|---|
| 124 | | - strlcpy(vs->name, name, sizeof(vs->name)); |
|---|
| 131 | + strscpy(vs->name, name, sizeof(vs->name)); |
|---|
| 125 | 132 | return 0; |
|---|
| 126 | 133 | } |
|---|
| 127 | 134 | EXPORT_SYMBOL(v4l2_video_std_construct); |
|---|
| .. | .. |
|---|
| 268 | 275 | { |
|---|
| 269 | 276 | const struct v4l2_fmtdesc *p = arg; |
|---|
| 270 | 277 | |
|---|
| 271 | | - pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n", |
|---|
| 278 | + pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, mbus_code=0x%04x, description='%.*s'\n", |
|---|
| 272 | 279 | p->index, prt_names(p->type, v4l2_type_names), |
|---|
| 273 | 280 | p->flags, (p->pixelformat & 0xff), |
|---|
| 274 | 281 | (p->pixelformat >> 8) & 0xff, |
|---|
| 275 | 282 | (p->pixelformat >> 16) & 0xff, |
|---|
| 276 | 283 | (p->pixelformat >> 24) & 0xff, |
|---|
| 284 | + p->mbus_code, |
|---|
| 277 | 285 | (int)sizeof(p->description), p->description); |
|---|
| 278 | 286 | } |
|---|
| 279 | 287 | |
|---|
| .. | .. |
|---|
| 478 | 486 | const struct v4l2_plane *plane; |
|---|
| 479 | 487 | int i; |
|---|
| 480 | 488 | |
|---|
| 481 | | - pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s", |
|---|
| 482 | | - p->timestamp.tv_sec / 3600, |
|---|
| 483 | | - (int)(p->timestamp.tv_sec / 60) % 60, |
|---|
| 484 | | - (int)(p->timestamp.tv_sec % 60), |
|---|
| 489 | + pr_cont("%02d:%02d:%02d.%09ld index=%d, type=%s, request_fd=%d, flags=0x%08x, field=%s, sequence=%d, memory=%s", |
|---|
| 490 | + (int)p->timestamp.tv_sec / 3600, |
|---|
| 491 | + ((int)p->timestamp.tv_sec / 60) % 60, |
|---|
| 492 | + ((int)p->timestamp.tv_sec % 60), |
|---|
| 485 | 493 | (long)p->timestamp.tv_usec, |
|---|
| 486 | 494 | p->index, |
|---|
| 487 | | - prt_names(p->type, v4l2_type_names), |
|---|
| 495 | + prt_names(p->type, v4l2_type_names), p->request_fd, |
|---|
| 488 | 496 | p->flags, prt_names(p->field, v4l2_field_names), |
|---|
| 489 | 497 | p->sequence, prt_names(p->memory, v4l2_memory_names)); |
|---|
| 490 | 498 | |
|---|
| .. | .. |
|---|
| 585 | 593 | static void v4l_print_control(const void *arg, bool write_only) |
|---|
| 586 | 594 | { |
|---|
| 587 | 595 | const struct v4l2_control *p = arg; |
|---|
| 596 | + const char *name = v4l2_ctrl_get_name(p->id); |
|---|
| 588 | 597 | |
|---|
| 598 | + if (name) |
|---|
| 599 | + pr_cont("name=%s, ", name); |
|---|
| 589 | 600 | pr_cont("id=0x%x, value=%d\n", p->id, p->value); |
|---|
| 590 | 601 | } |
|---|
| 591 | 602 | |
|---|
| .. | .. |
|---|
| 594 | 605 | const struct v4l2_ext_controls *p = arg; |
|---|
| 595 | 606 | int i; |
|---|
| 596 | 607 | |
|---|
| 597 | | - pr_cont("which=0x%x, count=%d, error_idx=%d", |
|---|
| 598 | | - p->which, p->count, p->error_idx); |
|---|
| 608 | + pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d", |
|---|
| 609 | + p->which, p->count, p->error_idx, p->request_fd); |
|---|
| 599 | 610 | for (i = 0; i < p->count; i++) { |
|---|
| 611 | + unsigned int id = p->controls[i].id; |
|---|
| 612 | + const char *name = v4l2_ctrl_get_name(id); |
|---|
| 613 | + |
|---|
| 614 | + if (name) |
|---|
| 615 | + pr_cont(", name=%s", name); |
|---|
| 600 | 616 | if (!p->controls[i].size) |
|---|
| 601 | | - pr_cont(", id/val=0x%x/0x%x", |
|---|
| 602 | | - p->controls[i].id, p->controls[i].value); |
|---|
| 617 | + pr_cont(", id/val=0x%x/0x%x", id, p->controls[i].value); |
|---|
| 603 | 618 | else |
|---|
| 604 | | - pr_cont(", id/size=0x%x/%u", |
|---|
| 605 | | - p->controls[i].id, p->controls[i].size); |
|---|
| 619 | + pr_cont(", id/size=0x%x/%u", id, p->controls[i].size); |
|---|
| 606 | 620 | } |
|---|
| 607 | 621 | pr_cont("\n"); |
|---|
| 608 | 622 | } |
|---|
| .. | .. |
|---|
| 779 | 793 | p->stepwise.step_height); |
|---|
| 780 | 794 | break; |
|---|
| 781 | 795 | case V4L2_FRMSIZE_TYPE_CONTINUOUS: |
|---|
| 782 | | - /* fall through */ |
|---|
| 783 | 796 | default: |
|---|
| 784 | 797 | pr_cont("\n"); |
|---|
| 785 | 798 | break; |
|---|
| .. | .. |
|---|
| 813 | 826 | p->stepwise.step.denominator); |
|---|
| 814 | 827 | break; |
|---|
| 815 | 828 | case V4L2_FRMIVAL_TYPE_CONTINUOUS: |
|---|
| 816 | | - /* fall through */ |
|---|
| 817 | 829 | default: |
|---|
| 818 | 830 | pr_cont("\n"); |
|---|
| 819 | 831 | break; |
|---|
| .. | .. |
|---|
| 825 | 837 | const struct v4l2_event *p = arg; |
|---|
| 826 | 838 | const struct v4l2_event_ctrl *c; |
|---|
| 827 | 839 | |
|---|
| 828 | | - pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%lu.%9.9lu\n", |
|---|
| 840 | + pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%llu.%9.9llu\n", |
|---|
| 829 | 841 | p->type, p->pending, p->sequence, p->id, |
|---|
| 830 | 842 | p->timestamp.tv_sec, p->timestamp.tv_nsec); |
|---|
| 831 | 843 | switch (p->type) { |
|---|
| .. | .. |
|---|
| 906 | 918 | pr_cont("driver-specific ioctl\n"); |
|---|
| 907 | 919 | } |
|---|
| 908 | 920 | |
|---|
| 909 | | -static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) |
|---|
| 921 | +static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) |
|---|
| 910 | 922 | { |
|---|
| 911 | 923 | __u32 i; |
|---|
| 912 | 924 | |
|---|
| 913 | 925 | /* zero the reserved fields */ |
|---|
| 914 | | - c->reserved[0] = c->reserved[1] = 0; |
|---|
| 926 | + c->reserved[0] = 0; |
|---|
| 915 | 927 | for (i = 0; i < c->count; i++) |
|---|
| 916 | 928 | c->controls[i].reserved2[0] = 0; |
|---|
| 917 | 929 | |
|---|
| 918 | | - /* V4L2_CID_PRIVATE_BASE cannot be used as control class |
|---|
| 919 | | - when using extended controls. |
|---|
| 920 | | - Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL |
|---|
| 921 | | - is it allowed for backwards compatibility. |
|---|
| 922 | | - */ |
|---|
| 923 | | - if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) |
|---|
| 924 | | - return 0; |
|---|
| 925 | | - if (!c->which) |
|---|
| 926 | | - return 1; |
|---|
| 930 | + switch (c->which) { |
|---|
| 931 | + case V4L2_CID_PRIVATE_BASE: |
|---|
| 932 | + /* |
|---|
| 933 | + * V4L2_CID_PRIVATE_BASE cannot be used as control class |
|---|
| 934 | + * when using extended controls. |
|---|
| 935 | + * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL |
|---|
| 936 | + * is it allowed for backwards compatibility. |
|---|
| 937 | + */ |
|---|
| 938 | + if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL) |
|---|
| 939 | + return false; |
|---|
| 940 | + break; |
|---|
| 941 | + case V4L2_CTRL_WHICH_DEF_VAL: |
|---|
| 942 | + /* Default value cannot be changed */ |
|---|
| 943 | + if (ioctl == VIDIOC_S_EXT_CTRLS || |
|---|
| 944 | + ioctl == VIDIOC_TRY_EXT_CTRLS) { |
|---|
| 945 | + c->error_idx = c->count; |
|---|
| 946 | + return false; |
|---|
| 947 | + } |
|---|
| 948 | + return true; |
|---|
| 949 | + case V4L2_CTRL_WHICH_CUR_VAL: |
|---|
| 950 | + return true; |
|---|
| 951 | + case V4L2_CTRL_WHICH_REQUEST_VAL: |
|---|
| 952 | + c->error_idx = c->count; |
|---|
| 953 | + return false; |
|---|
| 954 | + } |
|---|
| 955 | + |
|---|
| 927 | 956 | /* Check that all controls are from the same control class. */ |
|---|
| 928 | 957 | for (i = 0; i < c->count; i++) { |
|---|
| 929 | 958 | if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { |
|---|
| 930 | | - c->error_idx = i; |
|---|
| 931 | | - return 0; |
|---|
| 959 | + c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : |
|---|
| 960 | + c->count; |
|---|
| 961 | + return false; |
|---|
| 932 | 962 | } |
|---|
| 933 | 963 | } |
|---|
| 934 | | - return 1; |
|---|
| 964 | + return true; |
|---|
| 935 | 965 | } |
|---|
| 936 | 966 | |
|---|
| 937 | 967 | static int check_fmt(struct file *file, enum v4l2_buf_type type) |
|---|
| 938 | 968 | { |
|---|
| 969 | + const u32 vid_caps = V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 970 | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
|---|
| 971 | + V4L2_CAP_VIDEO_OUTPUT | |
|---|
| 972 | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | |
|---|
| 973 | + V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE; |
|---|
| 974 | + const u32 meta_caps = V4L2_CAP_META_CAPTURE | |
|---|
| 975 | + V4L2_CAP_META_OUTPUT; |
|---|
| 939 | 976 | struct video_device *vfd = video_devdata(file); |
|---|
| 940 | 977 | const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; |
|---|
| 941 | | - bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; |
|---|
| 978 | + bool is_vid = vfd->vfl_type == VFL_TYPE_VIDEO && |
|---|
| 979 | + (vfd->device_caps & vid_caps); |
|---|
| 942 | 980 | bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI; |
|---|
| 943 | 981 | bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; |
|---|
| 944 | 982 | bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; |
|---|
| 983 | + bool is_meta = vfd->vfl_type == VFL_TYPE_VIDEO && |
|---|
| 984 | + (vfd->device_caps & meta_caps); |
|---|
| 945 | 985 | bool is_rx = vfd->vfl_dir != VFL_DIR_TX; |
|---|
| 946 | 986 | bool is_tx = vfd->vfl_dir != VFL_DIR_RX; |
|---|
| 947 | 987 | |
|---|
| .. | .. |
|---|
| 955 | 995 | return 0; |
|---|
| 956 | 996 | break; |
|---|
| 957 | 997 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
|---|
| 958 | | - if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) |
|---|
| 998 | + if ((is_vid || is_tch) && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) |
|---|
| 959 | 999 | return 0; |
|---|
| 960 | 1000 | break; |
|---|
| 961 | 1001 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
|---|
| .. | .. |
|---|
| 1000 | 1040 | return 0; |
|---|
| 1001 | 1041 | break; |
|---|
| 1002 | 1042 | case V4L2_BUF_TYPE_META_CAPTURE: |
|---|
| 1003 | | - if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap) |
|---|
| 1043 | + if (is_meta && is_rx && ops->vidioc_g_fmt_meta_cap) |
|---|
| 1004 | 1044 | return 0; |
|---|
| 1005 | 1045 | break; |
|---|
| 1006 | 1046 | case V4L2_BUF_TYPE_META_OUTPUT: |
|---|
| 1007 | | - if (is_vid && is_tx && ops->vidioc_g_fmt_meta_out) |
|---|
| 1047 | + if (is_meta && is_tx && ops->vidioc_g_fmt_meta_out) |
|---|
| 1008 | 1048 | return 0; |
|---|
| 1009 | 1049 | break; |
|---|
| 1010 | 1050 | default: |
|---|
| .. | .. |
|---|
| 1016 | 1056 | static void v4l_sanitize_format(struct v4l2_format *fmt) |
|---|
| 1017 | 1057 | { |
|---|
| 1018 | 1058 | unsigned int offset; |
|---|
| 1059 | + |
|---|
| 1060 | + /* Make sure num_planes is not bogus */ |
|---|
| 1061 | + if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || |
|---|
| 1062 | + fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 1063 | + fmt->fmt.pix_mp.num_planes = min_t(u32, fmt->fmt.pix_mp.num_planes, |
|---|
| 1064 | + VIDEO_MAX_PLANES); |
|---|
| 1019 | 1065 | |
|---|
| 1020 | 1066 | /* |
|---|
| 1021 | 1067 | * The v4l2_pix_format structure has been extended with fields that were |
|---|
| .. | .. |
|---|
| 1055 | 1101 | |
|---|
| 1056 | 1102 | ret = ops->vidioc_querycap(file, fh, cap); |
|---|
| 1057 | 1103 | |
|---|
| 1058 | | - cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; |
|---|
| 1059 | 1104 | /* |
|---|
| 1060 | | - * Drivers MUST fill in device_caps, so check for this and |
|---|
| 1061 | | - * warn if it was forgotten. |
|---|
| 1105 | + * Drivers must not change device_caps, so check for this and |
|---|
| 1106 | + * warn if this happened. |
|---|
| 1062 | 1107 | */ |
|---|
| 1063 | | - WARN(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) || |
|---|
| 1064 | | - !cap->device_caps, "Bad caps for driver %s, %x %x", |
|---|
| 1065 | | - cap->driver, cap->capabilities, cap->device_caps); |
|---|
| 1108 | + WARN_ON(cap->device_caps != vfd->device_caps); |
|---|
| 1109 | + /* |
|---|
| 1110 | + * Check that capabilities is a superset of |
|---|
| 1111 | + * vfd->device_caps | V4L2_CAP_DEVICE_CAPS |
|---|
| 1112 | + */ |
|---|
| 1113 | + WARN_ON((cap->capabilities & |
|---|
| 1114 | + (vfd->device_caps | V4L2_CAP_DEVICE_CAPS)) != |
|---|
| 1115 | + (vfd->device_caps | V4L2_CAP_DEVICE_CAPS)); |
|---|
| 1116 | + cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; |
|---|
| 1066 | 1117 | cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; |
|---|
| 1067 | 1118 | |
|---|
| 1068 | 1119 | return ret; |
|---|
| 1120 | +} |
|---|
| 1121 | + |
|---|
| 1122 | +static int v4l_g_input(const struct v4l2_ioctl_ops *ops, |
|---|
| 1123 | + struct file *file, void *fh, void *arg) |
|---|
| 1124 | +{ |
|---|
| 1125 | + struct video_device *vfd = video_devdata(file); |
|---|
| 1126 | + |
|---|
| 1127 | + if (vfd->device_caps & V4L2_CAP_IO_MC) { |
|---|
| 1128 | + *(int *)arg = 0; |
|---|
| 1129 | + return 0; |
|---|
| 1130 | + } |
|---|
| 1131 | + |
|---|
| 1132 | + return ops->vidioc_g_input(file, fh, arg); |
|---|
| 1133 | +} |
|---|
| 1134 | + |
|---|
| 1135 | +static int v4l_g_output(const struct v4l2_ioctl_ops *ops, |
|---|
| 1136 | + struct file *file, void *fh, void *arg) |
|---|
| 1137 | +{ |
|---|
| 1138 | + struct video_device *vfd = video_devdata(file); |
|---|
| 1139 | + |
|---|
| 1140 | + if (vfd->device_caps & V4L2_CAP_IO_MC) { |
|---|
| 1141 | + *(int *)arg = 0; |
|---|
| 1142 | + return 0; |
|---|
| 1143 | + } |
|---|
| 1144 | + |
|---|
| 1145 | + return ops->vidioc_g_output(file, fh, arg); |
|---|
| 1069 | 1146 | } |
|---|
| 1070 | 1147 | |
|---|
| 1071 | 1148 | static int v4l_s_input(const struct v4l2_ioctl_ops *ops, |
|---|
| .. | .. |
|---|
| 1077 | 1154 | ret = v4l_enable_media_source(vfd); |
|---|
| 1078 | 1155 | if (ret) |
|---|
| 1079 | 1156 | return ret; |
|---|
| 1157 | + |
|---|
| 1158 | + if (vfd->device_caps & V4L2_CAP_IO_MC) |
|---|
| 1159 | + return *(int *)arg ? -EINVAL : 0; |
|---|
| 1160 | + |
|---|
| 1080 | 1161 | return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); |
|---|
| 1081 | 1162 | } |
|---|
| 1082 | 1163 | |
|---|
| 1083 | 1164 | static int v4l_s_output(const struct v4l2_ioctl_ops *ops, |
|---|
| 1084 | 1165 | struct file *file, void *fh, void *arg) |
|---|
| 1085 | 1166 | { |
|---|
| 1167 | + struct video_device *vfd = video_devdata(file); |
|---|
| 1168 | + |
|---|
| 1169 | + if (vfd->device_caps & V4L2_CAP_IO_MC) |
|---|
| 1170 | + return *(int *)arg ? -EINVAL : 0; |
|---|
| 1171 | + |
|---|
| 1086 | 1172 | return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); |
|---|
| 1087 | 1173 | } |
|---|
| 1088 | 1174 | |
|---|
| .. | .. |
|---|
| 1126 | 1212 | if (is_valid_ioctl(vfd, VIDIOC_S_STD)) |
|---|
| 1127 | 1213 | p->capabilities |= V4L2_IN_CAP_STD; |
|---|
| 1128 | 1214 | |
|---|
| 1215 | + if (vfd->device_caps & V4L2_CAP_IO_MC) { |
|---|
| 1216 | + if (p->index) |
|---|
| 1217 | + return -EINVAL; |
|---|
| 1218 | + strscpy(p->name, vfd->name, sizeof(p->name)); |
|---|
| 1219 | + p->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 1220 | + return 0; |
|---|
| 1221 | + } |
|---|
| 1222 | + |
|---|
| 1129 | 1223 | return ops->vidioc_enum_input(file, fh, p); |
|---|
| 1130 | 1224 | } |
|---|
| 1131 | 1225 | |
|---|
| .. | .. |
|---|
| 1143 | 1237 | */ |
|---|
| 1144 | 1238 | if (is_valid_ioctl(vfd, VIDIOC_S_STD)) |
|---|
| 1145 | 1239 | p->capabilities |= V4L2_OUT_CAP_STD; |
|---|
| 1240 | + |
|---|
| 1241 | + if (vfd->device_caps & V4L2_CAP_IO_MC) { |
|---|
| 1242 | + if (p->index) |
|---|
| 1243 | + return -EINVAL; |
|---|
| 1244 | + strscpy(p->name, vfd->name, sizeof(p->name)); |
|---|
| 1245 | + p->type = V4L2_OUTPUT_TYPE_ANALOG; |
|---|
| 1246 | + return 0; |
|---|
| 1247 | + } |
|---|
| 1146 | 1248 | |
|---|
| 1147 | 1249 | return ops->vidioc_enum_output(file, fh, p); |
|---|
| 1148 | 1250 | } |
|---|
| .. | .. |
|---|
| 1167 | 1269 | case V4L2_PIX_FMT_RGB444: descr = "16-bit A/XRGB 4-4-4-4"; break; |
|---|
| 1168 | 1270 | case V4L2_PIX_FMT_ARGB444: descr = "16-bit ARGB 4-4-4-4"; break; |
|---|
| 1169 | 1271 | case V4L2_PIX_FMT_XRGB444: descr = "16-bit XRGB 4-4-4-4"; break; |
|---|
| 1272 | + case V4L2_PIX_FMT_RGBA444: descr = "16-bit RGBA 4-4-4-4"; break; |
|---|
| 1273 | + case V4L2_PIX_FMT_RGBX444: descr = "16-bit RGBX 4-4-4-4"; break; |
|---|
| 1274 | + case V4L2_PIX_FMT_ABGR444: descr = "16-bit ABGR 4-4-4-4"; break; |
|---|
| 1275 | + case V4L2_PIX_FMT_XBGR444: descr = "16-bit XBGR 4-4-4-4"; break; |
|---|
| 1276 | + case V4L2_PIX_FMT_BGRA444: descr = "16-bit BGRA 4-4-4-4"; break; |
|---|
| 1277 | + case V4L2_PIX_FMT_BGRX444: descr = "16-bit BGRX 4-4-4-4"; break; |
|---|
| 1170 | 1278 | case V4L2_PIX_FMT_RGB555: descr = "16-bit A/XRGB 1-5-5-5"; break; |
|---|
| 1171 | 1279 | case V4L2_PIX_FMT_ARGB555: descr = "16-bit ARGB 1-5-5-5"; break; |
|---|
| 1172 | 1280 | case V4L2_PIX_FMT_XRGB555: descr = "16-bit XRGB 1-5-5-5"; break; |
|---|
| 1281 | + case V4L2_PIX_FMT_ABGR555: descr = "16-bit ABGR 1-5-5-5"; break; |
|---|
| 1282 | + case V4L2_PIX_FMT_XBGR555: descr = "16-bit XBGR 1-5-5-5"; break; |
|---|
| 1283 | + case V4L2_PIX_FMT_RGBA555: descr = "16-bit RGBA 5-5-5-1"; break; |
|---|
| 1284 | + case V4L2_PIX_FMT_RGBX555: descr = "16-bit RGBX 5-5-5-1"; break; |
|---|
| 1285 | + case V4L2_PIX_FMT_BGRA555: descr = "16-bit BGRA 5-5-5-1"; break; |
|---|
| 1286 | + case V4L2_PIX_FMT_BGRX555: descr = "16-bit BGRX 5-5-5-1"; break; |
|---|
| 1173 | 1287 | case V4L2_PIX_FMT_RGB565: descr = "16-bit RGB 5-6-5"; break; |
|---|
| 1174 | 1288 | case V4L2_PIX_FMT_RGB555X: descr = "16-bit A/XRGB 1-5-5-5 BE"; break; |
|---|
| 1175 | 1289 | case V4L2_PIX_FMT_ARGB555X: descr = "16-bit ARGB 1-5-5-5 BE"; break; |
|---|
| .. | .. |
|---|
| 1184 | 1298 | case V4L2_PIX_FMT_RGB32: descr = "32-bit A/XRGB 8-8-8-8"; break; |
|---|
| 1185 | 1299 | case V4L2_PIX_FMT_ARGB32: descr = "32-bit ARGB 8-8-8-8"; break; |
|---|
| 1186 | 1300 | case V4L2_PIX_FMT_XRGB32: descr = "32-bit XRGB 8-8-8-8"; break; |
|---|
| 1301 | + case V4L2_PIX_FMT_BGRA32: descr = "32-bit ABGR 8-8-8-8"; break; |
|---|
| 1302 | + case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break; |
|---|
| 1303 | + case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break; |
|---|
| 1304 | + case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break; |
|---|
| 1187 | 1305 | case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; |
|---|
| 1188 | 1306 | case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; |
|---|
| 1189 | 1307 | case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; |
|---|
| 1190 | 1308 | case V4L2_PIX_FMT_Y10: descr = "10-bit Greyscale"; break; |
|---|
| 1191 | 1309 | case V4L2_PIX_FMT_Y12: descr = "12-bit Greyscale"; break; |
|---|
| 1310 | + case V4L2_PIX_FMT_Y14: descr = "14-bit Greyscale"; break; |
|---|
| 1192 | 1311 | case V4L2_PIX_FMT_Y16: descr = "16-bit Greyscale"; break; |
|---|
| 1193 | 1312 | case V4L2_PIX_FMT_Y16_BE: descr = "16-bit Greyscale BE"; break; |
|---|
| 1194 | 1313 | case V4L2_PIX_FMT_Y10BPACK: descr = "10-bit Greyscale (Packed)"; break; |
|---|
| .. | .. |
|---|
| 1197 | 1316 | case V4L2_PIX_FMT_Y12I: descr = "Interleaved 12-bit Greyscale"; break; |
|---|
| 1198 | 1317 | case V4L2_PIX_FMT_Z16: descr = "16-bit Depth"; break; |
|---|
| 1199 | 1318 | case V4L2_PIX_FMT_INZI: descr = "Planar 10:16 Greyscale Depth"; break; |
|---|
| 1319 | + case V4L2_PIX_FMT_CNF4: descr = "4-bit Depth Confidence (Packed)"; break; |
|---|
| 1200 | 1320 | case V4L2_PIX_FMT_PAL8: descr = "8-bit Palette"; break; |
|---|
| 1201 | 1321 | case V4L2_PIX_FMT_UV8: descr = "8-bit Chrominance UV 4-4"; break; |
|---|
| 1202 | 1322 | case V4L2_PIX_FMT_YVU410: descr = "Planar YVU 4:1:0"; break; |
|---|
| .. | .. |
|---|
| 1213 | 1333 | case V4L2_PIX_FMT_YUV555: descr = "16-bit A/XYUV 1-5-5-5"; break; |
|---|
| 1214 | 1334 | case V4L2_PIX_FMT_YUV565: descr = "16-bit YUV 5-6-5"; break; |
|---|
| 1215 | 1335 | case V4L2_PIX_FMT_YUV32: descr = "32-bit A/XYUV 8-8-8-8"; break; |
|---|
| 1336 | + case V4L2_PIX_FMT_AYUV32: descr = "32-bit AYUV 8-8-8-8"; break; |
|---|
| 1337 | + case V4L2_PIX_FMT_XYUV32: descr = "32-bit XYUV 8-8-8-8"; break; |
|---|
| 1338 | + case V4L2_PIX_FMT_VUYA32: descr = "32-bit VUYA 8-8-8-8"; break; |
|---|
| 1339 | + case V4L2_PIX_FMT_VUYX32: descr = "32-bit VUYX 8-8-8-8"; break; |
|---|
| 1216 | 1340 | case V4L2_PIX_FMT_YUV410: descr = "Planar YUV 4:1:0"; break; |
|---|
| 1217 | 1341 | case V4L2_PIX_FMT_YUV420: descr = "Planar YUV 4:2:0"; break; |
|---|
| 1218 | 1342 | case V4L2_PIX_FMT_HI240: descr = "8-bit Dithered RGB (BTTV)"; break; |
|---|
| .. | .. |
|---|
| 1268 | 1392 | case V4L2_PIX_FMT_SGBRG12P: descr = "12-bit Bayer GBGB/RGRG Packed"; break; |
|---|
| 1269 | 1393 | case V4L2_PIX_FMT_SGRBG12P: descr = "12-bit Bayer GRGR/BGBG Packed"; break; |
|---|
| 1270 | 1394 | case V4L2_PIX_FMT_SRGGB12P: descr = "12-bit Bayer RGRG/GBGB Packed"; break; |
|---|
| 1395 | + case V4L2_PIX_FMT_SBGGR14: descr = "14-bit Bayer BGBG/GRGR"; break; |
|---|
| 1396 | + case V4L2_PIX_FMT_SGBRG14: descr = "14-bit Bayer GBGB/RGRG"; break; |
|---|
| 1397 | + case V4L2_PIX_FMT_SGRBG14: descr = "14-bit Bayer GRGR/BGBG"; break; |
|---|
| 1398 | + case V4L2_PIX_FMT_SRGGB14: descr = "14-bit Bayer RGRG/GBGB"; break; |
|---|
| 1271 | 1399 | case V4L2_PIX_FMT_SBGGR14P: descr = "14-bit Bayer BGBG/GRGR Packed"; break; |
|---|
| 1272 | 1400 | case V4L2_PIX_FMT_SGBRG14P: descr = "14-bit Bayer GBGB/RGRG Packed"; break; |
|---|
| 1273 | 1401 | case V4L2_PIX_FMT_SGRBG14P: descr = "14-bit Bayer GRGR/BGBG Packed"; break; |
|---|
| .. | .. |
|---|
| 1294 | 1422 | case V4L2_SDR_FMT_PCU16BE: descr = "Planar Complex U16BE"; break; |
|---|
| 1295 | 1423 | case V4L2_SDR_FMT_PCU18BE: descr = "Planar Complex U18BE"; break; |
|---|
| 1296 | 1424 | case V4L2_SDR_FMT_PCU20BE: descr = "Planar Complex U20BE"; break; |
|---|
| 1297 | | - case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit signed deltas"; break; |
|---|
| 1298 | | - case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit signed deltas"; break; |
|---|
| 1299 | | - case V4L2_TCH_FMT_TU16: descr = "16-bit unsigned touch data"; break; |
|---|
| 1300 | | - case V4L2_TCH_FMT_TU08: descr = "8-bit unsigned touch data"; break; |
|---|
| 1425 | + case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit Signed Deltas"; break; |
|---|
| 1426 | + case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit Signed Deltas"; break; |
|---|
| 1427 | + case V4L2_TCH_FMT_TU16: descr = "16-bit Unsigned Touch Data"; break; |
|---|
| 1428 | + case V4L2_TCH_FMT_TU08: descr = "8-bit Unsigned Touch Data"; break; |
|---|
| 1301 | 1429 | case V4L2_META_FMT_VSP1_HGO: descr = "R-Car VSP1 1-D Histogram"; break; |
|---|
| 1302 | 1430 | case V4L2_META_FMT_VSP1_HGT: descr = "R-Car VSP1 2-D Histogram"; break; |
|---|
| 1303 | | - case V4L2_META_FMT_UVC: descr = "UVC payload header metadata"; break; |
|---|
| 1304 | | - case V4L2_PIX_FMT_NV12_UBWC: |
|---|
| 1305 | | - descr = "NV12 UBWC"; break; |
|---|
| 1306 | | - case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS: |
|---|
| 1307 | | - descr = "Y/CbCr 4:2:0 P10 Venus"; break; |
|---|
| 1308 | | - case V4L2_PIX_FMT_NV12_TP10_UBWC: |
|---|
| 1309 | | - descr = "Y/CbCr 4:2:0 TP10 UBWC"; break; |
|---|
| 1310 | | - case V4L2_PIX_FMT_NV12_512: |
|---|
| 1311 | | - descr = "Y/CbCr 4:2:0 (512 align)"; break; |
|---|
| 1312 | | - case V4L2_META_FMT_RK_ISP1_PARAMS: |
|---|
| 1313 | | - descr = "Rockchip ISP1 3A params"; |
|---|
| 1314 | | - break; |
|---|
| 1315 | | - case V4L2_META_FMT_RK_ISP1_STAT_3A: |
|---|
| 1316 | | - descr = "Rockchip ISP1 3A statistics"; |
|---|
| 1317 | | - break; |
|---|
| 1431 | + case V4L2_META_FMT_UVC: descr = "UVC Payload Header Metadata"; break; |
|---|
| 1432 | + case V4L2_META_FMT_D4XX: descr = "Intel D4xx UVC Metadata"; break; |
|---|
| 1433 | + case V4L2_META_FMT_VIVID: descr = "Vivid Metadata"; break; |
|---|
| 1318 | 1434 | |
|---|
| 1319 | 1435 | default: |
|---|
| 1320 | 1436 | /* Compressed formats */ |
|---|
| .. | .. |
|---|
| 1328 | 1444 | case V4L2_PIX_FMT_H264: descr = "H.264"; break; |
|---|
| 1329 | 1445 | case V4L2_PIX_FMT_H264_NO_SC: descr = "H.264 (No Start Codes)"; break; |
|---|
| 1330 | 1446 | case V4L2_PIX_FMT_H264_MVC: descr = "H.264 MVC"; break; |
|---|
| 1447 | + case V4L2_PIX_FMT_H264_SLICE: descr = "H.264 Parsed Slice Data"; break; |
|---|
| 1331 | 1448 | case V4L2_PIX_FMT_H263: descr = "H.263"; break; |
|---|
| 1332 | 1449 | case V4L2_PIX_FMT_MPEG1: descr = "MPEG-1 ES"; break; |
|---|
| 1333 | 1450 | case V4L2_PIX_FMT_MPEG2: descr = "MPEG-2 ES"; break; |
|---|
| 1334 | | - case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 part 2 ES"; break; |
|---|
| 1451 | + case V4L2_PIX_FMT_MPEG2_SLICE: descr = "MPEG-2 Parsed Slice Data"; break; |
|---|
| 1452 | + case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 Part 2 ES"; break; |
|---|
| 1335 | 1453 | case V4L2_PIX_FMT_XVID: descr = "Xvid"; break; |
|---|
| 1336 | 1454 | case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break; |
|---|
| 1337 | 1455 | case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break; |
|---|
| 1338 | 1456 | case V4L2_PIX_FMT_VP8: descr = "VP8"; break; |
|---|
| 1457 | + case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; |
|---|
| 1339 | 1458 | case V4L2_PIX_FMT_VP9: descr = "VP9"; break; |
|---|
| 1340 | 1459 | case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ |
|---|
| 1460 | + case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; |
|---|
| 1341 | 1461 | case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ |
|---|
| 1462 | + case V4L2_PIX_FMT_FWHT_STATELESS: descr = "FWHT Stateless"; break; /* used in vicodec */ |
|---|
| 1342 | 1463 | case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break; |
|---|
| 1343 | 1464 | case V4L2_PIX_FMT_WNVA: descr = "WNVA"; break; |
|---|
| 1344 | 1465 | case V4L2_PIX_FMT_SN9C10X: descr = "GSPCA SN9C10X"; break; |
|---|
| .. | .. |
|---|
| 1358 | 1479 | case V4L2_PIX_FMT_SE401: descr = "GSPCA SE401"; break; |
|---|
| 1359 | 1480 | case V4L2_PIX_FMT_S5C_UYVY_JPG: descr = "S5C73MX interleaved UYVY/JPEG"; break; |
|---|
| 1360 | 1481 | case V4L2_PIX_FMT_MT21C: descr = "Mediatek Compressed Format"; break; |
|---|
| 1361 | | - case V4L2_PIX_FMT_FBC2: descr = "Rockchip yuv422sp fbc encoder"; break; |
|---|
| 1362 | | - case V4L2_PIX_FMT_FBC0: descr = "Rockchip yuv420sp fbc encoder"; break; |
|---|
| 1363 | | - case V4L2_PIX_FMT_FBCG: descr = "Rockchip fbc gain"; break; |
|---|
| 1364 | | - case V4l2_PIX_FMT_EBD8: descr = "Embedded data 8-bit"; break; |
|---|
| 1365 | | - case V4l2_PIX_FMT_SPD16: descr = "Shield pix data 16-bit"; break; |
|---|
| 1482 | + case V4L2_PIX_FMT_SUNXI_TILED_NV12: descr = "Sunxi Tiled NV12 Format"; break; |
|---|
| 1366 | 1483 | default: |
|---|
| 1367 | | - WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat); |
|---|
| 1484 | + trace_android_vh_fill_ext_fmtdesc(fmt, &descr); |
|---|
| 1485 | + if (descr) |
|---|
| 1486 | + break; |
|---|
| 1368 | 1487 | if (fmt->description[0]) |
|---|
| 1369 | 1488 | return; |
|---|
| 1489 | + WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat); |
|---|
| 1370 | 1490 | flags = 0; |
|---|
| 1371 | 1491 | snprintf(fmt->description, sz, "%c%c%c%c%s", |
|---|
| 1372 | 1492 | (char)(fmt->pixelformat & 0x7f), |
|---|
| 1373 | 1493 | (char)((fmt->pixelformat >> 8) & 0x7f), |
|---|
| 1374 | 1494 | (char)((fmt->pixelformat >> 16) & 0x7f), |
|---|
| 1375 | 1495 | (char)((fmt->pixelformat >> 24) & 0x7f), |
|---|
| 1376 | | - (fmt->pixelformat & (1 << 31)) ? "-BE" : ""); |
|---|
| 1496 | + (fmt->pixelformat & (1UL << 31)) ? "-BE" : ""); |
|---|
| 1377 | 1497 | break; |
|---|
| 1378 | 1498 | } |
|---|
| 1379 | 1499 | } |
|---|
| 1380 | 1500 | |
|---|
| 1381 | 1501 | if (descr) |
|---|
| 1382 | | - WARN_ON(strlcpy(fmt->description, descr, sz) >= sz); |
|---|
| 1383 | | - fmt->flags = flags; |
|---|
| 1502 | + WARN_ON(strscpy(fmt->description, descr, sz) < 0); |
|---|
| 1503 | + fmt->flags |= flags; |
|---|
| 1384 | 1504 | } |
|---|
| 1385 | 1505 | |
|---|
| 1386 | 1506 | static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, |
|---|
| 1387 | 1507 | struct file *file, void *fh, void *arg) |
|---|
| 1388 | 1508 | { |
|---|
| 1509 | + struct video_device *vdev = video_devdata(file); |
|---|
| 1389 | 1510 | struct v4l2_fmtdesc *p = arg; |
|---|
| 1390 | 1511 | int ret = check_fmt(file, p->type); |
|---|
| 1512 | + u32 mbus_code; |
|---|
| 1513 | + u32 cap_mask; |
|---|
| 1391 | 1514 | |
|---|
| 1392 | 1515 | if (ret) |
|---|
| 1393 | 1516 | return ret; |
|---|
| 1394 | 1517 | ret = -EINVAL; |
|---|
| 1395 | 1518 | |
|---|
| 1519 | + if (!(vdev->device_caps & V4L2_CAP_IO_MC)) |
|---|
| 1520 | + p->mbus_code = 0; |
|---|
| 1521 | + |
|---|
| 1522 | + mbus_code = p->mbus_code; |
|---|
| 1523 | + CLEAR_AFTER_FIELD(p, type); |
|---|
| 1524 | + p->mbus_code = mbus_code; |
|---|
| 1525 | + |
|---|
| 1396 | 1526 | switch (p->type) { |
|---|
| 1397 | 1527 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
|---|
| 1528 | + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
|---|
| 1529 | + cap_mask = V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
|---|
| 1530 | + V4L2_CAP_VIDEO_M2M_MPLANE; |
|---|
| 1531 | + if (!!(vdev->device_caps & cap_mask) != |
|---|
| 1532 | + (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) |
|---|
| 1533 | + break; |
|---|
| 1534 | + |
|---|
| 1398 | 1535 | if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) |
|---|
| 1399 | 1536 | break; |
|---|
| 1400 | 1537 | ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); |
|---|
| 1401 | | - break; |
|---|
| 1402 | | - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
|---|
| 1403 | | - if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) |
|---|
| 1404 | | - break; |
|---|
| 1405 | | - ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); |
|---|
| 1406 | 1538 | break; |
|---|
| 1407 | 1539 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
|---|
| 1408 | 1540 | if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) |
|---|
| .. | .. |
|---|
| 1410 | 1542 | ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); |
|---|
| 1411 | 1543 | break; |
|---|
| 1412 | 1544 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: |
|---|
| 1545 | + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
|---|
| 1546 | + cap_mask = V4L2_CAP_VIDEO_OUTPUT_MPLANE | |
|---|
| 1547 | + V4L2_CAP_VIDEO_M2M_MPLANE; |
|---|
| 1548 | + if (!!(vdev->device_caps & cap_mask) != |
|---|
| 1549 | + (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) |
|---|
| 1550 | + break; |
|---|
| 1551 | + |
|---|
| 1413 | 1552 | if (unlikely(!ops->vidioc_enum_fmt_vid_out)) |
|---|
| 1414 | 1553 | break; |
|---|
| 1415 | 1554 | ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg); |
|---|
| 1416 | | - break; |
|---|
| 1417 | | - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
|---|
| 1418 | | - if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) |
|---|
| 1419 | | - break; |
|---|
| 1420 | | - ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); |
|---|
| 1421 | 1555 | break; |
|---|
| 1422 | 1556 | case V4L2_BUF_TYPE_SDR_CAPTURE: |
|---|
| 1423 | 1557 | if (unlikely(!ops->vidioc_enum_fmt_sdr_cap)) |
|---|
| .. | .. |
|---|
| 1547 | 1681 | struct v4l2_format *p = arg; |
|---|
| 1548 | 1682 | struct video_device *vfd = video_devdata(file); |
|---|
| 1549 | 1683 | int ret = check_fmt(file, p->type); |
|---|
| 1684 | + unsigned int i; |
|---|
| 1550 | 1685 | |
|---|
| 1551 | 1686 | if (ret) |
|---|
| 1552 | 1687 | return ret; |
|---|
| .. | .. |
|---|
| 1570 | 1705 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
|---|
| 1571 | 1706 | if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) |
|---|
| 1572 | 1707 | break; |
|---|
| 1573 | | - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); |
|---|
| 1708 | + clear_reserved(p); |
|---|
| 1709 | + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) |
|---|
| 1710 | + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], |
|---|
| 1711 | + bytesperline); |
|---|
| 1574 | 1712 | return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); |
|---|
| 1575 | 1713 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
|---|
| 1576 | 1714 | if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) |
|---|
| .. | .. |
|---|
| 1598 | 1736 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
|---|
| 1599 | 1737 | if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) |
|---|
| 1600 | 1738 | break; |
|---|
| 1601 | | - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); |
|---|
| 1739 | + clear_reserved(p); |
|---|
| 1740 | + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) |
|---|
| 1741 | + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], |
|---|
| 1742 | + bytesperline); |
|---|
| 1602 | 1743 | return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); |
|---|
| 1603 | 1744 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: |
|---|
| 1604 | 1745 | if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) |
|---|
| .. | .. |
|---|
| 1643 | 1784 | struct file *file, void *fh, void *arg) |
|---|
| 1644 | 1785 | { |
|---|
| 1645 | 1786 | struct v4l2_format *p = arg; |
|---|
| 1787 | + struct video_device *vfd = video_devdata(file); |
|---|
| 1646 | 1788 | int ret = check_fmt(file, p->type); |
|---|
| 1789 | + unsigned int i; |
|---|
| 1647 | 1790 | |
|---|
| 1648 | 1791 | if (ret) |
|---|
| 1649 | 1792 | return ret; |
|---|
| .. | .. |
|---|
| 1658 | 1801 | ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); |
|---|
| 1659 | 1802 | /* just in case the driver zeroed it again */ |
|---|
| 1660 | 1803 | p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; |
|---|
| 1804 | + if (vfd->vfl_type == VFL_TYPE_TOUCH) |
|---|
| 1805 | + v4l_pix_format_touch(&p->fmt.pix); |
|---|
| 1661 | 1806 | return ret; |
|---|
| 1662 | 1807 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
|---|
| 1663 | 1808 | if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) |
|---|
| 1664 | 1809 | break; |
|---|
| 1665 | | - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); |
|---|
| 1810 | + clear_reserved(p); |
|---|
| 1811 | + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) |
|---|
| 1812 | + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], |
|---|
| 1813 | + bytesperline); |
|---|
| 1666 | 1814 | return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); |
|---|
| 1667 | 1815 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
|---|
| 1668 | 1816 | if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) |
|---|
| .. | .. |
|---|
| 1690 | 1838 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
|---|
| 1691 | 1839 | if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) |
|---|
| 1692 | 1840 | break; |
|---|
| 1693 | | - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); |
|---|
| 1841 | + clear_reserved(p); |
|---|
| 1842 | + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) |
|---|
| 1843 | + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], |
|---|
| 1844 | + bytesperline); |
|---|
| 1694 | 1845 | return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); |
|---|
| 1695 | 1846 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: |
|---|
| 1696 | 1847 | if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) |
|---|
| .. | .. |
|---|
| 1924 | 2075 | if (ret) |
|---|
| 1925 | 2076 | return ret; |
|---|
| 1926 | 2077 | |
|---|
| 1927 | | - CLEAR_AFTER_FIELD(p, memory); |
|---|
| 2078 | + CLEAR_AFTER_FIELD(p, capabilities); |
|---|
| 1928 | 2079 | |
|---|
| 1929 | 2080 | return ops->vidioc_reqbufs(file, fh, p); |
|---|
| 1930 | 2081 | } |
|---|
| .. | .. |
|---|
| 1965 | 2116 | if (ret) |
|---|
| 1966 | 2117 | return ret; |
|---|
| 1967 | 2118 | |
|---|
| 1968 | | - CLEAR_AFTER_FIELD(create, format); |
|---|
| 2119 | + CLEAR_AFTER_FIELD(create, capabilities); |
|---|
| 1969 | 2120 | |
|---|
| 1970 | 2121 | v4l_sanitize_format(&create->format); |
|---|
| 1971 | 2122 | |
|---|
| .. | .. |
|---|
| 1990 | 2141 | static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, |
|---|
| 1991 | 2142 | struct file *file, void *fh, void *arg) |
|---|
| 1992 | 2143 | { |
|---|
| 2144 | + struct video_device *vfd = video_devdata(file); |
|---|
| 1993 | 2145 | struct v4l2_streamparm *p = arg; |
|---|
| 1994 | 2146 | v4l2_std_id std; |
|---|
| 1995 | 2147 | int ret = check_fmt(file, p->type); |
|---|
| .. | .. |
|---|
| 2001 | 2153 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && |
|---|
| 2002 | 2154 | p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
|---|
| 2003 | 2155 | return -EINVAL; |
|---|
| 2004 | | - p->parm.capture.readbuffers = 2; |
|---|
| 2156 | + if (vfd->device_caps & V4L2_CAP_READWRITE) |
|---|
| 2157 | + p->parm.capture.readbuffers = 2; |
|---|
| 2005 | 2158 | ret = ops->vidioc_g_std(file, fh, &std); |
|---|
| 2006 | 2159 | if (ret == 0) |
|---|
| 2007 | 2160 | v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); |
|---|
| .. | .. |
|---|
| 2107 | 2260 | ctrls.controls = &ctrl; |
|---|
| 2108 | 2261 | ctrl.id = p->id; |
|---|
| 2109 | 2262 | ctrl.value = p->value; |
|---|
| 2110 | | - if (check_ext_ctrls(&ctrls, 1)) { |
|---|
| 2263 | + if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) { |
|---|
| 2111 | 2264 | int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); |
|---|
| 2112 | 2265 | |
|---|
| 2113 | 2266 | if (ret == 0) |
|---|
| .. | .. |
|---|
| 2126 | 2279 | test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; |
|---|
| 2127 | 2280 | struct v4l2_ext_controls ctrls; |
|---|
| 2128 | 2281 | struct v4l2_ext_control ctrl; |
|---|
| 2282 | + int ret; |
|---|
| 2129 | 2283 | |
|---|
| 2130 | 2284 | if (vfh && vfh->ctrl_handler) |
|---|
| 2131 | 2285 | return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); |
|---|
| .. | .. |
|---|
| 2141 | 2295 | ctrls.controls = &ctrl; |
|---|
| 2142 | 2296 | ctrl.id = p->id; |
|---|
| 2143 | 2297 | ctrl.value = p->value; |
|---|
| 2144 | | - if (check_ext_ctrls(&ctrls, 1)) |
|---|
| 2145 | | - return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); |
|---|
| 2146 | | - return -EINVAL; |
|---|
| 2298 | + if (!check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) |
|---|
| 2299 | + return -EINVAL; |
|---|
| 2300 | + ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); |
|---|
| 2301 | + p->value = ctrl.value; |
|---|
| 2302 | + return ret; |
|---|
| 2147 | 2303 | } |
|---|
| 2148 | 2304 | |
|---|
| 2149 | 2305 | static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, |
|---|
| .. | .. |
|---|
| 2156 | 2312 | |
|---|
| 2157 | 2313 | p->error_idx = p->count; |
|---|
| 2158 | 2314 | if (vfh && vfh->ctrl_handler) |
|---|
| 2159 | | - return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); |
|---|
| 2315 | + return v4l2_g_ext_ctrls(vfh->ctrl_handler, |
|---|
| 2316 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2160 | 2317 | if (vfd->ctrl_handler) |
|---|
| 2161 | | - return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); |
|---|
| 2318 | + return v4l2_g_ext_ctrls(vfd->ctrl_handler, |
|---|
| 2319 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2162 | 2320 | if (ops->vidioc_g_ext_ctrls == NULL) |
|---|
| 2163 | 2321 | return -ENOTTY; |
|---|
| 2164 | | - return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : |
|---|
| 2165 | | - -EINVAL; |
|---|
| 2322 | + return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? |
|---|
| 2323 | + ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL; |
|---|
| 2166 | 2324 | } |
|---|
| 2167 | 2325 | |
|---|
| 2168 | 2326 | static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, |
|---|
| .. | .. |
|---|
| 2175 | 2333 | |
|---|
| 2176 | 2334 | p->error_idx = p->count; |
|---|
| 2177 | 2335 | if (vfh && vfh->ctrl_handler) |
|---|
| 2178 | | - return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); |
|---|
| 2336 | + return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, |
|---|
| 2337 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2179 | 2338 | if (vfd->ctrl_handler) |
|---|
| 2180 | | - return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); |
|---|
| 2339 | + return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, |
|---|
| 2340 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2181 | 2341 | if (ops->vidioc_s_ext_ctrls == NULL) |
|---|
| 2182 | 2342 | return -ENOTTY; |
|---|
| 2183 | | - return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : |
|---|
| 2184 | | - -EINVAL; |
|---|
| 2343 | + return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? |
|---|
| 2344 | + ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL; |
|---|
| 2185 | 2345 | } |
|---|
| 2186 | 2346 | |
|---|
| 2187 | 2347 | static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, |
|---|
| .. | .. |
|---|
| 2194 | 2354 | |
|---|
| 2195 | 2355 | p->error_idx = p->count; |
|---|
| 2196 | 2356 | if (vfh && vfh->ctrl_handler) |
|---|
| 2197 | | - return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); |
|---|
| 2357 | + return v4l2_try_ext_ctrls(vfh->ctrl_handler, |
|---|
| 2358 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2198 | 2359 | if (vfd->ctrl_handler) |
|---|
| 2199 | | - return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); |
|---|
| 2360 | + return v4l2_try_ext_ctrls(vfd->ctrl_handler, |
|---|
| 2361 | + vfd, vfd->v4l2_dev->mdev, p); |
|---|
| 2200 | 2362 | if (ops->vidioc_try_ext_ctrls == NULL) |
|---|
| 2201 | 2363 | return -ENOTTY; |
|---|
| 2202 | | - return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : |
|---|
| 2203 | | - -EINVAL; |
|---|
| 2364 | + return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? |
|---|
| 2365 | + ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL; |
|---|
| 2204 | 2366 | } |
|---|
| 2205 | 2367 | |
|---|
| 2206 | 2368 | /* |
|---|
| .. | .. |
|---|
| 2247 | 2409 | static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, |
|---|
| 2248 | 2410 | struct file *file, void *fh, void *arg) |
|---|
| 2249 | 2411 | { |
|---|
| 2412 | + struct video_device *vfd = video_devdata(file); |
|---|
| 2250 | 2413 | struct v4l2_crop *p = arg; |
|---|
| 2251 | 2414 | struct v4l2_selection s = { |
|---|
| 2252 | 2415 | .type = p->type, |
|---|
| 2253 | 2416 | }; |
|---|
| 2254 | 2417 | int ret; |
|---|
| 2255 | 2418 | |
|---|
| 2256 | | - if (ops->vidioc_g_crop) |
|---|
| 2257 | | - return ops->vidioc_g_crop(file, fh, p); |
|---|
| 2258 | 2419 | /* simulate capture crop using selection api */ |
|---|
| 2259 | 2420 | |
|---|
| 2260 | 2421 | /* crop means compose for output devices */ |
|---|
| 2261 | 2422 | if (V4L2_TYPE_IS_OUTPUT(p->type)) |
|---|
| 2262 | | - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; |
|---|
| 2423 | + s.target = V4L2_SEL_TGT_COMPOSE; |
|---|
| 2263 | 2424 | else |
|---|
| 2264 | | - s.target = V4L2_SEL_TGT_CROP_ACTIVE; |
|---|
| 2425 | + s.target = V4L2_SEL_TGT_CROP; |
|---|
| 2426 | + |
|---|
| 2427 | + if (test_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags)) |
|---|
| 2428 | + s.target = s.target == V4L2_SEL_TGT_COMPOSE ? |
|---|
| 2429 | + V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE; |
|---|
| 2265 | 2430 | |
|---|
| 2266 | 2431 | ret = v4l_g_selection(ops, file, fh, &s); |
|---|
| 2267 | 2432 | |
|---|
| .. | .. |
|---|
| 2274 | 2439 | static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, |
|---|
| 2275 | 2440 | struct file *file, void *fh, void *arg) |
|---|
| 2276 | 2441 | { |
|---|
| 2442 | + struct video_device *vfd = video_devdata(file); |
|---|
| 2277 | 2443 | struct v4l2_crop *p = arg; |
|---|
| 2278 | 2444 | struct v4l2_selection s = { |
|---|
| 2279 | 2445 | .type = p->type, |
|---|
| 2280 | 2446 | .r = p->c, |
|---|
| 2281 | 2447 | }; |
|---|
| 2282 | 2448 | |
|---|
| 2283 | | - if (ops->vidioc_s_crop) |
|---|
| 2284 | | - return ops->vidioc_s_crop(file, fh, p); |
|---|
| 2285 | 2449 | /* simulate capture crop using selection api */ |
|---|
| 2286 | 2450 | |
|---|
| 2287 | 2451 | /* crop means compose for output devices */ |
|---|
| 2288 | 2452 | if (V4L2_TYPE_IS_OUTPUT(p->type)) |
|---|
| 2289 | | - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; |
|---|
| 2453 | + s.target = V4L2_SEL_TGT_COMPOSE; |
|---|
| 2290 | 2454 | else |
|---|
| 2291 | | - s.target = V4L2_SEL_TGT_CROP_ACTIVE; |
|---|
| 2455 | + s.target = V4L2_SEL_TGT_CROP; |
|---|
| 2456 | + |
|---|
| 2457 | + if (test_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags)) |
|---|
| 2458 | + s.target = s.target == V4L2_SEL_TGT_COMPOSE ? |
|---|
| 2459 | + V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE; |
|---|
| 2292 | 2460 | |
|---|
| 2293 | 2461 | return v4l_s_selection(ops, file, fh, &s); |
|---|
| 2294 | 2462 | } |
|---|
| .. | .. |
|---|
| 2296 | 2464 | static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, |
|---|
| 2297 | 2465 | struct file *file, void *fh, void *arg) |
|---|
| 2298 | 2466 | { |
|---|
| 2467 | + struct video_device *vfd = video_devdata(file); |
|---|
| 2299 | 2468 | struct v4l2_cropcap *p = arg; |
|---|
| 2300 | 2469 | struct v4l2_selection s = { .type = p->type }; |
|---|
| 2301 | 2470 | int ret = 0; |
|---|
| .. | .. |
|---|
| 2304 | 2473 | p->pixelaspect.numerator = 1; |
|---|
| 2305 | 2474 | p->pixelaspect.denominator = 1; |
|---|
| 2306 | 2475 | |
|---|
| 2476 | + if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
|---|
| 2477 | + s.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|---|
| 2478 | + else if (s.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 2479 | + s.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|---|
| 2480 | + |
|---|
| 2307 | 2481 | /* |
|---|
| 2308 | 2482 | * The determine_valid_ioctls() call already should ensure |
|---|
| 2309 | 2483 | * that this can never happen, but just in case... |
|---|
| 2310 | 2484 | */ |
|---|
| 2311 | | - if (WARN_ON(!ops->vidioc_cropcap && !ops->vidioc_g_selection)) |
|---|
| 2485 | + if (WARN_ON(!ops->vidioc_g_selection)) |
|---|
| 2312 | 2486 | return -ENOTTY; |
|---|
| 2313 | 2487 | |
|---|
| 2314 | | - if (ops->vidioc_cropcap) |
|---|
| 2315 | | - ret = ops->vidioc_cropcap(file, fh, p); |
|---|
| 2316 | | - |
|---|
| 2317 | | - if (!ops->vidioc_g_selection) |
|---|
| 2318 | | - return ret; |
|---|
| 2488 | + if (ops->vidioc_g_pixelaspect) |
|---|
| 2489 | + ret = ops->vidioc_g_pixelaspect(file, fh, s.type, |
|---|
| 2490 | + &p->pixelaspect); |
|---|
| 2319 | 2491 | |
|---|
| 2320 | 2492 | /* |
|---|
| 2321 | 2493 | * Ignore ENOTTY or ENOIOCTLCMD error returns, just use the |
|---|
| .. | .. |
|---|
| 2332 | 2504 | else |
|---|
| 2333 | 2505 | s.target = V4L2_SEL_TGT_CROP_BOUNDS; |
|---|
| 2334 | 2506 | |
|---|
| 2507 | + if (test_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags)) |
|---|
| 2508 | + s.target = s.target == V4L2_SEL_TGT_COMPOSE_BOUNDS ? |
|---|
| 2509 | + V4L2_SEL_TGT_CROP_BOUNDS : V4L2_SEL_TGT_COMPOSE_BOUNDS; |
|---|
| 2510 | + |
|---|
| 2335 | 2511 | ret = v4l_g_selection(ops, file, fh, &s); |
|---|
| 2336 | 2512 | if (ret) |
|---|
| 2337 | 2513 | return ret; |
|---|
| 2338 | 2514 | p->bounds = s.r; |
|---|
| 2339 | 2515 | |
|---|
| 2340 | 2516 | /* obtaining defrect */ |
|---|
| 2341 | | - if (V4L2_TYPE_IS_OUTPUT(p->type)) |
|---|
| 2517 | + if (s.target == V4L2_SEL_TGT_COMPOSE_BOUNDS) |
|---|
| 2342 | 2518 | s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; |
|---|
| 2343 | 2519 | else |
|---|
| 2344 | 2520 | s.target = V4L2_SEL_TGT_CROP_DEFAULT; |
|---|
| .. | .. |
|---|
| 2438 | 2614 | p->flags |= V4L2_CHIP_FL_WRITABLE; |
|---|
| 2439 | 2615 | if (ops->vidioc_g_register) |
|---|
| 2440 | 2616 | p->flags |= V4L2_CHIP_FL_READABLE; |
|---|
| 2441 | | - strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); |
|---|
| 2617 | + strscpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); |
|---|
| 2442 | 2618 | if (ops->vidioc_g_chip_info) |
|---|
| 2443 | 2619 | return ops->vidioc_g_chip_info(file, fh, arg); |
|---|
| 2444 | 2620 | if (p->match.addr) |
|---|
| .. | .. |
|---|
| 2455 | 2631 | p->flags |= V4L2_CHIP_FL_WRITABLE; |
|---|
| 2456 | 2632 | if (sd->ops->core && sd->ops->core->g_register) |
|---|
| 2457 | 2633 | p->flags |= V4L2_CHIP_FL_READABLE; |
|---|
| 2458 | | - strlcpy(p->name, sd->name, sizeof(p->name)); |
|---|
| 2634 | + strscpy(p->name, sd->name, sizeof(p->name)); |
|---|
| 2459 | 2635 | return 0; |
|---|
| 2460 | 2636 | } |
|---|
| 2461 | 2637 | break; |
|---|
| .. | .. |
|---|
| 2582 | 2758 | /* Zero struct from after the field to the end */ |
|---|
| 2583 | 2759 | #define INFO_FL_CLEAR(v4l2_struct, field) \ |
|---|
| 2584 | 2760 | ((offsetof(struct v4l2_struct, field) + \ |
|---|
| 2585 | | - sizeof(((struct v4l2_struct *)0)->field)) << 16) |
|---|
| 2761 | + sizeof_field(struct v4l2_struct, field)) << 16) |
|---|
| 2586 | 2762 | #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) |
|---|
| 2587 | 2763 | |
|---|
| 2588 | 2764 | #define DEFINE_V4L_STUB_FUNC(_vidioc) \ |
|---|
| .. | .. |
|---|
| 2608 | 2784 | DEFINE_V4L_STUB_FUNC(g_std) |
|---|
| 2609 | 2785 | DEFINE_V4L_STUB_FUNC(g_audio) |
|---|
| 2610 | 2786 | DEFINE_V4L_STUB_FUNC(s_audio) |
|---|
| 2611 | | -DEFINE_V4L_STUB_FUNC(g_input) |
|---|
| 2612 | 2787 | DEFINE_V4L_STUB_FUNC(g_edid) |
|---|
| 2613 | 2788 | DEFINE_V4L_STUB_FUNC(s_edid) |
|---|
| 2614 | | -DEFINE_V4L_STUB_FUNC(g_output) |
|---|
| 2615 | 2789 | DEFINE_V4L_STUB_FUNC(g_audout) |
|---|
| 2616 | 2790 | DEFINE_V4L_STUB_FUNC(s_audout) |
|---|
| 2617 | 2791 | DEFINE_V4L_STUB_FUNC(g_jpegcomp) |
|---|
| .. | .. |
|---|
| 2631 | 2805 | DEFINE_V4L_STUB_FUNC(query_dv_timings) |
|---|
| 2632 | 2806 | DEFINE_V4L_STUB_FUNC(dv_timings_cap) |
|---|
| 2633 | 2807 | |
|---|
| 2634 | | -static struct v4l2_ioctl_info v4l2_ioctls[] = { |
|---|
| 2808 | +static const struct v4l2_ioctl_info v4l2_ioctls[] = { |
|---|
| 2635 | 2809 | IOCTL_INFO(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), |
|---|
| 2636 | | - IOCTL_INFO(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), |
|---|
| 2810 | + IOCTL_INFO(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, 0), |
|---|
| 2637 | 2811 | IOCTL_INFO(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0), |
|---|
| 2638 | 2812 | IOCTL_INFO(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), |
|---|
| 2639 | 2813 | IOCTL_INFO(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), |
|---|
| .. | .. |
|---|
| 2660 | 2834 | IOCTL_INFO(VIDIOC_S_AUDIO, v4l_stub_s_audio, v4l_print_audio, INFO_FL_PRIO), |
|---|
| 2661 | 2835 | IOCTL_INFO(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), |
|---|
| 2662 | 2836 | IOCTL_INFO(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), |
|---|
| 2663 | | - IOCTL_INFO(VIDIOC_G_INPUT, v4l_stub_g_input, v4l_print_u32, 0), |
|---|
| 2837 | + IOCTL_INFO(VIDIOC_G_INPUT, v4l_g_input, v4l_print_u32, 0), |
|---|
| 2664 | 2838 | IOCTL_INFO(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), |
|---|
| 2665 | 2839 | IOCTL_INFO(VIDIOC_G_EDID, v4l_stub_g_edid, v4l_print_edid, INFO_FL_ALWAYS_COPY), |
|---|
| 2666 | 2840 | IOCTL_INFO(VIDIOC_S_EDID, v4l_stub_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_ALWAYS_COPY), |
|---|
| 2667 | | - IOCTL_INFO(VIDIOC_G_OUTPUT, v4l_stub_g_output, v4l_print_u32, 0), |
|---|
| 2841 | + IOCTL_INFO(VIDIOC_G_OUTPUT, v4l_g_output, v4l_print_u32, 0), |
|---|
| 2668 | 2842 | IOCTL_INFO(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), |
|---|
| 2669 | 2843 | IOCTL_INFO(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), |
|---|
| 2670 | 2844 | IOCTL_INFO(VIDIOC_G_AUDOUT, v4l_stub_g_audout, v4l_print_audioout, 0), |
|---|
| .. | .. |
|---|
| 2724 | 2898 | return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; |
|---|
| 2725 | 2899 | } |
|---|
| 2726 | 2900 | |
|---|
| 2727 | | -#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) |
|---|
| 2728 | | -static bool v4l2_ioctl_m2m_queue_is_output(unsigned int cmd, void *arg) |
|---|
| 2729 | | -{ |
|---|
| 2730 | | - switch (cmd) { |
|---|
| 2731 | | - case VIDIOC_CREATE_BUFS: { |
|---|
| 2732 | | - struct v4l2_create_buffers *cbufs = arg; |
|---|
| 2733 | | - |
|---|
| 2734 | | - return V4L2_TYPE_IS_OUTPUT(cbufs->format.type); |
|---|
| 2735 | | - } |
|---|
| 2736 | | - case VIDIOC_REQBUFS: { |
|---|
| 2737 | | - struct v4l2_requestbuffers *rbufs = arg; |
|---|
| 2738 | | - |
|---|
| 2739 | | - return V4L2_TYPE_IS_OUTPUT(rbufs->type); |
|---|
| 2740 | | - } |
|---|
| 2741 | | - case VIDIOC_QBUF: |
|---|
| 2742 | | - case VIDIOC_DQBUF: |
|---|
| 2743 | | - case VIDIOC_QUERYBUF: |
|---|
| 2744 | | - case VIDIOC_PREPARE_BUF: { |
|---|
| 2745 | | - struct v4l2_buffer *buf = arg; |
|---|
| 2746 | | - |
|---|
| 2747 | | - return V4L2_TYPE_IS_OUTPUT(buf->type); |
|---|
| 2748 | | - } |
|---|
| 2749 | | - case VIDIOC_EXPBUF: { |
|---|
| 2750 | | - struct v4l2_exportbuffer *expbuf = arg; |
|---|
| 2751 | | - |
|---|
| 2752 | | - return V4L2_TYPE_IS_OUTPUT(expbuf->type); |
|---|
| 2753 | | - } |
|---|
| 2754 | | - case VIDIOC_STREAMON: |
|---|
| 2755 | | - case VIDIOC_STREAMOFF: { |
|---|
| 2756 | | - int *type = arg; |
|---|
| 2757 | | - |
|---|
| 2758 | | - return V4L2_TYPE_IS_OUTPUT(*type); |
|---|
| 2759 | | - } |
|---|
| 2760 | | - default: |
|---|
| 2761 | | - return false; |
|---|
| 2762 | | - } |
|---|
| 2763 | | -} |
|---|
| 2764 | | -#endif |
|---|
| 2765 | | - |
|---|
| 2766 | 2901 | static struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, |
|---|
| 2767 | 2902 | struct v4l2_fh *vfh, unsigned int cmd, |
|---|
| 2768 | 2903 | void *arg) |
|---|
| 2769 | 2904 | { |
|---|
| 2770 | 2905 | if (_IOC_NR(cmd) >= V4L2_IOCTLS) |
|---|
| 2771 | 2906 | return vdev->lock; |
|---|
| 2772 | | -#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) |
|---|
| 2773 | 2907 | if (vfh && vfh->m2m_ctx && |
|---|
| 2774 | 2908 | (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) { |
|---|
| 2775 | | - bool is_output = v4l2_ioctl_m2m_queue_is_output(cmd, arg); |
|---|
| 2776 | | - struct v4l2_m2m_queue_ctx *ctx = is_output ? |
|---|
| 2777 | | - &vfh->m2m_ctx->out_q_ctx : &vfh->m2m_ctx->cap_q_ctx; |
|---|
| 2778 | | - |
|---|
| 2779 | | - if (ctx->q.lock) |
|---|
| 2780 | | - return ctx->q.lock; |
|---|
| 2909 | + if (vfh->m2m_ctx->q_lock) |
|---|
| 2910 | + return vfh->m2m_ctx->q_lock; |
|---|
| 2781 | 2911 | } |
|---|
| 2782 | | -#endif |
|---|
| 2783 | 2912 | if (vdev->queue && vdev->queue->lock && |
|---|
| 2784 | 2913 | (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) |
|---|
| 2785 | 2914 | return vdev->queue->lock; |
|---|
| .. | .. |
|---|
| 2827 | 2956 | unsigned int cmd, void *arg) |
|---|
| 2828 | 2957 | { |
|---|
| 2829 | 2958 | struct video_device *vfd = video_devdata(file); |
|---|
| 2959 | + struct mutex *req_queue_lock = NULL; |
|---|
| 2830 | 2960 | struct mutex *lock; /* ioctl serialization mutex */ |
|---|
| 2831 | 2961 | const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; |
|---|
| 2832 | 2962 | bool write_only = false; |
|---|
| .. | .. |
|---|
| 2846 | 2976 | if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) |
|---|
| 2847 | 2977 | vfh = file->private_data; |
|---|
| 2848 | 2978 | |
|---|
| 2979 | + /* |
|---|
| 2980 | + * We need to serialize streamon/off with queueing new requests. |
|---|
| 2981 | + * These ioctls may trigger the cancellation of a streaming |
|---|
| 2982 | + * operation, and that should not be mixed with queueing a new |
|---|
| 2983 | + * request at the same time. |
|---|
| 2984 | + */ |
|---|
| 2985 | + if (v4l2_device_supports_requests(vfd->v4l2_dev) && |
|---|
| 2986 | + (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) { |
|---|
| 2987 | + req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex; |
|---|
| 2988 | + |
|---|
| 2989 | + if (mutex_lock_interruptible(req_queue_lock)) |
|---|
| 2990 | + return -ERESTARTSYS; |
|---|
| 2991 | + } |
|---|
| 2992 | + |
|---|
| 2849 | 2993 | lock = v4l2_ioctl_get_lock(vfd, vfh, cmd, arg); |
|---|
| 2850 | 2994 | |
|---|
| 2851 | | - if (lock && mutex_lock_interruptible(lock)) |
|---|
| 2995 | + if (lock && mutex_lock_interruptible(lock)) { |
|---|
| 2996 | + if (req_queue_lock) |
|---|
| 2997 | + mutex_unlock(req_queue_lock); |
|---|
| 2852 | 2998 | return -ERESTARTSYS; |
|---|
| 2999 | + } |
|---|
| 2853 | 3000 | |
|---|
| 2854 | 3001 | if (!video_is_registered(vfd)) { |
|---|
| 2855 | 3002 | ret = -ENODEV; |
|---|
| .. | .. |
|---|
| 2908 | 3055 | unlock: |
|---|
| 2909 | 3056 | if (lock) |
|---|
| 2910 | 3057 | mutex_unlock(lock); |
|---|
| 3058 | + if (req_queue_lock) |
|---|
| 3059 | + mutex_unlock(req_queue_lock); |
|---|
| 2911 | 3060 | return ret; |
|---|
| 2912 | 3061 | } |
|---|
| 2913 | 3062 | |
|---|
| .. | .. |
|---|
| 2976 | 3125 | return ret; |
|---|
| 2977 | 3126 | } |
|---|
| 2978 | 3127 | |
|---|
| 3128 | +static unsigned int video_translate_cmd(unsigned int cmd) |
|---|
| 3129 | +{ |
|---|
| 3130 | + switch (cmd) { |
|---|
| 3131 | +#ifdef CONFIG_COMPAT_32BIT_TIME |
|---|
| 3132 | + case VIDIOC_DQEVENT_TIME32: |
|---|
| 3133 | + return VIDIOC_DQEVENT; |
|---|
| 3134 | + case VIDIOC_QUERYBUF_TIME32: |
|---|
| 3135 | + return VIDIOC_QUERYBUF; |
|---|
| 3136 | + case VIDIOC_QBUF_TIME32: |
|---|
| 3137 | + return VIDIOC_QBUF; |
|---|
| 3138 | + case VIDIOC_DQBUF_TIME32: |
|---|
| 3139 | + return VIDIOC_DQBUF; |
|---|
| 3140 | + case VIDIOC_PREPARE_BUF_TIME32: |
|---|
| 3141 | + return VIDIOC_PREPARE_BUF; |
|---|
| 3142 | +#endif |
|---|
| 3143 | + } |
|---|
| 3144 | + |
|---|
| 3145 | + return cmd; |
|---|
| 3146 | +} |
|---|
| 3147 | + |
|---|
| 3148 | +static int video_get_user(void __user *arg, void *parg, unsigned int cmd, |
|---|
| 3149 | + bool *always_copy) |
|---|
| 3150 | +{ |
|---|
| 3151 | + unsigned int n = _IOC_SIZE(cmd); |
|---|
| 3152 | + |
|---|
| 3153 | + if (!(_IOC_DIR(cmd) & _IOC_WRITE)) { |
|---|
| 3154 | + /* read-only ioctl */ |
|---|
| 3155 | + memset(parg, 0, n); |
|---|
| 3156 | + return 0; |
|---|
| 3157 | + } |
|---|
| 3158 | + |
|---|
| 3159 | + switch (cmd) { |
|---|
| 3160 | +#ifdef CONFIG_COMPAT_32BIT_TIME |
|---|
| 3161 | + case VIDIOC_QUERYBUF_TIME32: |
|---|
| 3162 | + case VIDIOC_QBUF_TIME32: |
|---|
| 3163 | + case VIDIOC_DQBUF_TIME32: |
|---|
| 3164 | + case VIDIOC_PREPARE_BUF_TIME32: { |
|---|
| 3165 | + struct v4l2_buffer_time32 vb32; |
|---|
| 3166 | + struct v4l2_buffer *vb = parg; |
|---|
| 3167 | + |
|---|
| 3168 | + if (copy_from_user(&vb32, arg, sizeof(vb32))) |
|---|
| 3169 | + return -EFAULT; |
|---|
| 3170 | + |
|---|
| 3171 | + *vb = (struct v4l2_buffer) { |
|---|
| 3172 | + .index = vb32.index, |
|---|
| 3173 | + .type = vb32.type, |
|---|
| 3174 | + .bytesused = vb32.bytesused, |
|---|
| 3175 | + .flags = vb32.flags, |
|---|
| 3176 | + .field = vb32.field, |
|---|
| 3177 | + .timestamp.tv_sec = vb32.timestamp.tv_sec, |
|---|
| 3178 | + .timestamp.tv_usec = vb32.timestamp.tv_usec, |
|---|
| 3179 | + .timecode = vb32.timecode, |
|---|
| 3180 | + .sequence = vb32.sequence, |
|---|
| 3181 | + .memory = vb32.memory, |
|---|
| 3182 | + .m.userptr = vb32.m.userptr, |
|---|
| 3183 | + .length = vb32.length, |
|---|
| 3184 | + .request_fd = vb32.request_fd, |
|---|
| 3185 | +#if defined(CONFIG_ARCH_ROCKCHIP) && IS_ENABLED(CONFIG_USB_F_UVC) |
|---|
| 3186 | + .reserved2 = vb32.reserved2, |
|---|
| 3187 | +#endif |
|---|
| 3188 | + }; |
|---|
| 3189 | + |
|---|
| 3190 | + if (cmd == VIDIOC_QUERYBUF_TIME32) |
|---|
| 3191 | + vb->request_fd = 0; |
|---|
| 3192 | + |
|---|
| 3193 | + break; |
|---|
| 3194 | + } |
|---|
| 3195 | +#endif |
|---|
| 3196 | + default: |
|---|
| 3197 | + /* |
|---|
| 3198 | + * In some cases, only a few fields are used as input, |
|---|
| 3199 | + * i.e. when the app sets "index" and then the driver |
|---|
| 3200 | + * fills in the rest of the structure for the thing |
|---|
| 3201 | + * with that index. We only need to copy up the first |
|---|
| 3202 | + * non-input field. |
|---|
| 3203 | + */ |
|---|
| 3204 | + if (v4l2_is_known_ioctl(cmd)) { |
|---|
| 3205 | + u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; |
|---|
| 3206 | + |
|---|
| 3207 | + if (flags & INFO_FL_CLEAR_MASK) |
|---|
| 3208 | + n = (flags & INFO_FL_CLEAR_MASK) >> 16; |
|---|
| 3209 | + *always_copy = flags & INFO_FL_ALWAYS_COPY; |
|---|
| 3210 | + trace_android_vh_clear_mask_adjust(v4l2_ioctls[_IOC_NR(cmd)].ioctl, &n); |
|---|
| 3211 | + } |
|---|
| 3212 | + |
|---|
| 3213 | + if (copy_from_user(parg, (void __user *)arg, n)) |
|---|
| 3214 | + return -EFAULT; |
|---|
| 3215 | + |
|---|
| 3216 | + /* zero out anything we don't copy from userspace */ |
|---|
| 3217 | + if (n < _IOC_SIZE(cmd)) |
|---|
| 3218 | + memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); |
|---|
| 3219 | + break; |
|---|
| 3220 | + } |
|---|
| 3221 | + |
|---|
| 3222 | + return 0; |
|---|
| 3223 | +} |
|---|
| 3224 | + |
|---|
| 3225 | +static int video_put_user(void __user *arg, void *parg, unsigned int cmd) |
|---|
| 3226 | +{ |
|---|
| 3227 | + if (!(_IOC_DIR(cmd) & _IOC_READ)) |
|---|
| 3228 | + return 0; |
|---|
| 3229 | + |
|---|
| 3230 | + switch (cmd) { |
|---|
| 3231 | +#ifdef CONFIG_COMPAT_32BIT_TIME |
|---|
| 3232 | + case VIDIOC_DQEVENT_TIME32: { |
|---|
| 3233 | + struct v4l2_event *ev = parg; |
|---|
| 3234 | + struct v4l2_event_time32 ev32; |
|---|
| 3235 | + |
|---|
| 3236 | + memset(&ev32, 0, sizeof(ev32)); |
|---|
| 3237 | + |
|---|
| 3238 | + ev32.type = ev->type; |
|---|
| 3239 | + ev32.pending = ev->pending; |
|---|
| 3240 | + ev32.sequence = ev->sequence; |
|---|
| 3241 | + ev32.timestamp.tv_sec = ev->timestamp.tv_sec; |
|---|
| 3242 | + ev32.timestamp.tv_nsec = ev->timestamp.tv_nsec; |
|---|
| 3243 | + ev32.id = ev->id; |
|---|
| 3244 | + |
|---|
| 3245 | + memcpy(&ev32.u, &ev->u, sizeof(ev->u)); |
|---|
| 3246 | + memcpy(&ev32.reserved, &ev->reserved, sizeof(ev->reserved)); |
|---|
| 3247 | + |
|---|
| 3248 | + if (copy_to_user(arg, &ev32, sizeof(ev32))) |
|---|
| 3249 | + return -EFAULT; |
|---|
| 3250 | + break; |
|---|
| 3251 | + } |
|---|
| 3252 | + case VIDIOC_QUERYBUF_TIME32: |
|---|
| 3253 | + case VIDIOC_QBUF_TIME32: |
|---|
| 3254 | + case VIDIOC_DQBUF_TIME32: |
|---|
| 3255 | + case VIDIOC_PREPARE_BUF_TIME32: { |
|---|
| 3256 | + struct v4l2_buffer *vb = parg; |
|---|
| 3257 | + struct v4l2_buffer_time32 vb32; |
|---|
| 3258 | + |
|---|
| 3259 | + memset(&vb32, 0, sizeof(vb32)); |
|---|
| 3260 | + |
|---|
| 3261 | + vb32.index = vb->index; |
|---|
| 3262 | + vb32.type = vb->type; |
|---|
| 3263 | + vb32.bytesused = vb->bytesused; |
|---|
| 3264 | + vb32.flags = vb->flags; |
|---|
| 3265 | + vb32.field = vb->field; |
|---|
| 3266 | + vb32.timestamp.tv_sec = vb->timestamp.tv_sec; |
|---|
| 3267 | + vb32.timestamp.tv_usec = vb->timestamp.tv_usec; |
|---|
| 3268 | + vb32.timecode = vb->timecode; |
|---|
| 3269 | + vb32.sequence = vb->sequence; |
|---|
| 3270 | + vb32.memory = vb->memory; |
|---|
| 3271 | + vb32.m.userptr = vb->m.userptr; |
|---|
| 3272 | + vb32.length = vb->length; |
|---|
| 3273 | + vb32.request_fd = vb->request_fd; |
|---|
| 3274 | + |
|---|
| 3275 | + if (copy_to_user(arg, &vb32, sizeof(vb32))) |
|---|
| 3276 | + return -EFAULT; |
|---|
| 3277 | + break; |
|---|
| 3278 | + } |
|---|
| 3279 | +#endif |
|---|
| 3280 | + default: |
|---|
| 3281 | + /* Copy results into user buffer */ |
|---|
| 3282 | + if (copy_to_user(arg, parg, _IOC_SIZE(cmd))) |
|---|
| 3283 | + return -EFAULT; |
|---|
| 3284 | + break; |
|---|
| 3285 | + } |
|---|
| 3286 | + |
|---|
| 3287 | + return 0; |
|---|
| 3288 | +} |
|---|
| 3289 | + |
|---|
| 2979 | 3290 | long |
|---|
| 2980 | | -video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, |
|---|
| 3291 | +video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg, |
|---|
| 2981 | 3292 | v4l2_kioctl func) |
|---|
| 2982 | 3293 | { |
|---|
| 2983 | 3294 | char sbuf[128]; |
|---|
| .. | .. |
|---|
| 2989 | 3300 | size_t array_size = 0; |
|---|
| 2990 | 3301 | void __user *user_ptr = NULL; |
|---|
| 2991 | 3302 | void **kernel_ptr = NULL; |
|---|
| 3303 | + unsigned int cmd = video_translate_cmd(orig_cmd); |
|---|
| 2992 | 3304 | const size_t ioc_size = _IOC_SIZE(cmd); |
|---|
| 2993 | 3305 | |
|---|
| 2994 | 3306 | /* Copy arguments into temp kernel buffer */ |
|---|
| .. | .. |
|---|
| 3003 | 3315 | parg = mbuf; |
|---|
| 3004 | 3316 | } |
|---|
| 3005 | 3317 | |
|---|
| 3006 | | - err = -EFAULT; |
|---|
| 3007 | | - if (_IOC_DIR(cmd) & _IOC_WRITE) { |
|---|
| 3008 | | - unsigned int n = ioc_size; |
|---|
| 3009 | | - |
|---|
| 3010 | | - /* |
|---|
| 3011 | | - * In some cases, only a few fields are used as input, |
|---|
| 3012 | | - * i.e. when the app sets "index" and then the driver |
|---|
| 3013 | | - * fills in the rest of the structure for the thing |
|---|
| 3014 | | - * with that index. We only need to copy up the first |
|---|
| 3015 | | - * non-input field. |
|---|
| 3016 | | - */ |
|---|
| 3017 | | - if (v4l2_is_known_ioctl(cmd)) { |
|---|
| 3018 | | - u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; |
|---|
| 3019 | | - |
|---|
| 3020 | | - if (flags & INFO_FL_CLEAR_MASK) |
|---|
| 3021 | | - n = (flags & INFO_FL_CLEAR_MASK) >> 16; |
|---|
| 3022 | | - always_copy = flags & INFO_FL_ALWAYS_COPY; |
|---|
| 3023 | | - } |
|---|
| 3024 | | - |
|---|
| 3025 | | - if (copy_from_user(parg, (void __user *)arg, n)) |
|---|
| 3026 | | - goto out; |
|---|
| 3027 | | - |
|---|
| 3028 | | - /* zero out anything we don't copy from userspace */ |
|---|
| 3029 | | - if (n < ioc_size) |
|---|
| 3030 | | - memset((u8 *)parg + n, 0, ioc_size - n); |
|---|
| 3031 | | - } else { |
|---|
| 3032 | | - /* read-only ioctl */ |
|---|
| 3033 | | - memset(parg, 0, ioc_size); |
|---|
| 3034 | | - } |
|---|
| 3318 | + err = video_get_user((void __user *)arg, parg, orig_cmd, |
|---|
| 3319 | + &always_copy); |
|---|
| 3320 | + if (err) |
|---|
| 3321 | + goto out; |
|---|
| 3035 | 3322 | } |
|---|
| 3036 | 3323 | |
|---|
| 3037 | 3324 | err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr); |
|---|
| .. | .. |
|---|
| 3078 | 3365 | goto out; |
|---|
| 3079 | 3366 | |
|---|
| 3080 | 3367 | out_array_args: |
|---|
| 3081 | | - /* Copy results into user buffer */ |
|---|
| 3082 | | - switch (_IOC_DIR(cmd)) { |
|---|
| 3083 | | - case _IOC_READ: |
|---|
| 3084 | | - case (_IOC_WRITE | _IOC_READ): |
|---|
| 3085 | | - if (copy_to_user((void __user *)arg, parg, ioc_size)) |
|---|
| 3086 | | - err = -EFAULT; |
|---|
| 3087 | | - break; |
|---|
| 3088 | | - } |
|---|
| 3089 | | - |
|---|
| 3368 | + if (video_put_user((void __user *)arg, parg, orig_cmd)) |
|---|
| 3369 | + err = -EFAULT; |
|---|
| 3090 | 3370 | out: |
|---|
| 3091 | 3371 | kvfree(array_buf); |
|---|
| 3092 | 3372 | kvfree(mbuf); |
|---|
| 3093 | 3373 | return err; |
|---|
| 3094 | 3374 | } |
|---|
| 3095 | | -EXPORT_SYMBOL_GPL(video_usercopy); |
|---|
| 3096 | 3375 | |
|---|
| 3097 | 3376 | long video_ioctl2(struct file *file, |
|---|
| 3098 | 3377 | unsigned int cmd, unsigned long arg) |
|---|