blob: 943d37ad0d33dd3983318bbddd0f4d19f185f55b [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)
Hans de Goede6eba9352011-06-26 06:49:59 -03005 (C) 2011 Hans de Goede <hdegoede@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
8 driver and thus may have bugs that are not present in the original version.
9 Please send bug reports and support requests to <luc@saillard.org>.
10 The decompression routines have been implemented by reverse-engineering the
11 Nemosoft binary pwcx module. Caveat emptor.
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
27*/
28
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030029/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 This code forms the interface between the USB layers and the Philips
31 specific stuff. Some adanved stuff of the driver falls under an
32 NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030033 is thus not distributed in source form. The binary pwcx.o module
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 contains the code that falls under the NDA.
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030035
36 In case you're wondering: 'pwc' stands for "Philips WebCam", but
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 I really didn't want to type 'philips_web_cam' every time (I'm lazy as
38 any Linux kernel hacker, but I don't like uncomprehensible abbreviations
39 without explanation).
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 Oh yes, convention: to disctinguish between all the various pointers to
42 device-structures, I use these names for the pointer variables:
43 udev: struct usb_device *
Hans de Goede9a7b2d12011-06-06 14:43:39 -030044 vdev: struct video_device (member of pwc_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 pdev: struct pwc_devive *
46*/
47
48/* Contributors:
49 - Alvarado: adding whitebalance code
50 - Alistar Moire: QuickCam 3000 Pro device/product ID
51 - Tony Hoyle: Creative Labs Webcam 5 device/product ID
52 - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
53 - Jk Fang: Sotec Afina Eye ID
54 - Xavier Roche: QuickCam Pro 4000 ID
55 - Jens Knudsen: QuickCam Zoom ID
56 - J. Debert: QuickCam for Notebooks ID
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -030057 - Pham Thanh Nam: webcam snapshot button as an event input device
Linus Torvalds1da177e2005-04-16 15:20:36 -070058*/
59
60#include <linux/errno.h>
61#include <linux/init.h>
62#include <linux/mm.h>
63#include <linux/module.h>
64#include <linux/poll.h>
65#include <linux/slab.h>
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -030066#ifdef CONFIG_USB_PWC_INPUT_EVDEV
67#include <linux/usb/input.h>
68#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#include <linux/vmalloc.h>
70#include <asm/io.h>
Andy Shevchenko2d8d7762009-09-24 07:58:09 -030071#include <linux/kernel.h> /* simple_strtol() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73#include "pwc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include "pwc-kiara.h"
75#include "pwc-timon.h"
Luc Saillard2b455db2006-04-24 10:29:46 -030076#include "pwc-dec23.h"
77#include "pwc-dec1.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
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);
Hans de Goede885fe182011-06-06 15:33:44 -0300119static void pwc_isoc_cleanup(struct pwc_device *pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121static struct usb_driver pwc_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 .name = "Philips webcam", /* name */
123 .id_table = pwc_device_table,
124 .probe = usb_pwc_probe, /* probe() */
125 .disconnect = usb_pwc_disconnect, /* disconnect() */
126};
127
128#define MAX_DEV_HINTS 20
129#define MAX_ISOC_ERRORS 20
130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131static int default_fps = 10;
Trent Piepho05ad3902007-01-30 23:26:01 -0300132#ifdef CONFIG_USB_PWC_DEBUG
Michael Krufkyb930e1d2007-08-27 18:16:54 -0300133 int pwc_trace = PWC_DEBUG_LEVEL;
Luc Saillard2b455db2006-04-24 10:29:46 -0300134#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300135static int power_save = -1;
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300136static int led_on = 100, led_off; /* defaults to LED that is on while in use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137static struct {
138 int type;
139 char serial_number[30];
140 int device_node;
141 struct pwc_device *pdev;
142} device_hint[MAX_DEV_HINTS];
143
144/***/
145
Hans Verkuilbec43662008-12-30 06:58:20 -0300146static int pwc_video_close(struct file *file);
Luc Saillard2b455db2006-04-24 10:29:46 -0300147static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 size_t count, loff_t *ppos);
149static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
151
Hans Verkuilbec43662008-12-30 06:58:20 -0300152static const struct v4l2_file_operations pwc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 .owner = THIS_MODULE,
Hans de Goede76ae8532011-07-19 07:14:22 -0300154 .open = v4l2_fh_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 .release = pwc_video_close,
156 .read = pwc_video_read,
157 .poll = pwc_video_poll,
158 .mmap = pwc_video_mmap,
Hans Verkuilafa38522011-01-22 06:34:55 -0300159 .unlocked_ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160};
161static struct video_device pwc_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 .name = "Philips Webcam", /* Filled in later */
Hans de Goede76ae8532011-07-19 07:14:22 -0300163 .release = video_device_release_empty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 .fops = &pwc_fops,
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300165 .ioctl_ops = &pwc_ioctl_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166};
167
168/***************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169/* Private functions */
170
Hans de Goede885fe182011-06-06 15:33:44 -0300171struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
Hans de Goede885fe182011-06-06 15:33:44 -0300173 unsigned long flags = 0;
174 struct pwc_frame_buf *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Hans de Goede885fe182011-06-06 15:33:44 -0300176 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
177 if (list_empty(&pdev->queued_bufs))
178 goto leave;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Hans de Goede885fe182011-06-06 15:33:44 -0300180 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
181 list_del(&buf->list);
182leave:
183 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
184 return buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300185}
186
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300187static void pwc_snapshot_button(struct pwc_device *pdev, int down)
188{
189 if (down) {
190 PWC_TRACE("Snapshot button pressed.\n");
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300191 } else {
192 PWC_TRACE("Snapshot button released.\n");
193 }
194
195#ifdef CONFIG_USB_PWC_INPUT_EVDEV
196 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300197 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300198 input_sync(pdev->button_dev);
199 }
200#endif
201}
202
Hans de Goede885fe182011-06-06 15:33:44 -0300203static void pwc_frame_complete(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300204{
Hans de Goede885fe182011-06-06 15:33:44 -0300205 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300206
207 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
208 frames on the USB wire after an exposure change. This conditition is
209 however detected in the cam and a bit is set in the header.
210 */
211 if (pdev->type == 730) {
212 unsigned char *ptr = (unsigned char *)fbuf->data;
213
214 if (ptr[1] == 1 && ptr[0] & 0x10) {
215 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
216 pdev->drop_frames += 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300217 }
218 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300219 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300220 }
221 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
222 if (ptr[0] & 0x02)
223 PWC_TRACE("Image is mirrored.\n");
224 else
225 PWC_TRACE("Image is normal.\n");
226 }
227 pdev->vmirror = ptr[0] & 0x03;
228 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
229 after a short frame; this condition is filtered out specifically. A 4 byte
230 frame doesn't make sense anyway.
231 So we get either this sequence:
232 drop_bit set -> 4 byte frame -> short frame -> good frame
233 Or this one:
234 drop_bit set -> short frame -> good frame
235 So we drop either 3 or 2 frames in all!
236 */
237 if (fbuf->filled == 4)
238 pdev->drop_frames++;
Hans de Goede885fe182011-06-06 15:33:44 -0300239 } else if (pdev->type == 740 || pdev->type == 720) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300240 unsigned char *ptr = (unsigned char *)fbuf->data;
241 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300242 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300243 }
244 pdev->vmirror = ptr[0] & 0x03;
245 }
246
Hans de Goede885fe182011-06-06 15:33:44 -0300247 /* In case we were instructed to drop the frame, do so silently. */
248 if (pdev->drop_frames > 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300249 pdev->drop_frames--;
Hans de Goede885fe182011-06-06 15:33:44 -0300250 } else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300251 /* Check for underflow first */
252 if (fbuf->filled < pdev->frame_total_size) {
253 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
254 " discarded.\n", fbuf->filled);
Hans de Goede885fe182011-06-06 15:33:44 -0300255 } else {
256 fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
257 fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
258 vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
259 pdev->fill_buf = NULL;
260 pdev->vsync = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300261 }
262 } /* !drop_frames */
263 pdev->vframe_count++;
Luc Saillard2b455db2006-04-24 10:29:46 -0300264}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266/* This gets called for the Isochronous pipe (video). This is done in
267 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
268 */
David Howells7d12e782006-10-05 14:55:46 +0100269static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{
Hans de Goede885fe182011-06-06 15:33:44 -0300271 struct pwc_device *pdev = (struct pwc_device *)urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 int i, fst, flen;
Hans de Goede885fe182011-06-06 15:33:44 -0300273 unsigned char *iso_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Hans de Goede885fe182011-06-06 15:33:44 -0300275 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
276 urb->status == -ESHUTDOWN) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300277 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 return;
279 }
Hans de Goede885fe182011-06-06 15:33:44 -0300280
281 if (pdev->fill_buf == NULL)
282 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
283
284 if (urb->status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 const char *errmsg;
286
287 errmsg = "Unknown";
288 switch(urb->status) {
289 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
290 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
291 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
292 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
293 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700294 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
Hans de Goede885fe182011-06-06 15:33:44 -0300296 PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
297 urb->status, errmsg);
298 /* Give up after a number of contiguous errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
300 {
Hans de Goede885fe182011-06-06 15:33:44 -0300301 PWC_ERROR("Too many ISOC errors, bailing out.\n");
302 if (pdev->fill_buf) {
303 vb2_buffer_done(&pdev->fill_buf->vb,
304 VB2_BUF_STATE_ERROR);
305 pdev->fill_buf = NULL;
306 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 }
Hans de Goede885fe182011-06-06 15:33:44 -0300308 pdev->vsync = 0; /* Drop the current frame */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 goto handler_end;
310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 /* Reset ISOC error counter. We did get here, after all. */
313 pdev->visoc_errors = 0;
314
315 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300316 1 = sync-hunt
317 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 */
319 /* Compact data */
320 for (i = 0; i < urb->number_of_packets; i++) {
321 fst = urb->iso_frame_desc[i].status;
322 flen = urb->iso_frame_desc[i].actual_length;
323 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Hans de Goede885fe182011-06-06 15:33:44 -0300324 if (fst != 0) {
325 PWC_ERROR("Iso frame %d has error %d\n", i, fst);
326 continue;
327 }
328 if (flen > 0 && pdev->vsync) {
329 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
Hans de Goede885fe182011-06-06 15:33:44 -0300331 if (pdev->vsync == 1) {
332 do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
333 pdev->vsync = 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300334 }
335
Hans de Goede885fe182011-06-06 15:33:44 -0300336 if (flen + fbuf->filled > pdev->frame_total_size) {
337 PWC_ERROR("Frame overflow (%d > %d)\n",
338 flen + fbuf->filled,
339 pdev->frame_total_size);
340 pdev->vsync = 0; /* Let's wait for an EOF */
341 } else {
342 memcpy(fbuf->data + fbuf->filled, iso_buf,
343 flen);
344 fbuf->filled += flen;
345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 }
Hans de Goede885fe182011-06-06 15:33:44 -0300347 if (flen < pdev->vlast_packet_size) {
348 /* Shorter packet... end of frame */
349 if (pdev->vsync == 2)
350 pwc_frame_complete(pdev);
351 if (pdev->fill_buf == NULL)
352 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
353 if (pdev->fill_buf) {
354 pdev->fill_buf->filled = 0;
355 pdev->vsync = 1;
356 }
357 }
358 pdev->vlast_packet_size = flen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 }
360
361handler_end:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 i = usb_submit_urb(urb, GFP_ATOMIC);
363 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300364 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365}
366
Hans de Goede885fe182011-06-06 15:33:44 -0300367static int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
369 struct usb_device *udev;
370 struct urb *urb;
371 int i, j, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 struct usb_interface *intf;
373 struct usb_host_interface *idesc = NULL;
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300374 int compression = 0; /* 0..3 = uncompressed..high */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (pdev->iso_init)
377 return 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 pdev->vsync = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300380 pdev->vlast_packet_size = 0;
Hans de Goede885fe182011-06-06 15:33:44 -0300381 pdev->fill_buf = NULL;
382 pdev->vframe_count = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300383 pdev->visoc_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 udev = pdev->udev;
385
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300386retry:
387 /* We first try with low compression and then retry with a higher
388 compression setting if there is not enough bandwidth. */
389 ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
390 pdev->vframes, &compression);
391
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 /* Get the current alternate interface, adjust packet size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 intf = usb_ifnum_to_if(udev, 0);
394 if (intf)
395 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if (!idesc)
Hans de Goedec2464122011-06-06 15:25:18 -0300397 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399 /* Search video endpoint */
400 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300401 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
403 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
404 break;
405 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300406 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300409 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600410 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 }
412
413 /* Set alternate interface */
Luc Saillard2b455db2006-04-24 10:29:46 -0300414 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300416 if (ret == -ENOSPC && compression < 3) {
417 compression++;
418 goto retry;
419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 if (ret < 0)
421 return ret;
422
Hans de Goede04613c52011-06-26 13:57:15 -0300423 /* Allocate and init Isochronuous urbs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 for (i = 0; i < MAX_ISO_BUFS; i++) {
425 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
426 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300427 PWC_ERROR("Failed to allocate urb %d\n", i);
Hans de Goede6eba9352011-06-26 06:49:59 -0300428 pdev->iso_init = 1;
429 pwc_isoc_cleanup(pdev);
430 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 }
Hans de Goede04613c52011-06-26 13:57:15 -0300432 pdev->urbs[i] = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300433 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 urb->interval = 1; // devik
436 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300437 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Hans de Goede04613c52011-06-26 13:57:15 -0300438 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
439 urb->transfer_buffer = usb_alloc_coherent(udev,
440 ISO_BUFFER_SIZE,
441 GFP_KERNEL,
442 &urb->transfer_dma);
443 if (urb->transfer_buffer == NULL) {
444 PWC_ERROR("Failed to allocate urb buffer %d\n", i);
445 pdev->iso_init = 1;
446 pwc_isoc_cleanup(pdev);
447 return -ENOMEM;
448 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300449 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
450 urb->complete = pwc_isoc_handler;
451 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 urb->start_frame = 0;
453 urb->number_of_packets = ISO_FRAMES_PER_DESC;
454 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
455 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
456 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
457 }
458 }
459
460 /* link */
461 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300462 ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300463 if (ret == -ENOSPC && compression < 3) {
464 compression++;
465 pdev->iso_init = 1;
466 pwc_isoc_cleanup(pdev);
467 goto retry;
468 }
Hans de Goede622d9f52010-11-16 12:32:09 -0300469 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300470 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Hans de Goede622d9f52010-11-16 12:32:09 -0300471 pdev->iso_init = 1;
472 pwc_isoc_cleanup(pdev);
473 return ret;
474 }
Hans de Goede04613c52011-06-26 13:57:15 -0300475 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
477
478 /* All is done... */
479 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300480 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 return 0;
482}
483
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300484static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 int i;
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 /* Unlinking ISOC buffers one by one */
489 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300490 if (pdev->urbs[i]) {
491 PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
492 usb_kill_urb(pdev->urbs[i]);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300493 }
494 }
495}
496
497static void pwc_iso_free(struct pwc_device *pdev)
498{
499 int i;
500
501 /* Freeing ISOC buffers one by one */
502 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300503 if (pdev->urbs[i]) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300504 PWC_DEBUG_MEMORY("Freeing URB\n");
Hans de Goede04613c52011-06-26 13:57:15 -0300505 if (pdev->urbs[i]->transfer_buffer) {
506 usb_free_coherent(pdev->udev,
507 pdev->urbs[i]->transfer_buffer_length,
508 pdev->urbs[i]->transfer_buffer,
509 pdev->urbs[i]->transfer_dma);
510 }
511 usb_free_urb(pdev->urbs[i]);
512 pdev->urbs[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 }
514 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300515}
516
Hans de Goede885fe182011-06-06 15:33:44 -0300517static void pwc_isoc_cleanup(struct pwc_device *pdev)
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300518{
519 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
Hans de Goedec2464122011-06-06 15:25:18 -0300520
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300521 if (pdev->iso_init == 0)
522 return;
523
524 pwc_iso_stop(pdev);
525 pwc_iso_free(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300526 usb_set_interface(pdev->udev, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300529 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530}
531
Hans de Goede885fe182011-06-06 15:33:44 -0300532static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
533{
Hans de Goedec20d78c2011-10-09 09:16:46 -0300534 unsigned long flags = 0;
535
536 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300537 while (!list_empty(&pdev->queued_bufs)) {
538 struct pwc_frame_buf *buf;
539
540 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
541 list);
542 list_del(&buf->list);
543 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
544 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300545 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300546}
547
Trent Piepho05ad3902007-01-30 23:26:01 -0300548#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -0300549static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
550{
551 switch(sensor_type) {
552 case 0x00:
553 return "Hyundai CMOS sensor";
554 case 0x20:
555 return "Sony CCD sensor + TDA8787";
556 case 0x2E:
557 return "Sony CCD sensor + Exas 98L59";
558 case 0x2F:
559 return "Sony CCD sensor + ADI 9804";
560 case 0x30:
561 return "Sharp CCD sensor + TDA8787";
562 case 0x3E:
563 return "Sharp CCD sensor + Exas 98L59";
564 case 0x3F:
565 return "Sharp CCD sensor + ADI 9804";
566 case 0x40:
567 return "UPA 1021 sensor";
568 case 0x100:
569 return "VGA sensor";
570 case 0x101:
571 return "PAL MR sensor";
572 default:
Trent Piepho657de3c2006-06-20 00:30:57 -0300573 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -0300574 }
575}
576#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
578/***************************************************************************/
579/* Video4Linux functions */
580
Hans de Goedec20d78c2011-10-09 09:16:46 -0300581int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
582{
583 int r = 0;
584
585 mutex_lock(&pdev->capt_file_lock);
586 if (pdev->capt_file != NULL &&
587 pdev->capt_file != file) {
588 r = -EBUSY;
589 goto leave;
590 }
591 pdev->capt_file = file;
592leave:
593 mutex_unlock(&pdev->capt_file_lock);
594 return r;
595}
596
Hans de Goede76ae8532011-07-19 07:14:22 -0300597static void pwc_video_release(struct v4l2_device *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
Hans de Goede76ae8532011-07-19 07:14:22 -0300599 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300600 int hint;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300601
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300602 /* search device_hint[] table if we occupy a slot, by any chance */
603 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
604 if (device_hint[hint].pdev == pdev)
605 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300606
Hans de Goede6eba9352011-06-26 06:49:59 -0300607 /* Free intermediate decompression buffer & tables */
608 if (pdev->decompress_data != NULL) {
609 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
610 pdev->decompress_data);
611 kfree(pdev->decompress_data);
612 pdev->decompress_data = NULL;
613 }
614
Hans de Goede6c9cac82011-06-26 12:52:01 -0300615 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
616
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300617 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +0200618}
619
Hans Verkuilbec43662008-12-30 06:58:20 -0300620static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
Hans de Goede76ae8532011-07-19 07:14:22 -0300622 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Hans de Goede4fba4712011-06-26 12:13:44 -0300624 if (pdev->capt_file == file) {
625 vb2_queue_release(&pdev->vb_queue);
626 pdev->capt_file = NULL;
627 }
Hans de Goede76ae8532011-07-19 07:14:22 -0300628 return v4l2_fh_release(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629}
630
Luc Saillard2b455db2006-04-24 10:29:46 -0300631static ssize_t pwc_video_read(struct file *file, char __user *buf,
Hans de Goede885fe182011-06-06 15:33:44 -0300632 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
Hans de Goede76ae8532011-07-19 07:14:22 -0300634 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Hans de Goedeb824bb42011-06-25 17:39:19 -0300636 if (!pdev->udev)
637 return -ENODEV;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300638
Hans de Goedec20d78c2011-10-09 09:16:46 -0300639 if (pwc_test_n_set_capt_file(pdev, file))
Hans de Goede4fba4712011-06-26 12:13:44 -0300640 return -EBUSY;
641
Hans de Goede885fe182011-06-06 15:33:44 -0300642 return vb2_read(&pdev->vb_queue, buf, count, ppos,
643 file->f_flags & O_NONBLOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
646static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
647{
Hans de Goede76ae8532011-07-19 07:14:22 -0300648 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Hans de Goedeb824bb42011-06-25 17:39:19 -0300650 if (!pdev->udev)
Hans de Goede885fe182011-06-06 15:33:44 -0300651 return POLL_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Hans de Goede885fe182011-06-06 15:33:44 -0300653 return vb2_poll(&pdev->vb_queue, file, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654}
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
657{
Hans de Goede76ae8532011-07-19 07:14:22 -0300658 struct pwc_device *pdev = video_drvdata(file);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300659
Hans de Goede4fba4712011-06-26 12:13:44 -0300660 if (pdev->capt_file != file)
661 return -EBUSY;
662
Hans de Goede885fe182011-06-06 15:33:44 -0300663 return vb2_mmap(&pdev->vb_queue, vma);
664}
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300665
Hans de Goede885fe182011-06-06 15:33:44 -0300666/***************************************************************************/
667/* Videobuf2 operations */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Guennadi Liakhovetskifc714e72011-08-24 10:30:21 -0300669static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
670 unsigned int *nbuffers, unsigned int *nplanes,
671 unsigned int sizes[], void *alloc_ctxs[])
Hans de Goede885fe182011-06-06 15:33:44 -0300672{
673 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Hans de Goede795e6eb2012-01-04 16:58:44 -0300674 int size;
Luc Saillard2b455db2006-04-24 10:29:46 -0300675
Hans de Goede885fe182011-06-06 15:33:44 -0300676 if (*nbuffers < MIN_FRAMES)
677 *nbuffers = MIN_FRAMES;
678 else if (*nbuffers > MAX_FRAMES)
679 *nbuffers = MAX_FRAMES;
680
681 *nplanes = 1;
682
Hans de Goede795e6eb2012-01-04 16:58:44 -0300683 size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
684 sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
685 pwc_image_sizes[size][1] * 3 / 2);
Hans de Goede885fe182011-06-06 15:33:44 -0300686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return 0;
688}
689
Hans de Goede885fe182011-06-06 15:33:44 -0300690static int buffer_init(struct vb2_buffer *vb)
691{
692 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
693
694 /* need vmalloc since frame buffer > 128K */
695 buf->data = vzalloc(PWC_FRAME_SIZE);
696 if (buf->data == NULL)
697 return -ENOMEM;
698
699 return 0;
700}
701
702static int buffer_prepare(struct vb2_buffer *vb)
703{
704 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
705
706 /* Don't allow queing new buffers after device disconnection */
Hans de Goedeb824bb42011-06-25 17:39:19 -0300707 if (!pdev->udev)
708 return -ENODEV;
Hans de Goede885fe182011-06-06 15:33:44 -0300709
710 return 0;
711}
712
713static int buffer_finish(struct vb2_buffer *vb)
714{
715 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
716 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
717
718 /*
719 * Application has called dqbuf and is getting back a buffer we've
720 * filled, take the pwc data we've stored in buf->data and decompress
721 * it into a usable format, storing the result in the vb2_buffer
722 */
723 return pwc_decompress(pdev, buf);
724}
725
726static void buffer_cleanup(struct vb2_buffer *vb)
727{
728 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
729
730 vfree(buf->data);
731}
732
733static void buffer_queue(struct vb2_buffer *vb)
734{
735 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
736 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
737 unsigned long flags = 0;
738
739 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300740 /* Check the device has not disconnected between prep and queuing */
741 if (pdev->udev)
742 list_add_tail(&buf->list, &pdev->queued_bufs);
743 else
744 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
Hans de Goede885fe182011-06-06 15:33:44 -0300745 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
746}
747
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300748static int start_streaming(struct vb2_queue *vq, unsigned int count)
Hans de Goede885fe182011-06-06 15:33:44 -0300749{
750 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300751 int r;
Hans de Goede885fe182011-06-06 15:33:44 -0300752
Hans de Goedec20d78c2011-10-09 09:16:46 -0300753 mutex_lock(&pdev->udevlock);
754 if (!pdev->udev) {
755 r = -ENODEV;
756 goto leave;
757 }
Hans de Goedeb824bb42011-06-25 17:39:19 -0300758
Hans de Goede6eba9352011-06-26 06:49:59 -0300759 /* Turn on camera and set LEDS on */
760 pwc_camera_power(pdev, 1);
Hans de Goede6eba9352011-06-26 06:49:59 -0300761 pwc_set_leds(pdev, led_on, led_off);
762
Hans de Goedec20d78c2011-10-09 09:16:46 -0300763 r = pwc_isoc_init(pdev);
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300764 if (r) {
765 /* If we failed turn camera and LEDS back off */
766 pwc_set_leds(pdev, 0, 0);
767 pwc_camera_power(pdev, 0);
768 /* And cleanup any queued bufs!! */
769 pwc_cleanup_queued_bufs(pdev);
770 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300771leave:
772 mutex_unlock(&pdev->udevlock);
773 return r;
Hans de Goede885fe182011-06-06 15:33:44 -0300774}
775
776static int stop_streaming(struct vb2_queue *vq)
777{
778 struct pwc_device *pdev = vb2_get_drv_priv(vq);
779
Hans de Goedec20d78c2011-10-09 09:16:46 -0300780 mutex_lock(&pdev->udevlock);
Hans de Goede6eba9352011-06-26 06:49:59 -0300781 if (pdev->udev) {
782 pwc_set_leds(pdev, 0, 0);
783 pwc_camera_power(pdev, 0);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300784 pwc_isoc_cleanup(pdev);
Hans de Goede6eba9352011-06-26 06:49:59 -0300785 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300786 mutex_unlock(&pdev->udevlock);
787
Hans de Goede885fe182011-06-06 15:33:44 -0300788 pwc_cleanup_queued_bufs(pdev);
789
790 return 0;
791}
792
Hans de Goede885fe182011-06-06 15:33:44 -0300793static struct vb2_ops pwc_vb_queue_ops = {
794 .queue_setup = queue_setup,
795 .buf_init = buffer_init,
796 .buf_prepare = buffer_prepare,
797 .buf_finish = buffer_finish,
798 .buf_cleanup = buffer_cleanup,
799 .buf_queue = buffer_queue,
800 .start_streaming = start_streaming,
801 .stop_streaming = stop_streaming,
Hans de Goede885fe182011-06-06 15:33:44 -0300802};
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804/***************************************************************************/
805/* USB functions */
806
807/* This function gets called when a new device is plugged in or the usb core
808 * is loaded.
809 */
810
811static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
812{
813 struct usb_device *udev = interface_to_usbdev(intf);
814 struct pwc_device *pdev = NULL;
815 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300816 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 int features = 0;
Hans de Goede5bbe18d2012-01-04 18:48:05 -0300818 int compression = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 int video_nr = -1; /* default: use next available device */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300820 int my_power_save = power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 char serial_number[30], *name;
822
Luc Saillard2b455db2006-04-24 10:29:46 -0300823 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
824 product_id = le16_to_cpu(udev->descriptor.idProduct);
825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -0300827 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
828 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 intf->altsetting->desc.bInterfaceNumber);
830
831 /* the interfaces are probed one by one. We are only interested in the
832 video interface (0) now.
833 Interface 1 is the Audio Control, and interface 2 Audio itself.
834 */
835 if (intf->altsetting->desc.bInterfaceNumber > 0)
836 return -ENODEV;
837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 if (vendor_id == 0x0471) {
839 switch (product_id) {
840 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -0300841 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 name = "Philips 645 webcam";
843 type_id = 645;
844 break;
845 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -0300846 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 name = "Philips 646 webcam";
848 type_id = 646;
849 break;
850 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -0300851 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 name = "Askey VC010 webcam";
853 type_id = 646;
854 break;
855 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -0300856 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 name = "Philips 675 webcam";
858 type_id = 675;
859 break;
860 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -0300861 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 name = "Philips 680 webcam";
863 type_id = 680;
864 break;
865 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -0300866 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 name = "Philips 690 webcam";
868 type_id = 690;
869 break;
870 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -0300871 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 name = "Philips 730 webcam";
873 type_id = 730;
874 break;
875 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -0300876 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 name = "Philips 740 webcam";
878 type_id = 740;
879 break;
880 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -0300881 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 name = "Philips 750 webcam";
883 type_id = 750;
884 break;
885 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -0300886 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 name = "Philips 720K/40 webcam";
888 type_id = 720;
889 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300890 case 0x0329:
891 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
892 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -0300893 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -0300894 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 default:
896 return -ENODEV;
897 break;
898 }
899 }
900 else if (vendor_id == 0x069A) {
901 switch(product_id) {
902 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300903 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 name = "Askey VC010 webcam";
905 type_id = 645;
906 break;
907 default:
908 return -ENODEV;
909 break;
910 }
911 }
912 else if (vendor_id == 0x046d) {
913 switch(product_id) {
914 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -0300915 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 name = "Logitech QuickCam Pro 3000";
917 type_id = 740; /* CCD sensor */
918 break;
919 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -0300920 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 name = "Logitech QuickCam Notebook Pro";
922 type_id = 740; /* CCD sensor */
923 break;
924 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -0300925 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 name = "Logitech QuickCam Pro 4000";
927 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300928 if (my_power_save == -1)
929 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 break;
931 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -0300932 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 name = "Logitech QuickCam Zoom";
934 type_id = 740; /* CCD sensor */
935 break;
936 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -0300937 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 name = "Logitech QuickCam Zoom";
939 type_id = 740; /* CCD sensor */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300940 if (my_power_save == -1)
941 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 break;
943 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -0300944 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 name = "Logitech QuickCam Orbit";
946 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300947 if (my_power_save == -1)
948 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 features |= FEATURE_MOTOR_PANTILT;
950 break;
951 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -0300952 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
953 name = "Cisco VT Camera";
954 type_id = 740; /* CCD sensor */
955 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -0300957 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
958 name = "Logitech ViewPort AV 100";
959 type_id = 740; /* CCD sensor */
960 break;
961 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -0300962 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 name = "Logitech QuickCam (res.)";
964 type_id = 730; /* Assuming CMOS */
965 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300966 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300968 break;
969 }
970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 else if (vendor_id == 0x055d) {
972 /* I don't know the difference between the C10 and the C30;
973 I suppose the difference is the sensor, but both cameras
974 work equally well with a type_id of 675
975 */
976 switch(product_id) {
977 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -0300978 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 name = "Samsung MPC-C10";
980 type_id = 675;
981 break;
982 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300983 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 name = "Samsung MPC-C30";
985 type_id = 675;
986 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300987 case 0x9002:
988 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
989 name = "Samsung MPC-C30";
990 type_id = 740;
991 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 default:
993 return -ENODEV;
994 break;
995 }
996 }
997 else if (vendor_id == 0x041e) {
998 switch(product_id) {
999 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -03001000 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 name = "Creative Labs Webcam 5";
1002 type_id = 730;
Hans de Goede51886df2011-07-03 15:52:54 -03001003 if (my_power_save == -1)
1004 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 break;
1006 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -03001007 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 name = "Creative Labs Webcam Pro Ex";
1009 type_id = 740;
1010 break;
1011 default:
1012 return -ENODEV;
1013 break;
1014 }
1015 }
1016 else if (vendor_id == 0x04cc) {
1017 switch(product_id) {
1018 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001019 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 name = "Sotec Afina Eye";
1021 type_id = 730;
1022 break;
1023 default:
1024 return -ENODEV;
1025 break;
1026 }
1027 }
1028 else if (vendor_id == 0x06be) {
1029 switch(product_id) {
1030 case 0x8116:
1031 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001032 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 name = "AME Co. Afina Eye";
1034 type_id = 750;
1035 break;
1036 default:
1037 return -ENODEV;
1038 break;
1039 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 }
1042 else if (vendor_id == 0x0d81) {
1043 switch(product_id) {
1044 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001045 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 name = "Visionite VCS-UC300";
1047 type_id = 740; /* CCD sensor */
1048 break;
1049 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001050 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 name = "Visionite VCS-UM100";
1052 type_id = 730; /* CMOS sensor */
1053 break;
1054 default:
1055 return -ENODEV;
1056 break;
1057 }
1058 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001059 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1061
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001062 if (my_power_save == -1)
1063 my_power_save = 0;
1064
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 memset(serial_number, 0, 30);
1066 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001067 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001070 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001073 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001075 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 return -ENOMEM;
1077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 pdev->type = type_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 pdev->vframes = default_fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 pdev->features = features;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001081 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Hans de Goedec20d78c2011-10-09 09:16:46 -03001083 mutex_init(&pdev->capt_file_lock);
Hans de Goedec1127132011-07-03 11:50:51 -03001084 mutex_init(&pdev->udevlock);
Hans de Goede885fe182011-06-06 15:33:44 -03001085 spin_lock_init(&pdev->queued_bufs_lock);
1086 INIT_LIST_HEAD(&pdev->queued_bufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 pdev->udev = udev;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001089 pdev->power_save = my_power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
Hans de Goede885fe182011-06-06 15:33:44 -03001091 /* Init videobuf2 queue structure */
1092 memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
1093 pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1094 pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1095 pdev->vb_queue.drv_priv = pdev;
1096 pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
1097 pdev->vb_queue.ops = &pwc_vb_queue_ops;
1098 pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
1099 vb2_queue_init(&pdev->vb_queue);
1100
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001101 /* Init video_device structure */
1102 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001103 strcpy(pdev->vdev.name, name);
Hans de Goede76ae8532011-07-19 07:14:22 -03001104 set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001105 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001108 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 /* Now search device_hint[] table for a match, so we can hint a node number. */
1111 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1112 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1113 (device_hint[hint].pdev == NULL)) {
1114 /* so far, so good... try serial number */
1115 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001116 /* match! */
1117 video_nr = device_hint[hint].device_node;
1118 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1119 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
1121 }
1122 }
1123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001125 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 device_hint[hint].pdev = pdev;
1127
Hans de Goede6eba9352011-06-26 06:49:59 -03001128#ifdef CONFIG_USB_PWC_DEBUG
1129 /* Query sensor type */
1130 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1131 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1132 pdev->vdev.name,
1133 pwc_sensor_type_to_string(rc), rc);
1134 }
1135#endif
1136
Luc Saillard2b455db2006-04-24 10:29:46 -03001137 /* Set the leds off */
1138 pwc_set_leds(pdev, 0, 0);
Hans de Goede6eba9352011-06-26 06:49:59 -03001139
1140 /* Setup intial videomode */
Hans de Goede5bbe18d2012-01-04 18:48:05 -03001141 rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
1142 &compression);
Hans de Goede6eba9352011-06-26 06:49:59 -03001143 if (rc)
1144 goto err_free_mem;
1145
Hans de Goede6c9cac82011-06-26 12:52:01 -03001146 /* Register controls (and read default values from camera */
1147 rc = pwc_init_controls(pdev);
1148 if (rc) {
1149 PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
1150 goto err_free_mem;
1151 }
1152
Hans de Goede6eba9352011-06-26 06:49:59 -03001153 /* And powerdown the camera until streaming starts */
Luc Saillard2b455db2006-04-24 10:29:46 -03001154 pwc_camera_power(pdev, 0);
1155
Hans de Goede76ae8532011-07-19 07:14:22 -03001156 /* Register the v4l2_device structure */
1157 pdev->v4l2_dev.release = pwc_video_release;
1158 rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
1159 if (rc) {
1160 PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
1161 goto err_free_controls;
1162 }
1163
1164 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
1165 pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
1166
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001167 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001168 if (rc < 0) {
1169 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede76ae8532011-07-19 07:14:22 -03001170 goto err_unregister_v4l2_dev;
Hans Verkuil479567c2010-09-12 17:05:11 -03001171 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001172 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001173
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001174#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1175 /* register webcam snapshot button input device */
1176 pdev->button_dev = input_allocate_device();
1177 if (!pdev->button_dev) {
1178 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001179 rc = -ENOMEM;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001180 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001181 }
1182
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001183 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1184 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1185
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001186 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001187 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001188 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1189 pdev->button_dev->dev.parent = &pdev->udev->dev;
1190 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001191 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001192
1193 rc = input_register_device(pdev->button_dev);
1194 if (rc) {
1195 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001196 pdev->button_dev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001197 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001198 }
1199#endif
1200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001202
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001203err_video_unreg:
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001204 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001205err_unregister_v4l2_dev:
1206 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001207err_free_controls:
1208 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001209err_free_mem:
Hans de Goede32c67ec2011-07-19 09:05:49 -03001210 if (hint < MAX_DEV_HINTS)
1211 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001212 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001213 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214}
1215
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001216/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217static void usb_pwc_disconnect(struct usb_interface *intf)
1218{
Hans de Goede76ae8532011-07-19 07:14:22 -03001219 struct v4l2_device *v = usb_get_intfdata(intf);
1220 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Hans de Goedec1127132011-07-03 11:50:51 -03001222 mutex_lock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001223 /* No need to keep the urbs around after disconnection */
1224 pwc_isoc_cleanup(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -03001225 pdev->udev = NULL;
Hans de Goedec1127132011-07-03 11:50:51 -03001226 mutex_unlock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001227
Hans de Goedec20d78c2011-10-09 09:16:46 -03001228 pwc_cleanup_queued_bufs(pdev);
1229
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001230 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001231 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001232
1233#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1234 if (pdev->button_dev)
1235 input_unregister_device(pdev->button_dev);
1236#endif
Hans de Goede76ae8532011-07-19 07:14:22 -03001237
1238 v4l2_device_put(&pdev->v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239}
1240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001242/*
1243 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 */
1245
Luc Saillard2b455db2006-04-24 10:29:46 -03001246static int fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001248static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001249static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001250static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Luc Saillard2b455db2006-04-24 10:29:46 -03001252module_param(fps, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001253#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001254module_param_named(trace, pwc_trace, int, 0644);
1255#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001256module_param(power_save, int, 0644);
Luc Saillard2b455db2006-04-24 10:29:46 -03001257module_param_array(leds, int, &leds_nargs, 0444);
1258module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Andrea Odetti4315c412009-12-10 16:26:10 -03001261#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001263#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001264MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266MODULE_PARM_DESC(dev_hint, "Device node hints");
1267
1268MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1269MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1270MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001271MODULE_ALIAS("pwcx");
1272MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274static int __init usb_pwc_init(void)
1275{
Hans de Goede6eba9352011-06-26 06:49:59 -03001276 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Hans de Goede6eba9352011-06-26 06:49:59 -03001278#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001279 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1280 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1281 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1282 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 -07001283
Hans de Goede6eba9352011-06-26 06:49:59 -03001284 if (pwc_trace >= 0) {
1285 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1286 }
1287#endif
1288
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 if (fps) {
1290 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001291 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 return -EINVAL;
1293 }
1294 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001295 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 if (leds[0] >= 0)
1299 led_on = leds[0];
1300 if (leds[1] >= 0)
1301 led_off = leds[1];
1302
Steven Cole093cf722005-05-03 19:07:24 -06001303 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 device node (/dev/videoX) to a camera, based on its type
1305 & serial number. The format is [type[.serialnumber]:]node.
1306
1307 Any camera that isn't matched by these rules gets the next
1308 available free device node.
1309 */
1310 for (i = 0; i < MAX_DEV_HINTS; i++) {
1311 char *s, *colon, *dot;
1312
1313 /* This loop also initializes the array */
1314 device_hint[i].pdev = NULL;
1315 s = dev_hint[i];
1316 if (s != NULL && *s != '\0') {
1317 device_hint[i].type = -1; /* wildcard */
1318 strcpy(device_hint[i].serial_number, "*");
1319
1320 /* parse string: chop at ':' & '/' */
1321 colon = dot = s;
1322 while (*colon != '\0' && *colon != ':')
1323 colon++;
1324 while (*dot != '\0' && *dot != '.')
1325 dot++;
1326 /* Few sanity checks */
1327 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001328 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return -EINVAL;
1330 }
1331
1332 if (*colon == '\0') {
1333 /* No colon */
1334 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001335 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 return -EINVAL;
1337 }
1338 else {
1339 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001340 device_hint[i].device_node =
1341 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 }
1343 }
1344 else {
1345 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001346 device_hint[i].type =
1347 simple_strtol(s, NULL, 10);
1348 device_hint[i].device_node =
1349 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if (*dot != '\0') {
1351 /* There's a serial number as well */
1352 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 dot++;
1355 k = 0;
1356 while (*dot != ':' && k < 29) {
1357 device_hint[i].serial_number[k++] = *dot;
1358 dot++;
1359 }
1360 device_hint[i].serial_number[k] = '\0';
1361 }
1362 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001363 PWC_TRACE("device_hint[%d]:\n", i);
1364 PWC_TRACE(" type : %d\n", device_hint[i].type);
1365 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1366 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 }
1368 else
1369 device_hint[i].type = 0; /* not filled */
1370 } /* ..for MAX_DEV_HINTS */
1371
Luc Saillard2b455db2006-04-24 10:29:46 -03001372 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return usb_register(&pwc_driver);
1374}
1375
1376static void __exit usb_pwc_exit(void)
1377{
Luc Saillard2b455db2006-04-24 10:29:46 -03001378 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001380 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381}
1382
1383module_init(usb_pwc_init);
1384module_exit(usb_pwc_exit);
1385
Luc Saillard2b455db2006-04-24 10:29:46 -03001386/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */