| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Linux driver for Philips webcam |
|---|
| 2 | 3 | USB and Video4Linux interface part. |
|---|
| 3 | 4 | (C) 1999-2004 Nemosoft Unv. |
|---|
| .. | .. |
|---|
| 10 | 11 | The decompression routines have been implemented by reverse-engineering the |
|---|
| 11 | 12 | Nemosoft binary pwcx module. Caveat emptor. |
|---|
| 12 | 13 | |
|---|
| 13 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 14 | | - it under the terms of the GNU General Public License as published by |
|---|
| 15 | | - the Free Software Foundation; either version 2 of the License, or |
|---|
| 16 | | - (at your option) any later version. |
|---|
| 17 | | - |
|---|
| 18 | | - This program is distributed in the hope that it will be useful, |
|---|
| 19 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | | - GNU General Public License for more details. |
|---|
| 22 | | - |
|---|
| 23 | | - You should have received a copy of the GNU General Public License |
|---|
| 24 | | - along with this program; if not, write to the Free Software |
|---|
| 25 | | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 26 | 14 | |
|---|
| 27 | 15 | */ |
|---|
| 28 | 16 | |
|---|
| .. | .. |
|---|
| 76 | 64 | #include "pwc-dec23.h" |
|---|
| 77 | 65 | #include "pwc-dec1.h" |
|---|
| 78 | 66 | |
|---|
| 67 | +#define CREATE_TRACE_POINTS |
|---|
| 68 | +#include <trace/events/pwc.h> |
|---|
| 69 | + |
|---|
| 79 | 70 | /* Function prototypes and driver templates */ |
|---|
| 80 | 71 | |
|---|
| 81 | 72 | /* hotplug device table support */ |
|---|
| 82 | 73 | static const struct usb_device_id pwc_device_table [] = { |
|---|
| 83 | | - { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ |
|---|
| 84 | | - { USB_DEVICE(0x0471, 0x0303) }, |
|---|
| 85 | | - { USB_DEVICE(0x0471, 0x0304) }, |
|---|
| 86 | | - { USB_DEVICE(0x0471, 0x0307) }, |
|---|
| 87 | | - { USB_DEVICE(0x0471, 0x0308) }, |
|---|
| 88 | | - { USB_DEVICE(0x0471, 0x030C) }, |
|---|
| 89 | | - { USB_DEVICE(0x0471, 0x0310) }, |
|---|
| 90 | | - { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */ |
|---|
| 91 | | - { USB_DEVICE(0x0471, 0x0312) }, |
|---|
| 92 | | - { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ |
|---|
| 93 | | - { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ |
|---|
| 94 | | - { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */ |
|---|
| 95 | | - { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ |
|---|
| 96 | | - { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ |
|---|
| 74 | + { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ |
|---|
| 75 | + { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ |
|---|
| 76 | + |
|---|
| 77 | + { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam 3000 Pro */ |
|---|
| 97 | 78 | { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ |
|---|
| 98 | | - { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ |
|---|
| 79 | + { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam 4000 Pro */ |
|---|
| 99 | 80 | { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */ |
|---|
| 100 | 81 | { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */ |
|---|
| 101 | 82 | { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */ |
|---|
| 102 | | - { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */ |
|---|
| 83 | + { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech/Cisco VT Camera */ |
|---|
| 103 | 84 | { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */ |
|---|
| 104 | | - { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ |
|---|
| 85 | + { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech QuickCam */ |
|---|
| 86 | + |
|---|
| 87 | + { USB_DEVICE(0x0471, 0x0302) }, /* Philips PCA645VC */ |
|---|
| 88 | + { USB_DEVICE(0x0471, 0x0303) }, /* Philips PCA646VC */ |
|---|
| 89 | + { USB_DEVICE(0x0471, 0x0304) }, /* Askey VC010 type 2 */ |
|---|
| 90 | + { USB_DEVICE(0x0471, 0x0307) }, /* Philips PCVC675K (Vesta) */ |
|---|
| 91 | + { USB_DEVICE(0x0471, 0x0308) }, /* Philips PCVC680K (Vesta Pro) */ |
|---|
| 92 | + { USB_DEVICE(0x0471, 0x030C) }, /* Philips PCVC690K (Vesta Pro Scan) */ |
|---|
| 93 | + { USB_DEVICE(0x0471, 0x0310) }, /* Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) */ |
|---|
| 94 | + { USB_DEVICE(0x0471, 0x0311) }, /* Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) */ |
|---|
| 95 | + { USB_DEVICE(0x0471, 0x0312) }, /* Philips PCVC750K (ToUCam Pro Scan) */ |
|---|
| 96 | + { USB_DEVICE(0x0471, 0x0313) }, /* Philips PCVC720K/40 (ToUCam XS) */ |
|---|
| 97 | + { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC webcam */ |
|---|
| 98 | + { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC webcam */ |
|---|
| 99 | + |
|---|
| 100 | + { USB_DEVICE(0x04CC, 0x8116) }, /* Sotec Afina Eye */ |
|---|
| 101 | + |
|---|
| 105 | 102 | { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */ |
|---|
| 106 | 103 | { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */ |
|---|
| 107 | 104 | { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */ |
|---|
| 108 | | - { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ |
|---|
| 109 | | - { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ |
|---|
| 110 | | - { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ |
|---|
| 111 | | - { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */ |
|---|
| 112 | | - { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ |
|---|
| 113 | | - { USB_DEVICE(0x0d81, 0x1900) }, |
|---|
| 105 | + |
|---|
| 106 | + { USB_DEVICE(0x069A, 0x0001) }, /* Askey VC010 type 1 */ |
|---|
| 107 | + |
|---|
| 108 | + { USB_DEVICE(0x06BE, 0x8116) }, /* AME Co. Afina Eye */ |
|---|
| 109 | + |
|---|
| 110 | + { USB_DEVICE(0x0d81, 0x1900) }, /* Visionite VCS-UC300 */ |
|---|
| 111 | + { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite VCS-UM100 */ |
|---|
| 112 | + |
|---|
| 114 | 113 | { } |
|---|
| 115 | 114 | }; |
|---|
| 116 | 115 | MODULE_DEVICE_TABLE(usb, pwc_device_table); |
|---|
| .. | .. |
|---|
| 155 | 154 | |
|---|
| 156 | 155 | /***************************************************************************/ |
|---|
| 157 | 156 | /* Private functions */ |
|---|
| 157 | + |
|---|
| 158 | +static void *pwc_alloc_urb_buffer(struct usb_device *dev, |
|---|
| 159 | + size_t size, dma_addr_t *dma_handle) |
|---|
| 160 | +{ |
|---|
| 161 | + struct device *dmadev = dev->bus->sysdev; |
|---|
| 162 | + void *buffer = kmalloc(size, GFP_KERNEL); |
|---|
| 163 | + |
|---|
| 164 | + if (!buffer) |
|---|
| 165 | + return NULL; |
|---|
| 166 | + |
|---|
| 167 | + *dma_handle = dma_map_single(dmadev, buffer, size, DMA_FROM_DEVICE); |
|---|
| 168 | + if (dma_mapping_error(dmadev, *dma_handle)) { |
|---|
| 169 | + kfree(buffer); |
|---|
| 170 | + return NULL; |
|---|
| 171 | + } |
|---|
| 172 | + |
|---|
| 173 | + return buffer; |
|---|
| 174 | +} |
|---|
| 175 | + |
|---|
| 176 | +static void pwc_free_urb_buffer(struct usb_device *dev, |
|---|
| 177 | + size_t size, |
|---|
| 178 | + void *buffer, |
|---|
| 179 | + dma_addr_t dma_handle) |
|---|
| 180 | +{ |
|---|
| 181 | + struct device *dmadev = dev->bus->sysdev; |
|---|
| 182 | + |
|---|
| 183 | + dma_unmap_single(dmadev, dma_handle, size, DMA_FROM_DEVICE); |
|---|
| 184 | + kfree(buffer); |
|---|
| 185 | +} |
|---|
| 158 | 186 | |
|---|
| 159 | 187 | static struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev) |
|---|
| 160 | 188 | { |
|---|
| .. | .. |
|---|
| 257 | 285 | static void pwc_isoc_handler(struct urb *urb) |
|---|
| 258 | 286 | { |
|---|
| 259 | 287 | struct pwc_device *pdev = (struct pwc_device *)urb->context; |
|---|
| 288 | + struct device *dmadev = urb->dev->bus->sysdev; |
|---|
| 260 | 289 | int i, fst, flen; |
|---|
| 261 | 290 | unsigned char *iso_buf = NULL; |
|---|
| 291 | + |
|---|
| 292 | + trace_pwc_handler_enter(urb, pdev); |
|---|
| 262 | 293 | |
|---|
| 263 | 294 | if (urb->status == -ENOENT || urb->status == -ECONNRESET || |
|---|
| 264 | 295 | urb->status == -ESHUTDOWN) { |
|---|
| .. | .. |
|---|
| 300 | 331 | |
|---|
| 301 | 332 | /* Reset ISOC error counter. We did get here, after all. */ |
|---|
| 302 | 333 | pdev->visoc_errors = 0; |
|---|
| 334 | + |
|---|
| 335 | + dma_sync_single_for_cpu(dmadev, |
|---|
| 336 | + urb->transfer_dma, |
|---|
| 337 | + urb->transfer_buffer_length, |
|---|
| 338 | + DMA_FROM_DEVICE); |
|---|
| 303 | 339 | |
|---|
| 304 | 340 | /* vsync: 0 = don't copy data |
|---|
| 305 | 341 | 1 = sync-hunt |
|---|
| .. | .. |
|---|
| 347 | 383 | pdev->vlast_packet_size = flen; |
|---|
| 348 | 384 | } |
|---|
| 349 | 385 | |
|---|
| 386 | + dma_sync_single_for_device(dmadev, |
|---|
| 387 | + urb->transfer_dma, |
|---|
| 388 | + urb->transfer_buffer_length, |
|---|
| 389 | + DMA_FROM_DEVICE); |
|---|
| 390 | + |
|---|
| 350 | 391 | handler_end: |
|---|
| 392 | + trace_pwc_handler_exit(urb, pdev); |
|---|
| 393 | + |
|---|
| 351 | 394 | i = usb_submit_urb(urb, GFP_ATOMIC); |
|---|
| 352 | 395 | if (i != 0) |
|---|
| 353 | 396 | PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); |
|---|
| .. | .. |
|---|
| 421 | 464 | urb->dev = udev; |
|---|
| 422 | 465 | urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); |
|---|
| 423 | 466 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
|---|
| 424 | | - urb->transfer_buffer = usb_alloc_coherent(udev, |
|---|
| 425 | | - ISO_BUFFER_SIZE, |
|---|
| 426 | | - GFP_KERNEL, |
|---|
| 427 | | - &urb->transfer_dma); |
|---|
| 467 | + urb->transfer_buffer_length = ISO_BUFFER_SIZE; |
|---|
| 468 | + urb->transfer_buffer = pwc_alloc_urb_buffer(udev, |
|---|
| 469 | + urb->transfer_buffer_length, |
|---|
| 470 | + &urb->transfer_dma); |
|---|
| 428 | 471 | if (urb->transfer_buffer == NULL) { |
|---|
| 429 | 472 | PWC_ERROR("Failed to allocate urb buffer %d\n", i); |
|---|
| 430 | 473 | pwc_isoc_cleanup(pdev); |
|---|
| 431 | 474 | return -ENOMEM; |
|---|
| 432 | 475 | } |
|---|
| 433 | | - urb->transfer_buffer_length = ISO_BUFFER_SIZE; |
|---|
| 434 | 476 | urb->complete = pwc_isoc_handler; |
|---|
| 435 | 477 | urb->context = pdev; |
|---|
| 436 | 478 | urb->start_frame = 0; |
|---|
| .. | .. |
|---|
| 481 | 523 | |
|---|
| 482 | 524 | /* Freeing ISOC buffers one by one */ |
|---|
| 483 | 525 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
|---|
| 484 | | - if (pdev->urbs[i]) { |
|---|
| 526 | + struct urb *urb = pdev->urbs[i]; |
|---|
| 527 | + |
|---|
| 528 | + if (urb) { |
|---|
| 485 | 529 | PWC_DEBUG_MEMORY("Freeing URB\n"); |
|---|
| 486 | | - if (pdev->urbs[i]->transfer_buffer) { |
|---|
| 487 | | - usb_free_coherent(pdev->udev, |
|---|
| 488 | | - pdev->urbs[i]->transfer_buffer_length, |
|---|
| 489 | | - pdev->urbs[i]->transfer_buffer, |
|---|
| 490 | | - pdev->urbs[i]->transfer_dma); |
|---|
| 491 | | - } |
|---|
| 492 | | - usb_free_urb(pdev->urbs[i]); |
|---|
| 530 | + if (urb->transfer_buffer) |
|---|
| 531 | + pwc_free_urb_buffer(urb->dev, |
|---|
| 532 | + urb->transfer_buffer_length, |
|---|
| 533 | + urb->transfer_buffer, |
|---|
| 534 | + urb->transfer_dma); |
|---|
| 535 | + usb_free_urb(urb); |
|---|
| 493 | 536 | pdev->urbs[i] = NULL; |
|---|
| 494 | 537 | } |
|---|
| 495 | 538 | } |
|---|
| .. | .. |
|---|
| 610 | 653 | { |
|---|
| 611 | 654 | struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); |
|---|
| 612 | 655 | |
|---|
| 613 | | - /* Don't allow queing new buffers after device disconnection */ |
|---|
| 656 | + /* Don't allow queueing new buffers after device disconnection */ |
|---|
| 614 | 657 | if (!pdev->udev) |
|---|
| 615 | 658 | return -ENODEV; |
|---|
| 616 | 659 | |
|---|
| .. | .. |
|---|
| 1027 | 1070 | |
|---|
| 1028 | 1071 | /* Init video_device structure */ |
|---|
| 1029 | 1072 | pdev->vdev = pwc_template; |
|---|
| 1030 | | - strcpy(pdev->vdev.name, name); |
|---|
| 1073 | + strscpy(pdev->vdev.name, name, sizeof(pdev->vdev.name)); |
|---|
| 1031 | 1074 | pdev->vdev.queue = &pdev->vb_queue; |
|---|
| 1032 | 1075 | pdev->vdev.queue->lock = &pdev->vb_queue_lock; |
|---|
| 1033 | 1076 | video_set_drvdata(&pdev->vdev, pdev); |
|---|
| .. | .. |
|---|
| 1082 | 1125 | pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; |
|---|
| 1083 | 1126 | pdev->vdev.v4l2_dev = &pdev->v4l2_dev; |
|---|
| 1084 | 1127 | pdev->vdev.lock = &pdev->v4l2_lock; |
|---|
| 1128 | + pdev->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | |
|---|
| 1129 | + V4L2_CAP_READWRITE; |
|---|
| 1085 | 1130 | |
|---|
| 1086 | | - rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 1131 | + rc = video_register_device(&pdev->vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 1087 | 1132 | if (rc < 0) { |
|---|
| 1088 | 1133 | PWC_ERROR("Failed to register as video device (%d).\n", rc); |
|---|
| 1089 | 1134 | goto err_unregister_v4l2_dev; |
|---|