blob: f3dc89da4c4eefcd23f7c457c75322c5eb96b0c9 [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 *
43 vdev: struct video_device *
44 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);
Hans Verkuil069b7472008-12-30 07:04:34 -0300154static long pwc_video_ioctl(struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 unsigned int ioctlnr, unsigned long arg);
156static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
157
Hans Verkuilbec43662008-12-30 06:58:20 -0300158static const struct v4l2_file_operations pwc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 .owner = THIS_MODULE,
160 .open = pwc_video_open,
161 .release = pwc_video_close,
162 .read = pwc_video_read,
163 .poll = pwc_video_poll,
164 .mmap = pwc_video_mmap,
Hans Verkuil7074f402010-09-15 14:49:07 -0300165 .unlocked_ioctl = pwc_video_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166};
167static struct video_device pwc_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 .name = "Philips Webcam", /* Filled in later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 .release = video_device_release,
170 .fops = &pwc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171};
172
173/***************************************************************************/
174
175/* Okay, this is some magic that I worked out and the reasoning behind it...
176
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300177 The biggest problem with any USB device is of course: "what to do
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 when the user unplugs the device while it is in use by an application?"
179 We have several options:
180 1) Curse them with the 7 plagues when they do (requires divine intervention)
181 2) Tell them not to (won't work: they'll do it anyway)
182 3) Oops the kernel (this will have a negative effect on a user's uptime)
183 4) Do something sensible.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 Of course, we go for option 4.
186
187 It happens that this device will be linked to two times, once from
188 usb_device and once from the video_device in their respective 'private'
189 pointers. This is done when the device is probed() and all initialization
190 succeeded. The pwc_device struct links back to both structures.
191
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300192 When a device is unplugged while in use it will be removed from the
193 list of known USB devices; I also de-register it as a V4L device, but
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 unfortunately I can't free the memory since the struct is still in use
195 by the file descriptor. This free-ing is then deferend until the first
196 opportunity. Crude, but it works.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 A small 'advantage' is that if a user unplugs the cam and plugs it back
199 in, it should get assigned the same video device minor, but unfortunately
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300200 it's non-trivial to re-link the cam back to the video device... (that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 would surely be magic! :))
202*/
203
204/***************************************************************************/
205/* Private functions */
206
207/* Here we want the physical address of the memory.
208 * This is used when initializing the contents of the area.
209 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Luc Saillard2b455db2006-04-24 10:29:46 -0300212
213static void *pwc_rvmalloc(unsigned long size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 void * mem;
216 unsigned long adr;
217
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300218 mem=vmalloc_32(size);
Luc Saillard2b455db2006-04-24 10:29:46 -0300219 if (!mem)
220 return NULL;
221
222 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
223 adr=(unsigned long) mem;
224 while (size > 0)
225 {
226 SetPageReserved(vmalloc_to_page((void *)adr));
227 adr += PAGE_SIZE;
228 size -= PAGE_SIZE;
229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 return mem;
231}
232
Luc Saillard2b455db2006-04-24 10:29:46 -0300233static void pwc_rvfree(void * mem, unsigned long size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300235 unsigned long adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Luc Saillard2b455db2006-04-24 10:29:46 -0300237 if (!mem)
238 return;
239
240 adr=(unsigned long) mem;
241 while ((long) size > 0)
242 {
243 ClearPageReserved(vmalloc_to_page((void *)adr));
244 adr += PAGE_SIZE;
245 size -= PAGE_SIZE;
246 }
247 vfree(mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248}
249
250
251
252
253static int pwc_allocate_buffers(struct pwc_device *pdev)
254{
Luc Saillard2b455db2006-04-24 10:29:46 -0300255 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 void *kbuf;
257
Luc Saillard2b455db2006-04-24 10:29:46 -0300258 PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 if (pdev == NULL)
261 return -ENXIO;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300262
Luc Saillard2b455db2006-04-24 10:29:46 -0300263 /* Allocate Isochronuous pipe buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 for (i = 0; i < MAX_ISO_BUFS; i++) {
265 if (pdev->sbuf[i].data == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300266 kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300268 PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 return -ENOMEM;
270 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300271 PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 pdev->sbuf[i].data = kbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274 }
275
276 /* Allocate frame buffer structure */
277 if (pdev->fbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300278 kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300280 PWC_ERROR("Failed to allocate frame buffer structure.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 return -ENOMEM;
282 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300283 PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 pdev->fbuf = kbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 /* create frame buffers, and make circular ring */
288 for (i = 0; i < default_fbufs; i++) {
289 if (pdev->fbuf[i].data == NULL) {
290 kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
291 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300292 PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 return -ENOMEM;
294 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300295 PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 pdev->fbuf[i].data = kbuf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300297 memset(kbuf, 0, PWC_FRAME_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 }
299 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 /* Allocate decompressor table space */
Luc Saillard2b455db2006-04-24 10:29:46 -0300302 if (DEVICE_USE_CODEC1(pdev->type))
303 err = pwc_dec1_alloc(pdev);
304 else
305 err = pwc_dec23_alloc(pdev);
306
307 if (err) {
308 PWC_ERROR("Failed to allocate decompress table.\n");
309 return err;
310 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 /* Allocate image buffer; double buffer for mmap() */
Luc Saillard2b455db2006-04-24 10:29:46 -0300313 kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (kbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300315 PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n",
316 pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 return -ENOMEM;
318 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300319 PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 pdev->image_data = kbuf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300321 for (i = 0; i < pwc_mbufs; i++) {
322 pdev->images[i].offset = i * pdev->len_per_image;
323 pdev->images[i].vma_use_count = 0;
324 }
325 for (; i < MAX_IMAGES; i++) {
326 pdev->images[i].offset = 0;
327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328
329 kbuf = NULL;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300330
Luc Saillard2b455db2006-04-24 10:29:46 -0300331 PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 return 0;
333}
334
335static void pwc_free_buffers(struct pwc_device *pdev)
336{
337 int i;
338
Luc Saillard2b455db2006-04-24 10:29:46 -0300339 PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 if (pdev == NULL)
342 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 /* Release Iso-pipe buffers */
344 for (i = 0; i < MAX_ISO_BUFS; i++)
345 if (pdev->sbuf[i].data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300346 PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 kfree(pdev->sbuf[i].data);
348 pdev->sbuf[i].data = NULL;
349 }
350
351 /* The same for frame buffers */
352 if (pdev->fbuf != NULL) {
353 for (i = 0; i < default_fbufs; i++) {
354 if (pdev->fbuf[i].data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300355 PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 vfree(pdev->fbuf[i].data);
357 pdev->fbuf[i].data = NULL;
358 }
359 }
360 kfree(pdev->fbuf);
361 pdev->fbuf = NULL;
362 }
363
364 /* Intermediate decompression buffer & tables */
365 if (pdev->decompress_data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300366 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 kfree(pdev->decompress_data);
368 pdev->decompress_data = NULL;
369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
371 /* Release image buffers */
372 if (pdev->image_data != NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300373 PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
374 pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 }
376 pdev->image_data = NULL;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300377
Luc Saillard2b455db2006-04-24 10:29:46 -0300378 PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300381/* The frame & image buffer mess.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 Yes, this is a mess. Well, it used to be simple, but alas... In this
384 module, 3 buffers schemes are used to get the data from the USB bus to
385 the user program. The first scheme involves the ISO buffers (called thus
386 since they transport ISO data from the USB controller), and not really
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300387 interesting. Suffices to say the data from this buffer is quickly
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 gathered in an interrupt handler (pwc_isoc_handler) and placed into the
389 frame buffer.
390
391 The frame buffer is the second scheme, and is the central element here.
392 It collects the data from a single frame from the camera (hence, the
393 name). Frames are delimited by the USB camera with a short USB packet,
394 so that's easy to detect. The frame buffers form a list that is filled
395 by the camera+USB controller and drained by the user process through
396 either read() or mmap().
397
398 The image buffer is the third scheme, in which frames are decompressed
399 and converted into planar format. For mmap() there is more than
400 one image buffer available.
401
402 The frame buffers provide the image buffering. In case the user process
403 is a bit slow, this introduces lag and some undesired side-effects.
404 The problem arises when the frame buffer is full. I used to drop the last
405 frame, which makes the data in the queue stale very quickly. But dropping
406 the frame at the head of the queue proved to be a litte bit more difficult.
407 I tried a circular linked scheme, but this introduced more problems than
408 it solved.
409
410 Because filling and draining are completely asynchronous processes, this
411 requires some fiddling with pointers and mutexes.
412
413 Eventually, I came up with a system with 2 lists: an 'empty' frame list
414 and a 'full' frame list:
415 * Initially, all frame buffers but one are on the 'empty' list; the one
416 remaining buffer is our initial fill frame.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300417 * If a frame is needed for filling, we try to take it from the 'empty'
418 list, unless that list is empty, in which case we take the buffer at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 the head of the 'full' list.
420 * When our fill buffer has been filled, it is appended to the 'full'
421 list.
422 * If a frame is needed by read() or mmap(), it is taken from the head of
423 the 'full' list, handled, and then appended to the 'empty' list. If no
424 buffer is present on the 'full' list, we wait.
425 The advantage is that the buffer that is currently being decompressed/
426 converted, is on neither list, and thus not in our way (any other scheme
427 I tried had the problem of old data lingering in the queue).
428
429 Whatever strategy you choose, it always remains a tradeoff: with more
430 frame buffers the chances of a missed frame are reduced. On the other
431 hand, on slower machines it introduces lag because the queue will
432 always be full.
433 */
434
435/**
436 \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
437 */
Luc Saillard2b455db2006-04-24 10:29:46 -0300438static int pwc_next_fill_frame(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 int ret;
441 unsigned long flags;
442
443 ret = 0;
444 spin_lock_irqsave(&pdev->ptrlock, flags);
445 if (pdev->fill_frame != NULL) {
446 /* append to 'full' list */
447 if (pdev->full_frames == NULL) {
448 pdev->full_frames = pdev->fill_frame;
449 pdev->full_frames_tail = pdev->full_frames;
450 }
451 else {
452 pdev->full_frames_tail->next = pdev->fill_frame;
453 pdev->full_frames_tail = pdev->fill_frame;
454 }
455 }
456 if (pdev->empty_frames != NULL) {
457 /* We have empty frames available. That's easy */
458 pdev->fill_frame = pdev->empty_frames;
459 pdev->empty_frames = pdev->empty_frames->next;
460 }
461 else {
462 /* Hmm. Take it from the full list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 /* sanity check */
464 if (pdev->full_frames == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300465 PWC_ERROR("Neither empty or full frames available!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 spin_unlock_irqrestore(&pdev->ptrlock, flags);
467 return -EINVAL;
468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 pdev->fill_frame = pdev->full_frames;
470 pdev->full_frames = pdev->full_frames->next;
471 ret = 1;
472 }
473 pdev->fill_frame->next = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 spin_unlock_irqrestore(&pdev->ptrlock, flags);
475 return ret;
476}
477
478
479/**
480 \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
481
482 If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
483 */
484static void pwc_reset_buffers(struct pwc_device *pdev)
485{
486 int i;
487 unsigned long flags;
488
Harvey Harrison645635b2008-04-08 23:20:00 -0300489 PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
Luc Saillard2b455db2006-04-24 10:29:46 -0300490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 spin_lock_irqsave(&pdev->ptrlock, flags);
492 pdev->full_frames = NULL;
493 pdev->full_frames_tail = NULL;
494 for (i = 0; i < default_fbufs; i++) {
495 pdev->fbuf[i].filled = 0;
496 if (i > 0)
497 pdev->fbuf[i].next = &pdev->fbuf[i - 1];
498 else
499 pdev->fbuf->next = NULL;
500 }
501 pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
502 pdev->empty_frames_tail = pdev->fbuf;
503 pdev->read_frame = NULL;
504 pdev->fill_frame = pdev->empty_frames;
505 pdev->empty_frames = pdev->empty_frames->next;
506
507 pdev->image_read_pos = 0;
508 pdev->fill_image = 0;
509 spin_unlock_irqrestore(&pdev->ptrlock, flags);
Luc Saillard2b455db2006-04-24 10:29:46 -0300510
Harvey Harrison645635b2008-04-08 23:20:00 -0300511 PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512}
513
514
515/**
516 \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
517 */
Luc Saillard2b455db2006-04-24 10:29:46 -0300518int pwc_handle_frame(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
520 int ret = 0;
521 unsigned long flags;
522
523 spin_lock_irqsave(&pdev->ptrlock, flags);
524 /* First grab our read_frame; this is removed from all lists, so
525 we can release the lock after this without problems */
526 if (pdev->read_frame != NULL) {
527 /* This can't theoretically happen */
Luc Saillard2b455db2006-04-24 10:29:46 -0300528 PWC_ERROR("Huh? Read frame still in use?\n");
529 spin_unlock_irqrestore(&pdev->ptrlock, flags);
530 return ret;
531 }
532
533
534 if (pdev->full_frames == NULL) {
535 PWC_ERROR("Woops. No frames ready.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 }
537 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300538 pdev->read_frame = pdev->full_frames;
539 pdev->full_frames = pdev->full_frames->next;
540 pdev->read_frame->next = NULL;
541 }
542
543 if (pdev->read_frame != NULL) {
Paulius Zaleckasefad798b2008-02-03 15:42:53 +0200544 /* Decompression is a lengthy process, so it's outside of the lock.
Luc Saillard2b455db2006-04-24 10:29:46 -0300545 This gives the isoc_handler the opportunity to fill more frames
546 in the mean time.
547 */
548 spin_unlock_irqrestore(&pdev->ptrlock, flags);
549 ret = pwc_decompress(pdev);
550 spin_lock_irqsave(&pdev->ptrlock, flags);
551
552 /* We're done with read_buffer, tack it to the end of the empty buffer list */
553 if (pdev->empty_frames == NULL) {
554 pdev->empty_frames = pdev->read_frame;
555 pdev->empty_frames_tail = pdev->empty_frames;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 }
557 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300558 pdev->empty_frames_tail->next = pdev->read_frame;
559 pdev->empty_frames_tail = pdev->read_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300561 pdev->read_frame = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 }
563 spin_unlock_irqrestore(&pdev->ptrlock, flags);
564 return ret;
565}
566
567/**
568 \brief Advance pointers of image buffer (after each user request)
569*/
Luc Saillard2b455db2006-04-24 10:29:46 -0300570void pwc_next_image(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 pdev->image_used[pdev->fill_image] = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300573 pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574}
575
Luc Saillard2b455db2006-04-24 10:29:46 -0300576/**
577 * Print debug information when a frame is discarded because all of our buffer
578 * is full
579 */
580static void pwc_frame_dumped(struct pwc_device *pdev)
581{
582 pdev->vframes_dumped++;
583 if (pdev->vframe_count < FRAME_LOWMARK)
584 return;
585
586 if (pdev->vframes_dumped < 20)
587 PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count);
588 else if (pdev->vframes_dumped == 20)
589 PWC_DEBUG_FLOW("Dumping frame %d (last message)\n",
590 pdev->vframe_count);
591}
592
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300593static void pwc_snapshot_button(struct pwc_device *pdev, int down)
594{
595 if (down) {
596 PWC_TRACE("Snapshot button pressed.\n");
597 pdev->snapshot_button_status = 1;
598 } else {
599 PWC_TRACE("Snapshot button released.\n");
600 }
601
602#ifdef CONFIG_USB_PWC_INPUT_EVDEV
603 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300604 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300605 input_sync(pdev->button_dev);
606 }
607#endif
608}
609
Luc Saillard2b455db2006-04-24 10:29:46 -0300610static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
611{
612 int awake = 0;
613
614 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
615 frames on the USB wire after an exposure change. This conditition is
616 however detected in the cam and a bit is set in the header.
617 */
618 if (pdev->type == 730) {
619 unsigned char *ptr = (unsigned char *)fbuf->data;
620
621 if (ptr[1] == 1 && ptr[0] & 0x10) {
622 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
623 pdev->drop_frames += 2;
624 pdev->vframes_error++;
625 }
626 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300627 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300628 }
629 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
630 if (ptr[0] & 0x02)
631 PWC_TRACE("Image is mirrored.\n");
632 else
633 PWC_TRACE("Image is normal.\n");
634 }
635 pdev->vmirror = ptr[0] & 0x03;
636 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
637 after a short frame; this condition is filtered out specifically. A 4 byte
638 frame doesn't make sense anyway.
639 So we get either this sequence:
640 drop_bit set -> 4 byte frame -> short frame -> good frame
641 Or this one:
642 drop_bit set -> short frame -> good frame
643 So we drop either 3 or 2 frames in all!
644 */
645 if (fbuf->filled == 4)
646 pdev->drop_frames++;
647 }
648 else if (pdev->type == 740 || pdev->type == 720) {
649 unsigned char *ptr = (unsigned char *)fbuf->data;
650 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300651 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300652 }
653 pdev->vmirror = ptr[0] & 0x03;
654 }
655
656 /* In case we were instructed to drop the frame, do so silently.
657 The buffer pointers are not updated either (but the counters are reset below).
658 */
659 if (pdev->drop_frames > 0)
660 pdev->drop_frames--;
661 else {
662 /* Check for underflow first */
663 if (fbuf->filled < pdev->frame_total_size) {
664 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
665 " discarded.\n", fbuf->filled);
666 pdev->vframes_error++;
667 }
668 else {
669 /* Send only once per EOF */
670 awake = 1; /* delay wake_ups */
671
672 /* Find our next frame to fill. This will always succeed, since we
673 * nick a frame from either empty or full list, but if we had to
674 * take it from the full list, it means a frame got dropped.
675 */
676 if (pwc_next_fill_frame(pdev))
677 pwc_frame_dumped(pdev);
678
679 }
680 } /* !drop_frames */
681 pdev->vframe_count++;
682 return awake;
683}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
685/* This gets called for the Isochronous pipe (video). This is done in
686 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
687 */
David Howells7d12e782006-10-05 14:55:46 +0100688static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
690 struct pwc_device *pdev;
691 int i, fst, flen;
692 int awake;
693 struct pwc_frame_buf *fbuf;
694 unsigned char *fillptr = NULL, *iso_buf = NULL;
695
696 awake = 0;
697 pdev = (struct pwc_device *)urb->context;
698 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300699 PWC_ERROR("isoc_handler() called with NULL device?!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 return;
701 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300702
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300704 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 return;
706 }
707 if (urb->status != -EINPROGRESS && urb->status != 0) {
708 const char *errmsg;
709
710 errmsg = "Unknown";
711 switch(urb->status) {
712 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
713 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
714 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
715 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
716 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700717 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300719 PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300720 /* Give up after a number of contiguous errors on the USB bus.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 Appearantly something is wrong so we simulate an unplug event.
722 */
723 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
724 {
Luc Saillard2b455db2006-04-24 10:29:46 -0300725 PWC_INFO("Too many ISOC errors, bailing out.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 pdev->error_status = EIO;
727 awake = 1;
728 wake_up_interruptible(&pdev->frameq);
729 }
730 goto handler_end; // ugly, but practical
731 }
732
733 fbuf = pdev->fill_frame;
734 if (fbuf == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300735 PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 awake = 1;
737 goto handler_end;
738 }
739 else {
740 fillptr = fbuf->data + fbuf->filled;
741 }
742
743 /* Reset ISOC error counter. We did get here, after all. */
744 pdev->visoc_errors = 0;
745
746 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300747 1 = sync-hunt
748 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 */
750 /* Compact data */
751 for (i = 0; i < urb->number_of_packets; i++) {
752 fst = urb->iso_frame_desc[i].status;
753 flen = urb->iso_frame_desc[i].actual_length;
754 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
755 if (fst == 0) {
756 if (flen > 0) { /* if valid data... */
757 if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
758 pdev->vsync = 2;
759
760 /* ...copy data to frame buffer, if possible */
761 if (flen + fbuf->filled > pdev->frame_total_size) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300762 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 -0700763 pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
764 pdev->vframes_error++;
765 }
766 else {
767 memmove(fillptr, iso_buf, flen);
768 fillptr += flen;
769 }
770 }
771 fbuf->filled += flen;
772 } /* ..flen > 0 */
773
774 if (flen < pdev->vlast_packet_size) {
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300775 /* Shorter packet... We probably have the end of an image-frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 wake up read() process and let select()/poll() do something.
777 Decompression is done in user time over there.
Luc Saillard2b455db2006-04-24 10:29:46 -0300778 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 if (pdev->vsync == 2) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300780 if (pwc_rcv_short_packet(pdev, fbuf)) {
781 awake = 1;
782 fbuf = pdev->fill_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 }
785 fbuf->filled = 0;
786 fillptr = fbuf->data;
787 pdev->vsync = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300788 }
789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 pdev->vlast_packet_size = flen;
791 } /* ..status == 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300793 /* This is normally not interesting to the user, unless
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300794 * you are really debugging something, default = 0 */
795 static int iso_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 iso_error++;
797 if (iso_error < 20)
Luc Saillard2b455db2006-04-24 10:29:46 -0300798 PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
801
802handler_end:
803 if (awake)
804 wake_up_interruptible(&pdev->frameq);
805
806 urb->dev = pdev->udev;
807 i = usb_submit_urb(urb, GFP_ATOMIC);
808 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300809 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810}
811
812
Luc Saillard2b455db2006-04-24 10:29:46 -0300813int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
815 struct usb_device *udev;
816 struct urb *urb;
817 int i, j, ret;
818
819 struct usb_interface *intf;
820 struct usb_host_interface *idesc = NULL;
821
822 if (pdev == NULL)
823 return -EFAULT;
824 if (pdev->iso_init)
825 return 0;
826 pdev->vsync = 0;
827 udev = pdev->udev;
828
829 /* Get the current alternate interface, adjust packet size */
830 if (!udev->actconfig)
831 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 intf = usb_ifnum_to_if(udev, 0);
833 if (intf)
834 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 if (!idesc)
837 return -EFAULT;
838
839 /* Search video endpoint */
840 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300841 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
843 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
844 break;
845 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300846 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300849 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600850 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852
853 /* Set alternate interface */
854 ret = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300855 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
857 if (ret < 0)
858 return ret;
859
860 for (i = 0; i < MAX_ISO_BUFS; i++) {
861 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
862 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300863 PWC_ERROR("Failed to allocate urb %d\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 ret = -ENOMEM;
865 break;
866 }
867 pdev->sbuf[i].urb = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300868 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 }
870 if (ret) {
871 /* De-allocate in reverse order */
Mariusz Kozlowski444f4f92006-11-16 16:38:57 +0100872 while (i--) {
Mariusz Kozlowski90b26252006-11-08 15:34:55 +0100873 usb_free_urb(pdev->sbuf[i].urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 pdev->sbuf[i].urb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
876 return ret;
877 }
878
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300879 /* init URB structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 for (i = 0; i < MAX_ISO_BUFS; i++) {
881 urb = pdev->sbuf[i].urb;
882
883 urb->interval = 1; // devik
884 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300885 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 urb->transfer_flags = URB_ISO_ASAP;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300887 urb->transfer_buffer = pdev->sbuf[i].data;
888 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
889 urb->complete = pwc_isoc_handler;
890 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 urb->start_frame = 0;
892 urb->number_of_packets = ISO_FRAMES_PER_DESC;
893 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
894 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
895 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
896 }
897 }
898
899 /* link */
900 for (i = 0; i < MAX_ISO_BUFS; i++) {
901 ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
902 if (ret)
Luc Saillard2b455db2006-04-24 10:29:46 -0300903 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 else
Luc Saillard2b455db2006-04-24 10:29:46 -0300905 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 }
907
908 /* All is done... */
909 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300910 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 return 0;
912}
913
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300914static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915{
916 int i;
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 /* Unlinking ISOC buffers one by one */
919 for (i = 0; i < MAX_ISO_BUFS; i++) {
920 struct urb *urb;
921
922 urb = pdev->sbuf[i].urb;
Al Viro5fa12472008-03-29 03:07:38 +0000923 if (urb) {
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300924 PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
925 usb_kill_urb(urb);
926 }
927 }
928}
929
930static void pwc_iso_free(struct pwc_device *pdev)
931{
932 int i;
933
934 /* Freeing ISOC buffers one by one */
935 for (i = 0; i < MAX_ISO_BUFS; i++) {
936 struct urb *urb;
937
938 urb = pdev->sbuf[i].urb;
Al Viro5fa12472008-03-29 03:07:38 +0000939 if (urb) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300940 PWC_DEBUG_MEMORY("Freeing URB\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 usb_free_urb(urb);
942 pdev->sbuf[i].urb = NULL;
943 }
944 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300945}
946
947void pwc_isoc_cleanup(struct pwc_device *pdev)
948{
949 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
950 if (pdev == NULL)
951 return;
952 if (pdev->iso_init == 0)
953 return;
954
955 pwc_iso_stop(pdev);
956 pwc_iso_free(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
958 /* Stop camera, but only if we are sure the camera is still there (unplug
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300959 is signalled by EPIPE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 */
961 if (pdev->error_status && pdev->error_status != EPIPE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300962 PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 usb_set_interface(pdev->udev, 0, 0);
964 }
965
966 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300967 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
970int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
971{
972 int ret, start;
973
974 /* Stop isoc stuff */
975 pwc_isoc_cleanup(pdev);
976 /* Reset parameters */
977 pwc_reset_buffers(pdev);
978 /* Try to set video mode... */
979 start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300980 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300981 PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 /* That failed... restore old mode (we know that worked) */
983 start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
984 if (start) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300985 PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 }
987 }
988 if (start == 0)
989 {
990 if (pwc_isoc_init(pdev) < 0)
991 {
Luc Saillard2b455db2006-04-24 10:29:46 -0300992 PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 ret = -EAGAIN; /* let's try again, who knows if it works a second time */
994 }
995 }
996 pdev->drop_frames++; /* try to avoid garbage during switch */
997 return ret; /* Return original error code */
998}
999
Luc Saillard2b455db2006-04-24 10:29:46 -03001000/*********
1001 * sysfs
1002 *********/
Kay Sievers54bd5b62007-10-08 16:26:13 -03001003static struct pwc_device *cd_to_pwc(struct device *cd)
Luc Saillard2b455db2006-04-24 10:29:46 -03001004{
1005 struct video_device *vdev = to_video_device(cd);
1006 return video_get_drvdata(vdev);
1007}
1008
Kay Sievers54bd5b62007-10-08 16:26:13 -03001009static ssize_t show_pan_tilt(struct device *class_dev,
1010 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -03001011{
1012 struct pwc_device *pdev = cd_to_pwc(class_dev);
1013 return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
1014}
1015
Kay Sievers54bd5b62007-10-08 16:26:13 -03001016static ssize_t store_pan_tilt(struct device *class_dev,
1017 struct device_attribute *attr,
1018 const char *buf, size_t count)
Luc Saillard2b455db2006-04-24 10:29:46 -03001019{
1020 struct pwc_device *pdev = cd_to_pwc(class_dev);
1021 int pan, tilt;
1022 int ret = -EINVAL;
1023
1024 if (strncmp(buf, "reset", 5) == 0)
1025 ret = pwc_mpt_reset(pdev, 0x3);
1026
1027 else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
1028 ret = pwc_mpt_set_angle(pdev, pan, tilt);
1029
1030 if (ret < 0)
1031 return ret;
1032 return strlen(buf);
1033}
Kay Sievers54bd5b62007-10-08 16:26:13 -03001034static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
1035 store_pan_tilt);
Luc Saillard2b455db2006-04-24 10:29:46 -03001036
Kay Sievers54bd5b62007-10-08 16:26:13 -03001037static ssize_t show_snapshot_button_status(struct device *class_dev,
1038 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -03001039{
1040 struct pwc_device *pdev = cd_to_pwc(class_dev);
1041 int status = pdev->snapshot_button_status;
1042 pdev->snapshot_button_status = 0;
1043 return sprintf(buf, "%d\n", status);
1044}
1045
Kay Sievers54bd5b62007-10-08 16:26:13 -03001046static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
1047 NULL);
Luc Saillard2b455db2006-04-24 10:29:46 -03001048
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001049static int pwc_create_sysfs_files(struct video_device *vdev)
Luc Saillard2b455db2006-04-24 10:29:46 -03001050{
1051 struct pwc_device *pdev = video_get_drvdata(vdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001052 int rc;
1053
Hans Verkuilf894dfd2008-07-25 07:39:54 -03001054 rc = device_create_file(&vdev->dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001055 if (rc)
1056 goto err;
1057 if (pdev->features & FEATURE_MOTOR_PANTILT) {
Hans Verkuilf894dfd2008-07-25 07:39:54 -03001058 rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001059 if (rc)
1060 goto err_button;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001061 }
1062
1063 return 0;
1064
1065err_button:
Hans Verkuilf894dfd2008-07-25 07:39:54 -03001066 device_remove_file(&vdev->dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001067err:
Hans Verkuilf894dfd2008-07-25 07:39:54 -03001068 PWC_ERROR("Could not create sysfs files.\n");
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001069 return rc;
Luc Saillard2b455db2006-04-24 10:29:46 -03001070}
1071
1072static void pwc_remove_sysfs_files(struct video_device *vdev)
1073{
1074 struct pwc_device *pdev = video_get_drvdata(vdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001075
Luc Saillard2b455db2006-04-24 10:29:46 -03001076 if (pdev->features & FEATURE_MOTOR_PANTILT)
Hans Verkuilf894dfd2008-07-25 07:39:54 -03001077 device_remove_file(&vdev->dev, &dev_attr_pan_tilt);
1078 device_remove_file(&vdev->dev, &dev_attr_button);
Luc Saillard2b455db2006-04-24 10:29:46 -03001079}
1080
Trent Piepho05ad3902007-01-30 23:26:01 -03001081#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001082static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
1083{
1084 switch(sensor_type) {
1085 case 0x00:
1086 return "Hyundai CMOS sensor";
1087 case 0x20:
1088 return "Sony CCD sensor + TDA8787";
1089 case 0x2E:
1090 return "Sony CCD sensor + Exas 98L59";
1091 case 0x2F:
1092 return "Sony CCD sensor + ADI 9804";
1093 case 0x30:
1094 return "Sharp CCD sensor + TDA8787";
1095 case 0x3E:
1096 return "Sharp CCD sensor + Exas 98L59";
1097 case 0x3F:
1098 return "Sharp CCD sensor + ADI 9804";
1099 case 0x40:
1100 return "UPA 1021 sensor";
1101 case 0x100:
1102 return "VGA sensor";
1103 case 0x101:
1104 return "PAL MR sensor";
1105 default:
Trent Piepho657de3c2006-06-20 00:30:57 -03001106 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -03001107 }
1108}
1109#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111/***************************************************************************/
1112/* Video4Linux functions */
1113
Hans Verkuilbec43662008-12-30 06:58:20 -03001114static int pwc_video_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115{
Luc Saillard2b455db2006-04-24 10:29:46 -03001116 int i, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 struct video_device *vdev = video_devdata(file);
1118 struct pwc_device *pdev;
1119
Luc Saillard2b455db2006-04-24 10:29:46 -03001120 PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001121
Hans Verkuil601e9442008-08-23 07:24:07 -03001122 pdev = video_get_drvdata(vdev);
Eric Sesterhenn5d9a2762006-11-30 05:26:46 +01001123 BUG_ON(!pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001124 if (pdev->vopen) {
1125 PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 return -EBUSY;
Luc Saillard2b455db2006-04-24 10:29:46 -03001127 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001128
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001129 mutex_lock(&pdev->modlock);
Martin Fuzzey5c8e2402009-03-09 20:16:00 -03001130 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 if (!pdev->usb_init) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001132 PWC_DEBUG_OPEN("Doing first time initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 pdev->usb_init = 1;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001134
Luc Saillard2b455db2006-04-24 10:29:46 -03001135 /* Query sensor type */
1136 ret = pwc_get_cmos_sensor(pdev, &i);
1137 if (ret >= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 {
Luc Saillard2b455db2006-04-24 10:29:46 -03001139 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1140 pdev->vdev->name,
1141 pwc_sensor_type_to_string(i), i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 }
1143 }
1144
1145 /* Turn on camera */
1146 if (power_save) {
1147 i = pwc_camera_power(pdev, 1);
1148 if (i < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001149 PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151 /* Set LED on/off time */
1152 if (pwc_set_leds(pdev, led_on, led_off) < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001153 PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
1156 /* So far, so good. Allocate memory. */
1157 i = pwc_allocate_buffers(pdev);
1158 if (i < 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001159 PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
1160 pwc_free_buffers(pdev);
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001161 mutex_unlock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 return i;
1163 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 /* Reset buffers & parameters */
1166 pwc_reset_buffers(pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001167 for (i = 0; i < pwc_mbufs; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 pdev->image_used[i] = 0;
1169 pdev->vframe_count = 0;
1170 pdev->vframes_dumped = 0;
1171 pdev->vframes_error = 0;
1172 pdev->visoc_errors = 0;
1173 pdev->error_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 pwc_construct(pdev); /* set min/max sizes correct */
1175
1176 /* Set some defaults */
1177 pdev->vsnapshot = 0;
1178
1179 /* Start iso pipe for video; first try the last used video size
1180 (or the default one); if that fails try QCIF/10 or QSIF/10;
1181 it that fails too, give up.
1182 */
1183 i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
1184 if (i) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001185 unsigned int default_resolution;
1186 PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
1187 if (pdev->type>= 730)
1188 default_resolution = PSZ_QSIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 else
Luc Saillard2b455db2006-04-24 10:29:46 -03001190 default_resolution = PSZ_QCIF;
1191
1192 i = pwc_set_video_mode(pdev,
1193 pwc_image_sizes[default_resolution].x,
1194 pwc_image_sizes[default_resolution].y,
1195 10,
1196 pdev->vcompression,
1197 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
1199 if (i) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001200 PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
1201 pwc_free_buffers(pdev);
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001202 mutex_unlock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 return i;
1204 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 i = pwc_isoc_init(pdev);
1207 if (i) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001208 PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
1209 pwc_isoc_cleanup(pdev);
1210 pwc_free_buffers(pdev);
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001211 mutex_unlock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return i;
1213 }
1214
Luc Saillard2b455db2006-04-24 10:29:46 -03001215 /* Initialize the webcam to sane value */
1216 pwc_set_brightness(pdev, 0x7fff);
1217 pwc_set_agc(pdev, 1, 0);
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 pdev->vopen++;
1220 file->private_data = vdev;
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001221 mutex_unlock(&pdev->modlock);
Luc Saillard2b455db2006-04-24 10:29:46 -03001222 PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 return 0;
1224}
1225
Oliver Neukum85237f22007-08-21 07:10:42 +02001226
1227static void pwc_cleanup(struct pwc_device *pdev)
1228{
1229 pwc_remove_sysfs_files(pdev->vdev);
1230 video_unregister_device(pdev->vdev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001231
1232#ifdef CONFIG_USB_PWC_INPUT_EVDEV
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001233 if (pdev->button_dev)
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001234 input_unregister_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001235#endif
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001236
1237 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +02001238}
1239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240/* Note that all cleanup is done in the reverse order as in _open */
Hans Verkuilbec43662008-12-30 06:58:20 -03001241static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242{
1243 struct video_device *vdev = file->private_data;
1244 struct pwc_device *pdev;
Oliver Neukum85237f22007-08-21 07:10:42 +02001245 int i, hint;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
Luc Saillard2b455db2006-04-24 10:29:46 -03001247 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Hans Verkuil601e9442008-08-23 07:24:07 -03001249 pdev = video_get_drvdata(vdev);
Hans Verkuil7074f402010-09-15 14:49:07 -03001250 mutex_lock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (pdev->vopen == 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001252 PWC_DEBUG_MODULE("video_close() called on closed device?\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 /* Dump statistics, but only if a reasonable amount of frames were
1255 processed (to prevent endless log-entries in case of snap-shot
1256 programs)
1257 */
1258 if (pdev->vframe_count > 20)
Luc Saillard2b455db2006-04-24 10:29:46 -03001259 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 -07001260
Luc Saillard2b455db2006-04-24 10:29:46 -03001261 if (DEVICE_USE_CODEC1(pdev->type))
1262 pwc_dec1_exit();
1263 else
1264 pwc_dec23_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
1266 pwc_isoc_cleanup(pdev);
1267 pwc_free_buffers(pdev);
1268
1269 /* Turn off LEDS and power down camera, but only when not unplugged */
Oliver Neukum85237f22007-08-21 07:10:42 +02001270 if (!pdev->unplugged) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 /* Turn LEDs off */
1272 if (pwc_set_leds(pdev, 0, 0) < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001273 PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 if (power_save) {
1275 i = pwc_camera_power(pdev, 0);
1276 if (i < 0)
Luc Saillard2b455db2006-04-24 10:29:46 -03001277 PWC_ERROR("Failed to power down camera (%d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
Oliver Neukum85237f22007-08-21 07:10:42 +02001279 pdev->vopen--;
Jean Delvare7b9fbc32007-09-03 11:51:51 -03001280 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
Oliver Neukum85237f22007-08-21 07:10:42 +02001281 } else {
1282 pwc_cleanup(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +02001283 /* search device_hint[] table if we occupy a slot, by any chance */
1284 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1285 if (device_hint[hint].pdev == pdev)
1286 device_hint[hint].pdev = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 }
Hans Verkuil7074f402010-09-15 14:49:07 -03001288 mutex_unlock(&pdev->modlock);
Oliver Neukum85237f22007-08-21 07:10:42 +02001289
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 return 0;
1291}
1292
1293/*
1294 * FIXME: what about two parallel reads ????
1295 * ANSWER: Not supported. You can't open the device more than once,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001296 despite what the V4L1 interface says. First, I don't see
1297 the need, second there's no mechanism of alerting the
1298 2nd/3rd/... process of events like changing image size.
1299 And I don't see the point of blocking that for the
1300 2nd/3rd/... process.
1301 In multi-threaded environments reading parallel from any
1302 device is tricky anyhow.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 */
1304
Luc Saillard2b455db2006-04-24 10:29:46 -03001305static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 size_t count, loff_t *ppos)
1307{
1308 struct video_device *vdev = file->private_data;
1309 struct pwc_device *pdev;
1310 int noblock = file->f_flags & O_NONBLOCK;
1311 DECLARE_WAITQUEUE(wait, current);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001312 int bytes_to_read, rv = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -03001313 void *image_buffer_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
Luc Saillard2b455db2006-04-24 10:29:46 -03001315 PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
1316 vdev, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 if (vdev == NULL)
1318 return -EFAULT;
Hans Verkuil601e9442008-08-23 07:24:07 -03001319 pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 if (pdev == NULL)
1321 return -EFAULT;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001322
1323 mutex_lock(&pdev->modlock);
1324 if (pdev->error_status) {
1325 rv = -pdev->error_status; /* Something happened, report what. */
1326 goto err_out;
1327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 /* In case we're doing partial reads, we don't have to wait for a frame */
1330 if (pdev->image_read_pos == 0) {
1331 /* Do wait queueing according to the (doc)book */
1332 add_wait_queue(&pdev->frameq, &wait);
1333 while (pdev->full_frames == NULL) {
1334 /* Check for unplugged/etc. here */
1335 if (pdev->error_status) {
1336 remove_wait_queue(&pdev->frameq, &wait);
1337 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001338 rv = -pdev->error_status ;
1339 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001341 if (noblock) {
1342 remove_wait_queue(&pdev->frameq, &wait);
1343 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001344 rv = -EWOULDBLOCK;
1345 goto err_out;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001346 }
1347 if (signal_pending(current)) {
1348 remove_wait_queue(&pdev->frameq, &wait);
1349 set_current_state(TASK_RUNNING);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001350 rv = -ERESTARTSYS;
1351 goto err_out;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001352 }
1353 schedule();
1354 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 }
1356 remove_wait_queue(&pdev->frameq, &wait);
1357 set_current_state(TASK_RUNNING);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 /* Decompress and release frame */
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001360 if (pwc_handle_frame(pdev)) {
1361 rv = -EFAULT;
1362 goto err_out;
1363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 }
1365
Luc Saillard2b455db2006-04-24 10:29:46 -03001366 PWC_DEBUG_READ("Copying data to user space.\n");
Hans Verkuil479567c2010-09-12 17:05:11 -03001367 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
Luc Saillard2b455db2006-04-24 10:29:46 -03001368 bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 else
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001370 bytes_to_read = pdev->view.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 /* copy bytes to user space; we allow for partial reads */
1373 if (count + pdev->image_read_pos > bytes_to_read)
1374 count = bytes_to_read - pdev->image_read_pos;
Luc Saillard2b455db2006-04-24 10:29:46 -03001375 image_buffer_addr = pdev->image_data;
1376 image_buffer_addr += pdev->images[pdev->fill_image].offset;
1377 image_buffer_addr += pdev->image_read_pos;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001378 if (copy_to_user(buf, image_buffer_addr, count)) {
1379 rv = -EFAULT;
1380 goto err_out;
1381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 pdev->image_read_pos += count;
1383 if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
1384 pdev->image_read_pos = 0;
1385 pwc_next_image(pdev);
1386 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001387 mutex_unlock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 return count;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001389err_out:
1390 mutex_unlock(&pdev->modlock);
1391 return rv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
1394static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
1395{
1396 struct video_device *vdev = file->private_data;
1397 struct pwc_device *pdev;
1398
1399 if (vdev == NULL)
1400 return -EFAULT;
Hans Verkuil601e9442008-08-23 07:24:07 -03001401 pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 if (pdev == NULL)
1403 return -EFAULT;
1404
1405 poll_wait(file, &pdev->frameq, wait);
1406 if (pdev->error_status)
1407 return POLLERR;
1408 if (pdev->full_frames != NULL) /* we have frames waiting */
1409 return (POLLIN | POLLRDNORM);
1410
1411 return 0;
1412}
1413
Hans Verkuil069b7472008-12-30 07:04:34 -03001414static long pwc_video_ioctl(struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 unsigned int cmd, unsigned long arg)
1416{
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001417 struct video_device *vdev = file->private_data;
1418 struct pwc_device *pdev;
Hans Verkuil069b7472008-12-30 07:04:34 -03001419 long r = -ENODEV;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001420
1421 if (!vdev)
1422 goto out;
Hans Verkuil601e9442008-08-23 07:24:07 -03001423 pdev = video_get_drvdata(vdev);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001424
1425 mutex_lock(&pdev->modlock);
1426 if (!pdev->unplugged)
Hans Verkuilf473bf72008-11-01 08:25:11 -03001427 r = video_usercopy(file, cmd, arg, pwc_video_do_ioctl);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001428 mutex_unlock(&pdev->modlock);
1429out:
1430 return r;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431}
1432
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
1434{
1435 struct video_device *vdev = file->private_data;
1436 struct pwc_device *pdev;
Luc Saillard2b455db2006-04-24 10:29:46 -03001437 unsigned long start;
1438 unsigned long size;
1439 unsigned long page, pos = 0;
1440 int index;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001441
Harvey Harrison645635b2008-04-08 23:20:00 -03001442 PWC_DEBUG_MEMORY(">> %s\n", __func__);
Hans Verkuil601e9442008-08-23 07:24:07 -03001443 pdev = video_get_drvdata(vdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001444 size = vma->vm_end - vma->vm_start;
1445 start = vma->vm_start;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001446
Luc Saillard2b455db2006-04-24 10:29:46 -03001447 /* Find the idx buffer for this mapping */
1448 for (index = 0; index < pwc_mbufs; index++) {
1449 pos = pdev->images[index].offset;
1450 if ((pos>>PAGE_SHIFT) == vma->vm_pgoff)
1451 break;
1452 }
1453 if (index == MAX_IMAGES)
1454 return -EINVAL;
1455 if (index == 0) {
1456 /*
1457 * Special case for v4l1. In v4l1, we map only one big buffer,
1458 * but in v4l2 each buffer is mapped
1459 */
1460 unsigned long total_size;
1461 total_size = pwc_mbufs * pdev->len_per_image;
1462 if (size != pdev->len_per_image && size != total_size) {
1463 PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
1464 size, pdev->len_per_image, total_size);
1465 return -EINVAL;
1466 }
1467 } else if (size > pdev->len_per_image)
1468 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Luc Saillard2b455db2006-04-24 10:29:46 -03001470 vma->vm_flags |= VM_IO; /* from 2.6.9-acX */
1471
1472 pos += (unsigned long)pdev->image_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 while (size > 0) {
1474 page = vmalloc_to_pfn((void *)pos);
1475 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1476 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 start += PAGE_SIZE;
1478 pos += PAGE_SIZE;
1479 if (size > PAGE_SIZE)
1480 size -= PAGE_SIZE;
1481 else
1482 size = 0;
1483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return 0;
1485}
1486
1487/***************************************************************************/
1488/* USB functions */
1489
1490/* This function gets called when a new device is plugged in or the usb core
1491 * is loaded.
1492 */
1493
1494static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
1495{
1496 struct usb_device *udev = interface_to_usbdev(intf);
1497 struct pwc_device *pdev = NULL;
1498 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001499 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 int features = 0;
1501 int video_nr = -1; /* default: use next available device */
1502 char serial_number[30], *name;
1503
Luc Saillard2b455db2006-04-24 10:29:46 -03001504 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
1505 product_id = le16_to_cpu(udev->descriptor.idProduct);
1506
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -03001508 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
1509 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 intf->altsetting->desc.bInterfaceNumber);
1511
1512 /* the interfaces are probed one by one. We are only interested in the
1513 video interface (0) now.
1514 Interface 1 is the Audio Control, and interface 2 Audio itself.
1515 */
1516 if (intf->altsetting->desc.bInterfaceNumber > 0)
1517 return -ENODEV;
1518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 if (vendor_id == 0x0471) {
1520 switch (product_id) {
1521 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -03001522 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 name = "Philips 645 webcam";
1524 type_id = 645;
1525 break;
1526 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -03001527 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 name = "Philips 646 webcam";
1529 type_id = 646;
1530 break;
1531 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -03001532 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 name = "Askey VC010 webcam";
1534 type_id = 646;
1535 break;
1536 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -03001537 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 name = "Philips 675 webcam";
1539 type_id = 675;
1540 break;
1541 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -03001542 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 name = "Philips 680 webcam";
1544 type_id = 680;
1545 break;
1546 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -03001547 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 name = "Philips 690 webcam";
1549 type_id = 690;
1550 break;
1551 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -03001552 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 name = "Philips 730 webcam";
1554 type_id = 730;
1555 break;
1556 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -03001557 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 name = "Philips 740 webcam";
1559 type_id = 740;
1560 break;
1561 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -03001562 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 name = "Philips 750 webcam";
1564 type_id = 750;
1565 break;
1566 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -03001567 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 name = "Philips 720K/40 webcam";
1569 type_id = 720;
1570 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001571 case 0x0329:
1572 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
1573 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -03001574 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -03001575 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 default:
1577 return -ENODEV;
1578 break;
1579 }
1580 }
1581 else if (vendor_id == 0x069A) {
1582 switch(product_id) {
1583 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001584 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 name = "Askey VC010 webcam";
1586 type_id = 645;
1587 break;
1588 default:
1589 return -ENODEV;
1590 break;
1591 }
1592 }
1593 else if (vendor_id == 0x046d) {
1594 switch(product_id) {
1595 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -03001596 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 name = "Logitech QuickCam Pro 3000";
1598 type_id = 740; /* CCD sensor */
1599 break;
1600 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -03001601 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 name = "Logitech QuickCam Notebook Pro";
1603 type_id = 740; /* CCD sensor */
1604 break;
1605 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -03001606 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 name = "Logitech QuickCam Pro 4000";
1608 type_id = 740; /* CCD sensor */
1609 break;
1610 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -03001611 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 name = "Logitech QuickCam Zoom";
1613 type_id = 740; /* CCD sensor */
1614 break;
1615 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -03001616 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 name = "Logitech QuickCam Zoom";
1618 type_id = 740; /* CCD sensor */
Luc Saillard2b455db2006-04-24 10:29:46 -03001619 power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 break;
1621 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -03001622 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 name = "Logitech QuickCam Orbit";
1624 type_id = 740; /* CCD sensor */
1625 features |= FEATURE_MOTOR_PANTILT;
1626 break;
1627 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -03001628 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
1629 name = "Cisco VT Camera";
1630 type_id = 740; /* CCD sensor */
1631 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -03001633 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
1634 name = "Logitech ViewPort AV 100";
1635 type_id = 740; /* CCD sensor */
1636 break;
1637 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -03001638 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 name = "Logitech QuickCam (res.)";
1640 type_id = 730; /* Assuming CMOS */
1641 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001642 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001644 break;
1645 }
1646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 else if (vendor_id == 0x055d) {
1648 /* I don't know the difference between the C10 and the C30;
1649 I suppose the difference is the sensor, but both cameras
1650 work equally well with a type_id of 675
1651 */
1652 switch(product_id) {
1653 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -03001654 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 name = "Samsung MPC-C10";
1656 type_id = 675;
1657 break;
1658 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001659 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 name = "Samsung MPC-C30";
1661 type_id = 675;
1662 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001663 case 0x9002:
1664 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
1665 name = "Samsung MPC-C30";
1666 type_id = 740;
1667 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 default:
1669 return -ENODEV;
1670 break;
1671 }
1672 }
1673 else if (vendor_id == 0x041e) {
1674 switch(product_id) {
1675 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -03001676 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 name = "Creative Labs Webcam 5";
1678 type_id = 730;
1679 break;
1680 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -03001681 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 name = "Creative Labs Webcam Pro Ex";
1683 type_id = 740;
1684 break;
1685 default:
1686 return -ENODEV;
1687 break;
1688 }
1689 }
1690 else if (vendor_id == 0x04cc) {
1691 switch(product_id) {
1692 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001693 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 name = "Sotec Afina Eye";
1695 type_id = 730;
1696 break;
1697 default:
1698 return -ENODEV;
1699 break;
1700 }
1701 }
1702 else if (vendor_id == 0x06be) {
1703 switch(product_id) {
1704 case 0x8116:
1705 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001706 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 name = "AME Co. Afina Eye";
1708 type_id = 750;
1709 break;
1710 default:
1711 return -ENODEV;
1712 break;
1713 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001714
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 }
1716 else if (vendor_id == 0x0d81) {
1717 switch(product_id) {
1718 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001719 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 name = "Visionite VCS-UC300";
1721 type_id = 740; /* CCD sensor */
1722 break;
1723 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001724 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 name = "Visionite VCS-UM100";
1726 type_id = 730; /* CMOS sensor */
1727 break;
1728 default:
1729 return -ENODEV;
1730 break;
1731 }
1732 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001733 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1735
1736 memset(serial_number, 0, 30);
1737 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001738 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
1740 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001741 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
1743 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001744 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001746 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 return -ENOMEM;
1748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 pdev->type = type_id;
1750 pdev->vsize = default_size;
1751 pdev->vframes = default_fps;
1752 strcpy(pdev->serial, serial_number);
1753 pdev->features = features;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001754 if (vendor_id == 0x046D && product_id == 0x08B5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 /* Logitech QuickCam Orbit
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001756 The ranges have been determined experimentally; they may differ from cam to cam.
1757 Also, the exact ranges left-right and up-down are different for my cam
1758 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 pdev->angle_range.pan_min = -7000;
1760 pdev->angle_range.pan_max = 7000;
1761 pdev->angle_range.tilt_min = -3000;
1762 pdev->angle_range.tilt_max = 2500;
1763 }
1764
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001765 mutex_init(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 spin_lock_init(&pdev->ptrlock);
1767
1768 pdev->udev = udev;
1769 init_waitqueue_head(&pdev->frameq);
1770 pdev->vcompression = pwc_preferred_compression;
1771
1772 /* Allocate video_device structure */
1773 pdev->vdev = video_device_alloc();
Al Viro5fa12472008-03-29 03:07:38 +00001774 if (!pdev->vdev) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001775 PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001776 rc = -ENOMEM;
1777 goto err_free_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 }
1779 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
Lennart Poettering52a85e12009-06-04 16:18:13 -03001780 pdev->vdev->parent = &intf->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 strcpy(pdev->vdev->name, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 video_set_drvdata(pdev->vdev, pdev);
1783
1784 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001785 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 /* Now search device_hint[] table for a match, so we can hint a node number. */
1788 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1789 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1790 (device_hint[hint].pdev == NULL)) {
1791 /* so far, so good... try serial number */
1792 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001793 /* match! */
1794 video_nr = device_hint[hint].device_node;
1795 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1796 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 }
1798 }
1799 }
1800
1801 pdev->vdev->release = video_device_release;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001804 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 device_hint[hint].pdev = pdev;
1806
Luc Saillard2b455db2006-04-24 10:29:46 -03001807 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001808 usb_set_intfdata(intf, pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001809
1810 /* Set the leds off */
1811 pwc_set_leds(pdev, 0, 0);
1812 pwc_camera_power(pdev, 0);
1813
Hans Verkuil479567c2010-09-12 17:05:11 -03001814 rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
1815 if (rc < 0) {
1816 PWC_ERROR("Failed to register as video device (%d).\n", rc);
1817 goto err_video_release;
1818 }
1819 rc = pwc_create_sysfs_files(pdev->vdev);
1820 if (rc)
1821 goto err_video_unreg;
1822
1823 PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
1824
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001825#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1826 /* register webcam snapshot button input device */
1827 pdev->button_dev = input_allocate_device();
1828 if (!pdev->button_dev) {
1829 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001830 rc = -ENOMEM;
1831 pwc_remove_sysfs_files(pdev->vdev);
1832 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001833 }
1834
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001835 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1836 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1837
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001838 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001839 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001840 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1841 pdev->button_dev->dev.parent = &pdev->udev->dev;
1842 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001843 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001844
1845 rc = input_register_device(pdev->button_dev);
1846 if (rc) {
1847 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001848 pdev->button_dev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001849 pwc_remove_sysfs_files(pdev->vdev);
1850 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001851 }
1852#endif
1853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001855
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001856err_video_unreg:
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001857 if (hint < MAX_DEV_HINTS)
1858 device_hint[hint].pdev = NULL;
1859 video_unregister_device(pdev->vdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001860 pdev->vdev = NULL; /* So we don't try to release it below */
1861err_video_release:
1862 video_device_release(pdev->vdev);
1863err_free_mem:
1864 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001865 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866}
1867
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001868/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869static void usb_pwc_disconnect(struct usb_interface *intf)
1870{
1871 struct pwc_device *pdev;
1872 int hint;
1873
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 pdev = usb_get_intfdata (intf);
Hans Verkuil7074f402010-09-15 14:49:07 -03001875 mutex_lock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 usb_set_intfdata (intf, NULL);
1877 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001878 PWC_ERROR("pwc_disconnect() Called without private pointer.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 goto disconnect_out;
1880 }
1881 if (pdev->udev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001882 PWC_ERROR("pwc_disconnect() already called for %p\n", pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 goto disconnect_out;
1884 }
1885 if (pdev->udev != interface_to_usbdev(intf)) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001886 PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 goto disconnect_out;
1888 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 /* We got unplugged; this is signalled by an EPIPE error code */
1891 if (pdev->vopen) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001892 PWC_INFO("Disconnected while webcam is in use!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 pdev->error_status = EPIPE;
1894 }
1895
1896 /* Alert waiting processes */
1897 wake_up_interruptible(&pdev->frameq);
1898 /* Wait until device is closed */
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001899 if (pdev->vopen) {
Oliver Neukum85237f22007-08-21 07:10:42 +02001900 pdev->unplugged = 1;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -03001901 pwc_iso_stop(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +02001902 } else {
1903 /* Device is closed, so we can safely unregister it */
1904 PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
1905 pwc_cleanup(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
1907disconnect_out:
Oliver Neukum85237f22007-08-21 07:10:42 +02001908 /* search device_hint[] table if we occupy a slot, by any chance */
1909 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1910 if (device_hint[hint].pdev == pdev)
1911 device_hint[hint].pdev = NULL;
1912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Hans Verkuil7074f402010-09-15 14:49:07 -03001914 mutex_unlock(&pdev->modlock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915}
1916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001918/*
1919 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 */
1921
Luc Saillard2b455db2006-04-24 10:29:46 -03001922static char *size;
1923static int fps;
1924static int fbufs;
1925static int mbufs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926static int compression = -1;
1927static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001928static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001929static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001930static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931
Luc Saillard2b455db2006-04-24 10:29:46 -03001932module_param(size, charp, 0444);
1933module_param(fps, int, 0444);
1934module_param(fbufs, int, 0444);
1935module_param(mbufs, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001936#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001937module_param_named(trace, pwc_trace, int, 0644);
1938#endif
1939module_param(power_save, int, 0444);
1940module_param(compression, int, 0444);
1941module_param_array(leds, int, &leds_nargs, 0444);
1942module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1943
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
Andrea Odetti4315c412009-12-10 16:26:10 -03001948#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001950#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954MODULE_PARM_DESC(dev_hint, "Device node hints");
1955
1956MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1957MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1958MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001959MODULE_ALIAS("pwcx");
1960MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
1962static int __init usb_pwc_init(void)
1963{
1964 int i, sz;
1965 char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
1966
Luc Saillard2b455db2006-04-24 10:29:46 -03001967 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1968 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1969 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1970 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 -07001971
1972 if (fps) {
1973 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001974 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 return -EINVAL;
1976 }
1977 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001978 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 }
1980
Luc Saillard2b455db2006-04-24 10:29:46 -03001981 if (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 /* string; try matching with array */
1983 for (sz = 0; sz < PSZ_MAX; sz++) {
1984 if (!strcmp(sizenames[sz], size)) { /* Found! */
1985 default_size = sz;
1986 break;
1987 }
1988 }
1989 if (sz == PSZ_MAX) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001990 PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 return -EINVAL;
1992 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001993 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 -07001994 }
1995 if (mbufs) {
1996 if (mbufs < 1 || mbufs > MAX_IMAGES) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001997 PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 return -EINVAL;
1999 }
Luc Saillard2b455db2006-04-24 10:29:46 -03002000 pwc_mbufs = mbufs;
2001 PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 }
2003 if (fbufs) {
2004 if (fbufs < 2 || fbufs > MAX_FRAMES) {
Luc Saillard2b455db2006-04-24 10:29:46 -03002005 PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 return -EINVAL;
2007 }
2008 default_fbufs = fbufs;
Luc Saillard2b455db2006-04-24 10:29:46 -03002009 PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 }
Trent Piepho05ad3902007-01-30 23:26:01 -03002011#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03002012 if (pwc_trace >= 0) {
2013 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 }
Luc Saillard2b455db2006-04-24 10:29:46 -03002015#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 if (compression >= 0) {
2017 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03002018 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 return -EINVAL;
2020 }
2021 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03002022 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 }
2024 if (power_save)
Luc Saillard2b455db2006-04-24 10:29:46 -03002025 PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 if (leds[0] >= 0)
2027 led_on = leds[0];
2028 if (leds[1] >= 0)
2029 led_off = leds[1];
2030
Steven Cole093cf722005-05-03 19:07:24 -06002031 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 device node (/dev/videoX) to a camera, based on its type
2033 & serial number. The format is [type[.serialnumber]:]node.
2034
2035 Any camera that isn't matched by these rules gets the next
2036 available free device node.
2037 */
2038 for (i = 0; i < MAX_DEV_HINTS; i++) {
2039 char *s, *colon, *dot;
2040
2041 /* This loop also initializes the array */
2042 device_hint[i].pdev = NULL;
2043 s = dev_hint[i];
2044 if (s != NULL && *s != '\0') {
2045 device_hint[i].type = -1; /* wildcard */
2046 strcpy(device_hint[i].serial_number, "*");
2047
2048 /* parse string: chop at ':' & '/' */
2049 colon = dot = s;
2050 while (*colon != '\0' && *colon != ':')
2051 colon++;
2052 while (*dot != '\0' && *dot != '.')
2053 dot++;
2054 /* Few sanity checks */
2055 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03002056 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 return -EINVAL;
2058 }
2059
2060 if (*colon == '\0') {
2061 /* No colon */
2062 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03002063 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 return -EINVAL;
2065 }
2066 else {
2067 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03002068 device_hint[i].device_node =
2069 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 }
2071 }
2072 else {
2073 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03002074 device_hint[i].type =
2075 simple_strtol(s, NULL, 10);
2076 device_hint[i].device_node =
2077 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 if (*dot != '\0') {
2079 /* There's a serial number as well */
2080 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002081
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 dot++;
2083 k = 0;
2084 while (*dot != ':' && k < 29) {
2085 device_hint[i].serial_number[k++] = *dot;
2086 dot++;
2087 }
2088 device_hint[i].serial_number[k] = '\0';
2089 }
2090 }
Luc Saillard2b455db2006-04-24 10:29:46 -03002091 PWC_TRACE("device_hint[%d]:\n", i);
2092 PWC_TRACE(" type : %d\n", device_hint[i].type);
2093 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
2094 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 }
2096 else
2097 device_hint[i].type = 0; /* not filled */
2098 } /* ..for MAX_DEV_HINTS */
2099
Luc Saillard2b455db2006-04-24 10:29:46 -03002100 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 return usb_register(&pwc_driver);
2102}
2103
2104static void __exit usb_pwc_exit(void)
2105{
Luc Saillard2b455db2006-04-24 10:29:46 -03002106 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03002108 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109}
2110
2111module_init(usb_pwc_init);
2112module_exit(usb_pwc_exit);
2113
Luc Saillard2b455db2006-04-24 10:29:46 -03002114/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */