| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Zoran 364xx based USB webcam module version 0.73 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Allows you to use your USB webcam with V4L2 applications |
|---|
| 5 | | - * This is still in heavy developpement ! |
|---|
| 6 | + * This is still in heavy development ! |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Copyright (C) 2004 Antoine Jacquet <royale@zerezo.com> |
|---|
| 8 | 9 | * http://royale.zerezo.com/zr364xx/ |
|---|
| .. | .. |
|---|
| 11 | 12 | * V4L2 version inspired by meye.c driver |
|---|
| 12 | 13 | * |
|---|
| 13 | 14 | * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 16 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 17 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 18 | | - * (at your option) any later version. |
|---|
| 19 | | - * |
|---|
| 20 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 21 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 22 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 23 | | - * GNU General Public License for more details. |
|---|
| 24 | 15 | */ |
|---|
| 25 | 16 | |
|---|
| 26 | 17 | |
|---|
| .. | .. |
|---|
| 29 | 20 | #include <linux/usb.h> |
|---|
| 30 | 21 | #include <linux/vmalloc.h> |
|---|
| 31 | 22 | #include <linux/slab.h> |
|---|
| 32 | | -#include <linux/proc_fs.h> |
|---|
| 33 | 23 | #include <linux/highmem.h> |
|---|
| 34 | 24 | #include <media/v4l2-common.h> |
|---|
| 35 | 25 | #include <media/v4l2-ioctl.h> |
|---|
| .. | .. |
|---|
| 150 | 140 | }; |
|---|
| 151 | 141 | |
|---|
| 152 | 142 | struct zr364xx_fmt { |
|---|
| 153 | | - char *name; |
|---|
| 154 | 143 | u32 fourcc; |
|---|
| 155 | 144 | int depth; |
|---|
| 156 | 145 | }; |
|---|
| .. | .. |
|---|
| 158 | 147 | /* image formats. */ |
|---|
| 159 | 148 | static const struct zr364xx_fmt formats[] = { |
|---|
| 160 | 149 | { |
|---|
| 161 | | - .name = "JPG", |
|---|
| 162 | 150 | .fourcc = V4L2_PIX_FMT_JPEG, |
|---|
| 163 | 151 | .depth = 24 |
|---|
| 164 | 152 | } |
|---|
| .. | .. |
|---|
| 208 | 196 | { |
|---|
| 209 | 197 | int status; |
|---|
| 210 | 198 | |
|---|
| 211 | | - unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); |
|---|
| 199 | + unsigned char *transfer_buffer = kmemdup(cp, size, GFP_KERNEL); |
|---|
| 212 | 200 | if (!transfer_buffer) |
|---|
| 213 | 201 | return -ENOMEM; |
|---|
| 214 | | - |
|---|
| 215 | | - memcpy(transfer_buffer, cp, size); |
|---|
| 216 | 202 | |
|---|
| 217 | 203 | status = usb_control_msg(udev, |
|---|
| 218 | 204 | usb_sndctrlpipe(udev, 0), |
|---|
| .. | .. |
|---|
| 385 | 371 | vb); |
|---|
| 386 | 372 | int rc; |
|---|
| 387 | 373 | |
|---|
| 388 | | - DBG("%s, field=%d, fmt name = %s\n", __func__, field, |
|---|
| 389 | | - cam->fmt ? cam->fmt->name : ""); |
|---|
| 374 | + DBG("%s, field=%d\n", __func__, field); |
|---|
| 390 | 375 | if (!cam->fmt) |
|---|
| 391 | 376 | return -EINVAL; |
|---|
| 392 | 377 | |
|---|
| .. | .. |
|---|
| 521 | 506 | /* tell v4l buffer was filled */ |
|---|
| 522 | 507 | |
|---|
| 523 | 508 | buf->vb.field_count = cam->frame_count * 2; |
|---|
| 524 | | - v4l2_get_timestamp(&buf->vb.ts); |
|---|
| 509 | + buf->vb.ts = ktime_get_ns(); |
|---|
| 525 | 510 | buf->vb.state = VIDEOBUF_DONE; |
|---|
| 526 | 511 | } |
|---|
| 527 | 512 | |
|---|
| .. | .. |
|---|
| 549 | 534 | goto unlock; |
|---|
| 550 | 535 | } |
|---|
| 551 | 536 | list_del(&buf->vb.queue); |
|---|
| 552 | | - v4l2_get_timestamp(&buf->vb.ts); |
|---|
| 537 | + buf->vb.ts = ktime_get_ns(); |
|---|
| 553 | 538 | DBG("[%p/%d] wakeup\n", buf, buf->vb.i); |
|---|
| 554 | 539 | zr364xx_fillbuff(cam, buf, jpgsize); |
|---|
| 555 | 540 | wake_up(&buf->vb.done); |
|---|
| .. | .. |
|---|
| 570 | 555 | { |
|---|
| 571 | 556 | unsigned char *pdest; |
|---|
| 572 | 557 | unsigned char *psrc; |
|---|
| 573 | | - s32 idx = -1; |
|---|
| 574 | | - struct zr364xx_framei *frm; |
|---|
| 558 | + s32 idx = cam->cur_frame; |
|---|
| 559 | + struct zr364xx_framei *frm = &cam->buffer.frame[idx]; |
|---|
| 575 | 560 | int i = 0; |
|---|
| 576 | 561 | unsigned char *ptr = NULL; |
|---|
| 577 | 562 | |
|---|
| 578 | 563 | _DBG("buffer to user\n"); |
|---|
| 579 | | - idx = cam->cur_frame; |
|---|
| 580 | | - frm = &cam->buffer.frame[idx]; |
|---|
| 581 | 564 | |
|---|
| 582 | 565 | /* swap bytes if camera needs it */ |
|---|
| 583 | 566 | if (cam->method == METHOD0) { |
|---|
| .. | .. |
|---|
| 702 | 685 | { |
|---|
| 703 | 686 | struct zr364xx_camera *cam = video_drvdata(file); |
|---|
| 704 | 687 | |
|---|
| 705 | | - strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); |
|---|
| 688 | + strscpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); |
|---|
| 706 | 689 | if (cam->udev->product) |
|---|
| 707 | | - strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); |
|---|
| 708 | | - strlcpy(cap->bus_info, dev_name(&cam->udev->dev), |
|---|
| 690 | + strscpy(cap->card, cam->udev->product, sizeof(cap->card)); |
|---|
| 691 | + strscpy(cap->bus_info, dev_name(&cam->udev->dev), |
|---|
| 709 | 692 | sizeof(cap->bus_info)); |
|---|
| 710 | | - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 711 | | - V4L2_CAP_READWRITE | |
|---|
| 712 | | - V4L2_CAP_STREAMING; |
|---|
| 713 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
|---|
| 714 | | - |
|---|
| 715 | 693 | return 0; |
|---|
| 716 | 694 | } |
|---|
| 717 | 695 | |
|---|
| .. | .. |
|---|
| 720 | 698 | { |
|---|
| 721 | 699 | if (i->index != 0) |
|---|
| 722 | 700 | return -EINVAL; |
|---|
| 723 | | - strcpy(i->name, DRIVER_DESC " Camera"); |
|---|
| 701 | + strscpy(i->name, DRIVER_DESC " Camera", sizeof(i->name)); |
|---|
| 724 | 702 | i->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 725 | 703 | return 0; |
|---|
| 726 | 704 | } |
|---|
| .. | .. |
|---|
| 765 | 743 | { |
|---|
| 766 | 744 | if (f->index > 0) |
|---|
| 767 | 745 | return -EINVAL; |
|---|
| 768 | | - f->flags = V4L2_FMT_FLAG_COMPRESSED; |
|---|
| 769 | | - strcpy(f->description, formats[0].name); |
|---|
| 770 | 746 | f->pixelformat = formats[0].fourcc; |
|---|
| 771 | 747 | return 0; |
|---|
| 772 | 748 | } |
|---|
| .. | .. |
|---|
| 1208 | 1184 | return err; |
|---|
| 1209 | 1185 | } |
|---|
| 1210 | 1186 | |
|---|
| 1211 | | -static void zr364xx_release(struct v4l2_device *v4l2_dev) |
|---|
| 1187 | +static void zr364xx_board_uninit(struct zr364xx_camera *cam) |
|---|
| 1212 | 1188 | { |
|---|
| 1213 | | - struct zr364xx_camera *cam = |
|---|
| 1214 | | - container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev); |
|---|
| 1215 | 1189 | unsigned long i; |
|---|
| 1216 | 1190 | |
|---|
| 1217 | | - v4l2_device_unregister(&cam->v4l2_dev); |
|---|
| 1218 | | - |
|---|
| 1219 | | - videobuf_mmap_free(&cam->vb_vidq); |
|---|
| 1191 | + zr364xx_stop_readpipe(cam); |
|---|
| 1220 | 1192 | |
|---|
| 1221 | 1193 | /* release sys buffers */ |
|---|
| 1222 | 1194 | for (i = 0; i < FRAMES; i++) { |
|---|
| .. | .. |
|---|
| 1227 | 1199 | cam->buffer.frame[i].lpvbits = NULL; |
|---|
| 1228 | 1200 | } |
|---|
| 1229 | 1201 | |
|---|
| 1230 | | - v4l2_ctrl_handler_free(&cam->ctrl_handler); |
|---|
| 1231 | 1202 | /* release transfer buffer */ |
|---|
| 1232 | 1203 | kfree(cam->pipe->transfer_buffer); |
|---|
| 1204 | +} |
|---|
| 1205 | + |
|---|
| 1206 | +static void zr364xx_release(struct v4l2_device *v4l2_dev) |
|---|
| 1207 | +{ |
|---|
| 1208 | + struct zr364xx_camera *cam = |
|---|
| 1209 | + container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev); |
|---|
| 1210 | + |
|---|
| 1211 | + videobuf_mmap_free(&cam->vb_vidq); |
|---|
| 1212 | + v4l2_ctrl_handler_free(&cam->ctrl_handler); |
|---|
| 1213 | + zr364xx_board_uninit(cam); |
|---|
| 1214 | + v4l2_device_unregister(&cam->v4l2_dev); |
|---|
| 1233 | 1215 | kfree(cam); |
|---|
| 1234 | 1216 | } |
|---|
| 1235 | 1217 | |
|---|
| .. | .. |
|---|
| 1339 | 1321 | .fops = &zr364xx_fops, |
|---|
| 1340 | 1322 | .ioctl_ops = &zr364xx_ioctl_ops, |
|---|
| 1341 | 1323 | .release = video_device_release_empty, |
|---|
| 1324 | + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | |
|---|
| 1325 | + V4L2_CAP_STREAMING, |
|---|
| 1342 | 1326 | }; |
|---|
| 1343 | 1327 | |
|---|
| 1344 | 1328 | |
|---|
| .. | .. |
|---|
| 1350 | 1334 | { |
|---|
| 1351 | 1335 | struct zr364xx_pipeinfo *pipe = cam->pipe; |
|---|
| 1352 | 1336 | unsigned long i; |
|---|
| 1337 | + int err; |
|---|
| 1353 | 1338 | |
|---|
| 1354 | 1339 | DBG("board init: %p\n", cam); |
|---|
| 1355 | 1340 | memset(pipe, 0, sizeof(*pipe)); |
|---|
| .. | .. |
|---|
| 1382 | 1367 | |
|---|
| 1383 | 1368 | if (i == 0) { |
|---|
| 1384 | 1369 | printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n"); |
|---|
| 1385 | | - kfree(cam->pipe->transfer_buffer); |
|---|
| 1386 | | - cam->pipe->transfer_buffer = NULL; |
|---|
| 1387 | | - return -ENOMEM; |
|---|
| 1370 | + err = -ENOMEM; |
|---|
| 1371 | + goto err_free; |
|---|
| 1388 | 1372 | } else |
|---|
| 1389 | 1373 | cam->buffer.dwFrames = i; |
|---|
| 1390 | 1374 | |
|---|
| .. | .. |
|---|
| 1399 | 1383 | /*** end create system buffers ***/ |
|---|
| 1400 | 1384 | |
|---|
| 1401 | 1385 | /* start read pipe */ |
|---|
| 1402 | | - zr364xx_start_readpipe(cam); |
|---|
| 1386 | + err = zr364xx_start_readpipe(cam); |
|---|
| 1387 | + if (err) |
|---|
| 1388 | + goto err_free_frames; |
|---|
| 1389 | + |
|---|
| 1403 | 1390 | DBG(": board initialized\n"); |
|---|
| 1404 | 1391 | return 0; |
|---|
| 1392 | + |
|---|
| 1393 | +err_free_frames: |
|---|
| 1394 | + for (i = 0; i < FRAMES; i++) |
|---|
| 1395 | + vfree(cam->buffer.frame[i].lpvbits); |
|---|
| 1396 | +err_free: |
|---|
| 1397 | + kfree(cam->pipe->transfer_buffer); |
|---|
| 1398 | + cam->pipe->transfer_buffer = NULL; |
|---|
| 1399 | + return err; |
|---|
| 1405 | 1400 | } |
|---|
| 1406 | 1401 | |
|---|
| 1407 | 1402 | static int zr364xx_probe(struct usb_interface *intf, |
|---|
| .. | .. |
|---|
| 1426 | 1421 | if (!cam) |
|---|
| 1427 | 1422 | return -ENOMEM; |
|---|
| 1428 | 1423 | |
|---|
| 1429 | | - cam->v4l2_dev.release = zr364xx_release; |
|---|
| 1430 | 1424 | err = v4l2_device_register(&intf->dev, &cam->v4l2_dev); |
|---|
| 1431 | 1425 | if (err < 0) { |
|---|
| 1432 | 1426 | dev_err(&udev->dev, "couldn't register v4l2_device\n"); |
|---|
| 1433 | | - kfree(cam); |
|---|
| 1434 | | - return err; |
|---|
| 1427 | + goto free_cam; |
|---|
| 1435 | 1428 | } |
|---|
| 1436 | 1429 | hdl = &cam->ctrl_handler; |
|---|
| 1437 | 1430 | v4l2_ctrl_handler_init(hdl, 1); |
|---|
| .. | .. |
|---|
| 1440 | 1433 | if (hdl->error) { |
|---|
| 1441 | 1434 | err = hdl->error; |
|---|
| 1442 | 1435 | dev_err(&udev->dev, "couldn't register control\n"); |
|---|
| 1443 | | - goto fail; |
|---|
| 1436 | + goto free_hdlr_and_unreg_dev; |
|---|
| 1444 | 1437 | } |
|---|
| 1445 | 1438 | /* save the init method used by this camera */ |
|---|
| 1446 | 1439 | cam->method = id->driver_info; |
|---|
| .. | .. |
|---|
| 1513 | 1506 | if (!cam->read_endpoint) { |
|---|
| 1514 | 1507 | err = -ENOMEM; |
|---|
| 1515 | 1508 | dev_err(&intf->dev, "Could not find bulk-in endpoint\n"); |
|---|
| 1516 | | - goto fail; |
|---|
| 1509 | + goto free_hdlr_and_unreg_dev; |
|---|
| 1517 | 1510 | } |
|---|
| 1518 | 1511 | |
|---|
| 1519 | 1512 | /* v4l */ |
|---|
| .. | .. |
|---|
| 1524 | 1517 | |
|---|
| 1525 | 1518 | /* load zr364xx board specific */ |
|---|
| 1526 | 1519 | err = zr364xx_board_init(cam); |
|---|
| 1527 | | - if (!err) |
|---|
| 1528 | | - err = v4l2_ctrl_handler_setup(hdl); |
|---|
| 1529 | 1520 | if (err) |
|---|
| 1530 | | - goto fail; |
|---|
| 1521 | + goto free_hdlr_and_unreg_dev; |
|---|
| 1522 | + err = v4l2_ctrl_handler_setup(hdl); |
|---|
| 1523 | + if (err) |
|---|
| 1524 | + goto board_uninit; |
|---|
| 1531 | 1525 | |
|---|
| 1532 | 1526 | spin_lock_init(&cam->slock); |
|---|
| 1533 | 1527 | |
|---|
| .. | .. |
|---|
| 1539 | 1533 | V4L2_FIELD_NONE, |
|---|
| 1540 | 1534 | sizeof(struct zr364xx_buffer), cam, &cam->lock); |
|---|
| 1541 | 1535 | |
|---|
| 1542 | | - err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 1536 | + err = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 1543 | 1537 | if (err) { |
|---|
| 1544 | 1538 | dev_err(&udev->dev, "video_register_device failed\n"); |
|---|
| 1545 | | - goto fail; |
|---|
| 1539 | + goto board_uninit; |
|---|
| 1546 | 1540 | } |
|---|
| 1541 | + cam->v4l2_dev.release = zr364xx_release; |
|---|
| 1547 | 1542 | |
|---|
| 1548 | 1543 | dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n", |
|---|
| 1549 | 1544 | video_device_node_name(&cam->vdev)); |
|---|
| 1550 | 1545 | return 0; |
|---|
| 1551 | 1546 | |
|---|
| 1552 | | -fail: |
|---|
| 1547 | +board_uninit: |
|---|
| 1548 | + zr364xx_board_uninit(cam); |
|---|
| 1549 | +free_hdlr_and_unreg_dev: |
|---|
| 1553 | 1550 | v4l2_ctrl_handler_free(hdl); |
|---|
| 1554 | 1551 | v4l2_device_unregister(&cam->v4l2_dev); |
|---|
| 1552 | +free_cam: |
|---|
| 1555 | 1553 | kfree(cam); |
|---|
| 1556 | 1554 | return err; |
|---|
| 1557 | 1555 | } |
|---|
| .. | .. |
|---|
| 1598 | 1596 | if (!cam->was_streaming) |
|---|
| 1599 | 1597 | return 0; |
|---|
| 1600 | 1598 | |
|---|
| 1601 | | - zr364xx_start_readpipe(cam); |
|---|
| 1599 | + res = zr364xx_start_readpipe(cam); |
|---|
| 1600 | + if (res) |
|---|
| 1601 | + return res; |
|---|
| 1602 | + |
|---|
| 1602 | 1603 | res = zr364xx_prepare(cam); |
|---|
| 1603 | | - if (!res) |
|---|
| 1604 | | - zr364xx_start_acquire(cam); |
|---|
| 1604 | + if (res) |
|---|
| 1605 | + goto err_prepare; |
|---|
| 1606 | + |
|---|
| 1607 | + zr364xx_start_acquire(cam); |
|---|
| 1608 | + return 0; |
|---|
| 1609 | + |
|---|
| 1610 | +err_prepare: |
|---|
| 1611 | + zr364xx_stop_readpipe(cam); |
|---|
| 1605 | 1612 | return res; |
|---|
| 1606 | 1613 | } |
|---|
| 1607 | 1614 | #endif |
|---|