.. | .. |
---|
| 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; |
---|