| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /**************************************************************************** |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Filename: cpia2_v4l.c |
|---|
| .. | .. |
|---|
| 10 | 11 | * This is a USB driver for CPia2 based video cameras. |
|---|
| 11 | 12 | * The infrastructure of this driver is based on the cpia usb driver by |
|---|
| 12 | 13 | * Jochen Scharrlach and Johannes Erdfeldt. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 15 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 16 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 17 | | - * (at your option) any later version. |
|---|
| 18 | | - * |
|---|
| 19 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 20 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 21 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 22 | | - * GNU General Public License for more details. |
|---|
| 23 | 14 | * |
|---|
| 24 | 15 | * Stripped of 2.4 stuff ready for main kernel submit by |
|---|
| 25 | 16 | * Alan Cox <alan@lxorguk.ukuu.org.uk> |
|---|
| .. | .. |
|---|
| 219 | 210 | { |
|---|
| 220 | 211 | struct camera_data *cam = video_drvdata(file); |
|---|
| 221 | 212 | |
|---|
| 222 | | - strcpy(vc->driver, "cpia2"); |
|---|
| 213 | + strscpy(vc->driver, "cpia2", sizeof(vc->driver)); |
|---|
| 223 | 214 | |
|---|
| 224 | 215 | if (cam->params.pnp_id.product == 0x151) |
|---|
| 225 | | - strcpy(vc->card, "QX5 Microscope"); |
|---|
| 216 | + strscpy(vc->card, "QX5 Microscope", sizeof(vc->card)); |
|---|
| 226 | 217 | else |
|---|
| 227 | | - strcpy(vc->card, "CPiA2 Camera"); |
|---|
| 218 | + strscpy(vc->card, "CPiA2 Camera", sizeof(vc->card)); |
|---|
| 228 | 219 | switch (cam->params.pnp_id.device_type) { |
|---|
| 229 | 220 | case DEVICE_STV_672: |
|---|
| 230 | 221 | strcat(vc->card, " (672/"); |
|---|
| .. | .. |
|---|
| 259 | 250 | |
|---|
| 260 | 251 | if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0) |
|---|
| 261 | 252 | memset(vc->bus_info,0, sizeof(vc->bus_info)); |
|---|
| 262 | | - |
|---|
| 263 | | - vc->device_caps = V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 264 | | - V4L2_CAP_READWRITE | |
|---|
| 265 | | - V4L2_CAP_STREAMING; |
|---|
| 266 | | - vc->capabilities = vc->device_caps | |
|---|
| 267 | | - V4L2_CAP_DEVICE_CAPS; |
|---|
| 268 | | - |
|---|
| 269 | 253 | return 0; |
|---|
| 270 | 254 | } |
|---|
| 271 | 255 | |
|---|
| .. | .. |
|---|
| 281 | 265 | { |
|---|
| 282 | 266 | if (i->index) |
|---|
| 283 | 267 | return -EINVAL; |
|---|
| 284 | | - strcpy(i->name, "Camera"); |
|---|
| 268 | + strscpy(i->name, "Camera", sizeof(i->name)); |
|---|
| 285 | 269 | i->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 286 | 270 | return 0; |
|---|
| 287 | 271 | } |
|---|
| .. | .. |
|---|
| 308 | 292 | static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh, |
|---|
| 309 | 293 | struct v4l2_fmtdesc *f) |
|---|
| 310 | 294 | { |
|---|
| 311 | | - int index = f->index; |
|---|
| 312 | | - |
|---|
| 313 | | - if (index < 0 || index > 1) |
|---|
| 314 | | - return -EINVAL; |
|---|
| 315 | | - |
|---|
| 316 | | - memset(f, 0, sizeof(*f)); |
|---|
| 317 | | - f->index = index; |
|---|
| 318 | | - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|---|
| 319 | | - f->flags = V4L2_FMT_FLAG_COMPRESSED; |
|---|
| 320 | | - switch(index) { |
|---|
| 321 | | - case 0: |
|---|
| 322 | | - strcpy(f->description, "MJPEG"); |
|---|
| 323 | | - f->pixelformat = V4L2_PIX_FMT_MJPEG; |
|---|
| 324 | | - break; |
|---|
| 325 | | - case 1: |
|---|
| 326 | | - strcpy(f->description, "JPEG"); |
|---|
| 327 | | - f->pixelformat = V4L2_PIX_FMT_JPEG; |
|---|
| 328 | | - break; |
|---|
| 329 | | - default: |
|---|
| 295 | + if (f->index > 1) |
|---|
| 330 | 296 | return -EINVAL; |
|---|
| 331 | | - } |
|---|
| 332 | 297 | |
|---|
| 298 | + if (f->index == 0) |
|---|
| 299 | + f->pixelformat = V4L2_PIX_FMT_MJPEG; |
|---|
| 300 | + else |
|---|
| 301 | + f->pixelformat = V4L2_PIX_FMT_JPEG; |
|---|
| 333 | 302 | return 0; |
|---|
| 334 | 303 | } |
|---|
| 335 | 304 | |
|---|
| .. | .. |
|---|
| 354 | 323 | f->fmt.pix.bytesperline = 0; |
|---|
| 355 | 324 | f->fmt.pix.sizeimage = cam->frame_size; |
|---|
| 356 | 325 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; |
|---|
| 357 | | - f->fmt.pix.priv = 0; |
|---|
| 358 | 326 | |
|---|
| 359 | 327 | switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) { |
|---|
| 360 | 328 | case VIDEOSIZE_VGA: |
|---|
| .. | .. |
|---|
| 465 | 433 | f->fmt.pix.bytesperline = 0; |
|---|
| 466 | 434 | f->fmt.pix.sizeimage = cam->frame_size; |
|---|
| 467 | 435 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; |
|---|
| 468 | | - f->fmt.pix.priv = 0; |
|---|
| 469 | 436 | |
|---|
| 470 | 437 | return 0; |
|---|
| 471 | 438 | } |
|---|
| .. | .. |
|---|
| 479 | 446 | * |
|---|
| 480 | 447 | *****************************************************************************/ |
|---|
| 481 | 448 | |
|---|
| 482 | | -static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c) |
|---|
| 449 | +static int cpia2_g_selection(struct file *file, void *fh, |
|---|
| 450 | + struct v4l2_selection *s) |
|---|
| 483 | 451 | { |
|---|
| 484 | 452 | struct camera_data *cam = video_drvdata(file); |
|---|
| 485 | 453 | |
|---|
| 486 | | - if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 487 | | - return -EINVAL; |
|---|
| 454 | + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 455 | + return -EINVAL; |
|---|
| 488 | 456 | |
|---|
| 489 | | - c->bounds.left = 0; |
|---|
| 490 | | - c->bounds.top = 0; |
|---|
| 491 | | - c->bounds.width = cam->width; |
|---|
| 492 | | - c->bounds.height = cam->height; |
|---|
| 493 | | - c->defrect.left = 0; |
|---|
| 494 | | - c->defrect.top = 0; |
|---|
| 495 | | - c->defrect.width = cam->width; |
|---|
| 496 | | - c->defrect.height = cam->height; |
|---|
| 497 | | - c->pixelaspect.numerator = 1; |
|---|
| 498 | | - c->pixelaspect.denominator = 1; |
|---|
| 499 | | - |
|---|
| 457 | + switch (s->target) { |
|---|
| 458 | + case V4L2_SEL_TGT_CROP_BOUNDS: |
|---|
| 459 | + case V4L2_SEL_TGT_CROP_DEFAULT: |
|---|
| 460 | + s->r.left = 0; |
|---|
| 461 | + s->r.top = 0; |
|---|
| 462 | + s->r.width = cam->width; |
|---|
| 463 | + s->r.height = cam->height; |
|---|
| 464 | + break; |
|---|
| 465 | + default: |
|---|
| 466 | + return -EINVAL; |
|---|
| 467 | + } |
|---|
| 500 | 468 | return 0; |
|---|
| 501 | 469 | } |
|---|
| 502 | 470 | |
|---|
| .. | .. |
|---|
| 832 | 800 | break; |
|---|
| 833 | 801 | case FRAME_READY: |
|---|
| 834 | 802 | buf->bytesused = cam->buffers[buf->index].length; |
|---|
| 835 | | - buf->timestamp = cam->buffers[buf->index].timestamp; |
|---|
| 803 | + v4l2_buffer_set_timestamp(buf, cam->buffers[buf->index].ts); |
|---|
| 836 | 804 | buf->sequence = cam->buffers[buf->index].seq; |
|---|
| 837 | 805 | buf->flags = V4L2_BUF_FLAG_DONE; |
|---|
| 838 | 806 | break; |
|---|
| .. | .. |
|---|
| 888 | 856 | found = i; |
|---|
| 889 | 857 | } else { |
|---|
| 890 | 858 | /* find which buffer is earlier */ |
|---|
| 891 | | - struct timeval *tv1, *tv2; |
|---|
| 892 | | - tv1 = &cam->buffers[i].timestamp; |
|---|
| 893 | | - tv2 = &cam->buffers[found].timestamp; |
|---|
| 894 | | - if(tv1->tv_sec < tv2->tv_sec || |
|---|
| 895 | | - (tv1->tv_sec == tv2->tv_sec && |
|---|
| 896 | | - tv1->tv_usec < tv2->tv_usec)) |
|---|
| 859 | + if (cam->buffers[i].ts < cam->buffers[found].ts) |
|---|
| 897 | 860 | found = i; |
|---|
| 898 | 861 | } |
|---|
| 899 | 862 | } |
|---|
| .. | .. |
|---|
| 944 | 907 | buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE |
|---|
| 945 | 908 | | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
|---|
| 946 | 909 | buf->field = V4L2_FIELD_NONE; |
|---|
| 947 | | - buf->timestamp = cam->buffers[buf->index].timestamp; |
|---|
| 910 | + v4l2_buffer_set_timestamp(buf, cam->buffers[buf->index].ts); |
|---|
| 948 | 911 | buf->sequence = cam->buffers[buf->index].seq; |
|---|
| 949 | 912 | buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; |
|---|
| 950 | 913 | buf->length = cam->frame_size; |
|---|
| 951 | 914 | buf->reserved2 = 0; |
|---|
| 952 | | - buf->reserved = 0; |
|---|
| 915 | + buf->request_fd = 0; |
|---|
| 953 | 916 | memset(&buf->timecode, 0, sizeof(buf->timecode)); |
|---|
| 954 | 917 | |
|---|
| 955 | 918 | DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index, |
|---|
| .. | .. |
|---|
| 1047 | 1010 | .vidioc_try_fmt_vid_cap = cpia2_try_fmt_vid_cap, |
|---|
| 1048 | 1011 | .vidioc_g_jpegcomp = cpia2_g_jpegcomp, |
|---|
| 1049 | 1012 | .vidioc_s_jpegcomp = cpia2_s_jpegcomp, |
|---|
| 1050 | | - .vidioc_cropcap = cpia2_cropcap, |
|---|
| 1013 | + .vidioc_g_selection = cpia2_g_selection, |
|---|
| 1051 | 1014 | .vidioc_reqbufs = cpia2_reqbufs, |
|---|
| 1052 | 1015 | .vidioc_querybuf = cpia2_querybuf, |
|---|
| 1053 | 1016 | .vidioc_qbuf = cpia2_qbuf, |
|---|
| .. | .. |
|---|
| 1165 | 1128 | cam->vdev.lock = &cam->v4l2_lock; |
|---|
| 1166 | 1129 | cam->vdev.ctrl_handler = hdl; |
|---|
| 1167 | 1130 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
|---|
| 1131 | + cam->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | |
|---|
| 1132 | + V4L2_CAP_STREAMING; |
|---|
| 1168 | 1133 | |
|---|
| 1169 | 1134 | reset_camera_struct_v4l(cam); |
|---|
| 1170 | 1135 | |
|---|
| 1171 | 1136 | /* register v4l device */ |
|---|
| 1172 | | - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { |
|---|
| 1137 | + if (video_register_device(&cam->vdev, VFL_TYPE_VIDEO, video_nr) < 0) { |
|---|
| 1173 | 1138 | ERR("video_register_device failed\n"); |
|---|
| 1174 | 1139 | return -ENODEV; |
|---|
| 1175 | 1140 | } |
|---|