blob: be4406a7c80aede3dcb92ed01b8480d961367523 [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 Liakhovetskifc714e702011-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);
Hans de Goede795e6eb2012-01-04 16:58:44 -0300659 int size;
Luc Saillard2b455db2006-04-24 10:29:46 -0300660
Hans de Goede885fe182011-06-06 15:33:44 -0300661 if (*nbuffers < MIN_FRAMES)
662 *nbuffers = MIN_FRAMES;
663 else if (*nbuffers > MAX_FRAMES)
664 *nbuffers = MAX_FRAMES;
665
666 *nplanes = 1;
667
Hans de Goede795e6eb2012-01-04 16:58:44 -0300668 size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
669 sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
670 pwc_image_sizes[size][1] * 3 / 2);
Hans de Goede885fe182011-06-06 15:33:44 -0300671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 return 0;
673}
674
Hans de Goede885fe182011-06-06 15:33:44 -0300675static int buffer_init(struct vb2_buffer *vb)
676{
677 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
678
679 /* need vmalloc since frame buffer > 128K */
680 buf->data = vzalloc(PWC_FRAME_SIZE);
681 if (buf->data == NULL)
682 return -ENOMEM;
683
684 return 0;
685}
686
687static int buffer_prepare(struct vb2_buffer *vb)
688{
689 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
690
691 /* Don't allow queing new buffers after device disconnection */
Hans de Goedeb824bb42011-06-25 17:39:19 -0300692 if (!pdev->udev)
693 return -ENODEV;
Hans de Goede885fe182011-06-06 15:33:44 -0300694
695 return 0;
696}
697
698static int buffer_finish(struct vb2_buffer *vb)
699{
700 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
701 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
702
703 /*
704 * Application has called dqbuf and is getting back a buffer we've
705 * filled, take the pwc data we've stored in buf->data and decompress
706 * it into a usable format, storing the result in the vb2_buffer
707 */
708 return pwc_decompress(pdev, buf);
709}
710
711static void buffer_cleanup(struct vb2_buffer *vb)
712{
713 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
714
715 vfree(buf->data);
716}
717
718static void buffer_queue(struct vb2_buffer *vb)
719{
720 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
721 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
722 unsigned long flags = 0;
723
724 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300725 /* Check the device has not disconnected between prep and queuing */
726 if (pdev->udev)
727 list_add_tail(&buf->list, &pdev->queued_bufs);
728 else
729 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
Hans de Goede885fe182011-06-06 15:33:44 -0300730 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
731}
732
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300733static int start_streaming(struct vb2_queue *vq, unsigned int count)
Hans de Goede885fe182011-06-06 15:33:44 -0300734{
735 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300736 int r;
Hans de Goede885fe182011-06-06 15:33:44 -0300737
Hans de Goedec20d78c2011-10-09 09:16:46 -0300738 mutex_lock(&pdev->udevlock);
739 if (!pdev->udev) {
740 r = -ENODEV;
741 goto leave;
742 }
Hans de Goedeb824bb42011-06-25 17:39:19 -0300743
Hans de Goede6eba9352011-06-26 06:49:59 -0300744 /* Turn on camera and set LEDS on */
745 pwc_camera_power(pdev, 1);
746 if (pdev->power_save) {
747 /* Restore video mode */
Hans de Goede795e6eb2012-01-04 16:58:44 -0300748 pwc_set_video_mode(pdev, pdev->width, pdev->height,
Hans de Goededc8a7e82011-12-31 10:52:02 -0300749 pdev->vframes, pdev->vcompression);
Hans de Goede6eba9352011-06-26 06:49:59 -0300750 }
751 pwc_set_leds(pdev, led_on, led_off);
752
Hans de Goedec20d78c2011-10-09 09:16:46 -0300753 r = pwc_isoc_init(pdev);
754leave:
755 mutex_unlock(&pdev->udevlock);
756 return r;
Hans de Goede885fe182011-06-06 15:33:44 -0300757}
758
759static int stop_streaming(struct vb2_queue *vq)
760{
761 struct pwc_device *pdev = vb2_get_drv_priv(vq);
762
Hans de Goedec20d78c2011-10-09 09:16:46 -0300763 mutex_lock(&pdev->udevlock);
Hans de Goede6eba9352011-06-26 06:49:59 -0300764 if (pdev->udev) {
765 pwc_set_leds(pdev, 0, 0);
766 pwc_camera_power(pdev, 0);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300767 pwc_isoc_cleanup(pdev);
Hans de Goede6eba9352011-06-26 06:49:59 -0300768 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300769 mutex_unlock(&pdev->udevlock);
770
Hans de Goede885fe182011-06-06 15:33:44 -0300771 pwc_cleanup_queued_bufs(pdev);
772
773 return 0;
774}
775
Hans de Goede885fe182011-06-06 15:33:44 -0300776static struct vb2_ops pwc_vb_queue_ops = {
777 .queue_setup = queue_setup,
778 .buf_init = buffer_init,
779 .buf_prepare = buffer_prepare,
780 .buf_finish = buffer_finish,
781 .buf_cleanup = buffer_cleanup,
782 .buf_queue = buffer_queue,
783 .start_streaming = start_streaming,
784 .stop_streaming = stop_streaming,
Hans de Goede885fe182011-06-06 15:33:44 -0300785};
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787/***************************************************************************/
788/* USB functions */
789
790/* This function gets called when a new device is plugged in or the usb core
791 * is loaded.
792 */
793
794static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
795{
796 struct usb_device *udev = interface_to_usbdev(intf);
797 struct pwc_device *pdev = NULL;
798 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300799 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 int features = 0;
801 int video_nr = -1; /* default: use next available device */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300802 int my_power_save = power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 char serial_number[30], *name;
804
Luc Saillard2b455db2006-04-24 10:29:46 -0300805 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
806 product_id = le16_to_cpu(udev->descriptor.idProduct);
807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -0300809 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
810 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 intf->altsetting->desc.bInterfaceNumber);
812
813 /* the interfaces are probed one by one. We are only interested in the
814 video interface (0) now.
815 Interface 1 is the Audio Control, and interface 2 Audio itself.
816 */
817 if (intf->altsetting->desc.bInterfaceNumber > 0)
818 return -ENODEV;
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 if (vendor_id == 0x0471) {
821 switch (product_id) {
822 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -0300823 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 name = "Philips 645 webcam";
825 type_id = 645;
826 break;
827 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -0300828 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 name = "Philips 646 webcam";
830 type_id = 646;
831 break;
832 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -0300833 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 name = "Askey VC010 webcam";
835 type_id = 646;
836 break;
837 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -0300838 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 name = "Philips 675 webcam";
840 type_id = 675;
841 break;
842 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -0300843 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 name = "Philips 680 webcam";
845 type_id = 680;
846 break;
847 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -0300848 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 name = "Philips 690 webcam";
850 type_id = 690;
851 break;
852 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -0300853 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 name = "Philips 730 webcam";
855 type_id = 730;
856 break;
857 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -0300858 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 name = "Philips 740 webcam";
860 type_id = 740;
861 break;
862 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -0300863 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 name = "Philips 750 webcam";
865 type_id = 750;
866 break;
867 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -0300868 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 name = "Philips 720K/40 webcam";
870 type_id = 720;
871 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300872 case 0x0329:
873 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
874 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -0300875 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -0300876 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 default:
878 return -ENODEV;
879 break;
880 }
881 }
882 else if (vendor_id == 0x069A) {
883 switch(product_id) {
884 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300885 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 name = "Askey VC010 webcam";
887 type_id = 645;
888 break;
889 default:
890 return -ENODEV;
891 break;
892 }
893 }
894 else if (vendor_id == 0x046d) {
895 switch(product_id) {
896 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -0300897 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 name = "Logitech QuickCam Pro 3000";
899 type_id = 740; /* CCD sensor */
900 break;
901 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -0300902 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 name = "Logitech QuickCam Notebook Pro";
904 type_id = 740; /* CCD sensor */
905 break;
906 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -0300907 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 name = "Logitech QuickCam Pro 4000";
909 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300910 if (my_power_save == -1)
911 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 break;
913 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -0300914 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 name = "Logitech QuickCam Zoom";
916 type_id = 740; /* CCD sensor */
917 break;
918 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -0300919 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 name = "Logitech QuickCam Zoom";
921 type_id = 740; /* CCD sensor */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300922 if (my_power_save == -1)
923 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 break;
925 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -0300926 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 name = "Logitech QuickCam Orbit";
928 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300929 if (my_power_save == -1)
930 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 features |= FEATURE_MOTOR_PANTILT;
932 break;
933 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -0300934 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
935 name = "Cisco VT Camera";
936 type_id = 740; /* CCD sensor */
937 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -0300939 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
940 name = "Logitech ViewPort AV 100";
941 type_id = 740; /* CCD sensor */
942 break;
943 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -0300944 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 name = "Logitech QuickCam (res.)";
946 type_id = 730; /* Assuming CMOS */
947 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300948 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300950 break;
951 }
952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 else if (vendor_id == 0x055d) {
954 /* I don't know the difference between the C10 and the C30;
955 I suppose the difference is the sensor, but both cameras
956 work equally well with a type_id of 675
957 */
958 switch(product_id) {
959 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -0300960 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 name = "Samsung MPC-C10";
962 type_id = 675;
963 break;
964 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300965 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 name = "Samsung MPC-C30";
967 type_id = 675;
968 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300969 case 0x9002:
970 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
971 name = "Samsung MPC-C30";
972 type_id = 740;
973 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 default:
975 return -ENODEV;
976 break;
977 }
978 }
979 else if (vendor_id == 0x041e) {
980 switch(product_id) {
981 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -0300982 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 name = "Creative Labs Webcam 5";
984 type_id = 730;
Hans de Goede51886df2011-07-03 15:52:54 -0300985 if (my_power_save == -1)
986 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 break;
988 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -0300989 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 name = "Creative Labs Webcam Pro Ex";
991 type_id = 740;
992 break;
993 default:
994 return -ENODEV;
995 break;
996 }
997 }
998 else if (vendor_id == 0x04cc) {
999 switch(product_id) {
1000 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001001 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 name = "Sotec Afina Eye";
1003 type_id = 730;
1004 break;
1005 default:
1006 return -ENODEV;
1007 break;
1008 }
1009 }
1010 else if (vendor_id == 0x06be) {
1011 switch(product_id) {
1012 case 0x8116:
1013 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001014 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 name = "AME Co. Afina Eye";
1016 type_id = 750;
1017 break;
1018 default:
1019 return -ENODEV;
1020 break;
1021 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 }
1024 else if (vendor_id == 0x0d81) {
1025 switch(product_id) {
1026 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001027 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 name = "Visionite VCS-UC300";
1029 type_id = 740; /* CCD sensor */
1030 break;
1031 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001032 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 name = "Visionite VCS-UM100";
1034 type_id = 730; /* CMOS sensor */
1035 break;
1036 default:
1037 return -ENODEV;
1038 break;
1039 }
1040 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001041 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1043
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001044 if (my_power_save == -1)
1045 my_power_save = 0;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 memset(serial_number, 0, 30);
1048 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001049 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001052 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001055 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001057 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 return -ENOMEM;
1059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 pdev->type = type_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 pdev->vframes = default_fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 pdev->features = features;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001063 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
Hans de Goedec20d78c2011-10-09 09:16:46 -03001065 mutex_init(&pdev->capt_file_lock);
Hans de Goedec1127132011-07-03 11:50:51 -03001066 mutex_init(&pdev->udevlock);
Hans de Goede885fe182011-06-06 15:33:44 -03001067 spin_lock_init(&pdev->queued_bufs_lock);
1068 INIT_LIST_HEAD(&pdev->queued_bufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 pdev->udev = udev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 pdev->vcompression = pwc_preferred_compression;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001072 pdev->power_save = my_power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Hans de Goede885fe182011-06-06 15:33:44 -03001074 /* Init videobuf2 queue structure */
1075 memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
1076 pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1077 pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1078 pdev->vb_queue.drv_priv = pdev;
1079 pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
1080 pdev->vb_queue.ops = &pwc_vb_queue_ops;
1081 pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
1082 vb2_queue_init(&pdev->vb_queue);
1083
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001084 /* Init video_device structure */
1085 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001086 strcpy(pdev->vdev.name, name);
Hans de Goede76ae8532011-07-19 07:14:22 -03001087 set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001088 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001091 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 /* Now search device_hint[] table for a match, so we can hint a node number. */
1094 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1095 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1096 (device_hint[hint].pdev == NULL)) {
1097 /* so far, so good... try serial number */
1098 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001099 /* match! */
1100 video_nr = device_hint[hint].device_node;
1101 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1102 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 }
1104 }
1105 }
1106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001108 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 device_hint[hint].pdev = pdev;
1110
Hans de Goede6eba9352011-06-26 06:49:59 -03001111#ifdef CONFIG_USB_PWC_DEBUG
1112 /* Query sensor type */
1113 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1114 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1115 pdev->vdev.name,
1116 pwc_sensor_type_to_string(rc), rc);
1117 }
1118#endif
1119
Luc Saillard2b455db2006-04-24 10:29:46 -03001120 /* Set the leds off */
1121 pwc_set_leds(pdev, 0, 0);
Hans de Goede6eba9352011-06-26 06:49:59 -03001122
1123 /* Setup intial videomode */
Hans de Goede795e6eb2012-01-04 16:58:44 -03001124 rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
Hans de Goededc8a7e82011-12-31 10:52:02 -03001125 pdev->vframes, pdev->vcompression);
Hans de Goede6eba9352011-06-26 06:49:59 -03001126 if (rc)
1127 goto err_free_mem;
1128
Hans de Goede6c9cac82011-06-26 12:52:01 -03001129 /* Register controls (and read default values from camera */
1130 rc = pwc_init_controls(pdev);
1131 if (rc) {
1132 PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
1133 goto err_free_mem;
1134 }
1135
Hans de Goede6eba9352011-06-26 06:49:59 -03001136 /* And powerdown the camera until streaming starts */
Luc Saillard2b455db2006-04-24 10:29:46 -03001137 pwc_camera_power(pdev, 0);
1138
Hans de Goede76ae8532011-07-19 07:14:22 -03001139 /* Register the v4l2_device structure */
1140 pdev->v4l2_dev.release = pwc_video_release;
1141 rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
1142 if (rc) {
1143 PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
1144 goto err_free_controls;
1145 }
1146
1147 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
1148 pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
1149
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001150 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001151 if (rc < 0) {
1152 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede76ae8532011-07-19 07:14:22 -03001153 goto err_unregister_v4l2_dev;
Hans Verkuil479567c2010-09-12 17:05:11 -03001154 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001155 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001156
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001157#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1158 /* register webcam snapshot button input device */
1159 pdev->button_dev = input_allocate_device();
1160 if (!pdev->button_dev) {
1161 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001162 rc = -ENOMEM;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001163 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001164 }
1165
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001166 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1167 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1168
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001169 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001170 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001171 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1172 pdev->button_dev->dev.parent = &pdev->udev->dev;
1173 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001174 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001175
1176 rc = input_register_device(pdev->button_dev);
1177 if (rc) {
1178 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001179 pdev->button_dev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001180 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001181 }
1182#endif
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001185
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001186err_video_unreg:
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001187 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001188err_unregister_v4l2_dev:
1189 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001190err_free_controls:
1191 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001192err_free_mem:
Hans de Goede32c67ec2011-07-19 09:05:49 -03001193 if (hint < MAX_DEV_HINTS)
1194 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001195 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001196 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001199/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200static void usb_pwc_disconnect(struct usb_interface *intf)
1201{
Hans de Goede76ae8532011-07-19 07:14:22 -03001202 struct v4l2_device *v = usb_get_intfdata(intf);
1203 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Hans de Goedec1127132011-07-03 11:50:51 -03001205 mutex_lock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001206 /* No need to keep the urbs around after disconnection */
1207 pwc_isoc_cleanup(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -03001208 pdev->udev = NULL;
Hans de Goedec1127132011-07-03 11:50:51 -03001209 mutex_unlock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001210
Hans de Goedec20d78c2011-10-09 09:16:46 -03001211 pwc_cleanup_queued_bufs(pdev);
1212
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001213 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001214 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001215
1216#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1217 if (pdev->button_dev)
1218 input_unregister_device(pdev->button_dev);
1219#endif
Hans de Goede76ae8532011-07-19 07:14:22 -03001220
1221 v4l2_device_put(&pdev->v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222}
1223
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001225/*
1226 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 */
1228
Luc Saillard2b455db2006-04-24 10:29:46 -03001229static int fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230static int compression = -1;
1231static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001232static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001233static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001234static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Luc Saillard2b455db2006-04-24 10:29:46 -03001236module_param(fps, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001237#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001238module_param_named(trace, pwc_trace, int, 0644);
1239#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001240module_param(power_save, int, 0644);
Luc Saillard2b455db2006-04-24 10:29:46 -03001241module_param(compression, int, 0444);
1242module_param_array(leds, int, &leds_nargs, 0444);
1243module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1244
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Andrea Odetti4315c412009-12-10 16:26:10 -03001246#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001248#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001249MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252MODULE_PARM_DESC(dev_hint, "Device node hints");
1253
1254MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1255MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1256MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001257MODULE_ALIAS("pwcx");
1258MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260static int __init usb_pwc_init(void)
1261{
Hans de Goede6eba9352011-06-26 06:49:59 -03001262 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Hans de Goede6eba9352011-06-26 06:49:59 -03001264#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001265 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1266 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1267 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1268 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 -07001269
Hans de Goede6eba9352011-06-26 06:49:59 -03001270 if (pwc_trace >= 0) {
1271 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1272 }
1273#endif
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 if (fps) {
1276 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001277 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return -EINVAL;
1279 }
1280 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001281 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 }
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (compression >= 0) {
1285 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001286 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 return -EINVAL;
1288 }
1289 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03001290 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (leds[0] >= 0)
1293 led_on = leds[0];
1294 if (leds[1] >= 0)
1295 led_off = leds[1];
1296
Steven Cole093cf722005-05-03 19:07:24 -06001297 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 device node (/dev/videoX) to a camera, based on its type
1299 & serial number. The format is [type[.serialnumber]:]node.
1300
1301 Any camera that isn't matched by these rules gets the next
1302 available free device node.
1303 */
1304 for (i = 0; i < MAX_DEV_HINTS; i++) {
1305 char *s, *colon, *dot;
1306
1307 /* This loop also initializes the array */
1308 device_hint[i].pdev = NULL;
1309 s = dev_hint[i];
1310 if (s != NULL && *s != '\0') {
1311 device_hint[i].type = -1; /* wildcard */
1312 strcpy(device_hint[i].serial_number, "*");
1313
1314 /* parse string: chop at ':' & '/' */
1315 colon = dot = s;
1316 while (*colon != '\0' && *colon != ':')
1317 colon++;
1318 while (*dot != '\0' && *dot != '.')
1319 dot++;
1320 /* Few sanity checks */
1321 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001322 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return -EINVAL;
1324 }
1325
1326 if (*colon == '\0') {
1327 /* No colon */
1328 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001329 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 return -EINVAL;
1331 }
1332 else {
1333 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001334 device_hint[i].device_node =
1335 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
1337 }
1338 else {
1339 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001340 device_hint[i].type =
1341 simple_strtol(s, NULL, 10);
1342 device_hint[i].device_node =
1343 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 if (*dot != '\0') {
1345 /* There's a serial number as well */
1346 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 dot++;
1349 k = 0;
1350 while (*dot != ':' && k < 29) {
1351 device_hint[i].serial_number[k++] = *dot;
1352 dot++;
1353 }
1354 device_hint[i].serial_number[k] = '\0';
1355 }
1356 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001357 PWC_TRACE("device_hint[%d]:\n", i);
1358 PWC_TRACE(" type : %d\n", device_hint[i].type);
1359 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1360 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 }
1362 else
1363 device_hint[i].type = 0; /* not filled */
1364 } /* ..for MAX_DEV_HINTS */
1365
Luc Saillard2b455db2006-04-24 10:29:46 -03001366 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 return usb_register(&pwc_driver);
1368}
1369
1370static void __exit usb_pwc_exit(void)
1371{
Luc Saillard2b455db2006-04-24 10:29:46 -03001372 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001374 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375}
1376
1377module_init(usb_pwc_init);
1378module_exit(usb_pwc_exit);
1379
Luc Saillard2b455db2006-04-24 10:29:46 -03001380/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */