blob: 963b4a55ec7530fe381e5d9ce47923de30931b16 [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 */
Adrian Bunkb20c3cf2006-06-23 06:49:34 -0300137static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138static struct {
139 int type;
140 char serial_number[30];
141 int device_node;
142 struct pwc_device *pdev;
143} device_hint[MAX_DEV_HINTS];
144
145/***/
146
Hans Verkuilbec43662008-12-30 06:58:20 -0300147static int pwc_video_close(struct file *file);
Luc Saillard2b455db2006-04-24 10:29:46 -0300148static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 size_t count, loff_t *ppos);
150static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
152
Hans Verkuilbec43662008-12-30 06:58:20 -0300153static const struct v4l2_file_operations pwc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 .owner = THIS_MODULE,
Hans de Goede76ae8532011-07-19 07:14:22 -0300155 .open = v4l2_fh_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 .release = pwc_video_close,
157 .read = pwc_video_read,
158 .poll = pwc_video_poll,
159 .mmap = pwc_video_mmap,
Hans Verkuilafa38522011-01-22 06:34:55 -0300160 .unlocked_ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161};
162static struct video_device pwc_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 .name = "Philips Webcam", /* Filled in later */
Hans de Goede76ae8532011-07-19 07:14:22 -0300164 .release = video_device_release_empty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 .fops = &pwc_fops,
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300166 .ioctl_ops = &pwc_ioctl_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167};
168
169/***************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170/* Private functions */
171
Hans de Goede885fe182011-06-06 15:33:44 -0300172struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
Hans de Goede885fe182011-06-06 15:33:44 -0300174 unsigned long flags = 0;
175 struct pwc_frame_buf *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
Hans de Goede885fe182011-06-06 15:33:44 -0300177 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
178 if (list_empty(&pdev->queued_bufs))
179 goto leave;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Hans de Goede885fe182011-06-06 15:33:44 -0300181 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
182 list_del(&buf->list);
183leave:
184 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
185 return buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300186}
187
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300188static void pwc_snapshot_button(struct pwc_device *pdev, int down)
189{
190 if (down) {
191 PWC_TRACE("Snapshot button pressed.\n");
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300192 } else {
193 PWC_TRACE("Snapshot button released.\n");
194 }
195
196#ifdef CONFIG_USB_PWC_INPUT_EVDEV
197 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300198 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300199 input_sync(pdev->button_dev);
200 }
201#endif
202}
203
Hans de Goede885fe182011-06-06 15:33:44 -0300204static void pwc_frame_complete(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300205{
Hans de Goede885fe182011-06-06 15:33:44 -0300206 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300207
208 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
209 frames on the USB wire after an exposure change. This conditition is
210 however detected in the cam and a bit is set in the header.
211 */
212 if (pdev->type == 730) {
213 unsigned char *ptr = (unsigned char *)fbuf->data;
214
215 if (ptr[1] == 1 && ptr[0] & 0x10) {
216 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
217 pdev->drop_frames += 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300218 }
219 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300220 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300221 }
222 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
223 if (ptr[0] & 0x02)
224 PWC_TRACE("Image is mirrored.\n");
225 else
226 PWC_TRACE("Image is normal.\n");
227 }
228 pdev->vmirror = ptr[0] & 0x03;
229 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
230 after a short frame; this condition is filtered out specifically. A 4 byte
231 frame doesn't make sense anyway.
232 So we get either this sequence:
233 drop_bit set -> 4 byte frame -> short frame -> good frame
234 Or this one:
235 drop_bit set -> short frame -> good frame
236 So we drop either 3 or 2 frames in all!
237 */
238 if (fbuf->filled == 4)
239 pdev->drop_frames++;
Hans de Goede885fe182011-06-06 15:33:44 -0300240 } else if (pdev->type == 740 || pdev->type == 720) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300241 unsigned char *ptr = (unsigned char *)fbuf->data;
242 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300243 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300244 }
245 pdev->vmirror = ptr[0] & 0x03;
246 }
247
Hans de Goede885fe182011-06-06 15:33:44 -0300248 /* In case we were instructed to drop the frame, do so silently. */
249 if (pdev->drop_frames > 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300250 pdev->drop_frames--;
Hans de Goede885fe182011-06-06 15:33:44 -0300251 } else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300252 /* Check for underflow first */
253 if (fbuf->filled < pdev->frame_total_size) {
254 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
255 " discarded.\n", fbuf->filled);
Hans de Goede885fe182011-06-06 15:33:44 -0300256 } else {
257 fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
258 fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
259 vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
260 pdev->fill_buf = NULL;
261 pdev->vsync = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300262 }
263 } /* !drop_frames */
264 pdev->vframe_count++;
Luc Saillard2b455db2006-04-24 10:29:46 -0300265}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267/* This gets called for the Isochronous pipe (video). This is done in
268 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
269 */
David Howells7d12e782006-10-05 14:55:46 +0100270static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
Hans de Goede885fe182011-06-06 15:33:44 -0300272 struct pwc_device *pdev = (struct pwc_device *)urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 int i, fst, flen;
Hans de Goede885fe182011-06-06 15:33:44 -0300274 unsigned char *iso_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Hans de Goede885fe182011-06-06 15:33:44 -0300276 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
277 urb->status == -ESHUTDOWN) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300278 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 return;
280 }
Hans de Goede885fe182011-06-06 15:33:44 -0300281
282 if (pdev->fill_buf == NULL)
283 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
284
285 if (urb->status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 const char *errmsg;
287
288 errmsg = "Unknown";
289 switch(urb->status) {
290 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
291 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
292 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
293 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
294 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700295 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
Hans de Goede885fe182011-06-06 15:33:44 -0300297 PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
298 urb->status, errmsg);
299 /* Give up after a number of contiguous errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
301 {
Hans de Goede885fe182011-06-06 15:33:44 -0300302 PWC_ERROR("Too many ISOC errors, bailing out.\n");
303 if (pdev->fill_buf) {
304 vb2_buffer_done(&pdev->fill_buf->vb,
305 VB2_BUF_STATE_ERROR);
306 pdev->fill_buf = NULL;
307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 }
Hans de Goede885fe182011-06-06 15:33:44 -0300309 pdev->vsync = 0; /* Drop the current frame */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 goto handler_end;
311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
313 /* Reset ISOC error counter. We did get here, after all. */
314 pdev->visoc_errors = 0;
315
316 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300317 1 = sync-hunt
318 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 */
320 /* Compact data */
321 for (i = 0; i < urb->number_of_packets; i++) {
322 fst = urb->iso_frame_desc[i].status;
323 flen = urb->iso_frame_desc[i].actual_length;
324 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Hans de Goede885fe182011-06-06 15:33:44 -0300325 if (fst != 0) {
326 PWC_ERROR("Iso frame %d has error %d\n", i, fst);
327 continue;
328 }
329 if (flen > 0 && pdev->vsync) {
330 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
Hans de Goede885fe182011-06-06 15:33:44 -0300332 if (pdev->vsync == 1) {
333 do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
334 pdev->vsync = 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300335 }
336
Hans de Goede885fe182011-06-06 15:33:44 -0300337 if (flen + fbuf->filled > pdev->frame_total_size) {
338 PWC_ERROR("Frame overflow (%d > %d)\n",
339 flen + fbuf->filled,
340 pdev->frame_total_size);
341 pdev->vsync = 0; /* Let's wait for an EOF */
342 } else {
343 memcpy(fbuf->data + fbuf->filled, iso_buf,
344 flen);
345 fbuf->filled += flen;
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 }
Hans de Goede885fe182011-06-06 15:33:44 -0300348 if (flen < pdev->vlast_packet_size) {
349 /* Shorter packet... end of frame */
350 if (pdev->vsync == 2)
351 pwc_frame_complete(pdev);
352 if (pdev->fill_buf == NULL)
353 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
354 if (pdev->fill_buf) {
355 pdev->fill_buf->filled = 0;
356 pdev->vsync = 1;
357 }
358 }
359 pdev->vlast_packet_size = flen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 }
361
362handler_end:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 i = usb_submit_urb(urb, GFP_ATOMIC);
364 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300365 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366}
367
Hans de Goede885fe182011-06-06 15:33:44 -0300368static int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
370 struct usb_device *udev;
371 struct urb *urb;
372 int i, j, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 struct usb_interface *intf;
374 struct usb_host_interface *idesc = NULL;
375
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
386 /* Get the current alternate interface, adjust packet size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 intf = usb_ifnum_to_if(udev, 0);
388 if (intf)
389 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 if (!idesc)
Hans de Goedec2464122011-06-06 15:25:18 -0300391 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393 /* Search video endpoint */
394 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300395 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
397 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
398 break;
399 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300400 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300403 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600404 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 }
406
407 /* Set alternate interface */
408 ret = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300409 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
411 if (ret < 0)
412 return ret;
413
Hans de Goede04613c52011-06-26 13:57:15 -0300414 /* Allocate and init Isochronuous urbs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 for (i = 0; i < MAX_ISO_BUFS; i++) {
416 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
417 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300418 PWC_ERROR("Failed to allocate urb %d\n", i);
Hans de Goede6eba9352011-06-26 06:49:59 -0300419 pdev->iso_init = 1;
420 pwc_isoc_cleanup(pdev);
421 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 }
Hans de Goede04613c52011-06-26 13:57:15 -0300423 pdev->urbs[i] = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300424 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 urb->interval = 1; // devik
427 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300428 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Hans de Goede04613c52011-06-26 13:57:15 -0300429 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
430 urb->transfer_buffer = usb_alloc_coherent(udev,
431 ISO_BUFFER_SIZE,
432 GFP_KERNEL,
433 &urb->transfer_dma);
434 if (urb->transfer_buffer == NULL) {
435 PWC_ERROR("Failed to allocate urb buffer %d\n", i);
436 pdev->iso_init = 1;
437 pwc_isoc_cleanup(pdev);
438 return -ENOMEM;
439 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300440 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
441 urb->complete = pwc_isoc_handler;
442 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 urb->start_frame = 0;
444 urb->number_of_packets = ISO_FRAMES_PER_DESC;
445 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
446 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
447 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
448 }
449 }
450
451 /* link */
452 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300453 ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
Hans de Goede622d9f52010-11-16 12:32:09 -0300454 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300455 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Hans de Goede622d9f52010-11-16 12:32:09 -0300456 pdev->iso_init = 1;
457 pwc_isoc_cleanup(pdev);
458 return ret;
459 }
Hans de Goede04613c52011-06-26 13:57:15 -0300460 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 }
462
463 /* All is done... */
464 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300465 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return 0;
467}
468
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300469static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 int i;
472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 /* Unlinking ISOC buffers one by one */
474 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300475 if (pdev->urbs[i]) {
476 PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
477 usb_kill_urb(pdev->urbs[i]);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300478 }
479 }
480}
481
482static void pwc_iso_free(struct pwc_device *pdev)
483{
484 int i;
485
486 /* Freeing ISOC buffers one by one */
487 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300488 if (pdev->urbs[i]) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300489 PWC_DEBUG_MEMORY("Freeing URB\n");
Hans de Goede04613c52011-06-26 13:57:15 -0300490 if (pdev->urbs[i]->transfer_buffer) {
491 usb_free_coherent(pdev->udev,
492 pdev->urbs[i]->transfer_buffer_length,
493 pdev->urbs[i]->transfer_buffer,
494 pdev->urbs[i]->transfer_dma);
495 }
496 usb_free_urb(pdev->urbs[i]);
497 pdev->urbs[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300500}
501
Hans de Goede885fe182011-06-06 15:33:44 -0300502static void pwc_isoc_cleanup(struct pwc_device *pdev)
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300503{
504 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
Hans de Goedec2464122011-06-06 15:25:18 -0300505
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300506 if (pdev->iso_init == 0)
507 return;
508
509 pwc_iso_stop(pdev);
510 pwc_iso_free(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300511 usb_set_interface(pdev->udev, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300514 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515}
516
Hans de Goede885fe182011-06-06 15:33:44 -0300517static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
518{
Hans de Goedec20d78c2011-10-09 09:16:46 -0300519 unsigned long flags = 0;
520
521 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300522 while (!list_empty(&pdev->queued_bufs)) {
523 struct pwc_frame_buf *buf;
524
525 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
526 list);
527 list_del(&buf->list);
528 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
529 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300530 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300531}
532
Trent Piepho05ad3902007-01-30 23:26:01 -0300533#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -0300534static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
535{
536 switch(sensor_type) {
537 case 0x00:
538 return "Hyundai CMOS sensor";
539 case 0x20:
540 return "Sony CCD sensor + TDA8787";
541 case 0x2E:
542 return "Sony CCD sensor + Exas 98L59";
543 case 0x2F:
544 return "Sony CCD sensor + ADI 9804";
545 case 0x30:
546 return "Sharp CCD sensor + TDA8787";
547 case 0x3E:
548 return "Sharp CCD sensor + Exas 98L59";
549 case 0x3F:
550 return "Sharp CCD sensor + ADI 9804";
551 case 0x40:
552 return "UPA 1021 sensor";
553 case 0x100:
554 return "VGA sensor";
555 case 0x101:
556 return "PAL MR sensor";
557 default:
Trent Piepho657de3c2006-06-20 00:30:57 -0300558 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -0300559 }
560}
561#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
563/***************************************************************************/
564/* Video4Linux functions */
565
Hans de Goedec20d78c2011-10-09 09:16:46 -0300566int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
567{
568 int r = 0;
569
570 mutex_lock(&pdev->capt_file_lock);
571 if (pdev->capt_file != NULL &&
572 pdev->capt_file != file) {
573 r = -EBUSY;
574 goto leave;
575 }
576 pdev->capt_file = file;
577leave:
578 mutex_unlock(&pdev->capt_file_lock);
579 return r;
580}
581
Hans de Goede76ae8532011-07-19 07:14:22 -0300582static void pwc_video_release(struct v4l2_device *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583{
Hans de Goede76ae8532011-07-19 07:14:22 -0300584 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300585 int hint;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300586
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300587 /* search device_hint[] table if we occupy a slot, by any chance */
588 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
589 if (device_hint[hint].pdev == pdev)
590 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300591
Hans de Goede6eba9352011-06-26 06:49:59 -0300592 /* Free intermediate decompression buffer & tables */
593 if (pdev->decompress_data != NULL) {
594 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
595 pdev->decompress_data);
596 kfree(pdev->decompress_data);
597 pdev->decompress_data = NULL;
598 }
599
Hans de Goede6c9cac82011-06-26 12:52:01 -0300600 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
601
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300602 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +0200603}
604
Hans Verkuilbec43662008-12-30 06:58:20 -0300605static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
Hans de Goede76ae8532011-07-19 07:14:22 -0300607 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Hans de Goede4fba4712011-06-26 12:13:44 -0300609 if (pdev->capt_file == file) {
610 vb2_queue_release(&pdev->vb_queue);
611 pdev->capt_file = NULL;
612 }
Hans de Goede76ae8532011-07-19 07:14:22 -0300613 return v4l2_fh_release(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
Luc Saillard2b455db2006-04-24 10:29:46 -0300616static ssize_t pwc_video_read(struct file *file, char __user *buf,
Hans de Goede885fe182011-06-06 15:33:44 -0300617 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618{
Hans de Goede76ae8532011-07-19 07:14:22 -0300619 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Hans de Goedeb824bb42011-06-25 17:39:19 -0300621 if (!pdev->udev)
622 return -ENODEV;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300623
Hans de Goedec20d78c2011-10-09 09:16:46 -0300624 if (pwc_test_n_set_capt_file(pdev, file))
Hans de Goede4fba4712011-06-26 12:13:44 -0300625 return -EBUSY;
626
Hans de Goede885fe182011-06-06 15:33:44 -0300627 return vb2_read(&pdev->vb_queue, buf, count, ppos,
628 file->f_flags & O_NONBLOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629}
630
631static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
632{
Hans de Goede76ae8532011-07-19 07:14:22 -0300633 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Hans de Goedeb824bb42011-06-25 17:39:19 -0300635 if (!pdev->udev)
Hans de Goede885fe182011-06-06 15:33:44 -0300636 return POLL_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Hans de Goede885fe182011-06-06 15:33:44 -0300638 return vb2_poll(&pdev->vb_queue, file, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639}
640
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
642{
Hans de Goede76ae8532011-07-19 07:14:22 -0300643 struct pwc_device *pdev = video_drvdata(file);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300644
Hans de Goede4fba4712011-06-26 12:13:44 -0300645 if (pdev->capt_file != file)
646 return -EBUSY;
647
Hans de Goede885fe182011-06-06 15:33:44 -0300648 return vb2_mmap(&pdev->vb_queue, vma);
649}
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300650
Hans de Goede885fe182011-06-06 15:33:44 -0300651/***************************************************************************/
652/* Videobuf2 operations */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Guennadi Liakhovetskifc714e72011-08-24 10:30:21 -0300654static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
655 unsigned int *nbuffers, unsigned int *nplanes,
656 unsigned int sizes[], void *alloc_ctxs[])
Hans de Goede885fe182011-06-06 15:33:44 -0300657{
658 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Luc Saillard2b455db2006-04-24 10:29:46 -0300659
Hans de Goede885fe182011-06-06 15:33:44 -0300660 if (*nbuffers < MIN_FRAMES)
661 *nbuffers = MIN_FRAMES;
662 else if (*nbuffers > MAX_FRAMES)
663 *nbuffers = MAX_FRAMES;
664
665 *nplanes = 1;
666
667 sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
668
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 return 0;
670}
671
Hans de Goede885fe182011-06-06 15:33:44 -0300672static int buffer_init(struct vb2_buffer *vb)
673{
674 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
675
676 /* need vmalloc since frame buffer > 128K */
677 buf->data = vzalloc(PWC_FRAME_SIZE);
678 if (buf->data == NULL)
679 return -ENOMEM;
680
681 return 0;
682}
683
684static int buffer_prepare(struct vb2_buffer *vb)
685{
686 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
687
688 /* Don't allow queing new buffers after device disconnection */
Hans de Goedeb824bb42011-06-25 17:39:19 -0300689 if (!pdev->udev)
690 return -ENODEV;
Hans de Goede885fe182011-06-06 15:33:44 -0300691
692 return 0;
693}
694
695static int buffer_finish(struct vb2_buffer *vb)
696{
697 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
698 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
699
700 /*
701 * Application has called dqbuf and is getting back a buffer we've
702 * filled, take the pwc data we've stored in buf->data and decompress
703 * it into a usable format, storing the result in the vb2_buffer
704 */
705 return pwc_decompress(pdev, buf);
706}
707
708static void buffer_cleanup(struct vb2_buffer *vb)
709{
710 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
711
712 vfree(buf->data);
713}
714
715static void buffer_queue(struct vb2_buffer *vb)
716{
717 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
718 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
719 unsigned long flags = 0;
720
721 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300722 /* Check the device has not disconnected between prep and queuing */
723 if (pdev->udev)
724 list_add_tail(&buf->list, &pdev->queued_bufs);
725 else
726 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
Hans de Goede885fe182011-06-06 15:33:44 -0300727 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
728}
729
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300730static int start_streaming(struct vb2_queue *vq, unsigned int count)
Hans de Goede885fe182011-06-06 15:33:44 -0300731{
732 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300733 int r;
Hans de Goede885fe182011-06-06 15:33:44 -0300734
Hans de Goedec20d78c2011-10-09 09:16:46 -0300735 mutex_lock(&pdev->udevlock);
736 if (!pdev->udev) {
737 r = -ENODEV;
738 goto leave;
739 }
Hans de Goedeb824bb42011-06-25 17:39:19 -0300740
Hans de Goede6eba9352011-06-26 06:49:59 -0300741 /* Turn on camera and set LEDS on */
742 pwc_camera_power(pdev, 1);
743 if (pdev->power_save) {
744 /* Restore video mode */
745 pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
Hans de Goededc8a7e82011-12-31 10:52:02 -0300746 pdev->vframes, pdev->vcompression);
Hans de Goede6eba9352011-06-26 06:49:59 -0300747 }
748 pwc_set_leds(pdev, led_on, led_off);
749
Hans de Goedec20d78c2011-10-09 09:16:46 -0300750 r = pwc_isoc_init(pdev);
751leave:
752 mutex_unlock(&pdev->udevlock);
753 return r;
Hans de Goede885fe182011-06-06 15:33:44 -0300754}
755
756static int stop_streaming(struct vb2_queue *vq)
757{
758 struct pwc_device *pdev = vb2_get_drv_priv(vq);
759
Hans de Goedec20d78c2011-10-09 09:16:46 -0300760 mutex_lock(&pdev->udevlock);
Hans de Goede6eba9352011-06-26 06:49:59 -0300761 if (pdev->udev) {
762 pwc_set_leds(pdev, 0, 0);
763 pwc_camera_power(pdev, 0);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300764 pwc_isoc_cleanup(pdev);
Hans de Goede6eba9352011-06-26 06:49:59 -0300765 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300766 mutex_unlock(&pdev->udevlock);
767
Hans de Goede885fe182011-06-06 15:33:44 -0300768 pwc_cleanup_queued_bufs(pdev);
769
770 return 0;
771}
772
Hans de Goede885fe182011-06-06 15:33:44 -0300773static struct vb2_ops pwc_vb_queue_ops = {
774 .queue_setup = queue_setup,
775 .buf_init = buffer_init,
776 .buf_prepare = buffer_prepare,
777 .buf_finish = buffer_finish,
778 .buf_cleanup = buffer_cleanup,
779 .buf_queue = buffer_queue,
780 .start_streaming = start_streaming,
781 .stop_streaming = stop_streaming,
Hans de Goede885fe182011-06-06 15:33:44 -0300782};
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784/***************************************************************************/
785/* USB functions */
786
787/* This function gets called when a new device is plugged in or the usb core
788 * is loaded.
789 */
790
791static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
792{
793 struct usb_device *udev = interface_to_usbdev(intf);
794 struct pwc_device *pdev = NULL;
795 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300796 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 int features = 0;
798 int video_nr = -1; /* default: use next available device */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300799 int my_power_save = power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 char serial_number[30], *name;
801
Luc Saillard2b455db2006-04-24 10:29:46 -0300802 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
803 product_id = le16_to_cpu(udev->descriptor.idProduct);
804
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -0300806 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
807 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 intf->altsetting->desc.bInterfaceNumber);
809
810 /* the interfaces are probed one by one. We are only interested in the
811 video interface (0) now.
812 Interface 1 is the Audio Control, and interface 2 Audio itself.
813 */
814 if (intf->altsetting->desc.bInterfaceNumber > 0)
815 return -ENODEV;
816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 if (vendor_id == 0x0471) {
818 switch (product_id) {
819 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -0300820 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 name = "Philips 645 webcam";
822 type_id = 645;
823 break;
824 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -0300825 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 name = "Philips 646 webcam";
827 type_id = 646;
828 break;
829 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -0300830 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 name = "Askey VC010 webcam";
832 type_id = 646;
833 break;
834 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -0300835 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 name = "Philips 675 webcam";
837 type_id = 675;
838 break;
839 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -0300840 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 name = "Philips 680 webcam";
842 type_id = 680;
843 break;
844 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -0300845 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 name = "Philips 690 webcam";
847 type_id = 690;
848 break;
849 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -0300850 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 name = "Philips 730 webcam";
852 type_id = 730;
853 break;
854 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -0300855 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 name = "Philips 740 webcam";
857 type_id = 740;
858 break;
859 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -0300860 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 name = "Philips 750 webcam";
862 type_id = 750;
863 break;
864 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -0300865 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 name = "Philips 720K/40 webcam";
867 type_id = 720;
868 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300869 case 0x0329:
870 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
871 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -0300872 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -0300873 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 default:
875 return -ENODEV;
876 break;
877 }
878 }
879 else if (vendor_id == 0x069A) {
880 switch(product_id) {
881 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300882 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 name = "Askey VC010 webcam";
884 type_id = 645;
885 break;
886 default:
887 return -ENODEV;
888 break;
889 }
890 }
891 else if (vendor_id == 0x046d) {
892 switch(product_id) {
893 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -0300894 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 name = "Logitech QuickCam Pro 3000";
896 type_id = 740; /* CCD sensor */
897 break;
898 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -0300899 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 name = "Logitech QuickCam Notebook Pro";
901 type_id = 740; /* CCD sensor */
902 break;
903 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -0300904 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 name = "Logitech QuickCam Pro 4000";
906 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300907 if (my_power_save == -1)
908 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 break;
910 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -0300911 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 name = "Logitech QuickCam Zoom";
913 type_id = 740; /* CCD sensor */
914 break;
915 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -0300916 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 name = "Logitech QuickCam Zoom";
918 type_id = 740; /* CCD sensor */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300919 if (my_power_save == -1)
920 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 break;
922 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -0300923 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 name = "Logitech QuickCam Orbit";
925 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300926 if (my_power_save == -1)
927 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 features |= FEATURE_MOTOR_PANTILT;
929 break;
930 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -0300931 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
932 name = "Cisco VT Camera";
933 type_id = 740; /* CCD sensor */
934 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -0300936 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
937 name = "Logitech ViewPort AV 100";
938 type_id = 740; /* CCD sensor */
939 break;
940 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -0300941 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 name = "Logitech QuickCam (res.)";
943 type_id = 730; /* Assuming CMOS */
944 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300945 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300947 break;
948 }
949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 else if (vendor_id == 0x055d) {
951 /* I don't know the difference between the C10 and the C30;
952 I suppose the difference is the sensor, but both cameras
953 work equally well with a type_id of 675
954 */
955 switch(product_id) {
956 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -0300957 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 name = "Samsung MPC-C10";
959 type_id = 675;
960 break;
961 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300962 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 name = "Samsung MPC-C30";
964 type_id = 675;
965 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300966 case 0x9002:
967 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
968 name = "Samsung MPC-C30";
969 type_id = 740;
970 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 default:
972 return -ENODEV;
973 break;
974 }
975 }
976 else if (vendor_id == 0x041e) {
977 switch(product_id) {
978 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -0300979 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 name = "Creative Labs Webcam 5";
981 type_id = 730;
Hans de Goede51886df2011-07-03 15:52:54 -0300982 if (my_power_save == -1)
983 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 break;
985 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -0300986 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 name = "Creative Labs Webcam Pro Ex";
988 type_id = 740;
989 break;
990 default:
991 return -ENODEV;
992 break;
993 }
994 }
995 else if (vendor_id == 0x04cc) {
996 switch(product_id) {
997 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -0300998 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 name = "Sotec Afina Eye";
1000 type_id = 730;
1001 break;
1002 default:
1003 return -ENODEV;
1004 break;
1005 }
1006 }
1007 else if (vendor_id == 0x06be) {
1008 switch(product_id) {
1009 case 0x8116:
1010 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001011 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 name = "AME Co. Afina Eye";
1013 type_id = 750;
1014 break;
1015 default:
1016 return -ENODEV;
1017 break;
1018 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 }
1021 else if (vendor_id == 0x0d81) {
1022 switch(product_id) {
1023 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001024 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 name = "Visionite VCS-UC300";
1026 type_id = 740; /* CCD sensor */
1027 break;
1028 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001029 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 name = "Visionite VCS-UM100";
1031 type_id = 730; /* CMOS sensor */
1032 break;
1033 default:
1034 return -ENODEV;
1035 break;
1036 }
1037 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001038 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1040
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001041 if (my_power_save == -1)
1042 my_power_save = 0;
1043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 memset(serial_number, 0, 30);
1045 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001046 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001049 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001052 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001054 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return -ENOMEM;
1056 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 pdev->type = type_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 pdev->vframes = default_fps;
1059 strcpy(pdev->serial, serial_number);
1060 pdev->features = features;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001061 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Hans de Goedec20d78c2011-10-09 09:16:46 -03001063 mutex_init(&pdev->capt_file_lock);
Hans de Goedec1127132011-07-03 11:50:51 -03001064 mutex_init(&pdev->udevlock);
Hans de Goede885fe182011-06-06 15:33:44 -03001065 spin_lock_init(&pdev->queued_bufs_lock);
1066 INIT_LIST_HEAD(&pdev->queued_bufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068 pdev->udev = udev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 pdev->vcompression = pwc_preferred_compression;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001070 pdev->power_save = my_power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Hans de Goede885fe182011-06-06 15:33:44 -03001072 /* Init videobuf2 queue structure */
1073 memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
1074 pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1075 pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1076 pdev->vb_queue.drv_priv = pdev;
1077 pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
1078 pdev->vb_queue.ops = &pwc_vb_queue_ops;
1079 pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
1080 vb2_queue_init(&pdev->vb_queue);
1081
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001082 /* Init video_device structure */
1083 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001084 strcpy(pdev->vdev.name, name);
Hans de Goede76ae8532011-07-19 07:14:22 -03001085 set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001086 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001089 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 /* Now search device_hint[] table for a match, so we can hint a node number. */
1092 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1093 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1094 (device_hint[hint].pdev == NULL)) {
1095 /* so far, so good... try serial number */
1096 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001097 /* match! */
1098 video_nr = device_hint[hint].device_node;
1099 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1100 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 }
1102 }
1103 }
1104
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001106 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 device_hint[hint].pdev = pdev;
1108
Hans de Goede6eba9352011-06-26 06:49:59 -03001109#ifdef CONFIG_USB_PWC_DEBUG
1110 /* Query sensor type */
1111 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1112 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1113 pdev->vdev.name,
1114 pwc_sensor_type_to_string(rc), rc);
1115 }
1116#endif
1117
Luc Saillard2b455db2006-04-24 10:29:46 -03001118 /* Set the leds off */
1119 pwc_set_leds(pdev, 0, 0);
Hans de Goede6eba9352011-06-26 06:49:59 -03001120
1121 /* Setup intial videomode */
1122 rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
Hans de Goededc8a7e82011-12-31 10:52:02 -03001123 pdev->vframes, pdev->vcompression);
Hans de Goede6eba9352011-06-26 06:49:59 -03001124 if (rc)
1125 goto err_free_mem;
1126
Hans de Goede6c9cac82011-06-26 12:52:01 -03001127 /* Register controls (and read default values from camera */
1128 rc = pwc_init_controls(pdev);
1129 if (rc) {
1130 PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
1131 goto err_free_mem;
1132 }
1133
Hans de Goede6eba9352011-06-26 06:49:59 -03001134 /* And powerdown the camera until streaming starts */
Luc Saillard2b455db2006-04-24 10:29:46 -03001135 pwc_camera_power(pdev, 0);
1136
Hans de Goede76ae8532011-07-19 07:14:22 -03001137 /* Register the v4l2_device structure */
1138 pdev->v4l2_dev.release = pwc_video_release;
1139 rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
1140 if (rc) {
1141 PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
1142 goto err_free_controls;
1143 }
1144
1145 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
1146 pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
1147
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001148 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001149 if (rc < 0) {
1150 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede76ae8532011-07-19 07:14:22 -03001151 goto err_unregister_v4l2_dev;
Hans Verkuil479567c2010-09-12 17:05:11 -03001152 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001153 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001154
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001155#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1156 /* register webcam snapshot button input device */
1157 pdev->button_dev = input_allocate_device();
1158 if (!pdev->button_dev) {
1159 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001160 rc = -ENOMEM;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001161 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001162 }
1163
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001164 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1165 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1166
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001167 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001168 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001169 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1170 pdev->button_dev->dev.parent = &pdev->udev->dev;
1171 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001172 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001173
1174 rc = input_register_device(pdev->button_dev);
1175 if (rc) {
1176 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001177 pdev->button_dev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001178 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001179 }
1180#endif
1181
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001183
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001184err_video_unreg:
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001185 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001186err_unregister_v4l2_dev:
1187 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001188err_free_controls:
1189 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001190err_free_mem:
Hans de Goede32c67ec2011-07-19 09:05:49 -03001191 if (hint < MAX_DEV_HINTS)
1192 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001193 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001194 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195}
1196
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001197/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198static void usb_pwc_disconnect(struct usb_interface *intf)
1199{
Hans de Goede76ae8532011-07-19 07:14:22 -03001200 struct v4l2_device *v = usb_get_intfdata(intf);
1201 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
Hans de Goedec1127132011-07-03 11:50:51 -03001203 mutex_lock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001204 /* No need to keep the urbs around after disconnection */
1205 pwc_isoc_cleanup(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -03001206 pdev->udev = NULL;
Hans de Goedec1127132011-07-03 11:50:51 -03001207 mutex_unlock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001208
Hans de Goedec20d78c2011-10-09 09:16:46 -03001209 pwc_cleanup_queued_bufs(pdev);
1210
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001211 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001212 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001213
1214#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1215 if (pdev->button_dev)
1216 input_unregister_device(pdev->button_dev);
1217#endif
Hans de Goede76ae8532011-07-19 07:14:22 -03001218
1219 v4l2_device_put(&pdev->v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220}
1221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001223/*
1224 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 */
1226
Luc Saillard2b455db2006-04-24 10:29:46 -03001227static int fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228static int compression = -1;
1229static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001230static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001231static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001232static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Luc Saillard2b455db2006-04-24 10:29:46 -03001234module_param(fps, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001235#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001236module_param_named(trace, pwc_trace, int, 0644);
1237#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001238module_param(power_save, int, 0644);
Luc Saillard2b455db2006-04-24 10:29:46 -03001239module_param(compression, int, 0444);
1240module_param_array(leds, int, &leds_nargs, 0444);
1241module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Andrea Odetti4315c412009-12-10 16:26:10 -03001244#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001246#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001247MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250MODULE_PARM_DESC(dev_hint, "Device node hints");
1251
1252MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1253MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1254MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001255MODULE_ALIAS("pwcx");
1256MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
1258static int __init usb_pwc_init(void)
1259{
Hans de Goede6eba9352011-06-26 06:49:59 -03001260 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Hans de Goede6eba9352011-06-26 06:49:59 -03001262#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001263 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1264 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1265 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1266 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 -07001267
Hans de Goede6eba9352011-06-26 06:49:59 -03001268 if (pwc_trace >= 0) {
1269 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1270 }
1271#endif
1272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (fps) {
1274 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001275 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return -EINVAL;
1277 }
1278 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001279 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 }
1281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 if (compression >= 0) {
1283 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001284 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return -EINVAL;
1286 }
1287 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03001288 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 if (leds[0] >= 0)
1291 led_on = leds[0];
1292 if (leds[1] >= 0)
1293 led_off = leds[1];
1294
Steven Cole093cf722005-05-03 19:07:24 -06001295 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 device node (/dev/videoX) to a camera, based on its type
1297 & serial number. The format is [type[.serialnumber]:]node.
1298
1299 Any camera that isn't matched by these rules gets the next
1300 available free device node.
1301 */
1302 for (i = 0; i < MAX_DEV_HINTS; i++) {
1303 char *s, *colon, *dot;
1304
1305 /* This loop also initializes the array */
1306 device_hint[i].pdev = NULL;
1307 s = dev_hint[i];
1308 if (s != NULL && *s != '\0') {
1309 device_hint[i].type = -1; /* wildcard */
1310 strcpy(device_hint[i].serial_number, "*");
1311
1312 /* parse string: chop at ':' & '/' */
1313 colon = dot = s;
1314 while (*colon != '\0' && *colon != ':')
1315 colon++;
1316 while (*dot != '\0' && *dot != '.')
1317 dot++;
1318 /* Few sanity checks */
1319 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001320 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 return -EINVAL;
1322 }
1323
1324 if (*colon == '\0') {
1325 /* No colon */
1326 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001327 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 return -EINVAL;
1329 }
1330 else {
1331 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001332 device_hint[i].device_node =
1333 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 }
1335 }
1336 else {
1337 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001338 device_hint[i].type =
1339 simple_strtol(s, NULL, 10);
1340 device_hint[i].device_node =
1341 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (*dot != '\0') {
1343 /* There's a serial number as well */
1344 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 dot++;
1347 k = 0;
1348 while (*dot != ':' && k < 29) {
1349 device_hint[i].serial_number[k++] = *dot;
1350 dot++;
1351 }
1352 device_hint[i].serial_number[k] = '\0';
1353 }
1354 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001355 PWC_TRACE("device_hint[%d]:\n", i);
1356 PWC_TRACE(" type : %d\n", device_hint[i].type);
1357 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1358 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 }
1360 else
1361 device_hint[i].type = 0; /* not filled */
1362 } /* ..for MAX_DEV_HINTS */
1363
Luc Saillard2b455db2006-04-24 10:29:46 -03001364 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 return usb_register(&pwc_driver);
1366}
1367
1368static void __exit usb_pwc_exit(void)
1369{
Luc Saillard2b455db2006-04-24 10:29:46 -03001370 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001372 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373}
1374
1375module_init(usb_pwc_init);
1376module_exit(usb_pwc_exit);
1377
Luc Saillard2b455db2006-04-24 10:29:46 -03001378/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */