blob: a5fe4a1532ac3f670aa009f4ff4a3ac296aa67d2 [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#include "pwc-uncompress.h"
79
80/* Function prototypes and driver templates */
81
82/* hotplug device table support */
Luc Saillard2b455db2006-04-24 10:29:46 -030083static const struct usb_device_id pwc_device_table [] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
85 { USB_DEVICE(0x0471, 0x0303) },
86 { USB_DEVICE(0x0471, 0x0304) },
87 { USB_DEVICE(0x0471, 0x0307) },
88 { USB_DEVICE(0x0471, 0x0308) },
89 { USB_DEVICE(0x0471, 0x030C) },
90 { USB_DEVICE(0x0471, 0x0310) },
Luc Saillard2b455db2006-04-24 10:29:46 -030091 { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 { USB_DEVICE(0x0471, 0x0312) },
93 { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
Luc Saillard2b455db2006-04-24 10:29:46 -030094 { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
96 { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
97 { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
98 { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
99 { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
100 { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
101 { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -0300102 { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */
103 { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
Luc Saillard2b455db2006-04-24 10:29:46 -0300105 { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
106 { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
107 { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
109 { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
110 { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
111 { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
112 { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
113 { USB_DEVICE(0x0d81, 0x1900) },
114 { }
115};
116MODULE_DEVICE_TABLE(usb, pwc_device_table);
117
118static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
119static void usb_pwc_disconnect(struct usb_interface *intf);
Hans de Goede885fe182011-06-06 15:33:44 -0300120static void pwc_isoc_cleanup(struct pwc_device *pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122static struct usb_driver pwc_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 .name = "Philips webcam", /* name */
124 .id_table = pwc_device_table,
125 .probe = usb_pwc_probe, /* probe() */
126 .disconnect = usb_pwc_disconnect, /* disconnect() */
127};
128
129#define MAX_DEV_HINTS 20
130#define MAX_ISOC_ERRORS 20
131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132static int default_fps = 10;
Trent Piepho05ad3902007-01-30 23:26:01 -0300133#ifdef CONFIG_USB_PWC_DEBUG
Michael Krufkyb930e1d2007-08-27 18:16:54 -0300134 int pwc_trace = PWC_DEBUG_LEVEL;
Luc Saillard2b455db2006-04-24 10:29:46 -0300135#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300136static int power_save = -1;
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300137static int led_on = 100, led_off; /* defaults to LED that is on while in use */
Adrian Bunkb20c3cf2006-06-23 06:49:34 -0300138static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139static struct {
140 int type;
141 char serial_number[30];
142 int device_node;
143 struct pwc_device *pdev;
144} device_hint[MAX_DEV_HINTS];
145
146/***/
147
Hans Verkuilbec43662008-12-30 06:58:20 -0300148static int pwc_video_open(struct file *file);
149static int pwc_video_close(struct file *file);
Luc Saillard2b455db2006-04-24 10:29:46 -0300150static ssize_t pwc_video_read(struct file *file, char __user *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 size_t count, loff_t *ppos);
152static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300154static void pwc_video_release(struct video_device *vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Hans Verkuilbec43662008-12-30 06:58:20 -0300156static const struct v4l2_file_operations pwc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 .owner = THIS_MODULE,
158 .open = pwc_video_open,
159 .release = pwc_video_close,
160 .read = pwc_video_read,
161 .poll = pwc_video_poll,
162 .mmap = pwc_video_mmap,
Hans Verkuilafa38522011-01-22 06:34:55 -0300163 .unlocked_ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164};
165static struct video_device pwc_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 .name = "Philips Webcam", /* Filled in later */
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300167 .release = pwc_video_release,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 .fops = &pwc_fops,
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300169 .ioctl_ops = &pwc_ioctl_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170};
171
172/***************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173/* Private functions */
174
Hans de Goede885fe182011-06-06 15:33:44 -0300175struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
Hans de Goede885fe182011-06-06 15:33:44 -0300177 unsigned long flags = 0;
178 struct pwc_frame_buf *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Hans de Goede885fe182011-06-06 15:33:44 -0300180 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
181 if (list_empty(&pdev->queued_bufs))
182 goto leave;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Hans de Goede885fe182011-06-06 15:33:44 -0300184 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
185 list_del(&buf->list);
186leave:
187 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
188 return buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300189}
190
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300191static void pwc_snapshot_button(struct pwc_device *pdev, int down)
192{
193 if (down) {
194 PWC_TRACE("Snapshot button pressed.\n");
195 pdev->snapshot_button_status = 1;
196 } else {
197 PWC_TRACE("Snapshot button released.\n");
198 }
199
200#ifdef CONFIG_USB_PWC_INPUT_EVDEV
201 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300202 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300203 input_sync(pdev->button_dev);
204 }
205#endif
206}
207
Hans de Goede885fe182011-06-06 15:33:44 -0300208static void pwc_frame_complete(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300209{
Hans de Goede885fe182011-06-06 15:33:44 -0300210 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300211
212 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
213 frames on the USB wire after an exposure change. This conditition is
214 however detected in the cam and a bit is set in the header.
215 */
216 if (pdev->type == 730) {
217 unsigned char *ptr = (unsigned char *)fbuf->data;
218
219 if (ptr[1] == 1 && ptr[0] & 0x10) {
220 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
221 pdev->drop_frames += 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300222 }
223 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300224 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300225 }
226 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
227 if (ptr[0] & 0x02)
228 PWC_TRACE("Image is mirrored.\n");
229 else
230 PWC_TRACE("Image is normal.\n");
231 }
232 pdev->vmirror = ptr[0] & 0x03;
233 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
234 after a short frame; this condition is filtered out specifically. A 4 byte
235 frame doesn't make sense anyway.
236 So we get either this sequence:
237 drop_bit set -> 4 byte frame -> short frame -> good frame
238 Or this one:
239 drop_bit set -> short frame -> good frame
240 So we drop either 3 or 2 frames in all!
241 */
242 if (fbuf->filled == 4)
243 pdev->drop_frames++;
Hans de Goede885fe182011-06-06 15:33:44 -0300244 } else if (pdev->type == 740 || pdev->type == 720) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300245 unsigned char *ptr = (unsigned char *)fbuf->data;
246 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300247 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300248 }
249 pdev->vmirror = ptr[0] & 0x03;
250 }
251
Hans de Goede885fe182011-06-06 15:33:44 -0300252 /* In case we were instructed to drop the frame, do so silently. */
253 if (pdev->drop_frames > 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300254 pdev->drop_frames--;
Hans de Goede885fe182011-06-06 15:33:44 -0300255 } else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300256 /* Check for underflow first */
257 if (fbuf->filled < pdev->frame_total_size) {
258 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
259 " discarded.\n", fbuf->filled);
Hans de Goede885fe182011-06-06 15:33:44 -0300260 } else {
261 fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
262 fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
263 vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
264 pdev->fill_buf = NULL;
265 pdev->vsync = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300266 }
267 } /* !drop_frames */
268 pdev->vframe_count++;
Luc Saillard2b455db2006-04-24 10:29:46 -0300269}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271/* This gets called for the Isochronous pipe (video). This is done in
272 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
273 */
David Howells7d12e782006-10-05 14:55:46 +0100274static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
Hans de Goede885fe182011-06-06 15:33:44 -0300276 struct pwc_device *pdev = (struct pwc_device *)urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 int i, fst, flen;
Hans de Goede885fe182011-06-06 15:33:44 -0300278 unsigned char *iso_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Hans de Goede885fe182011-06-06 15:33:44 -0300280 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
281 urb->status == -ESHUTDOWN) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300282 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 return;
284 }
Hans de Goede885fe182011-06-06 15:33:44 -0300285
286 if (pdev->fill_buf == NULL)
287 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
288
289 if (urb->status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 const char *errmsg;
291
292 errmsg = "Unknown";
293 switch(urb->status) {
294 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
295 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
296 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
297 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
298 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700299 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 }
Hans de Goede885fe182011-06-06 15:33:44 -0300301 PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
302 urb->status, errmsg);
303 /* Give up after a number of contiguous errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
305 {
Hans de Goede885fe182011-06-06 15:33:44 -0300306 PWC_ERROR("Too many ISOC errors, bailing out.\n");
307 if (pdev->fill_buf) {
308 vb2_buffer_done(&pdev->fill_buf->vb,
309 VB2_BUF_STATE_ERROR);
310 pdev->fill_buf = NULL;
311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 }
Hans de Goede885fe182011-06-06 15:33:44 -0300313 pdev->vsync = 0; /* Drop the current frame */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 goto handler_end;
315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317 /* Reset ISOC error counter. We did get here, after all. */
318 pdev->visoc_errors = 0;
319
320 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300321 1 = sync-hunt
322 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 */
324 /* Compact data */
325 for (i = 0; i < urb->number_of_packets; i++) {
326 fst = urb->iso_frame_desc[i].status;
327 flen = urb->iso_frame_desc[i].actual_length;
328 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Hans de Goede885fe182011-06-06 15:33:44 -0300329 if (fst != 0) {
330 PWC_ERROR("Iso frame %d has error %d\n", i, fst);
331 continue;
332 }
333 if (flen > 0 && pdev->vsync) {
334 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
Hans de Goede885fe182011-06-06 15:33:44 -0300336 if (pdev->vsync == 1) {
337 do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
338 pdev->vsync = 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300339 }
340
Hans de Goede885fe182011-06-06 15:33:44 -0300341 if (flen + fbuf->filled > pdev->frame_total_size) {
342 PWC_ERROR("Frame overflow (%d > %d)\n",
343 flen + fbuf->filled,
344 pdev->frame_total_size);
345 pdev->vsync = 0; /* Let's wait for an EOF */
346 } else {
347 memcpy(fbuf->data + fbuf->filled, iso_buf,
348 flen);
349 fbuf->filled += flen;
350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
Hans de Goede885fe182011-06-06 15:33:44 -0300352 if (flen < pdev->vlast_packet_size) {
353 /* Shorter packet... end of frame */
354 if (pdev->vsync == 2)
355 pwc_frame_complete(pdev);
356 if (pdev->fill_buf == NULL)
357 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
358 if (pdev->fill_buf) {
359 pdev->fill_buf->filled = 0;
360 pdev->vsync = 1;
361 }
362 }
363 pdev->vlast_packet_size = flen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 }
365
366handler_end:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 i = usb_submit_urb(urb, GFP_ATOMIC);
368 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300369 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370}
371
Hans de Goede885fe182011-06-06 15:33:44 -0300372static int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 struct usb_device *udev;
375 struct urb *urb;
376 int i, j, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 struct usb_interface *intf;
378 struct usb_host_interface *idesc = NULL;
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (pdev->iso_init)
381 return 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 pdev->vsync = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300384 pdev->vlast_packet_size = 0;
Hans de Goede885fe182011-06-06 15:33:44 -0300385 pdev->fill_buf = NULL;
386 pdev->vframe_count = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300387 pdev->visoc_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 udev = pdev->udev;
389
390 /* Get the current alternate interface, adjust packet size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 intf = usb_ifnum_to_if(udev, 0);
392 if (intf)
393 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 if (!idesc)
Hans de Goedec2464122011-06-06 15:25:18 -0300395 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 /* Search video endpoint */
398 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300399 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
401 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
402 break;
403 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300404 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300407 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600408 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 }
410
411 /* Set alternate interface */
412 ret = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300413 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
415 if (ret < 0)
416 return ret;
417
Hans de Goede04613c52011-06-26 13:57:15 -0300418 /* Allocate and init Isochronuous urbs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 for (i = 0; i < MAX_ISO_BUFS; i++) {
420 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
421 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300422 PWC_ERROR("Failed to allocate urb %d\n", i);
Hans de Goede6eba9352011-06-26 06:49:59 -0300423 pdev->iso_init = 1;
424 pwc_isoc_cleanup(pdev);
425 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 }
Hans de Goede04613c52011-06-26 13:57:15 -0300427 pdev->urbs[i] = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300428 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430 urb->interval = 1; // devik
431 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300432 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Hans de Goede04613c52011-06-26 13:57:15 -0300433 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
434 urb->transfer_buffer = usb_alloc_coherent(udev,
435 ISO_BUFFER_SIZE,
436 GFP_KERNEL,
437 &urb->transfer_dma);
438 if (urb->transfer_buffer == NULL) {
439 PWC_ERROR("Failed to allocate urb buffer %d\n", i);
440 pdev->iso_init = 1;
441 pwc_isoc_cleanup(pdev);
442 return -ENOMEM;
443 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300444 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
445 urb->complete = pwc_isoc_handler;
446 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 urb->start_frame = 0;
448 urb->number_of_packets = ISO_FRAMES_PER_DESC;
449 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
450 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
451 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
452 }
453 }
454
455 /* link */
456 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300457 ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
Hans de Goede622d9f52010-11-16 12:32:09 -0300458 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300459 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Hans de Goede622d9f52010-11-16 12:32:09 -0300460 pdev->iso_init = 1;
461 pwc_isoc_cleanup(pdev);
462 return ret;
463 }
Hans de Goede04613c52011-06-26 13:57:15 -0300464 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 }
466
467 /* All is done... */
468 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300469 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 return 0;
471}
472
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300473static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 int i;
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 /* Unlinking ISOC buffers one by one */
478 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300479 if (pdev->urbs[i]) {
480 PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
481 usb_kill_urb(pdev->urbs[i]);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300482 }
483 }
484}
485
486static void pwc_iso_free(struct pwc_device *pdev)
487{
488 int i;
489
490 /* Freeing ISOC buffers one by one */
491 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300492 if (pdev->urbs[i]) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300493 PWC_DEBUG_MEMORY("Freeing URB\n");
Hans de Goede04613c52011-06-26 13:57:15 -0300494 if (pdev->urbs[i]->transfer_buffer) {
495 usb_free_coherent(pdev->udev,
496 pdev->urbs[i]->transfer_buffer_length,
497 pdev->urbs[i]->transfer_buffer,
498 pdev->urbs[i]->transfer_dma);
499 }
500 usb_free_urb(pdev->urbs[i]);
501 pdev->urbs[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
503 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300504}
505
Hans de Goede885fe182011-06-06 15:33:44 -0300506static void pwc_isoc_cleanup(struct pwc_device *pdev)
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300507{
508 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
Hans de Goedec2464122011-06-06 15:25:18 -0300509
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300510 if (pdev->iso_init == 0)
511 return;
512
513 pwc_iso_stop(pdev);
514 pwc_iso_free(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300515 usb_set_interface(pdev->udev, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
517 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300518 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
Hans de Goede885fe182011-06-06 15:33:44 -0300521/*
522 * Release all queued buffers, no need to take queued_bufs_lock, since all
523 * iso urbs have been killed when we're called so pwc_isoc_handler won't run.
524 */
525static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
526{
527 while (!list_empty(&pdev->queued_bufs)) {
528 struct pwc_frame_buf *buf;
529
530 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
531 list);
532 list_del(&buf->list);
533 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
534 }
535}
536
Luc Saillard2b455db2006-04-24 10:29:46 -0300537/*********
538 * sysfs
539 *********/
Kay Sievers54bd5b62007-10-08 16:26:13 -0300540static struct pwc_device *cd_to_pwc(struct device *cd)
Luc Saillard2b455db2006-04-24 10:29:46 -0300541{
542 struct video_device *vdev = to_video_device(cd);
543 return video_get_drvdata(vdev);
544}
545
Kay Sievers54bd5b62007-10-08 16:26:13 -0300546static ssize_t show_pan_tilt(struct device *class_dev,
547 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300548{
549 struct pwc_device *pdev = cd_to_pwc(class_dev);
550 return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
551}
552
Kay Sievers54bd5b62007-10-08 16:26:13 -0300553static ssize_t store_pan_tilt(struct device *class_dev,
554 struct device_attribute *attr,
555 const char *buf, size_t count)
Luc Saillard2b455db2006-04-24 10:29:46 -0300556{
557 struct pwc_device *pdev = cd_to_pwc(class_dev);
558 int pan, tilt;
559 int ret = -EINVAL;
560
561 if (strncmp(buf, "reset", 5) == 0)
562 ret = pwc_mpt_reset(pdev, 0x3);
563
564 else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
565 ret = pwc_mpt_set_angle(pdev, pan, tilt);
566
567 if (ret < 0)
568 return ret;
569 return strlen(buf);
570}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300571static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
572 store_pan_tilt);
Luc Saillard2b455db2006-04-24 10:29:46 -0300573
Kay Sievers54bd5b62007-10-08 16:26:13 -0300574static ssize_t show_snapshot_button_status(struct device *class_dev,
575 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300576{
577 struct pwc_device *pdev = cd_to_pwc(class_dev);
578 int status = pdev->snapshot_button_status;
579 pdev->snapshot_button_status = 0;
580 return sprintf(buf, "%d\n", status);
581}
582
Kay Sievers54bd5b62007-10-08 16:26:13 -0300583static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
584 NULL);
Luc Saillard2b455db2006-04-24 10:29:46 -0300585
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300586static int pwc_create_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300587{
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300588 int rc;
589
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300590 rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300591 if (rc)
592 goto err;
593 if (pdev->features & FEATURE_MOTOR_PANTILT) {
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300594 rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300595 if (rc)
596 goto err_button;
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300597 }
598
599 return 0;
600
601err_button:
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300602 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300603err:
Hans Verkuilf894dfd2008-07-25 07:39:54 -0300604 PWC_ERROR("Could not create sysfs files.\n");
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300605 return rc;
Luc Saillard2b455db2006-04-24 10:29:46 -0300606}
607
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300608static void pwc_remove_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300609{
Luc Saillard2b455db2006-04-24 10:29:46 -0300610 if (pdev->features & FEATURE_MOTOR_PANTILT)
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300611 device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
612 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Luc Saillard2b455db2006-04-24 10:29:46 -0300613}
614
Trent Piepho05ad3902007-01-30 23:26:01 -0300615#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -0300616static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
617{
618 switch(sensor_type) {
619 case 0x00:
620 return "Hyundai CMOS sensor";
621 case 0x20:
622 return "Sony CCD sensor + TDA8787";
623 case 0x2E:
624 return "Sony CCD sensor + Exas 98L59";
625 case 0x2F:
626 return "Sony CCD sensor + ADI 9804";
627 case 0x30:
628 return "Sharp CCD sensor + TDA8787";
629 case 0x3E:
630 return "Sharp CCD sensor + Exas 98L59";
631 case 0x3F:
632 return "Sharp CCD sensor + ADI 9804";
633 case 0x40:
634 return "UPA 1021 sensor";
635 case 0x100:
636 return "VGA sensor";
637 case 0x101:
638 return "PAL MR sensor";
639 default:
Trent Piepho657de3c2006-06-20 00:30:57 -0300640 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -0300641 }
642}
643#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645/***************************************************************************/
646/* Video4Linux functions */
647
Hans Verkuilbec43662008-12-30 06:58:20 -0300648static int pwc_video_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 struct video_device *vdev = video_devdata(file);
651 struct pwc_device *pdev;
652
Luc Saillard2b455db2006-04-24 10:29:46 -0300653 PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300654
Hans Verkuil601e9442008-08-23 07:24:07 -0300655 pdev = video_get_drvdata(vdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300656 if (!pdev->udev)
657 return -ENODEV;
658
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 file->private_data = vdev;
Luc Saillard2b455db2006-04-24 10:29:46 -0300660 PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 return 0;
662}
663
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300664static void pwc_video_release(struct video_device *vfd)
Oliver Neukum85237f22007-08-21 07:10:42 +0200665{
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300666 struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
667 int hint;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300668
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300669 /* search device_hint[] table if we occupy a slot, by any chance */
670 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
671 if (device_hint[hint].pdev == pdev)
672 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300673
Hans de Goede6eba9352011-06-26 06:49:59 -0300674 /* Free intermediate decompression buffer & tables */
675 if (pdev->decompress_data != NULL) {
676 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
677 pdev->decompress_data);
678 kfree(pdev->decompress_data);
679 pdev->decompress_data = NULL;
680 }
681
Hans de Goede6c9cac82011-06-26 12:52:01 -0300682 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
683
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300684 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +0200685}
686
Hans Verkuilbec43662008-12-30 06:58:20 -0300687static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
689 struct video_device *vdev = file->private_data;
690 struct pwc_device *pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Luc Saillard2b455db2006-04-24 10:29:46 -0300692 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Hans Verkuil601e9442008-08-23 07:24:07 -0300694 pdev = video_get_drvdata(vdev);
Hans de Goede4fba4712011-06-26 12:13:44 -0300695 if (pdev->capt_file == file) {
696 vb2_queue_release(&pdev->vb_queue);
697 pdev->capt_file = NULL;
698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Hans de Goede4fba4712011-06-26 12:13:44 -0300700 PWC_DEBUG_OPEN("<< video_close()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 return 0;
702}
703
Luc Saillard2b455db2006-04-24 10:29:46 -0300704static ssize_t pwc_video_read(struct file *file, char __user *buf,
Hans de Goede885fe182011-06-06 15:33:44 -0300705 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 struct video_device *vdev = file->private_data;
Hans de Goede885fe182011-06-06 15:33:44 -0300708 struct pwc_device *pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Hans de Goedeb824bb42011-06-25 17:39:19 -0300710 if (!pdev->udev)
711 return -ENODEV;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300712
Hans de Goede4fba4712011-06-26 12:13:44 -0300713 if (pdev->capt_file != NULL &&
714 pdev->capt_file != file)
715 return -EBUSY;
716
717 pdev->capt_file = file;
718
Hans de Goede885fe182011-06-06 15:33:44 -0300719 return vb2_read(&pdev->vb_queue, buf, count, ppos,
720 file->f_flags & O_NONBLOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721}
722
723static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
724{
725 struct video_device *vdev = file->private_data;
Hans de Goede885fe182011-06-06 15:33:44 -0300726 struct pwc_device *pdev = video_get_drvdata(vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
Hans de Goedeb824bb42011-06-25 17:39:19 -0300728 if (!pdev->udev)
Hans de Goede885fe182011-06-06 15:33:44 -0300729 return POLL_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
Hans de Goede885fe182011-06-06 15:33:44 -0300731 return vb2_poll(&pdev->vb_queue, file, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732}
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
735{
736 struct video_device *vdev = file->private_data;
Hans de Goede885fe182011-06-06 15:33:44 -0300737 struct pwc_device *pdev = video_get_drvdata(vdev);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300738
Hans de Goede4fba4712011-06-26 12:13:44 -0300739 if (pdev->capt_file != file)
740 return -EBUSY;
741
Hans de Goede885fe182011-06-06 15:33:44 -0300742 return vb2_mmap(&pdev->vb_queue, vma);
743}
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300744
Hans de Goede885fe182011-06-06 15:33:44 -0300745/***************************************************************************/
746/* Videobuf2 operations */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Hans de Goede885fe182011-06-06 15:33:44 -0300748static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
749 unsigned int *nplanes, unsigned long sizes[],
750 void *alloc_ctxs[])
751{
752 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Luc Saillard2b455db2006-04-24 10:29:46 -0300753
Hans de Goede885fe182011-06-06 15:33:44 -0300754 if (*nbuffers < MIN_FRAMES)
755 *nbuffers = MIN_FRAMES;
756 else if (*nbuffers > MAX_FRAMES)
757 *nbuffers = MAX_FRAMES;
758
759 *nplanes = 1;
760
761 sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 return 0;
764}
765
Hans de Goede885fe182011-06-06 15:33:44 -0300766static int buffer_init(struct vb2_buffer *vb)
767{
768 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
769
770 /* need vmalloc since frame buffer > 128K */
771 buf->data = vzalloc(PWC_FRAME_SIZE);
772 if (buf->data == NULL)
773 return -ENOMEM;
774
775 return 0;
776}
777
778static int buffer_prepare(struct vb2_buffer *vb)
779{
780 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
781
782 /* Don't allow queing new buffers after device disconnection */
Hans de Goedeb824bb42011-06-25 17:39:19 -0300783 if (!pdev->udev)
784 return -ENODEV;
Hans de Goede885fe182011-06-06 15:33:44 -0300785
786 return 0;
787}
788
789static int buffer_finish(struct vb2_buffer *vb)
790{
791 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
792 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
793
794 /*
795 * Application has called dqbuf and is getting back a buffer we've
796 * filled, take the pwc data we've stored in buf->data and decompress
797 * it into a usable format, storing the result in the vb2_buffer
798 */
799 return pwc_decompress(pdev, buf);
800}
801
802static void buffer_cleanup(struct vb2_buffer *vb)
803{
804 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
805
806 vfree(buf->data);
807}
808
809static void buffer_queue(struct vb2_buffer *vb)
810{
811 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
812 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
813 unsigned long flags = 0;
814
815 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
816 list_add_tail(&buf->list, &pdev->queued_bufs);
817 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
818}
819
820static int start_streaming(struct vb2_queue *vq)
821{
822 struct pwc_device *pdev = vb2_get_drv_priv(vq);
823
Hans de Goedeb824bb42011-06-25 17:39:19 -0300824 if (!pdev->udev)
825 return -ENODEV;
826
Hans de Goede6eba9352011-06-26 06:49:59 -0300827 /* Turn on camera and set LEDS on */
828 pwc_camera_power(pdev, 1);
829 if (pdev->power_save) {
830 /* Restore video mode */
831 pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
832 pdev->vframes, pdev->vcompression,
833 pdev->vsnapshot);
834 }
835 pwc_set_leds(pdev, led_on, led_off);
836
Hans de Goede885fe182011-06-06 15:33:44 -0300837 return pwc_isoc_init(pdev);
838}
839
840static int stop_streaming(struct vb2_queue *vq)
841{
842 struct pwc_device *pdev = vb2_get_drv_priv(vq);
843
Hans de Goede6eba9352011-06-26 06:49:59 -0300844 if (pdev->udev) {
845 pwc_set_leds(pdev, 0, 0);
846 pwc_camera_power(pdev, 0);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300847 pwc_isoc_cleanup(pdev);
Hans de Goede6eba9352011-06-26 06:49:59 -0300848 }
Hans de Goede885fe182011-06-06 15:33:44 -0300849 pwc_cleanup_queued_bufs(pdev);
850
851 return 0;
852}
853
854static void pwc_lock(struct vb2_queue *vq)
855{
856 struct pwc_device *pdev = vb2_get_drv_priv(vq);
857 mutex_lock(&pdev->modlock);
858}
859
860static void pwc_unlock(struct vb2_queue *vq)
861{
862 struct pwc_device *pdev = vb2_get_drv_priv(vq);
863 mutex_unlock(&pdev->modlock);
864}
865
866static struct vb2_ops pwc_vb_queue_ops = {
867 .queue_setup = queue_setup,
868 .buf_init = buffer_init,
869 .buf_prepare = buffer_prepare,
870 .buf_finish = buffer_finish,
871 .buf_cleanup = buffer_cleanup,
872 .buf_queue = buffer_queue,
873 .start_streaming = start_streaming,
874 .stop_streaming = stop_streaming,
875 .wait_prepare = pwc_unlock,
876 .wait_finish = pwc_lock,
877};
878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879/***************************************************************************/
880/* USB functions */
881
882/* This function gets called when a new device is plugged in or the usb core
883 * is loaded.
884 */
885
886static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
887{
888 struct usb_device *udev = interface_to_usbdev(intf);
889 struct pwc_device *pdev = NULL;
890 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300891 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 int features = 0;
893 int video_nr = -1; /* default: use next available device */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300894 int my_power_save = power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 char serial_number[30], *name;
896
Luc Saillard2b455db2006-04-24 10:29:46 -0300897 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
898 product_id = le16_to_cpu(udev->descriptor.idProduct);
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -0300901 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
902 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 intf->altsetting->desc.bInterfaceNumber);
904
905 /* the interfaces are probed one by one. We are only interested in the
906 video interface (0) now.
907 Interface 1 is the Audio Control, and interface 2 Audio itself.
908 */
909 if (intf->altsetting->desc.bInterfaceNumber > 0)
910 return -ENODEV;
911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 if (vendor_id == 0x0471) {
913 switch (product_id) {
914 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -0300915 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 name = "Philips 645 webcam";
917 type_id = 645;
918 break;
919 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -0300920 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 name = "Philips 646 webcam";
922 type_id = 646;
923 break;
924 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -0300925 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 name = "Askey VC010 webcam";
927 type_id = 646;
928 break;
929 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -0300930 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 name = "Philips 675 webcam";
932 type_id = 675;
933 break;
934 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -0300935 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 name = "Philips 680 webcam";
937 type_id = 680;
938 break;
939 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -0300940 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 name = "Philips 690 webcam";
942 type_id = 690;
943 break;
944 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -0300945 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 name = "Philips 730 webcam";
947 type_id = 730;
948 break;
949 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -0300950 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 name = "Philips 740 webcam";
952 type_id = 740;
953 break;
954 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -0300955 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 name = "Philips 750 webcam";
957 type_id = 750;
958 break;
959 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -0300960 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 name = "Philips 720K/40 webcam";
962 type_id = 720;
963 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300964 case 0x0329:
965 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
966 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -0300967 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -0300968 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 default:
970 return -ENODEV;
971 break;
972 }
973 }
974 else if (vendor_id == 0x069A) {
975 switch(product_id) {
976 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300977 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 name = "Askey VC010 webcam";
979 type_id = 645;
980 break;
981 default:
982 return -ENODEV;
983 break;
984 }
985 }
986 else if (vendor_id == 0x046d) {
987 switch(product_id) {
988 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -0300989 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 name = "Logitech QuickCam Pro 3000";
991 type_id = 740; /* CCD sensor */
992 break;
993 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -0300994 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 name = "Logitech QuickCam Notebook Pro";
996 type_id = 740; /* CCD sensor */
997 break;
998 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -0300999 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 name = "Logitech QuickCam Pro 4000";
1001 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -03001002 if (my_power_save == -1)
1003 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 break;
1005 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -03001006 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 name = "Logitech QuickCam Zoom";
1008 type_id = 740; /* CCD sensor */
1009 break;
1010 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -03001011 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 name = "Logitech QuickCam Zoom";
1013 type_id = 740; /* CCD sensor */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001014 if (my_power_save == -1)
1015 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 break;
1017 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -03001018 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 name = "Logitech QuickCam Orbit";
1020 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -03001021 if (my_power_save == -1)
1022 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 features |= FEATURE_MOTOR_PANTILT;
1024 break;
1025 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -03001026 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
1027 name = "Cisco VT Camera";
1028 type_id = 740; /* CCD sensor */
1029 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -03001031 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
1032 name = "Logitech ViewPort AV 100";
1033 type_id = 740; /* CCD sensor */
1034 break;
1035 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -03001036 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 name = "Logitech QuickCam (res.)";
1038 type_id = 730; /* Assuming CMOS */
1039 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001040 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001042 break;
1043 }
1044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 else if (vendor_id == 0x055d) {
1046 /* I don't know the difference between the C10 and the C30;
1047 I suppose the difference is the sensor, but both cameras
1048 work equally well with a type_id of 675
1049 */
1050 switch(product_id) {
1051 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -03001052 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 name = "Samsung MPC-C10";
1054 type_id = 675;
1055 break;
1056 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001057 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 name = "Samsung MPC-C30";
1059 type_id = 675;
1060 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001061 case 0x9002:
1062 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
1063 name = "Samsung MPC-C30";
1064 type_id = 740;
1065 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 default:
1067 return -ENODEV;
1068 break;
1069 }
1070 }
1071 else if (vendor_id == 0x041e) {
1072 switch(product_id) {
1073 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -03001074 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 name = "Creative Labs Webcam 5";
1076 type_id = 730;
Hans de Goede51886df2011-07-03 15:52:54 -03001077 if (my_power_save == -1)
1078 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 break;
1080 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -03001081 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 name = "Creative Labs Webcam Pro Ex";
1083 type_id = 740;
1084 break;
1085 default:
1086 return -ENODEV;
1087 break;
1088 }
1089 }
1090 else if (vendor_id == 0x04cc) {
1091 switch(product_id) {
1092 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001093 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 name = "Sotec Afina Eye";
1095 type_id = 730;
1096 break;
1097 default:
1098 return -ENODEV;
1099 break;
1100 }
1101 }
1102 else if (vendor_id == 0x06be) {
1103 switch(product_id) {
1104 case 0x8116:
1105 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001106 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 name = "AME Co. Afina Eye";
1108 type_id = 750;
1109 break;
1110 default:
1111 return -ENODEV;
1112 break;
1113 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 }
1116 else if (vendor_id == 0x0d81) {
1117 switch(product_id) {
1118 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001119 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 name = "Visionite VCS-UC300";
1121 type_id = 740; /* CCD sensor */
1122 break;
1123 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001124 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 name = "Visionite VCS-UM100";
1126 type_id = 730; /* CMOS sensor */
1127 break;
1128 default:
1129 return -ENODEV;
1130 break;
1131 }
1132 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001133 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1135
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001136 if (my_power_save == -1)
1137 my_power_save = 0;
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 memset(serial_number, 0, 30);
1140 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001141 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001144 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001147 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001149 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return -ENOMEM;
1151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 pdev->type = type_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 pdev->vframes = default_fps;
1154 strcpy(pdev->serial, serial_number);
1155 pdev->features = features;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001156 if (vendor_id == 0x046D && product_id == 0x08B5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 /* Logitech QuickCam Orbit
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001158 The ranges have been determined experimentally; they may differ from cam to cam.
1159 Also, the exact ranges left-right and up-down are different for my cam
1160 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 pdev->angle_range.pan_min = -7000;
1162 pdev->angle_range.pan_max = 7000;
1163 pdev->angle_range.tilt_min = -3000;
1164 pdev->angle_range.tilt_max = 2500;
1165 }
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001166 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Matthias Kaehlckeb9378fd2007-07-02 10:04:52 -03001168 mutex_init(&pdev->modlock);
Hans de Goedec1127132011-07-03 11:50:51 -03001169 mutex_init(&pdev->udevlock);
Hans de Goede885fe182011-06-06 15:33:44 -03001170 spin_lock_init(&pdev->queued_bufs_lock);
1171 INIT_LIST_HEAD(&pdev->queued_bufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
1173 pdev->udev = udev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 pdev->vcompression = pwc_preferred_compression;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001175 pdev->power_save = my_power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176
Hans de Goede885fe182011-06-06 15:33:44 -03001177 /* Init videobuf2 queue structure */
1178 memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
1179 pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1180 pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1181 pdev->vb_queue.drv_priv = pdev;
1182 pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
1183 pdev->vb_queue.ops = &pwc_vb_queue_ops;
1184 pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
1185 vb2_queue_init(&pdev->vb_queue);
1186
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001187 /* Init video_device structure */
1188 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
1189 pdev->vdev.parent = &intf->dev;
1190 pdev->vdev.lock = &pdev->modlock;
1191 strcpy(pdev->vdev.name, name);
1192 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001195 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
1197 /* Now search device_hint[] table for a match, so we can hint a node number. */
1198 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1199 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1200 (device_hint[hint].pdev == NULL)) {
1201 /* so far, so good... try serial number */
1202 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001203 /* match! */
1204 video_nr = device_hint[hint].device_node;
1205 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1206 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 }
1208 }
1209 }
1210
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001212 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 device_hint[hint].pdev = pdev;
1214
Luc Saillard2b455db2006-04-24 10:29:46 -03001215 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001216 usb_set_intfdata(intf, pdev);
Luc Saillard2b455db2006-04-24 10:29:46 -03001217
Hans de Goede6eba9352011-06-26 06:49:59 -03001218#ifdef CONFIG_USB_PWC_DEBUG
1219 /* Query sensor type */
1220 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1221 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1222 pdev->vdev.name,
1223 pwc_sensor_type_to_string(rc), rc);
1224 }
1225#endif
1226
Luc Saillard2b455db2006-04-24 10:29:46 -03001227 /* Set the leds off */
1228 pwc_set_leds(pdev, 0, 0);
Hans de Goede6eba9352011-06-26 06:49:59 -03001229
1230 /* Setup intial videomode */
1231 rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
1232 pdev->vframes, pdev->vcompression, 0);
1233 if (rc)
1234 goto err_free_mem;
1235
Hans de Goede6c9cac82011-06-26 12:52:01 -03001236 /* Register controls (and read default values from camera */
1237 rc = pwc_init_controls(pdev);
1238 if (rc) {
1239 PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
1240 goto err_free_mem;
1241 }
1242
1243 pdev->vdev.ctrl_handler = &pdev->ctrl_handler;
Hans de Goede6eba9352011-06-26 06:49:59 -03001244
1245 /* And powerdown the camera until streaming starts */
Luc Saillard2b455db2006-04-24 10:29:46 -03001246 pwc_camera_power(pdev, 0);
1247
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001248 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001249 if (rc < 0) {
1250 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001251 goto err_free_controls;
Hans Verkuil479567c2010-09-12 17:05:11 -03001252 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001253 rc = pwc_create_sysfs_files(pdev);
Hans Verkuil479567c2010-09-12 17:05:11 -03001254 if (rc)
1255 goto err_video_unreg;
1256
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001257 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001258
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001259#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1260 /* register webcam snapshot button input device */
1261 pdev->button_dev = input_allocate_device();
1262 if (!pdev->button_dev) {
1263 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001264 rc = -ENOMEM;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001265 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001266 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001267 }
1268
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001269 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1270 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1271
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001272 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001273 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001274 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1275 pdev->button_dev->dev.parent = &pdev->udev->dev;
1276 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001277 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001278
1279 rc = input_register_device(pdev->button_dev);
1280 if (rc) {
1281 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001282 pdev->button_dev = NULL;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001283 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001284 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001285 }
1286#endif
1287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001289
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001290err_video_unreg:
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001291 if (hint < MAX_DEV_HINTS)
1292 device_hint[hint].pdev = NULL;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001293 video_unregister_device(&pdev->vdev);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001294err_free_controls:
1295 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001296err_free_mem:
Hans de Goede6c9cac82011-06-26 12:52:01 -03001297 usb_set_intfdata(intf, NULL);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001298 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001299 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300}
1301
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001302/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303static void usb_pwc_disconnect(struct usb_interface *intf)
1304{
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001305 struct pwc_device *pdev = usb_get_intfdata(intf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Hans de Goedec1127132011-07-03 11:50:51 -03001307 mutex_lock(&pdev->udevlock);
Hans Verkuil7074f402010-09-15 14:49:07 -03001308 mutex_lock(&pdev->modlock);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001309
Hans de Goedeb824bb42011-06-25 17:39:19 -03001310 usb_set_intfdata(intf, NULL);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001311 /* No need to keep the urbs around after disconnection */
1312 pwc_isoc_cleanup(pdev);
Hans de Goede885fe182011-06-06 15:33:44 -03001313 pwc_cleanup_queued_bufs(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -03001314 pdev->udev = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Hans Verkuil7074f402010-09-15 14:49:07 -03001316 mutex_unlock(&pdev->modlock);
Hans de Goedec1127132011-07-03 11:50:51 -03001317 mutex_unlock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001318
1319 pwc_remove_sysfs_files(pdev);
1320 video_unregister_device(&pdev->vdev);
1321
1322#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1323 if (pdev->button_dev)
1324 input_unregister_device(pdev->button_dev);
1325#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326}
1327
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001329/*
1330 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 */
1332
Luc Saillard2b455db2006-04-24 10:29:46 -03001333static int fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334static int compression = -1;
1335static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001336static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001337static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001338static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Luc Saillard2b455db2006-04-24 10:29:46 -03001340module_param(fps, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001341#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001342module_param_named(trace, pwc_trace, int, 0644);
1343#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001344module_param(power_save, int, 0644);
Luc Saillard2b455db2006-04-24 10:29:46 -03001345module_param(compression, int, 0444);
1346module_param_array(leds, int, &leds_nargs, 0444);
1347module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Andrea Odetti4315c412009-12-10 16:26:10 -03001350#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001352#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001353MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356MODULE_PARM_DESC(dev_hint, "Device node hints");
1357
1358MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1359MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1360MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001361MODULE_ALIAS("pwcx");
1362MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364static int __init usb_pwc_init(void)
1365{
Hans de Goede6eba9352011-06-26 06:49:59 -03001366 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Hans de Goede6eba9352011-06-26 06:49:59 -03001368#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001369 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1370 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1371 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1372 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 -07001373
Hans de Goede6eba9352011-06-26 06:49:59 -03001374 if (pwc_trace >= 0) {
1375 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1376 }
1377#endif
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if (fps) {
1380 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001381 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 return -EINVAL;
1383 }
1384 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001385 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 }
1387
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 if (compression >= 0) {
1389 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001390 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 return -EINVAL;
1392 }
1393 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03001394 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 if (leds[0] >= 0)
1397 led_on = leds[0];
1398 if (leds[1] >= 0)
1399 led_off = leds[1];
1400
Steven Cole093cf722005-05-03 19:07:24 -06001401 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 device node (/dev/videoX) to a camera, based on its type
1403 & serial number. The format is [type[.serialnumber]:]node.
1404
1405 Any camera that isn't matched by these rules gets the next
1406 available free device node.
1407 */
1408 for (i = 0; i < MAX_DEV_HINTS; i++) {
1409 char *s, *colon, *dot;
1410
1411 /* This loop also initializes the array */
1412 device_hint[i].pdev = NULL;
1413 s = dev_hint[i];
1414 if (s != NULL && *s != '\0') {
1415 device_hint[i].type = -1; /* wildcard */
1416 strcpy(device_hint[i].serial_number, "*");
1417
1418 /* parse string: chop at ':' & '/' */
1419 colon = dot = s;
1420 while (*colon != '\0' && *colon != ':')
1421 colon++;
1422 while (*dot != '\0' && *dot != '.')
1423 dot++;
1424 /* Few sanity checks */
1425 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001426 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 return -EINVAL;
1428 }
1429
1430 if (*colon == '\0') {
1431 /* No colon */
1432 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001433 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 return -EINVAL;
1435 }
1436 else {
1437 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001438 device_hint[i].device_node =
1439 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 }
1441 }
1442 else {
1443 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001444 device_hint[i].type =
1445 simple_strtol(s, NULL, 10);
1446 device_hint[i].device_node =
1447 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 if (*dot != '\0') {
1449 /* There's a serial number as well */
1450 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001451
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 dot++;
1453 k = 0;
1454 while (*dot != ':' && k < 29) {
1455 device_hint[i].serial_number[k++] = *dot;
1456 dot++;
1457 }
1458 device_hint[i].serial_number[k] = '\0';
1459 }
1460 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001461 PWC_TRACE("device_hint[%d]:\n", i);
1462 PWC_TRACE(" type : %d\n", device_hint[i].type);
1463 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1464 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 }
1466 else
1467 device_hint[i].type = 0; /* not filled */
1468 } /* ..for MAX_DEV_HINTS */
1469
Luc Saillard2b455db2006-04-24 10:29:46 -03001470 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 return usb_register(&pwc_driver);
1472}
1473
1474static void __exit usb_pwc_exit(void)
1475{
Luc Saillard2b455db2006-04-24 10:29:46 -03001476 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001478 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479}
1480
1481module_init(usb_pwc_init);
1482module_exit(usb_pwc_exit);
1483
Luc Saillard2b455db2006-04-24 10:29:46 -03001484/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */