| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Main USB camera driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Camera button input handling by Márton Németh |
|---|
| 7 | 8 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 10 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 11 | | - * Free Software Foundation; either version 2 of the License, or (at your |
|---|
| 12 | | - * option) any later version. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 15 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|---|
| 16 | | - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|---|
| 17 | | - * for more details. |
|---|
| 18 | 9 | */ |
|---|
| 19 | 10 | |
|---|
| 20 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 916 | 907 | } |
|---|
| 917 | 908 | |
|---|
| 918 | 909 | static int wxh_to_mode(struct gspca_dev *gspca_dev, |
|---|
| 919 | | - int width, int height) |
|---|
| 910 | + int width, int height, u32 pixelformat) |
|---|
| 920 | 911 | { |
|---|
| 921 | 912 | int i; |
|---|
| 922 | 913 | |
|---|
| 923 | 914 | for (i = 0; i < gspca_dev->cam.nmodes; i++) { |
|---|
| 924 | 915 | if (width == gspca_dev->cam.cam_mode[i].width |
|---|
| 925 | | - && height == gspca_dev->cam.cam_mode[i].height) |
|---|
| 916 | + && height == gspca_dev->cam.cam_mode[i].height |
|---|
| 917 | + && pixelformat == gspca_dev->cam.cam_mode[i].pixelformat) |
|---|
| 926 | 918 | return i; |
|---|
| 927 | 919 | } |
|---|
| 928 | 920 | return -EINVAL; |
|---|
| 929 | 921 | } |
|---|
| 930 | 922 | |
|---|
| 931 | 923 | static int wxh_to_nearest_mode(struct gspca_dev *gspca_dev, |
|---|
| 932 | | - int width, int height) |
|---|
| 924 | + int width, int height, u32 pixelformat) |
|---|
| 933 | 925 | { |
|---|
| 934 | 926 | int i; |
|---|
| 935 | 927 | |
|---|
| 928 | + for (i = gspca_dev->cam.nmodes; --i >= 0; ) { |
|---|
| 929 | + if (width >= gspca_dev->cam.cam_mode[i].width |
|---|
| 930 | + && height >= gspca_dev->cam.cam_mode[i].height |
|---|
| 931 | + && pixelformat == gspca_dev->cam.cam_mode[i].pixelformat) |
|---|
| 932 | + return i; |
|---|
| 933 | + } |
|---|
| 936 | 934 | for (i = gspca_dev->cam.nmodes; --i > 0; ) { |
|---|
| 937 | 935 | if (width >= gspca_dev->cam.cam_mode[i].width |
|---|
| 938 | 936 | && height >= gspca_dev->cam.cam_mode[i].height) |
|---|
| .. | .. |
|---|
| 1026 | 1024 | return -EINVAL; /* no more format */ |
|---|
| 1027 | 1025 | |
|---|
| 1028 | 1026 | fmtdesc->pixelformat = fmt_tb[index]; |
|---|
| 1029 | | - if (gspca_dev->cam.cam_mode[i].sizeimage < |
|---|
| 1030 | | - gspca_dev->cam.cam_mode[i].width * |
|---|
| 1031 | | - gspca_dev->cam.cam_mode[i].height) |
|---|
| 1032 | | - fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; |
|---|
| 1033 | | - fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; |
|---|
| 1034 | | - fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; |
|---|
| 1035 | | - fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; |
|---|
| 1036 | | - fmtdesc->description[3] = fmtdesc->pixelformat >> 24; |
|---|
| 1037 | | - fmtdesc->description[4] = '\0'; |
|---|
| 1038 | 1027 | return 0; |
|---|
| 1039 | 1028 | } |
|---|
| 1040 | 1029 | |
|---|
| 1041 | | -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 1042 | | - struct v4l2_format *fmt) |
|---|
| 1030 | +static int vidioc_g_fmt_vid_cap(struct file *file, void *_priv, |
|---|
| 1031 | + struct v4l2_format *fmt) |
|---|
| 1043 | 1032 | { |
|---|
| 1044 | 1033 | struct gspca_dev *gspca_dev = video_drvdata(file); |
|---|
| 1034 | + u32 priv = fmt->fmt.pix.priv; |
|---|
| 1045 | 1035 | |
|---|
| 1046 | 1036 | fmt->fmt.pix = gspca_dev->pixfmt; |
|---|
| 1047 | | - /* some drivers use priv internally, zero it before giving it back to |
|---|
| 1048 | | - the core */ |
|---|
| 1049 | | - fmt->fmt.pix.priv = 0; |
|---|
| 1037 | + /* some drivers use priv internally, so keep the original value */ |
|---|
| 1038 | + fmt->fmt.pix.priv = priv; |
|---|
| 1050 | 1039 | return 0; |
|---|
| 1051 | 1040 | } |
|---|
| 1052 | 1041 | |
|---|
| .. | .. |
|---|
| 1062 | 1051 | fmt->fmt.pix.pixelformat, w, h); |
|---|
| 1063 | 1052 | |
|---|
| 1064 | 1053 | /* search the nearest mode for width and height */ |
|---|
| 1065 | | - mode = wxh_to_nearest_mode(gspca_dev, w, h); |
|---|
| 1054 | + mode = wxh_to_nearest_mode(gspca_dev, w, h, fmt->fmt.pix.pixelformat); |
|---|
| 1066 | 1055 | |
|---|
| 1067 | 1056 | /* OK if right palette */ |
|---|
| 1068 | 1057 | if (gspca_dev->cam.cam_mode[mode].pixelformat |
|---|
| .. | .. |
|---|
| 1081 | 1070 | fmt->fmt.pix.height = h; |
|---|
| 1082 | 1071 | gspca_dev->sd_desc->try_fmt(gspca_dev, fmt); |
|---|
| 1083 | 1072 | } |
|---|
| 1084 | | - /* some drivers use priv internally, zero it before giving it back to |
|---|
| 1085 | | - the core */ |
|---|
| 1086 | | - fmt->fmt.pix.priv = 0; |
|---|
| 1087 | 1073 | return mode; /* used when s_fmt */ |
|---|
| 1088 | 1074 | } |
|---|
| 1089 | 1075 | |
|---|
| 1090 | | -static int vidioc_try_fmt_vid_cap(struct file *file, |
|---|
| 1091 | | - void *priv, |
|---|
| 1092 | | - struct v4l2_format *fmt) |
|---|
| 1076 | +static int vidioc_try_fmt_vid_cap(struct file *file, void *_priv, |
|---|
| 1077 | + struct v4l2_format *fmt) |
|---|
| 1093 | 1078 | { |
|---|
| 1094 | 1079 | struct gspca_dev *gspca_dev = video_drvdata(file); |
|---|
| 1080 | + u32 priv = fmt->fmt.pix.priv; |
|---|
| 1095 | 1081 | |
|---|
| 1096 | 1082 | if (try_fmt_vid_cap(gspca_dev, fmt) < 0) |
|---|
| 1097 | 1083 | return -EINVAL; |
|---|
| 1084 | + /* some drivers use priv internally, so keep the original value */ |
|---|
| 1085 | + fmt->fmt.pix.priv = priv; |
|---|
| 1098 | 1086 | return 0; |
|---|
| 1099 | 1087 | } |
|---|
| 1100 | 1088 | |
|---|
| 1101 | | -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 1102 | | - struct v4l2_format *fmt) |
|---|
| 1089 | +static int vidioc_s_fmt_vid_cap(struct file *file, void *_priv, |
|---|
| 1090 | + struct v4l2_format *fmt) |
|---|
| 1103 | 1091 | { |
|---|
| 1104 | 1092 | struct gspca_dev *gspca_dev = video_drvdata(file); |
|---|
| 1093 | + u32 priv = fmt->fmt.pix.priv; |
|---|
| 1105 | 1094 | int mode; |
|---|
| 1106 | 1095 | |
|---|
| 1107 | 1096 | if (vb2_is_busy(&gspca_dev->queue)) |
|---|
| .. | .. |
|---|
| 1117 | 1106 | gspca_dev->pixfmt = fmt->fmt.pix; |
|---|
| 1118 | 1107 | else |
|---|
| 1119 | 1108 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode]; |
|---|
| 1109 | + /* some drivers use priv internally, so keep the original value */ |
|---|
| 1110 | + fmt->fmt.pix.priv = priv; |
|---|
| 1120 | 1111 | return 0; |
|---|
| 1121 | 1112 | } |
|---|
| 1122 | 1113 | |
|---|
| .. | .. |
|---|
| 1156 | 1147 | int mode; |
|---|
| 1157 | 1148 | __u32 i; |
|---|
| 1158 | 1149 | |
|---|
| 1159 | | - mode = wxh_to_mode(gspca_dev, fival->width, fival->height); |
|---|
| 1150 | + mode = wxh_to_mode(gspca_dev, fival->width, fival->height, |
|---|
| 1151 | + fival->pixel_format); |
|---|
| 1160 | 1152 | if (mode < 0) |
|---|
| 1161 | 1153 | return -EINVAL; |
|---|
| 1162 | 1154 | |
|---|
| .. | .. |
|---|
| 1197 | 1189 | { |
|---|
| 1198 | 1190 | struct gspca_dev *gspca_dev = video_drvdata(file); |
|---|
| 1199 | 1191 | |
|---|
| 1200 | | - strlcpy((char *) cap->driver, gspca_dev->sd_desc->name, |
|---|
| 1201 | | - sizeof cap->driver); |
|---|
| 1192 | + strscpy((char *)cap->driver, gspca_dev->sd_desc->name, |
|---|
| 1193 | + sizeof(cap->driver)); |
|---|
| 1202 | 1194 | if (gspca_dev->dev->product != NULL) { |
|---|
| 1203 | | - strlcpy((char *) cap->card, gspca_dev->dev->product, |
|---|
| 1204 | | - sizeof cap->card); |
|---|
| 1195 | + strscpy((char *)cap->card, gspca_dev->dev->product, |
|---|
| 1196 | + sizeof(cap->card)); |
|---|
| 1205 | 1197 | } else { |
|---|
| 1206 | 1198 | snprintf((char *) cap->card, sizeof cap->card, |
|---|
| 1207 | 1199 | "USB Camera (%04x:%04x)", |
|---|
| .. | .. |
|---|
| 1210 | 1202 | } |
|---|
| 1211 | 1203 | usb_make_path(gspca_dev->dev, (char *) cap->bus_info, |
|---|
| 1212 | 1204 | sizeof(cap->bus_info)); |
|---|
| 1213 | | - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
|---|
| 1214 | | - | V4L2_CAP_STREAMING |
|---|
| 1215 | | - | V4L2_CAP_READWRITE; |
|---|
| 1216 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
|---|
| 1217 | 1205 | return 0; |
|---|
| 1218 | 1206 | } |
|---|
| 1219 | 1207 | |
|---|
| .. | .. |
|---|
| 1226 | 1214 | return -EINVAL; |
|---|
| 1227 | 1215 | input->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 1228 | 1216 | input->status = gspca_dev->cam.input_flags; |
|---|
| 1229 | | - strlcpy(input->name, gspca_dev->sd_desc->name, |
|---|
| 1217 | + strscpy(input->name, gspca_dev->sd_desc->name, |
|---|
| 1230 | 1218 | sizeof input->name); |
|---|
| 1231 | 1219 | return 0; |
|---|
| 1232 | 1220 | } |
|---|
| .. | .. |
|---|
| 1509 | 1497 | gspca_dev->empty_packet = -1; /* don't check the empty packets */ |
|---|
| 1510 | 1498 | gspca_dev->vdev = gspca_template; |
|---|
| 1511 | 1499 | gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev; |
|---|
| 1500 | + gspca_dev->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 1501 | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; |
|---|
| 1512 | 1502 | video_set_drvdata(&gspca_dev->vdev, gspca_dev); |
|---|
| 1513 | 1503 | gspca_dev->module = module; |
|---|
| 1514 | 1504 | |
|---|
| .. | .. |
|---|
| 1565 | 1555 | |
|---|
| 1566 | 1556 | /* init video stuff */ |
|---|
| 1567 | 1557 | ret = video_register_device(&gspca_dev->vdev, |
|---|
| 1568 | | - VFL_TYPE_GRABBER, |
|---|
| 1558 | + VFL_TYPE_VIDEO, |
|---|
| 1569 | 1559 | -1); |
|---|
| 1570 | 1560 | if (ret < 0) { |
|---|
| 1571 | 1561 | pr_err("video_register_device err %d\n", ret); |
|---|