blob: 3d3ff603098772129c2e5ce0042ba2e746af9156 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Linux driver for Philips webcam
2 USB and Video4Linux interface part.
3 (C) 1999-2004 Nemosoft Unv.
Luc Saillard2b455db2006-04-24 10:29:46 -03004 (C) 2004-2006 Luc Saillard (luc@saillard.org)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005
6 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
7 driver and thus may have bugs that are not present in the original version.
8 Please send bug reports and support requests to <luc@saillard.org>.
9 The decompression routines have been implemented by reverse-engineering the
10 Nemosoft binary pwcx module. Caveat emptor.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26*/
27
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030028/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 This code forms the interface between the USB layers and the Philips
30 specific stuff. Some adanved stuff of the driver falls under an
31 NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030032 is thus not distributed in source form. The binary pwcx.o module
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 contains the code that falls under the NDA.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030034
35 In case you're wondering: 'pwc' stands for "Philips WebCam", but
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 I really didn't want to type 'philips_web_cam' every time (I'm lazy as
37 any Linux kernel hacker, but I don't like uncomprehensible abbreviations
38 without explanation).
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030039
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 Oh yes, convention: to disctinguish between all the various pointers to
41 device-structures, I use these names for the pointer variables:
42 udev: struct usb_device *
Hans de Goede9a7b2d12011-06-06 14:43:39 -030043 vdev: struct video_device (member of pwc_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 pdev: struct pwc_devive *
45*/
46
47/* Contributors:
48 - Alvarado: adding whitebalance code
49 - Alistar Moire: QuickCam 3000 Pro device/product ID
50 - Tony Hoyle: Creative Labs Webcam 5 device/product ID
51 - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
52 - Jk Fang: Sotec Afina Eye ID
53 - Xavier Roche: QuickCam Pro 4000 ID
54 - Jens Knudsen: QuickCam Zoom ID
55 - J. Debert: QuickCam for Notebooks ID
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -030056 - Pham Thanh Nam: webcam snapshot button as an event input device
Linus Torvalds1da177e2005-04-16 15:20:36 -070057*/
58
59#include <linux/errno.h>
60#include <linux/init.h>
61#include <linux/mm.h>
62#include <linux/module.h>
63#include <linux/poll.h>
64#include <linux/slab.h>
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -030065#ifdef CONFIG_USB_PWC_INPUT_EVDEV
66#include <linux/usb/input.h>
67#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/vmalloc.h>
69#include <asm/io.h>
Andy Shevchenko2d8d7762009-09-24 07:58:09 -030070#include <linux/kernel.h> /* simple_strtol() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72#include "pwc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#include "pwc-kiara.h"
74#include "pwc-timon.h"
Luc Saillard2b455db2006-04-24 10:29:46 -030075#include "pwc-dec23.h"
76#include "pwc-dec1.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#include "pwc-uncompress.h"
78
79/* Function prototypes and driver templates */
80
81/* hotplug device table support */
Luc Saillard2b455db2006-04-24 10:29:46 -030082static const struct usb_device_id pwc_device_table [] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 { 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) },
Luc Saillard2b455db2006-04-24 10:29:46 -030090 { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 { USB_DEVICE(0x0471, 0x0312) },
92 { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
Luc Saillard2b455db2006-04-24 10:29:46 -030093 { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
95 { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
96 { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
97 { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
98 { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
99 { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
100 { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -0300101 { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */
102 { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
Luc Saillard2b455db2006-04-24 10:29:46 -0300104 { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
105 { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
106 { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
108 { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
109 { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
110 { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
111 { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
112 { USB_DEVICE(0x0d81, 0x1900) },
113 { }
114};
115MODULE_DEVICE_TABLE(usb, pwc_device_table);
116
117static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
118static void usb_pwc_disconnect(struct usb_interface *intf);
119
120static struct usb_driver pwc_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 .name = "Philips webcam", /* name */
122 .id_table = pwc_device_table,
123 .probe = usb_pwc_probe, /* probe() */
124 .disconnect = usb_pwc_disconnect, /* disconnect() */
125};
126
127#define MAX_DEV_HINTS 20
128#define MAX_ISOC_ERRORS 20
129
130static int default_size = PSZ_QCIF;
131static int default_fps = 10;
132static int default_fbufs = 3; /* Default number of frame buffers */
Michael Krufkyb930e1d2007-08-27 18:16:54 -0300133 int pwc_mbufs = 2; /* Default number of mmap() buffers */
Trent Piepho05ad3902007-01-30 23:26:01 -0300134#ifdef CONFIG_USB_PWC_DEBUG
Michael Krufkyb930e1d2007-08-27 18:16:54 -0300135 int pwc_trace = PWC_DEBUG_LEVEL;
Luc Saillard2b455db2006-04-24 10:29:46 -0300136#endif
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300137static int power_save;
138static int led_on = 100, led_off; /* defaults to LED that is on while in use */
Adrian Bunkb20c3cf2006-06-23 06:49:34 -0300139static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140static struct {
141 int type;
142 char serial_number[30];
143 int device_node;
144 struct pwc_device *pdev;
145} device_hint[MAX_DEV_HINTS];
146
147/***/
148
Hans Verkuilbec43662008-12-30 06:58:20 -0300149static int pwc_video_open(struct file *file);
150static int pwc_video_close(struct file *file);
Luc Saillard2b455db2006-04-24 10:29:46 -0300151static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 size_t count, loff_t *ppos);
153static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300155static void pwc_video_release(struct video_device *vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Hans Verkuilbec43662008-12-30 06:58:20 -0300157static const struct v4l2_file_operations pwc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 .owner = THIS_MODULE,
159 .open = pwc_video_open,
160 .release = pwc_video_close,
161 .read = pwc_video_read,
162 .poll = pwc_video_poll,
163 .mmap = pwc_video_mmap,
Hans Verkuilafa38522011-01-22 06:34:55 -0300164 .unlocked_ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165};
166static struct video_device pwc_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 .name = "Philips Webcam", /* Filled in later */
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300168 .release = pwc_video_release,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 .fops = &pwc_fops,
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300170 .ioctl_ops = &pwc_ioctl_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171};
172
173/***************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174/* Private functions */
175
176/* Here we want the physical address of the memory.
177 * This is used when initializing the contents of the area.
178 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Luc Saillard2b455db2006-04-24 10:29:46 -0300181
182static void *pwc_rvmalloc(unsigned long size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
184 void * mem;
185 unsigned long adr;
186
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300187 mem=vmalloc_32(size);
Luc Saillard2b455db2006-04-24 10:29:46 -0300188 if (!mem)
189 return NULL;
190
191 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
192 adr=(unsigned long) mem;
193 while (size > 0)
194 {
195 SetPageReserved(vmalloc_to_page((void *)adr));
196 adr += PAGE_SIZE;
197 size -= PAGE_SIZE;
198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 return mem;
200}
201
Luc Saillard2b455db2006-04-24 10:29:46 -0300202static void pwc_rvfree(void * mem, unsigned long size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300204 unsigned long adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Luc Saillard2b455db2006-04-24 10:29:46 -0300206 if (!mem)
207 return;
208
209 adr=(unsigned long) mem;
210 while ((long) size > 0)
211 {
212 ClearPageReserved(vmalloc_to_page((void *)adr));
213 adr += PAGE_SIZE;
214 size -= PAGE_SIZE;
215 }
216 vfree(mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217}
218
219
220
221
222static int pwc_allocate_buffers(struct pwc_device *pdev)
223{
Luc Saillard2b455db2006-04-24 10:29:46 -0300224 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 void *kbuf;
226
Luc Saillard2b455db2006-04-24 10:29:46 -0300227 PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Luc Saillard2b455db2006-04-24 10:29:46 -0300229 /* Allocate Isochronuous pipe buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 for (i = 0; i < MAX_ISO_BUFS; i++) {
231 if (pdev->sbuf[i].data == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300232 kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300234 PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 return -ENOMEM;
236 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300237 PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 pdev->sbuf[i].data = kbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 }
241
242 /* Allocate frame buffer structure */
243 if (pdev->fbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300244 kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300246 PWC_ERROR("Failed to allocate frame buffer structure.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 return -ENOMEM;
248 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300249 PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 pdev->fbuf = kbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 /* create frame buffers, and make circular ring */
254 for (i = 0; i < default_fbufs; i++) {
255 if (pdev->fbuf[i].data == NULL) {
Joe Perches101b25b2010-11-05 00:07:39 -0300256 kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300258 PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return -ENOMEM;
260 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300261 PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 pdev->fbuf[i].data = kbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 }
264 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 /* Allocate decompressor table space */
Luc Saillard2b455db2006-04-24 10:29:46 -0300267 if (DEVICE_USE_CODEC1(pdev->type))
268 err = pwc_dec1_alloc(pdev);
269 else
270 err = pwc_dec23_alloc(pdev);
271
272 if (err) {
273 PWC_ERROR("Failed to allocate decompress table.\n");
274 return err;
275 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 /* Allocate image buffer; double buffer for mmap() */
Luc Saillard2b455db2006-04-24 10:29:46 -0300278 kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300280 PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n",
281 pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 return -ENOMEM;
283 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300284 PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 pdev->image_data = kbuf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300286 for (i = 0; i < pwc_mbufs; i++) {
287 pdev->images[i].offset = i * pdev->len_per_image;
288 pdev->images[i].vma_use_count = 0;
289 }
290 for (; i < MAX_IMAGES; i++) {
291 pdev->images[i].offset = 0;
292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
294 kbuf = NULL;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300295
Luc Saillard2b455db2006-04-24 10:29:46 -0300296 PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 return 0;
298}
299
300static void pwc_free_buffers(struct pwc_device *pdev)
301{
302 int i;
303
Luc Saillard2b455db2006-04-24 10:29:46 -0300304 PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 /* Release Iso-pipe buffers */
307 for (i = 0; i < MAX_ISO_BUFS; i++)
308 if (pdev->sbuf[i].data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300309 PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 kfree(pdev->sbuf[i].data);
311 pdev->sbuf[i].data = NULL;
312 }
313
314 /* The same for frame buffers */
315 if (pdev->fbuf != NULL) {
316 for (i = 0; i < default_fbufs; i++) {
317 if (pdev->fbuf[i].data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300318 PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 vfree(pdev->fbuf[i].data);
320 pdev->fbuf[i].data = NULL;
321 }
322 }
323 kfree(pdev->fbuf);
324 pdev->fbuf = NULL;
325 }
326
327 /* Intermediate decompression buffer & tables */
328 if (pdev->decompress_data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300329 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 kfree(pdev->decompress_data);
331 pdev->decompress_data = NULL;
332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 /* Release image buffers */
335 if (pdev->image_data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300336 PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
337 pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
339 pdev->image_data = NULL;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300340
Luc Saillard2b455db2006-04-24 10:29:46 -0300341 PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342}
343
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300344/* The frame & image buffer mess.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346 Yes, this is a mess. Well, it used to be simple, but alas... In this
347 module, 3 buffers schemes are used to get the data from the USB bus to
348 the user program. The first scheme involves the ISO buffers (called thus
349 since they transport ISO data from the USB controller), and not really
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300350 interesting. Suffices to say the data from this buffer is quickly
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 gathered in an interrupt handler (pwc_isoc_handler) and placed into the
352 frame buffer.
353
354 The frame buffer is the second scheme, and is the central element here.
355 It collects the data from a single frame from the camera (hence, the
356 name). Frames are delimited by the USB camera with a short USB packet,
357 so that's easy to detect. The frame buffers form a list that is filled
358 by the camera+USB controller and drained by the user process through
359 either read() or mmap().
360
361 The image buffer is the third scheme, in which frames are decompressed
362 and converted into planar format. For mmap() there is more than
363 one image buffer available.
364
365 The frame buffers provide the image buffering. In case the user process
366 is a bit slow, this introduces lag and some undesired side-effects.
367 The problem arises when the frame buffer is full. I used to drop the last
368 frame, which makes the data in the queue stale very quickly. But dropping
369 the frame at the head of the queue proved to be a litte bit more difficult.
370 I tried a circular linked scheme, but this introduced more problems than
371 it solved.
372
373 Because filling and draining are completely asynchronous processes, this
374 requires some fiddling with pointers and mutexes.
375
376 Eventually, I came up with a system with 2 lists: an 'empty' frame list
377 and a 'full' frame list:
378 * Initially, all frame buffers but one are on the 'empty' list; the one
379 remaining buffer is our initial fill frame.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300380 * If a frame is needed for filling, we try to take it from the 'empty'
381 list, unless that list is empty, in which case we take the buffer at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 the head of the 'full' list.
383 * When our fill buffer has been filled, it is appended to the 'full'
384 list.
385 * If a frame is needed by read() or mmap(), it is taken from the head of
386 the 'full' list, handled, and then appended to the 'empty' list. If no
387 buffer is present on the 'full' list, we wait.
388 The advantage is that the buffer that is currently being decompressed/
389 converted, is on neither list, and thus not in our way (any other scheme
390 I tried had the problem of old data lingering in the queue).
391
392 Whatever strategy you choose, it always remains a tradeoff: with more
393 frame buffers the chances of a missed frame are reduced. On the other
394 hand, on slower machines it introduces lag because the queue will
395 always be full.
396 */
397
398/**
399 \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
400 */
Luc Saillard2b455db2006-04-24 10:29:46 -0300401static int pwc_next_fill_frame(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402{
403 int ret;
404 unsigned long flags;
405
406 ret = 0;
407 spin_lock_irqsave(&pdev->ptrlock, flags);
408 if (pdev->fill_frame != NULL) {
409 /* append to 'full' list */
410 if (pdev->full_frames == NULL) {
411 pdev->full_frames = pdev->fill_frame;
412 pdev->full_frames_tail = pdev->full_frames;
413 }
414 else {
415 pdev->full_frames_tail->next = pdev->fill_frame;
416 pdev->full_frames_tail = pdev->fill_frame;
417 }
418 }
419 if (pdev->empty_frames != NULL) {
420 /* We have empty frames available. That's easy */
421 pdev->fill_frame = pdev->empty_frames;
422 pdev->empty_frames = pdev->empty_frames->next;
423 }
424 else {
425 /* Hmm. Take it from the full list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* sanity check */
427 if (pdev->full_frames == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300428 PWC_ERROR("Neither empty or full frames available!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 spin_unlock_irqrestore(&pdev->ptrlock, flags);
430 return -EINVAL;
431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 pdev->fill_frame = pdev->full_frames;
433 pdev->full_frames = pdev->full_frames->next;
434 ret = 1;
435 }
436 pdev->fill_frame->next = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 spin_unlock_irqrestore(&pdev->ptrlock, flags);
438 return ret;
439}
440
441
442/**
443 \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
444
445 If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
446 */
447static void pwc_reset_buffers(struct pwc_device *pdev)
448{
449 int i;
450 unsigned long flags;
451
Harvey Harrison645635b2008-04-08 23:20:00 -0300452 PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
Luc Saillard2b455db2006-04-24 10:29:46 -0300453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 spin_lock_irqsave(&pdev->ptrlock, flags);
455 pdev->full_frames = NULL;
456 pdev->full_frames_tail = NULL;
457 for (i = 0; i < default_fbufs; i++) {
458 pdev->fbuf[i].filled = 0;
459 if (i > 0)
460 pdev->fbuf[i].next = &pdev->fbuf[i - 1];
461 else
462 pdev->fbuf->next = NULL;
463 }
464 pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
465 pdev->empty_frames_tail = pdev->fbuf;
466 pdev->read_frame = NULL;
467 pdev->fill_frame = pdev->empty_frames;
468 pdev->empty_frames = pdev->empty_frames->next;
469
470 pdev->image_read_pos = 0;
471 pdev->fill_image = 0;
472 spin_unlock_irqrestore(&pdev->ptrlock, flags);
Luc Saillard2b455db2006-04-24 10:29:46 -0300473
Harvey Harrison645635b2008-04-08 23:20:00 -0300474 PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475}
476
477
478/**
479 \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
480 */
Luc Saillard2b455db2006-04-24 10:29:46 -0300481int pwc_handle_frame(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 int ret = 0;
484 unsigned long flags;
485
486 spin_lock_irqsave(&pdev->ptrlock, flags);
487 /* First grab our read_frame; this is removed from all lists, so
488 we can release the lock after this without problems */
489 if (pdev->read_frame != NULL) {
490 /* This can't theoretically happen */
Luc Saillard2b455db2006-04-24 10:29:46 -0300491 PWC_ERROR("Huh? Read frame still in use?\n");
492 spin_unlock_irqrestore(&pdev->ptrlock, flags);
493 return ret;
494 }
495
496
497 if (pdev->full_frames == NULL) {
498 PWC_ERROR("Woops. No frames ready.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300501 pdev->read_frame = pdev->full_frames;
502 pdev->full_frames = pdev->full_frames->next;
503 pdev->read_frame->next = NULL;
504 }
505
506 if (pdev->read_frame != NULL) {
Paulius Zaleckasefad798b2008-02-03 15:42:53 +0200507 /* Decompression is a lengthy process, so it's outside of the lock.
Luc Saillard2b455db2006-04-24 10:29:46 -0300508 This gives the isoc_handler the opportunity to fill more frames
509 in the mean time.
510 */
511 spin_unlock_irqrestore(&pdev->ptrlock, flags);
512 ret = pwc_decompress(pdev);
513 spin_lock_irqsave(&pdev->ptrlock, flags);
514
515 /* We're done with read_buffer, tack it to the end of the empty buffer list */
516 if (pdev->empty_frames == NULL) {
517 pdev->empty_frames = pdev->read_frame;
518 pdev->empty_frames_tail = pdev->empty_frames;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
520 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300521 pdev->empty_frames_tail->next = pdev->read_frame;
522 pdev->empty_frames_tail = pdev->read_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300524 pdev->read_frame = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 }
526 spin_unlock_irqrestore(&pdev->ptrlock, flags);
527 return ret;
528}
529
530/**
531 \brief Advance pointers of image buffer (after each user request)
532*/
Luc Saillard2b455db2006-04-24 10:29:46 -0300533void pwc_next_image(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534{
535 pdev->image_used[pdev->fill_image] = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300536 pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537}
538
Luc Saillard2b455db2006-04-24 10:29:46 -0300539/**
540 * Print debug information when a frame is discarded because all of our buffer
541 * is full
542 */
543static void pwc_frame_dumped(struct pwc_device *pdev)
544{
545 pdev->vframes_dumped++;
546 if (pdev->vframe_count < FRAME_LOWMARK)
547 return;
548
549 if (pdev->vframes_dumped < 20)
550 PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count);
551 else if (pdev->vframes_dumped == 20)
552 PWC_DEBUG_FLOW("Dumping frame %d (last message)\n",
553 pdev->vframe_count);
554}
555
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300556static void pwc_snapshot_button(struct pwc_device *pdev, int down)
557{
558 if (down) {
559 PWC_TRACE("Snapshot button pressed.\n");
560 pdev->snapshot_button_status = 1;
561 } else {
562 PWC_TRACE("Snapshot button released.\n");
563 }
564
565#ifdef CONFIG_USB_PWC_INPUT_EVDEV
566 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300567 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300568 input_sync(pdev->button_dev);
569 }
570#endif
571}
572
Luc Saillard2b455db2006-04-24 10:29:46 -0300573static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
574{
575 int awake = 0;
576
577 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
578 frames on the USB wire after an exposure change. This conditition is
579 however detected in the cam and a bit is set in the header.
580 */
581 if (pdev->type == 730) {
582 unsigned char *ptr = (unsigned char *)fbuf->data;
583
584 if (ptr[1] == 1 && ptr[0] & 0x10) {
585 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
586 pdev->drop_frames += 2;
587 pdev->vframes_error++;
588 }
589 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300590 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300591 }
592 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
593 if (ptr[0] & 0x02)
594 PWC_TRACE("Image is mirrored.\n");
595 else
596 PWC_TRACE("Image is normal.\n");
597 }
598 pdev->vmirror = ptr[0] & 0x03;
599 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
600 after a short frame; this condition is filtered out specifically. A 4 byte
601 frame doesn't make sense anyway.
602 So we get either this sequence:
603 drop_bit set -> 4 byte frame -> short frame -> good frame
604 Or this one:
605 drop_bit set -> short frame -> good frame
606 So we drop either 3 or 2 frames in all!
607 */
608 if (fbuf->filled == 4)
609 pdev->drop_frames++;
610 }
611 else if (pdev->type == 740 || pdev->type == 720) {
612 unsigned char *ptr = (unsigned char *)fbuf->data;
613 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300614 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300615 }
616 pdev->vmirror = ptr[0] & 0x03;
617 }
618
619 /* In case we were instructed to drop the frame, do so silently.
620 The buffer pointers are not updated either (but the counters are reset below).
621 */
622 if (pdev->drop_frames > 0)
623 pdev->drop_frames--;
624 else {
625 /* Check for underflow first */
626 if (fbuf->filled < pdev->frame_total_size) {
627 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
628 " discarded.\n", fbuf->filled);
629 pdev->vframes_error++;
630 }
631 else {
632 /* Send only once per EOF */
633 awake = 1; /* delay wake_ups */
634
635 /* Find our next frame to fill. This will always succeed, since we
636 * nick a frame from either empty or full list, but if we had to
637 * take it from the full list, it means a frame got dropped.
638 */
639 if (pwc_next_fill_frame(pdev))
640 pwc_frame_dumped(pdev);
641
642 }
643 } /* !drop_frames */
644 pdev->vframe_count++;
645 return awake;
646}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
648/* This gets called for the Isochronous pipe (video). This is done in
649 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
650 */
David Howells7d12e782006-10-05 14:55:46 +0100651static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
653 struct pwc_device *pdev;
654 int i, fst, flen;
655 int awake;
656 struct pwc_frame_buf *fbuf;
657 unsigned char *fillptr = NULL, *iso_buf = NULL;
658
659 awake = 0;
660 pdev = (struct pwc_device *)urb->context;
661 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300662 PWC_ERROR("isoc_handler() called with NULL device?!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 return;
664 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300667 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 return;
669 }
670 if (urb->status != -EINPROGRESS && urb->status != 0) {
671 const char *errmsg;
672
673 errmsg = "Unknown";
674 switch(urb->status) {
675 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
676 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
677 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
678 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
679 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700680 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300682 PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300683 /* Give up after a number of contiguous errors on the USB bus.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 Appearantly something is wrong so we simulate an unplug event.
685 */
686 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
687 {
Luc Saillard2b455db2006-04-24 10:29:46 -0300688 PWC_INFO("Too many ISOC errors, bailing out.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 pdev->error_status = EIO;
690 awake = 1;
691 wake_up_interruptible(&pdev->frameq);
692 }
693 goto handler_end; // ugly, but practical
694 }
695
696 fbuf = pdev->fill_frame;
697 if (fbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300698 PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 awake = 1;
700 goto handler_end;
701 }
702 else {
703 fillptr = fbuf->data + fbuf->filled;
704 }
705
706 /* Reset ISOC error counter. We did get here, after all. */
707 pdev->visoc_errors = 0;
708
709 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300710 1 = sync-hunt
711 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 */
713 /* Compact data */
714 for (i = 0; i < urb->number_of_packets; i++) {
715 fst = urb->iso_frame_desc[i].status;
716 flen = urb->iso_frame_desc[i].actual_length;
717 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
718 if (fst == 0) {
719 if (flen > 0) { /* if valid data... */
720 if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
721 pdev->vsync = 2;
722
723 /* ...copy data to frame buffer, if possible */
724 if (flen + fbuf->filled > pdev->frame_total_size) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300725 PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
727 pdev->vframes_error++;
728 }
729 else {
730 memmove(fillptr, iso_buf, flen);
731 fillptr += flen;
732 }
733 }
734 fbuf->filled += flen;
735 } /* ..flen > 0 */
736
737 if (flen < pdev->vlast_packet_size) {
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300738 /* Shorter packet... We probably have the end of an image-frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 wake up read() process and let select()/poll() do something.
740 Decompression is done in user time over there.
Luc Saillard2b455db2006-04-24 10:29:46 -0300741 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 if (pdev->vsync == 2) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300743 if (pwc_rcv_short_packet(pdev, fbuf)) {
744 awake = 1;
745 fbuf = pdev->fill_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 }
748 fbuf->filled = 0;
749 fillptr = fbuf->data;
750 pdev->vsync = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300751 }
752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 pdev->vlast_packet_size = flen;
754 } /* ..status == 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300756 /* This is normally not interesting to the user, unless
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300757 * you are really debugging something, default = 0 */
758 static int iso_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 iso_error++;
760 if (iso_error < 20)
Luc Saillard2b455db2006-04-24 10:29:46 -0300761 PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
764
765handler_end:
766 if (awake)
767 wake_up_interruptible(&pdev->frameq);
768
769 urb->dev = pdev->udev;
770 i = usb_submit_urb(urb, GFP_ATOMIC);
771 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300772 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
775
Luc Saillard2b455db2006-04-24 10:29:46 -0300776int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
778 struct usb_device *udev;
779 struct urb *urb;
780 int i, j, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 struct usb_interface *intf;
782 struct usb_host_interface *idesc = NULL;
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (pdev->iso_init)
785 return 0;
786 pdev->vsync = 0;
787 udev = pdev->udev;
788
789 /* Get the current alternate interface, adjust packet size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 intf = usb_ifnum_to_if(udev, 0);
791 if (intf)
792 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 if (!idesc)
Hans de Goedec2464122011-06-06 15:25:18 -0300794 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
796 /* Search video endpoint */
797 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300798 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
800 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
801 break;
802 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300803 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300804
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300806 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600807 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 }
809
810 /* Set alternate interface */
811 ret = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300812 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
814 if (ret < 0)
815 return ret;
816
817 for (i = 0; i < MAX_ISO_BUFS; i++) {
818 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
819 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300820 PWC_ERROR("Failed to allocate urb %d\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 ret = -ENOMEM;
822 break;
823 }
824 pdev->sbuf[i].urb = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300825 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 }
827 if (ret) {
828 /* De-allocate in reverse order */
Mariusz Kozlowski444f4f92006-11-16 16:38:57 +0100829 while (i--) {
Mariusz Kozlowski90b26252006-11-08 15:34:55 +0100830 usb_free_urb(pdev->sbuf[i].urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 pdev->sbuf[i].urb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
833 return ret;
834 }
835
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300836 /* init URB structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 for (i = 0; i < MAX_ISO_BUFS; i++) {
838 urb = pdev->sbuf[i].urb;
839
840 urb->interval = 1; // devik
841 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300842 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 urb->transfer_flags = URB_ISO_ASAP;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300844 urb->transfer_buffer = pdev->sbuf[i].data;
845 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
846 urb->complete = pwc_isoc_handler;
847 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 urb->start_frame = 0;
849 urb->number_of_packets = ISO_FRAMES_PER_DESC;
850 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
851 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
852 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
853 }
854 }
855
856 /* link */
857 for (i = 0; i < MAX_ISO_BUFS; i++) {
858 ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
Hans de Goede622d9f52010-11-16 12:32:09 -0300859 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300860 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Hans de Goede622d9f52010-11-16 12:32:09 -0300861 pdev->iso_init = 1;
862 pwc_isoc_cleanup(pdev);
863 return ret;
864 }
865 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
867
868 /* All is done... */
869 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300870 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return 0;
872}
873
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300874static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
876 int i;
877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 /* Unlinking ISOC buffers one by one */
879 for (i = 0; i < MAX_ISO_BUFS; i++) {
880 struct urb *urb;
881
882 urb = pdev->sbuf[i].urb;
Al Viro5fa12472008-03-29 03:07:38 +0000883 if (urb) {
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300884 PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
885 usb_kill_urb(urb);
886 }
887 }
888}
889
890static void pwc_iso_free(struct pwc_device *pdev)
891{
892 int i;
893
894 /* Freeing ISOC buffers one by one */
895 for (i = 0; i < MAX_ISO_BUFS; i++) {
896 struct urb *urb;
897
898 urb = pdev->sbuf[i].urb;
Al Viro5fa12472008-03-29 03:07:38 +0000899 if (urb) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300900 PWC_DEBUG_MEMORY("Freeing URB\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 usb_free_urb(urb);
902 pdev->sbuf[i].urb = NULL;
903 }
904 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300905}
906
907void pwc_isoc_cleanup(struct pwc_device *pdev)
908{
909 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
Hans de Goedec2464122011-06-06 15:25:18 -0300910
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300911 if (pdev->iso_init == 0)
912 return;
913
914 pwc_iso_stop(pdev);
915 pwc_iso_free(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
917 /* Stop camera, but only if we are sure the camera is still there (unplug
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300918 is signalled by EPIPE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 */
Hans de Goedec7d188672010-11-16 12:26:00 -0300920 if (pdev->error_status != EPIPE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300921 PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 usb_set_interface(pdev->udev, 0, 0);
923 }
924
925 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300926 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927}
928
Luc Saillard2b455db2006-04-24 10:29:46 -0300929/*********
930 * sysfs
931 *********/
Kay Sievers54bd5b62007-10-08 16:26:13 -0300932static struct pwc_device *cd_to_pwc(struct device *cd)
Luc Saillard2b455db2006-04-24 10:29:46 -0300933{
934 struct video_device *vdev = to_video_device(cd);
935 return video_get_drvdata(vdev);
936}
937
Kay Sievers54bd5b62007-10-08 16:26:13 -0300938static ssize_t show_pan_tilt(struct device *class_dev,
939 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300940{
941 struct pwc_device *pdev = cd_to_pwc(class_dev);
942 return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
943}
944
Kay Sievers54bd5b62007-10-08 16:26:13 -0300945static ssize_t store_pan_tilt(struct device *class_dev,
946 struct device_attribute *attr,
947 const char *buf, size_t count)
Luc Saillard2b455db2006-04-24 10:29:46 -0300948{
949 struct pwc_device *pdev = cd_to_pwc(class_dev);
950 int pan, tilt;
951 int ret = -EINVAL;
952
953 if (strncmp(buf, "reset", 5) == 0)
954 ret = pwc_mpt_reset(pdev, 0x3);
955
956 else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
957 ret = pwc_mpt_set_angle(pdev, pan, tilt);
958
959 if (ret < 0)
960 return ret;
961 return strlen(buf);
962}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300963static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
964 store_pan_tilt);
Luc Saillard2b455db2006-04-24 10:29:46 -0300965
Kay Sievers54bd5b62007-10-08 16:26:13 -0300966static ssize_t show_snapshot_button_status(struct device *class_dev,
967 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300968{
969 struct pwc_device *pdev = cd_to_pwc(class_dev);
970 int status = pdev->snapshot_button_status;
971 pdev->snapshot_button_status = 0;
972 return sprintf(buf, "%d\n", status);
973}
974
Kay Sievers54bd5b62007-10-08 16:26:13 -0300975static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
976 NULL);
Luc Saillard2b455db2006-04-24 10:29:46 -0300977
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300978static int pwc_create_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300979{
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300980 int rc;
981
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300982 rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300983 if (rc)
984 goto err;
985 if (pdev->features & FEATURE_MOTOR_PANTILT) {
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300986 rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300987 if (rc)
988 goto err_button;
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300989 }
990
991 return 0;
992
993err_button:
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300994 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300995err:
Hans Verkuilf894dfd2008-07-25 07:39:54 -0300996 PWC_ERROR("Could not create sysfs files.\n");
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300997 return rc;
Luc Saillard2b455db2006-04-24 10:29:46 -0300998}
999
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001000static void pwc_remove_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -03001001{
Luc Saillard2b455db2006-04-24 10:29:46 -03001002 if (pdev->features & FEATURE_MOTOR_PANTILT)
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001003 device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
1004 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Luc Saillard2b455db2006-04-24 10:29:46 -03001005}
1006
Trent Piepho05ad3902007-01-30 23:26:01 -03001007#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001008static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
1009{
1010 switch(sensor_type) {
1011 case 0x00:
1012 return "Hyundai CMOS sensor";
1013 case 0x20:
1014 return "Sony CCD sensor + TDA8787";
1015 case 0x2E:
1016 return "Sony CCD sensor + Exas 98L59";
1017 case 0x2F:
1018 return "Sony CCD sensor + ADI 9804";
1019 case 0x30:
1020 return "Sharp CCD sensor + TDA8787";
1021 case 0x3E:
1022 return "Sharp CCD sensor + Exas 98L59";
1023 case 0x3F:
1024 return "Sharp CCD sensor + ADI 9804";
1025 case 0x40:
1026 return "UPA 1021 sensor";
1027 case 0x100:
1028 return "VGA sensor";
1029 case 0x101:
1030 return "PAL MR sensor";
1031 default:
Trent Piepho657de3c2006-06-20 00:30:57 -03001032 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -03001033 }
1034}
1035#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037/***************************************************************************/
1038/* Video4Linux functions */
1039
Hans Verkuilbec43662008-12-30 06:58:20 -03001040static int pwc_video_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041{
Luc Saillard2b455db2006-04-24 10:29:46 -03001042 int i, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 struct video_device *vdev = video_devdata(file);
1044 struct pwc_device *pdev;
1045
Luc Saillard2b455db2006-04-24 10:29:46 -03001046 PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001047
Hans Verkuil601e9442008-08-23 07:24:07 -03001048 pdev = video_get_drvdata(vdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001049 if (pdev->vopen) {
1050 PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 return -EBUSY;
Luc Saillard2b455db2006-04-24 10:29:46 -03001052 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001053
Martin Fuzzey5c8e2402009-03-09 20:16:00 -03001054 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 if (!pdev->usb_init) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001056 PWC_DEBUG_OPEN("Doing first time initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 pdev->usb_init = 1;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001058
Luc Saillard2b455db2006-04-24 10:29:46 -03001059 /* Query sensor type */
1060 ret = pwc_get_cmos_sensor(pdev, &i);
1061 if (ret >= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 {
Luc Saillard2b455db2006-04-24 10:29:46 -03001063 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001064 pdev->vdev.name,
Luc Saillard2b455db2006-04-24 10:29:46 -03001065 pwc_sensor_type_to_string(i), i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067 }
1068
1069 /* Turn on camera */
1070 if (power_save) {
1071 i = pwc_camera_power(pdev, 1);
1072 if (i < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001073 PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 }
1075 /* Set LED on/off time */
1076 if (pwc_set_leds(pdev, led_on, led_off) < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001077 PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001078
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080 /* So far, so good. Allocate memory. */
1081 i = pwc_allocate_buffers(pdev);
1082 if (i < 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001083 PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
1084 pwc_free_buffers(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 return i;
1086 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 /* Reset buffers & parameters */
1089 pwc_reset_buffers(pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001090 for (i = 0; i < pwc_mbufs; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 pdev->image_used[i] = 0;
1092 pdev->vframe_count = 0;
1093 pdev->vframes_dumped = 0;
1094 pdev->vframes_error = 0;
1095 pdev->visoc_errors = 0;
1096 pdev->error_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 pwc_construct(pdev); /* set min/max sizes correct */
1098
1099 /* Set some defaults */
1100 pdev->vsnapshot = 0;
1101
Hans de Goede3751e282010-11-16 11:39:25 -03001102 /* Set video size, first try the last used video size
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 (or the default one); if that fails try QCIF/10 or QSIF/10;
1104 it that fails too, give up.
1105 */
1106 i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
1107 if (i) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001108 unsigned int default_resolution;
1109 PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
1110 if (pdev->type>= 730)
1111 default_resolution = PSZ_QSIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 else
Luc Saillard2b455db2006-04-24 10:29:46 -03001113 default_resolution = PSZ_QCIF;
1114
1115 i = pwc_set_video_mode(pdev,
1116 pwc_image_sizes[default_resolution].x,
1117 pwc_image_sizes[default_resolution].y,
1118 10,
1119 pdev->vcompression,
1120 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
1122 if (i) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001123 PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
1124 pwc_free_buffers(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 return i;
1126 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001127
Luc Saillard2b455db2006-04-24 10:29:46 -03001128 /* Initialize the webcam to sane value */
1129 pwc_set_brightness(pdev, 0x7fff);
1130 pwc_set_agc(pdev, 1, 0);
1131
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 pdev->vopen++;
1133 file->private_data = vdev;
Luc Saillard2b455db2006-04-24 10:29:46 -03001134 PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 return 0;
1136}
1137
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001138static void pwc_video_release(struct video_device *vfd)
Oliver Neukum85237f22007-08-21 07:10:42 +02001139{
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001140 struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
1141 int hint;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001142
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001143 /* search device_hint[] table if we occupy a slot, by any chance */
1144 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1145 if (device_hint[hint].pdev == pdev)
1146 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001147
1148 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +02001149}
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151/* Note that all cleanup is done in the reverse order as in _open */
Hans Verkuilbec43662008-12-30 06:58:20 -03001152static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
1154 struct video_device *vdev = file->private_data;
1155 struct pwc_device *pdev;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001156 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Luc Saillard2b455db2006-04-24 10:29:46 -03001158 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Hans Verkuil601e9442008-08-23 07:24:07 -03001160 pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 if (pdev->vopen == 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001162 PWC_DEBUG_MODULE("video_close() called on closed device?\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 /* Dump statistics, but only if a reasonable amount of frames were
1165 processed (to prevent endless log-entries in case of snap-shot
1166 programs)
1167 */
1168 if (pdev->vframe_count > 20)
Luc Saillard2b455db2006-04-24 10:29:46 -03001169 PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Luc Saillard2b455db2006-04-24 10:29:46 -03001171 if (DEVICE_USE_CODEC1(pdev->type))
1172 pwc_dec1_exit();
1173 else
1174 pwc_dec23_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
1176 pwc_isoc_cleanup(pdev);
1177 pwc_free_buffers(pdev);
1178
1179 /* Turn off LEDS and power down camera, but only when not unplugged */
Oliver Neukum85237f22007-08-21 07:10:42 +02001180 if (!pdev->unplugged) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 /* Turn LEDs off */
1182 if (pwc_set_leds(pdev, 0, 0) < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001183 PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 if (power_save) {
1185 i = pwc_camera_power(pdev, 0);
1186 if (i < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001187 PWC_ERROR("Failed to power down camera (%d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
Oliver Neukum85237f22007-08-21 07:10:42 +02001189 pdev->vopen--;
Jean Delvare7b9fbc32007-09-03 11:51:51 -03001190 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
Oliver Neukum85237f22007-08-21 07:10:42 +02001192
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 return 0;
1194}
1195
1196/*
1197 * FIXME: what about two parallel reads ????
1198 * ANSWER: Not supported. You can't open the device more than once,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001199 despite what the V4L1 interface says. First, I don't see
1200 the need, second there's no mechanism of alerting the
1201 2nd/3rd/... process of events like changing image size.
1202 And I don't see the point of blocking that for the
1203 2nd/3rd/... process.
1204 In multi-threaded environments reading parallel from any
1205 device is tricky anyhow.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 */
1207
Luc Saillard2b455db2006-04-24 10:29:46 -03001208static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 size_t count, loff_t *ppos)
1210{
1211 struct video_device *vdev = file->private_data;
1212 struct pwc_device *pdev;
1213 int noblock = file->f_flags & O_NONBLOCK;
1214 DECLARE_WAITQUEUE(wait, current);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001215 int bytes_to_read, rv = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -03001216 void *image_buffer_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Luc Saillard2b455db2006-04-24 10:29:46 -03001218 PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
1219 vdev, buf, count);
Hans Verkuil601e9442008-08-23 07:24:07 -03001220 pdev = video_get_drvdata(vdev);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001221
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001222 if (pdev->error_status) {
1223 rv = -pdev->error_status; /* Something happened, report what. */
1224 goto err_out;
1225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Hans de Goede3751e282010-11-16 11:39:25 -03001227 /* Start the stream (if not already started) */
1228 rv = pwc_isoc_init(pdev);
1229 if (rv)
1230 goto err_out;
1231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 /* In case we're doing partial reads, we don't have to wait for a frame */
1233 if (pdev->image_read_pos == 0) {
1234 /* Do wait queueing according to the (doc)book */
1235 add_wait_queue(&pdev->frameq, &wait);
1236 while (pdev->full_frames == NULL) {
1237 /* Check for unplugged/etc. here */
1238 if (pdev->error_status) {
1239 remove_wait_queue(&pdev->frameq, &wait);
1240 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001241 rv = -pdev->error_status ;
1242 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001244 if (noblock) {
1245 remove_wait_queue(&pdev->frameq, &wait);
1246 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001247 rv = -EWOULDBLOCK;
1248 goto err_out;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001249 }
1250 if (signal_pending(current)) {
1251 remove_wait_queue(&pdev->frameq, &wait);
1252 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001253 rv = -ERESTARTSYS;
1254 goto err_out;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001255 }
Hans Verkuilb577f962011-01-13 05:05:36 -03001256 mutex_unlock(&pdev->modlock);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001257 schedule();
1258 set_current_state(TASK_INTERRUPTIBLE);
Hans Verkuilb577f962011-01-13 05:05:36 -03001259 mutex_lock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 }
1261 remove_wait_queue(&pdev->frameq, &wait);
1262 set_current_state(TASK_RUNNING);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001263
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 /* Decompress and release frame */
Hans de Goedec2464122011-06-06 15:25:18 -03001265 rv = pwc_handle_frame(pdev);
1266 if (rv)
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001267 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
1269
Luc Saillard2b455db2006-04-24 10:29:46 -03001270 PWC_DEBUG_READ("Copying data to user space.\n");
Hans Verkuil479567c2010-09-12 17:05:11 -03001271 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
Luc Saillard2b455db2006-04-24 10:29:46 -03001272 bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 else
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001274 bytes_to_read = pdev->view.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 /* copy bytes to user space; we allow for partial reads */
1277 if (count + pdev->image_read_pos > bytes_to_read)
1278 count = bytes_to_read - pdev->image_read_pos;
Luc Saillard2b455db2006-04-24 10:29:46 -03001279 image_buffer_addr = pdev->image_data;
1280 image_buffer_addr += pdev->images[pdev->fill_image].offset;
1281 image_buffer_addr += pdev->image_read_pos;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001282 if (copy_to_user(buf, image_buffer_addr, count)) {
1283 rv = -EFAULT;
1284 goto err_out;
1285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 pdev->image_read_pos += count;
1287 if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
1288 pdev->image_read_pos = 0;
1289 pwc_next_image(pdev);
1290 }
1291 return count;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001292err_out:
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001293 return rv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294}
1295
1296static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
1297{
1298 struct video_device *vdev = file->private_data;
1299 struct pwc_device *pdev;
Hans de Goede3751e282010-11-16 11:39:25 -03001300 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Hans Verkuil601e9442008-08-23 07:24:07 -03001302 pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Hans de Goede3751e282010-11-16 11:39:25 -03001304 /* Start the stream (if not already started) */
Hans de Goede3751e282010-11-16 11:39:25 -03001305 ret = pwc_isoc_init(pdev);
Hans de Goede3751e282010-11-16 11:39:25 -03001306 if (ret)
1307 return ret;
1308
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 poll_wait(file, &pdev->frameq, wait);
1310 if (pdev->error_status)
1311 return POLLERR;
1312 if (pdev->full_frames != NULL) /* we have frames waiting */
1313 return (POLLIN | POLLRDNORM);
1314
1315 return 0;
1316}
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
1319{
1320 struct video_device *vdev = file->private_data;
1321 struct pwc_device *pdev;
Luc Saillard2b455db2006-04-24 10:29:46 -03001322 unsigned long start;
1323 unsigned long size;
1324 unsigned long page, pos = 0;
1325 int index;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001326
Harvey Harrison645635b2008-04-08 23:20:00 -03001327 PWC_DEBUG_MEMORY(">> %s\n", __func__);
Hans Verkuil601e9442008-08-23 07:24:07 -03001328 pdev = video_get_drvdata(vdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001329 size = vma->vm_end - vma->vm_start;
1330 start = vma->vm_start;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001331
Luc Saillard2b455db2006-04-24 10:29:46 -03001332 /* Find the idx buffer for this mapping */
1333 for (index = 0; index < pwc_mbufs; index++) {
1334 pos = pdev->images[index].offset;
1335 if ((pos>>PAGE_SHIFT) == vma->vm_pgoff)
1336 break;
1337 }
1338 if (index == MAX_IMAGES)
1339 return -EINVAL;
1340 if (index == 0) {
1341 /*
1342 * Special case for v4l1. In v4l1, we map only one big buffer,
1343 * but in v4l2 each buffer is mapped
1344 */
1345 unsigned long total_size;
1346 total_size = pwc_mbufs * pdev->len_per_image;
1347 if (size != pdev->len_per_image && size != total_size) {
1348 PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
1349 size, pdev->len_per_image, total_size);
1350 return -EINVAL;
1351 }
1352 } else if (size > pdev->len_per_image)
1353 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Luc Saillard2b455db2006-04-24 10:29:46 -03001355 vma->vm_flags |= VM_IO; /* from 2.6.9-acX */
1356
1357 pos += (unsigned long)pdev->image_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 while (size > 0) {
1359 page = vmalloc_to_pfn((void *)pos);
1360 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1361 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 start += PAGE_SIZE;
1363 pos += PAGE_SIZE;
1364 if (size > PAGE_SIZE)
1365 size -= PAGE_SIZE;
1366 else
1367 size = 0;
1368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 return 0;
1370}
1371
1372/***************************************************************************/
1373/* USB functions */
1374
1375/* This function gets called when a new device is plugged in or the usb core
1376 * is loaded.
1377 */
1378
1379static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
1380{
1381 struct usb_device *udev = interface_to_usbdev(intf);
1382 struct pwc_device *pdev = NULL;
1383 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001384 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 int features = 0;
1386 int video_nr = -1; /* default: use next available device */
1387 char serial_number[30], *name;
1388
Luc Saillard2b455db2006-04-24 10:29:46 -03001389 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
1390 product_id = le16_to_cpu(udev->descriptor.idProduct);
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -03001393 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
1394 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 intf->altsetting->desc.bInterfaceNumber);
1396
1397 /* the interfaces are probed one by one. We are only interested in the
1398 video interface (0) now.
1399 Interface 1 is the Audio Control, and interface 2 Audio itself.
1400 */
1401 if (intf->altsetting->desc.bInterfaceNumber > 0)
1402 return -ENODEV;
1403
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (vendor_id == 0x0471) {
1405 switch (product_id) {
1406 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -03001407 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 name = "Philips 645 webcam";
1409 type_id = 645;
1410 break;
1411 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -03001412 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 name = "Philips 646 webcam";
1414 type_id = 646;
1415 break;
1416 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -03001417 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 name = "Askey VC010 webcam";
1419 type_id = 646;
1420 break;
1421 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -03001422 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 name = "Philips 675 webcam";
1424 type_id = 675;
1425 break;
1426 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -03001427 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 name = "Philips 680 webcam";
1429 type_id = 680;
1430 break;
1431 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -03001432 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 name = "Philips 690 webcam";
1434 type_id = 690;
1435 break;
1436 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -03001437 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 name = "Philips 730 webcam";
1439 type_id = 730;
1440 break;
1441 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -03001442 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 name = "Philips 740 webcam";
1444 type_id = 740;
1445 break;
1446 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -03001447 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 name = "Philips 750 webcam";
1449 type_id = 750;
1450 break;
1451 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -03001452 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 name = "Philips 720K/40 webcam";
1454 type_id = 720;
1455 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001456 case 0x0329:
1457 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
1458 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -03001459 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -03001460 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 default:
1462 return -ENODEV;
1463 break;
1464 }
1465 }
1466 else if (vendor_id == 0x069A) {
1467 switch(product_id) {
1468 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001469 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 name = "Askey VC010 webcam";
1471 type_id = 645;
1472 break;
1473 default:
1474 return -ENODEV;
1475 break;
1476 }
1477 }
1478 else if (vendor_id == 0x046d) {
1479 switch(product_id) {
1480 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -03001481 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 name = "Logitech QuickCam Pro 3000";
1483 type_id = 740; /* CCD sensor */
1484 break;
1485 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -03001486 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 name = "Logitech QuickCam Notebook Pro";
1488 type_id = 740; /* CCD sensor */
1489 break;
1490 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -03001491 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 name = "Logitech QuickCam Pro 4000";
1493 type_id = 740; /* CCD sensor */
1494 break;
1495 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -03001496 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 name = "Logitech QuickCam Zoom";
1498 type_id = 740; /* CCD sensor */
1499 break;
1500 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -03001501 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 name = "Logitech QuickCam Zoom";
1503 type_id = 740; /* CCD sensor */
Luc Saillard2b455db2006-04-24 10:29:46 -03001504 power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 break;
1506 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -03001507 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 name = "Logitech QuickCam Orbit";
1509 type_id = 740; /* CCD sensor */
1510 features |= FEATURE_MOTOR_PANTILT;
1511 break;
1512 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -03001513 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
1514 name = "Cisco VT Camera";
1515 type_id = 740; /* CCD sensor */
1516 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -03001518 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
1519 name = "Logitech ViewPort AV 100";
1520 type_id = 740; /* CCD sensor */
1521 break;
1522 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -03001523 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 name = "Logitech QuickCam (res.)";
1525 type_id = 730; /* Assuming CMOS */
1526 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001527 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001529 break;
1530 }
1531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 else if (vendor_id == 0x055d) {
1533 /* I don't know the difference between the C10 and the C30;
1534 I suppose the difference is the sensor, but both cameras
1535 work equally well with a type_id of 675
1536 */
1537 switch(product_id) {
1538 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -03001539 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 name = "Samsung MPC-C10";
1541 type_id = 675;
1542 break;
1543 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001544 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 name = "Samsung MPC-C30";
1546 type_id = 675;
1547 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001548 case 0x9002:
1549 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
1550 name = "Samsung MPC-C30";
1551 type_id = 740;
1552 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 default:
1554 return -ENODEV;
1555 break;
1556 }
1557 }
1558 else if (vendor_id == 0x041e) {
1559 switch(product_id) {
1560 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -03001561 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 name = "Creative Labs Webcam 5";
1563 type_id = 730;
1564 break;
1565 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -03001566 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 name = "Creative Labs Webcam Pro Ex";
1568 type_id = 740;
1569 break;
1570 default:
1571 return -ENODEV;
1572 break;
1573 }
1574 }
1575 else if (vendor_id == 0x04cc) {
1576 switch(product_id) {
1577 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001578 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 name = "Sotec Afina Eye";
1580 type_id = 730;
1581 break;
1582 default:
1583 return -ENODEV;
1584 break;
1585 }
1586 }
1587 else if (vendor_id == 0x06be) {
1588 switch(product_id) {
1589 case 0x8116:
1590 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001591 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 name = "AME Co. Afina Eye";
1593 type_id = 750;
1594 break;
1595 default:
1596 return -ENODEV;
1597 break;
1598 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 }
1601 else if (vendor_id == 0x0d81) {
1602 switch(product_id) {
1603 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001604 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 name = "Visionite VCS-UC300";
1606 type_id = 740; /* CCD sensor */
1607 break;
1608 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001609 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 name = "Visionite VCS-UM100";
1611 type_id = 730; /* CMOS sensor */
1612 break;
1613 default:
1614 return -ENODEV;
1615 break;
1616 }
1617 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001618 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1620
1621 memset(serial_number, 0, 30);
1622 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001623 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001626 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
1628 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001629 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001631 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 return -ENOMEM;
1633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 pdev->type = type_id;
1635 pdev->vsize = default_size;
1636 pdev->vframes = default_fps;
1637 strcpy(pdev->serial, serial_number);
1638 pdev->features = features;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001639 if (vendor_id == 0x046D && product_id == 0x08B5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 /* Logitech QuickCam Orbit
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001641 The ranges have been determined experimentally; they may differ from cam to cam.
1642 Also, the exact ranges left-right and up-down are different for my cam
1643 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 pdev->angle_range.pan_min = -7000;
1645 pdev->angle_range.pan_max = 7000;
1646 pdev->angle_range.tilt_min = -3000;
1647 pdev->angle_range.tilt_max = 2500;
1648 }
1649
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001650 mutex_init(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 spin_lock_init(&pdev->ptrlock);
1652
1653 pdev->udev = udev;
1654 init_waitqueue_head(&pdev->frameq);
1655 pdev->vcompression = pwc_preferred_compression;
1656
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001657 /* Init video_device structure */
1658 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
1659 pdev->vdev.parent = &intf->dev;
1660 pdev->vdev.lock = &pdev->modlock;
1661 strcpy(pdev->vdev.name, name);
1662 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663
1664 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001665 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 /* Now search device_hint[] table for a match, so we can hint a node number. */
1668 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1669 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1670 (device_hint[hint].pdev == NULL)) {
1671 /* so far, so good... try serial number */
1672 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001673 /* match! */
1674 video_nr = device_hint[hint].device_node;
1675 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1676 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 }
1678 }
1679 }
1680
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001682 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 device_hint[hint].pdev = pdev;
1684
Luc Saillard2b455db2006-04-24 10:29:46 -03001685 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001686 usb_set_intfdata(intf, pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001687
1688 /* Set the leds off */
1689 pwc_set_leds(pdev, 0, 0);
1690 pwc_camera_power(pdev, 0);
1691
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001692 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001693 if (rc < 0) {
1694 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001695 goto err_free_mem;
Hans Verkuil479567c2010-09-12 17:05:11 -03001696 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001697 rc = pwc_create_sysfs_files(pdev);
Hans Verkuil479567c2010-09-12 17:05:11 -03001698 if (rc)
1699 goto err_video_unreg;
1700
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001701 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001702
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001703#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1704 /* register webcam snapshot button input device */
1705 pdev->button_dev = input_allocate_device();
1706 if (!pdev->button_dev) {
1707 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001708 rc = -ENOMEM;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001709 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001710 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001711 }
1712
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001713 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1714 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1715
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001716 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001717 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001718 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1719 pdev->button_dev->dev.parent = &pdev->udev->dev;
1720 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001721 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001722
1723 rc = input_register_device(pdev->button_dev);
1724 if (rc) {
1725 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001726 pdev->button_dev = NULL;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001727 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001728 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001729 }
1730#endif
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001733
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001734err_video_unreg:
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001735 if (hint < MAX_DEV_HINTS)
1736 device_hint[hint].pdev = NULL;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001737 video_unregister_device(&pdev->vdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001738err_free_mem:
1739 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001740 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741}
1742
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001743/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744static void usb_pwc_disconnect(struct usb_interface *intf)
1745{
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001746 struct pwc_device *pdev = usb_get_intfdata(intf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
Hans Verkuil7074f402010-09-15 14:49:07 -03001748 mutex_lock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 usb_set_intfdata (intf, NULL);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 /* We got unplugged; this is signalled by an EPIPE error code */
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001752 pdev->error_status = EPIPE;
1753 pdev->unplugged = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 /* Alert waiting processes */
1756 wake_up_interruptible(&pdev->frameq);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001757
1758 /* No need to keep the urbs around after disconnection */
1759 pwc_isoc_cleanup(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Hans Verkuil7074f402010-09-15 14:49:07 -03001761 mutex_unlock(&pdev->modlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001762
1763 pwc_remove_sysfs_files(pdev);
1764 video_unregister_device(&pdev->vdev);
1765
1766#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1767 if (pdev->button_dev)
1768 input_unregister_device(pdev->button_dev);
1769#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001773/*
1774 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 */
1776
Luc Saillard2b455db2006-04-24 10:29:46 -03001777static char *size;
1778static int fps;
1779static int fbufs;
1780static int mbufs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781static int compression = -1;
1782static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001783static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001784static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001785static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
Luc Saillard2b455db2006-04-24 10:29:46 -03001787module_param(size, charp, 0444);
1788module_param(fps, int, 0444);
1789module_param(fbufs, int, 0444);
1790module_param(mbufs, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001791#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001792module_param_named(trace, pwc_trace, int, 0644);
1793#endif
1794module_param(power_save, int, 0444);
1795module_param(compression, int, 0444);
1796module_param_array(leds, int, &leds_nargs, 0444);
1797module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1798
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
Andrea Odetti4315c412009-12-10 16:26:10 -03001803#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001805#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809MODULE_PARM_DESC(dev_hint, "Device node hints");
1810
1811MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1812MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1813MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001814MODULE_ALIAS("pwcx");
1815MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
1817static int __init usb_pwc_init(void)
1818{
1819 int i, sz;
1820 char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
1821
Luc Saillard2b455db2006-04-24 10:29:46 -03001822 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1823 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1824 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1825 PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 if (fps) {
1828 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001829 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 return -EINVAL;
1831 }
1832 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001833 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 }
1835
Luc Saillard2b455db2006-04-24 10:29:46 -03001836 if (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 /* string; try matching with array */
1838 for (sz = 0; sz < PSZ_MAX; sz++) {
1839 if (!strcmp(sizenames[sz], size)) { /* Found! */
1840 default_size = sz;
1841 break;
1842 }
1843 }
1844 if (sz == PSZ_MAX) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001845 PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 return -EINVAL;
1847 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001848 PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 }
1850 if (mbufs) {
1851 if (mbufs < 1 || mbufs > MAX_IMAGES) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001852 PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 return -EINVAL;
1854 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001855 pwc_mbufs = mbufs;
1856 PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 }
1858 if (fbufs) {
1859 if (fbufs < 2 || fbufs > MAX_FRAMES) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001860 PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 return -EINVAL;
1862 }
1863 default_fbufs = fbufs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001864 PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 }
Trent Piepho05ad3902007-01-30 23:26:01 -03001866#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001867 if (pwc_trace >= 0) {
1868 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001870#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 if (compression >= 0) {
1872 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001873 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 return -EINVAL;
1875 }
1876 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03001877 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 }
1879 if (power_save)
Luc Saillard2b455db2006-04-24 10:29:46 -03001880 PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (leds[0] >= 0)
1882 led_on = leds[0];
1883 if (leds[1] >= 0)
1884 led_off = leds[1];
1885
Steven Cole093cf722005-05-03 19:07:24 -06001886 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 device node (/dev/videoX) to a camera, based on its type
1888 & serial number. The format is [type[.serialnumber]:]node.
1889
1890 Any camera that isn't matched by these rules gets the next
1891 available free device node.
1892 */
1893 for (i = 0; i < MAX_DEV_HINTS; i++) {
1894 char *s, *colon, *dot;
1895
1896 /* This loop also initializes the array */
1897 device_hint[i].pdev = NULL;
1898 s = dev_hint[i];
1899 if (s != NULL && *s != '\0') {
1900 device_hint[i].type = -1; /* wildcard */
1901 strcpy(device_hint[i].serial_number, "*");
1902
1903 /* parse string: chop at ':' & '/' */
1904 colon = dot = s;
1905 while (*colon != '\0' && *colon != ':')
1906 colon++;
1907 while (*dot != '\0' && *dot != '.')
1908 dot++;
1909 /* Few sanity checks */
1910 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001911 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 return -EINVAL;
1913 }
1914
1915 if (*colon == '\0') {
1916 /* No colon */
1917 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001918 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 return -EINVAL;
1920 }
1921 else {
1922 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001923 device_hint[i].device_node =
1924 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 }
1926 }
1927 else {
1928 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001929 device_hint[i].type =
1930 simple_strtol(s, NULL, 10);
1931 device_hint[i].device_node =
1932 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (*dot != '\0') {
1934 /* There's a serial number as well */
1935 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001936
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 dot++;
1938 k = 0;
1939 while (*dot != ':' && k < 29) {
1940 device_hint[i].serial_number[k++] = *dot;
1941 dot++;
1942 }
1943 device_hint[i].serial_number[k] = '\0';
1944 }
1945 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001946 PWC_TRACE("device_hint[%d]:\n", i);
1947 PWC_TRACE(" type : %d\n", device_hint[i].type);
1948 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1949 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
1951 else
1952 device_hint[i].type = 0; /* not filled */
1953 } /* ..for MAX_DEV_HINTS */
1954
Luc Saillard2b455db2006-04-24 10:29:46 -03001955 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 return usb_register(&pwc_driver);
1957}
1958
1959static void __exit usb_pwc_exit(void)
1960{
Luc Saillard2b455db2006-04-24 10:29:46 -03001961 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001963 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964}
1965
1966module_init(usb_pwc_init);
1967module_exit(usb_pwc_exit);
1968
Luc Saillard2b455db2006-04-24 10:29:46 -03001969/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */