blob: 550ad071a07387610d310f750ca4676be0207c01 [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");
192 pdev->snapshot_button_status = 1;
193 } else {
194 PWC_TRACE("Snapshot button released.\n");
195 }
196
197#ifdef CONFIG_USB_PWC_INPUT_EVDEV
198 if (pdev->button_dev) {
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -0300199 input_report_key(pdev->button_dev, KEY_CAMERA, down);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300200 input_sync(pdev->button_dev);
201 }
202#endif
203}
204
Hans de Goede885fe182011-06-06 15:33:44 -0300205static void pwc_frame_complete(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300206{
Hans de Goede885fe182011-06-06 15:33:44 -0300207 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Luc Saillard2b455db2006-04-24 10:29:46 -0300208
209 /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
210 frames on the USB wire after an exposure change. This conditition is
211 however detected in the cam and a bit is set in the header.
212 */
213 if (pdev->type == 730) {
214 unsigned char *ptr = (unsigned char *)fbuf->data;
215
216 if (ptr[1] == 1 && ptr[0] & 0x10) {
217 PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
218 pdev->drop_frames += 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300219 }
220 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300221 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300222 }
223 if ((ptr[0] ^ pdev->vmirror) & 0x02) {
224 if (ptr[0] & 0x02)
225 PWC_TRACE("Image is mirrored.\n");
226 else
227 PWC_TRACE("Image is normal.\n");
228 }
229 pdev->vmirror = ptr[0] & 0x03;
230 /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
231 after a short frame; this condition is filtered out specifically. A 4 byte
232 frame doesn't make sense anyway.
233 So we get either this sequence:
234 drop_bit set -> 4 byte frame -> short frame -> good frame
235 Or this one:
236 drop_bit set -> short frame -> good frame
237 So we drop either 3 or 2 frames in all!
238 */
239 if (fbuf->filled == 4)
240 pdev->drop_frames++;
Hans de Goede885fe182011-06-06 15:33:44 -0300241 } else if (pdev->type == 740 || pdev->type == 720) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300242 unsigned char *ptr = (unsigned char *)fbuf->data;
243 if ((ptr[0] ^ pdev->vmirror) & 0x01) {
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300244 pwc_snapshot_button(pdev, ptr[0] & 0x01);
Luc Saillard2b455db2006-04-24 10:29:46 -0300245 }
246 pdev->vmirror = ptr[0] & 0x03;
247 }
248
Hans de Goede885fe182011-06-06 15:33:44 -0300249 /* In case we were instructed to drop the frame, do so silently. */
250 if (pdev->drop_frames > 0) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300251 pdev->drop_frames--;
Hans de Goede885fe182011-06-06 15:33:44 -0300252 } else {
Luc Saillard2b455db2006-04-24 10:29:46 -0300253 /* Check for underflow first */
254 if (fbuf->filled < pdev->frame_total_size) {
255 PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
256 " discarded.\n", fbuf->filled);
Hans de Goede885fe182011-06-06 15:33:44 -0300257 } else {
258 fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
259 fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
260 vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
261 pdev->fill_buf = NULL;
262 pdev->vsync = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300263 }
264 } /* !drop_frames */
265 pdev->vframe_count++;
Luc Saillard2b455db2006-04-24 10:29:46 -0300266}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268/* This gets called for the Isochronous pipe (video). This is done in
269 * interrupt time, so it has to be fast, not crash, and not stall. Neat.
270 */
David Howells7d12e782006-10-05 14:55:46 +0100271static void pwc_isoc_handler(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272{
Hans de Goede885fe182011-06-06 15:33:44 -0300273 struct pwc_device *pdev = (struct pwc_device *)urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 int i, fst, flen;
Hans de Goede885fe182011-06-06 15:33:44 -0300275 unsigned char *iso_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
Hans de Goede885fe182011-06-06 15:33:44 -0300277 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
278 urb->status == -ESHUTDOWN) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300279 PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 return;
281 }
Hans de Goede885fe182011-06-06 15:33:44 -0300282
283 if (pdev->fill_buf == NULL)
284 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
285
286 if (urb->status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 const char *errmsg;
288
289 errmsg = "Unknown";
290 switch(urb->status) {
291 case -ENOSR: errmsg = "Buffer error (overrun)"; break;
292 case -EPIPE: errmsg = "Stalled (device not responding)"; break;
293 case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
294 case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
295 case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
Pete Zaitcev38e2bfc2006-09-18 22:49:02 -0700296 case -ETIME: errmsg = "Device does not respond"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 }
Hans de Goede885fe182011-06-06 15:33:44 -0300298 PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
299 urb->status, errmsg);
300 /* Give up after a number of contiguous errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
302 {
Hans de Goede885fe182011-06-06 15:33:44 -0300303 PWC_ERROR("Too many ISOC errors, bailing out.\n");
304 if (pdev->fill_buf) {
305 vb2_buffer_done(&pdev->fill_buf->vb,
306 VB2_BUF_STATE_ERROR);
307 pdev->fill_buf = NULL;
308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 }
Hans de Goede885fe182011-06-06 15:33:44 -0300310 pdev->vsync = 0; /* Drop the current frame */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 goto handler_end;
312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 /* Reset ISOC error counter. We did get here, after all. */
315 pdev->visoc_errors = 0;
316
317 /* vsync: 0 = don't copy data
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300318 1 = sync-hunt
319 2 = synched
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 */
321 /* Compact data */
322 for (i = 0; i < urb->number_of_packets; i++) {
323 fst = urb->iso_frame_desc[i].status;
324 flen = urb->iso_frame_desc[i].actual_length;
325 iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Hans de Goede885fe182011-06-06 15:33:44 -0300326 if (fst != 0) {
327 PWC_ERROR("Iso frame %d has error %d\n", i, fst);
328 continue;
329 }
330 if (flen > 0 && pdev->vsync) {
331 struct pwc_frame_buf *fbuf = pdev->fill_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Hans de Goede885fe182011-06-06 15:33:44 -0300333 if (pdev->vsync == 1) {
334 do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
335 pdev->vsync = 2;
Luc Saillard2b455db2006-04-24 10:29:46 -0300336 }
337
Hans de Goede885fe182011-06-06 15:33:44 -0300338 if (flen + fbuf->filled > pdev->frame_total_size) {
339 PWC_ERROR("Frame overflow (%d > %d)\n",
340 flen + fbuf->filled,
341 pdev->frame_total_size);
342 pdev->vsync = 0; /* Let's wait for an EOF */
343 } else {
344 memcpy(fbuf->data + fbuf->filled, iso_buf,
345 flen);
346 fbuf->filled += flen;
347 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 }
Hans de Goede885fe182011-06-06 15:33:44 -0300349 if (flen < pdev->vlast_packet_size) {
350 /* Shorter packet... end of frame */
351 if (pdev->vsync == 2)
352 pwc_frame_complete(pdev);
353 if (pdev->fill_buf == NULL)
354 pdev->fill_buf = pwc_get_next_fill_buf(pdev);
355 if (pdev->fill_buf) {
356 pdev->fill_buf->filled = 0;
357 pdev->vsync = 1;
358 }
359 }
360 pdev->vlast_packet_size = flen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 }
362
363handler_end:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 i = usb_submit_urb(urb, GFP_ATOMIC);
365 if (i != 0)
Luc Saillard2b455db2006-04-24 10:29:46 -0300366 PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367}
368
Hans de Goede885fe182011-06-06 15:33:44 -0300369static int pwc_isoc_init(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370{
371 struct usb_device *udev;
372 struct urb *urb;
373 int i, j, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 struct usb_interface *intf;
375 struct usb_host_interface *idesc = NULL;
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (pdev->iso_init)
378 return 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 pdev->vsync = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300381 pdev->vlast_packet_size = 0;
Hans de Goede885fe182011-06-06 15:33:44 -0300382 pdev->fill_buf = NULL;
383 pdev->vframe_count = 0;
Hans de Goede6eba9352011-06-26 06:49:59 -0300384 pdev->visoc_errors = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 udev = pdev->udev;
386
387 /* Get the current alternate interface, adjust packet size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 intf = usb_ifnum_to_if(udev, 0);
389 if (intf)
390 idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (!idesc)
Hans de Goedec2464122011-06-06 15:25:18 -0300392 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
394 /* Search video endpoint */
395 pdev->vmax_packet_size = -1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300396 for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
398 pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
399 break;
400 }
Luc Saillard2b455db2006-04-24 10:29:46 -0300401 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300404 PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
Steven Cole093cf722005-05-03 19:07:24 -0600405 return -ENFILE; /* Odd error, that should be noticeable */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 }
407
408 /* Set alternate interface */
409 ret = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300410 PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
412 if (ret < 0)
413 return ret;
414
Hans de Goede04613c52011-06-26 13:57:15 -0300415 /* Allocate and init Isochronuous urbs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 for (i = 0; i < MAX_ISO_BUFS; i++) {
417 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
418 if (urb == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300419 PWC_ERROR("Failed to allocate urb %d\n", i);
Hans de Goede6eba9352011-06-26 06:49:59 -0300420 pdev->iso_init = 1;
421 pwc_isoc_cleanup(pdev);
422 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 }
Hans de Goede04613c52011-06-26 13:57:15 -0300424 pdev->urbs[i] = urb;
Luc Saillard2b455db2006-04-24 10:29:46 -0300425 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427 urb->interval = 1; // devik
428 urb->dev = udev;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300429 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
Hans de Goede04613c52011-06-26 13:57:15 -0300430 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
431 urb->transfer_buffer = usb_alloc_coherent(udev,
432 ISO_BUFFER_SIZE,
433 GFP_KERNEL,
434 &urb->transfer_dma);
435 if (urb->transfer_buffer == NULL) {
436 PWC_ERROR("Failed to allocate urb buffer %d\n", i);
437 pdev->iso_init = 1;
438 pwc_isoc_cleanup(pdev);
439 return -ENOMEM;
440 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300441 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
442 urb->complete = pwc_isoc_handler;
443 urb->context = pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 urb->start_frame = 0;
445 urb->number_of_packets = ISO_FRAMES_PER_DESC;
446 for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
447 urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
448 urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
449 }
450 }
451
452 /* link */
453 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300454 ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
Hans de Goede622d9f52010-11-16 12:32:09 -0300455 if (ret) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300456 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
Hans de Goede622d9f52010-11-16 12:32:09 -0300457 pdev->iso_init = 1;
458 pwc_isoc_cleanup(pdev);
459 return ret;
460 }
Hans de Goede04613c52011-06-26 13:57:15 -0300461 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 }
463
464 /* All is done... */
465 pdev->iso_init = 1;
Luc Saillard2b455db2006-04-24 10:29:46 -0300466 PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 return 0;
468}
469
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300470static void pwc_iso_stop(struct pwc_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
472 int i;
473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 /* Unlinking ISOC buffers one by one */
475 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300476 if (pdev->urbs[i]) {
477 PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
478 usb_kill_urb(pdev->urbs[i]);
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300479 }
480 }
481}
482
483static void pwc_iso_free(struct pwc_device *pdev)
484{
485 int i;
486
487 /* Freeing ISOC buffers one by one */
488 for (i = 0; i < MAX_ISO_BUFS; i++) {
Hans de Goede04613c52011-06-26 13:57:15 -0300489 if (pdev->urbs[i]) {
Luc Saillard2b455db2006-04-24 10:29:46 -0300490 PWC_DEBUG_MEMORY("Freeing URB\n");
Hans de Goede04613c52011-06-26 13:57:15 -0300491 if (pdev->urbs[i]->transfer_buffer) {
492 usb_free_coherent(pdev->udev,
493 pdev->urbs[i]->transfer_buffer_length,
494 pdev->urbs[i]->transfer_buffer,
495 pdev->urbs[i]->transfer_dma);
496 }
497 usb_free_urb(pdev->urbs[i]);
498 pdev->urbs[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 }
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300501}
502
Hans de Goede885fe182011-06-06 15:33:44 -0300503static void pwc_isoc_cleanup(struct pwc_device *pdev)
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300504{
505 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
Hans de Goedec2464122011-06-06 15:25:18 -0300506
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300507 if (pdev->iso_init == 0)
508 return;
509
510 pwc_iso_stop(pdev);
511 pwc_iso_free(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300512 usb_set_interface(pdev->udev, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514 pdev->iso_init = 0;
Luc Saillard2b455db2006-04-24 10:29:46 -0300515 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516}
517
Hans de Goede885fe182011-06-06 15:33:44 -0300518static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
519{
Hans de Goedec20d78c2011-10-09 09:16:46 -0300520 unsigned long flags = 0;
521
522 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300523 while (!list_empty(&pdev->queued_bufs)) {
524 struct pwc_frame_buf *buf;
525
526 buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
527 list);
528 list_del(&buf->list);
529 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
530 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300531 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
Hans de Goede885fe182011-06-06 15:33:44 -0300532}
533
Luc Saillard2b455db2006-04-24 10:29:46 -0300534/*********
535 * sysfs
536 *********/
Kay Sievers54bd5b62007-10-08 16:26:13 -0300537static struct pwc_device *cd_to_pwc(struct device *cd)
Luc Saillard2b455db2006-04-24 10:29:46 -0300538{
539 struct video_device *vdev = to_video_device(cd);
540 return video_get_drvdata(vdev);
541}
542
Kay Sievers54bd5b62007-10-08 16:26:13 -0300543static ssize_t show_pan_tilt(struct device *class_dev,
544 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300545{
546 struct pwc_device *pdev = cd_to_pwc(class_dev);
547 return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
548}
549
Kay Sievers54bd5b62007-10-08 16:26:13 -0300550static ssize_t store_pan_tilt(struct device *class_dev,
551 struct device_attribute *attr,
552 const char *buf, size_t count)
Luc Saillard2b455db2006-04-24 10:29:46 -0300553{
554 struct pwc_device *pdev = cd_to_pwc(class_dev);
555 int pan, tilt;
556 int ret = -EINVAL;
557
558 if (strncmp(buf, "reset", 5) == 0)
559 ret = pwc_mpt_reset(pdev, 0x3);
560
561 else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
562 ret = pwc_mpt_set_angle(pdev, pan, tilt);
563
564 if (ret < 0)
565 return ret;
566 return strlen(buf);
567}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300568static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
569 store_pan_tilt);
Luc Saillard2b455db2006-04-24 10:29:46 -0300570
Kay Sievers54bd5b62007-10-08 16:26:13 -0300571static ssize_t show_snapshot_button_status(struct device *class_dev,
572 struct device_attribute *attr, char *buf)
Luc Saillard2b455db2006-04-24 10:29:46 -0300573{
574 struct pwc_device *pdev = cd_to_pwc(class_dev);
575 int status = pdev->snapshot_button_status;
576 pdev->snapshot_button_status = 0;
577 return sprintf(buf, "%d\n", status);
578}
579
Kay Sievers54bd5b62007-10-08 16:26:13 -0300580static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
581 NULL);
Luc Saillard2b455db2006-04-24 10:29:46 -0300582
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300583static int pwc_create_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300584{
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300585 int rc;
586
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300587 rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300588 if (rc)
589 goto err;
590 if (pdev->features & FEATURE_MOTOR_PANTILT) {
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300591 rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300592 if (rc)
593 goto err_button;
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300594 }
595
596 return 0;
597
598err_button:
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300599 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300600err:
Hans Verkuilf894dfd2008-07-25 07:39:54 -0300601 PWC_ERROR("Could not create sysfs files.\n");
Jeff Garzikc12e3be2006-10-13 07:17:32 -0300602 return rc;
Luc Saillard2b455db2006-04-24 10:29:46 -0300603}
604
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300605static void pwc_remove_sysfs_files(struct pwc_device *pdev)
Luc Saillard2b455db2006-04-24 10:29:46 -0300606{
Luc Saillard2b455db2006-04-24 10:29:46 -0300607 if (pdev->features & FEATURE_MOTOR_PANTILT)
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300608 device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
609 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
Luc Saillard2b455db2006-04-24 10:29:46 -0300610}
611
Trent Piepho05ad3902007-01-30 23:26:01 -0300612#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -0300613static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
614{
615 switch(sensor_type) {
616 case 0x00:
617 return "Hyundai CMOS sensor";
618 case 0x20:
619 return "Sony CCD sensor + TDA8787";
620 case 0x2E:
621 return "Sony CCD sensor + Exas 98L59";
622 case 0x2F:
623 return "Sony CCD sensor + ADI 9804";
624 case 0x30:
625 return "Sharp CCD sensor + TDA8787";
626 case 0x3E:
627 return "Sharp CCD sensor + Exas 98L59";
628 case 0x3F:
629 return "Sharp CCD sensor + ADI 9804";
630 case 0x40:
631 return "UPA 1021 sensor";
632 case 0x100:
633 return "VGA sensor";
634 case 0x101:
635 return "PAL MR sensor";
636 default:
Trent Piepho657de3c2006-06-20 00:30:57 -0300637 return "unknown type of sensor";
Luc Saillard2b455db2006-04-24 10:29:46 -0300638 }
639}
640#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642/***************************************************************************/
643/* Video4Linux functions */
644
Hans de Goedec20d78c2011-10-09 09:16:46 -0300645int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
646{
647 int r = 0;
648
649 mutex_lock(&pdev->capt_file_lock);
650 if (pdev->capt_file != NULL &&
651 pdev->capt_file != file) {
652 r = -EBUSY;
653 goto leave;
654 }
655 pdev->capt_file = file;
656leave:
657 mutex_unlock(&pdev->capt_file_lock);
658 return r;
659}
660
Hans de Goede76ae8532011-07-19 07:14:22 -0300661static void pwc_video_release(struct v4l2_device *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Hans de Goede76ae8532011-07-19 07:14:22 -0300663 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300664 int hint;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -0300665
Hans de Goede9a7b2d12011-06-06 14:43:39 -0300666 /* search device_hint[] table if we occupy a slot, by any chance */
667 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
668 if (device_hint[hint].pdev == pdev)
669 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300670
Hans de Goede6eba9352011-06-26 06:49:59 -0300671 /* Free intermediate decompression buffer & tables */
672 if (pdev->decompress_data != NULL) {
673 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
674 pdev->decompress_data);
675 kfree(pdev->decompress_data);
676 pdev->decompress_data = NULL;
677 }
678
Hans de Goede6c9cac82011-06-26 12:52:01 -0300679 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
680
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300681 kfree(pdev);
Oliver Neukum85237f22007-08-21 07:10:42 +0200682}
683
Hans Verkuilbec43662008-12-30 06:58:20 -0300684static int pwc_video_close(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Hans de Goede76ae8532011-07-19 07:14:22 -0300686 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Hans de Goede4fba4712011-06-26 12:13:44 -0300688 if (pdev->capt_file == file) {
689 vb2_queue_release(&pdev->vb_queue);
690 pdev->capt_file = NULL;
691 }
Hans de Goede76ae8532011-07-19 07:14:22 -0300692 return v4l2_fh_release(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
Luc Saillard2b455db2006-04-24 10:29:46 -0300695static ssize_t pwc_video_read(struct file *file, char __user *buf,
Hans de Goede885fe182011-06-06 15:33:44 -0300696 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
Hans de Goede76ae8532011-07-19 07:14:22 -0300698 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Hans de Goedeb824bb42011-06-25 17:39:19 -0300700 if (!pdev->udev)
701 return -ENODEV;
Oliver Neukum0b67f5c2007-09-26 10:19:01 -0300702
Hans de Goedec20d78c2011-10-09 09:16:46 -0300703 if (pwc_test_n_set_capt_file(pdev, file))
Hans de Goede4fba4712011-06-26 12:13:44 -0300704 return -EBUSY;
705
Hans de Goede885fe182011-06-06 15:33:44 -0300706 return vb2_read(&pdev->vb_queue, buf, count, ppos,
707 file->f_flags & O_NONBLOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708}
709
710static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
711{
Hans de Goede76ae8532011-07-19 07:14:22 -0300712 struct pwc_device *pdev = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Hans de Goedeb824bb42011-06-25 17:39:19 -0300714 if (!pdev->udev)
Hans de Goede885fe182011-06-06 15:33:44 -0300715 return POLL_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Hans de Goede885fe182011-06-06 15:33:44 -0300717 return vb2_poll(&pdev->vb_queue, file, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718}
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
721{
Hans de Goede76ae8532011-07-19 07:14:22 -0300722 struct pwc_device *pdev = video_drvdata(file);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300723
Hans de Goede4fba4712011-06-26 12:13:44 -0300724 if (pdev->capt_file != file)
725 return -EBUSY;
726
Hans de Goede885fe182011-06-06 15:33:44 -0300727 return vb2_mmap(&pdev->vb_queue, vma);
728}
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300729
Hans de Goede885fe182011-06-06 15:33:44 -0300730/***************************************************************************/
731/* Videobuf2 operations */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Guennadi Liakhovetskifc714e702011-08-24 10:30:21 -0300733static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
734 unsigned int *nbuffers, unsigned int *nplanes,
735 unsigned int sizes[], void *alloc_ctxs[])
Hans de Goede885fe182011-06-06 15:33:44 -0300736{
737 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Luc Saillard2b455db2006-04-24 10:29:46 -0300738
Hans de Goede885fe182011-06-06 15:33:44 -0300739 if (*nbuffers < MIN_FRAMES)
740 *nbuffers = MIN_FRAMES;
741 else if (*nbuffers > MAX_FRAMES)
742 *nbuffers = MAX_FRAMES;
743
744 *nplanes = 1;
745
746 sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return 0;
749}
750
Hans de Goede885fe182011-06-06 15:33:44 -0300751static int buffer_init(struct vb2_buffer *vb)
752{
753 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
754
755 /* need vmalloc since frame buffer > 128K */
756 buf->data = vzalloc(PWC_FRAME_SIZE);
757 if (buf->data == NULL)
758 return -ENOMEM;
759
760 return 0;
761}
762
763static int buffer_prepare(struct vb2_buffer *vb)
764{
765 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
766
767 /* Don't allow queing new buffers after device disconnection */
Hans de Goedeb824bb42011-06-25 17:39:19 -0300768 if (!pdev->udev)
769 return -ENODEV;
Hans de Goede885fe182011-06-06 15:33:44 -0300770
771 return 0;
772}
773
774static int buffer_finish(struct vb2_buffer *vb)
775{
776 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
777 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
778
779 /*
780 * Application has called dqbuf and is getting back a buffer we've
781 * filled, take the pwc data we've stored in buf->data and decompress
782 * it into a usable format, storing the result in the vb2_buffer
783 */
784 return pwc_decompress(pdev, buf);
785}
786
787static void buffer_cleanup(struct vb2_buffer *vb)
788{
789 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
790
791 vfree(buf->data);
792}
793
794static void buffer_queue(struct vb2_buffer *vb)
795{
796 struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
797 struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
798 unsigned long flags = 0;
799
800 spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300801 /* Check the device has not disconnected between prep and queuing */
802 if (pdev->udev)
803 list_add_tail(&buf->list, &pdev->queued_bufs);
804 else
805 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
Hans de Goede885fe182011-06-06 15:33:44 -0300806 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
807}
808
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300809static int start_streaming(struct vb2_queue *vq, unsigned int count)
Hans de Goede885fe182011-06-06 15:33:44 -0300810{
811 struct pwc_device *pdev = vb2_get_drv_priv(vq);
Hans de Goedec20d78c2011-10-09 09:16:46 -0300812 int r;
Hans de Goede885fe182011-06-06 15:33:44 -0300813
Hans de Goedec20d78c2011-10-09 09:16:46 -0300814 mutex_lock(&pdev->udevlock);
815 if (!pdev->udev) {
816 r = -ENODEV;
817 goto leave;
818 }
Hans de Goedeb824bb42011-06-25 17:39:19 -0300819
Hans de Goede6eba9352011-06-26 06:49:59 -0300820 /* Turn on camera and set LEDS on */
821 pwc_camera_power(pdev, 1);
822 if (pdev->power_save) {
823 /* Restore video mode */
824 pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
825 pdev->vframes, pdev->vcompression,
826 pdev->vsnapshot);
827 }
828 pwc_set_leds(pdev, led_on, led_off);
829
Hans de Goedec20d78c2011-10-09 09:16:46 -0300830 r = pwc_isoc_init(pdev);
831leave:
832 mutex_unlock(&pdev->udevlock);
833 return r;
Hans de Goede885fe182011-06-06 15:33:44 -0300834}
835
836static int stop_streaming(struct vb2_queue *vq)
837{
838 struct pwc_device *pdev = vb2_get_drv_priv(vq);
839
Hans de Goedec20d78c2011-10-09 09:16:46 -0300840 mutex_lock(&pdev->udevlock);
Hans de Goede6eba9352011-06-26 06:49:59 -0300841 if (pdev->udev) {
842 pwc_set_leds(pdev, 0, 0);
843 pwc_camera_power(pdev, 0);
Hans de Goedeb824bb42011-06-25 17:39:19 -0300844 pwc_isoc_cleanup(pdev);
Hans de Goede6eba9352011-06-26 06:49:59 -0300845 }
Hans de Goedec20d78c2011-10-09 09:16:46 -0300846 mutex_unlock(&pdev->udevlock);
847
Hans de Goede885fe182011-06-06 15:33:44 -0300848 pwc_cleanup_queued_bufs(pdev);
849
850 return 0;
851}
852
Hans de Goede885fe182011-06-06 15:33:44 -0300853static struct vb2_ops pwc_vb_queue_ops = {
854 .queue_setup = queue_setup,
855 .buf_init = buffer_init,
856 .buf_prepare = buffer_prepare,
857 .buf_finish = buffer_finish,
858 .buf_cleanup = buffer_cleanup,
859 .buf_queue = buffer_queue,
860 .start_streaming = start_streaming,
861 .stop_streaming = stop_streaming,
Hans de Goede885fe182011-06-06 15:33:44 -0300862};
863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864/***************************************************************************/
865/* USB functions */
866
867/* This function gets called when a new device is plugged in or the usb core
868 * is loaded.
869 */
870
871static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
872{
873 struct usb_device *udev = interface_to_usbdev(intf);
874 struct pwc_device *pdev = NULL;
875 int vendor_id, product_id, type_id;
Dmitry Torokhov89dec012009-08-14 02:22:52 -0300876 int hint, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 int features = 0;
878 int video_nr = -1; /* default: use next available device */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300879 int my_power_save = power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 char serial_number[30], *name;
881
Luc Saillard2b455db2006-04-24 10:29:46 -0300882 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
883 product_id = le16_to_cpu(udev->descriptor.idProduct);
884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* Check if we can handle this device */
Luc Saillard2b455db2006-04-24 10:29:46 -0300886 PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
887 vendor_id, product_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 intf->altsetting->desc.bInterfaceNumber);
889
890 /* the interfaces are probed one by one. We are only interested in the
891 video interface (0) now.
892 Interface 1 is the Audio Control, and interface 2 Audio itself.
893 */
894 if (intf->altsetting->desc.bInterfaceNumber > 0)
895 return -ENODEV;
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 if (vendor_id == 0x0471) {
898 switch (product_id) {
899 case 0x0302:
Luc Saillard2b455db2006-04-24 10:29:46 -0300900 PWC_INFO("Philips PCA645VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 name = "Philips 645 webcam";
902 type_id = 645;
903 break;
904 case 0x0303:
Luc Saillard2b455db2006-04-24 10:29:46 -0300905 PWC_INFO("Philips PCA646VC USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 name = "Philips 646 webcam";
907 type_id = 646;
908 break;
909 case 0x0304:
Luc Saillard2b455db2006-04-24 10:29:46 -0300910 PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 name = "Askey VC010 webcam";
912 type_id = 646;
913 break;
914 case 0x0307:
Luc Saillard2b455db2006-04-24 10:29:46 -0300915 PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 name = "Philips 675 webcam";
917 type_id = 675;
918 break;
919 case 0x0308:
Luc Saillard2b455db2006-04-24 10:29:46 -0300920 PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 name = "Philips 680 webcam";
922 type_id = 680;
923 break;
924 case 0x030C:
Luc Saillard2b455db2006-04-24 10:29:46 -0300925 PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 name = "Philips 690 webcam";
927 type_id = 690;
928 break;
929 case 0x0310:
Luc Saillard2b455db2006-04-24 10:29:46 -0300930 PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 name = "Philips 730 webcam";
932 type_id = 730;
933 break;
934 case 0x0311:
Luc Saillard2b455db2006-04-24 10:29:46 -0300935 PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 name = "Philips 740 webcam";
937 type_id = 740;
938 break;
939 case 0x0312:
Luc Saillard2b455db2006-04-24 10:29:46 -0300940 PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 name = "Philips 750 webcam";
942 type_id = 750;
943 break;
944 case 0x0313:
Luc Saillard2b455db2006-04-24 10:29:46 -0300945 PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 name = "Philips 720K/40 webcam";
947 type_id = 720;
948 break;
Luc Saillard2b455db2006-04-24 10:29:46 -0300949 case 0x0329:
950 PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
951 name = "Philips SPC 900NC webcam";
Luc Saillard9ee6d782007-04-22 23:54:36 -0300952 type_id = 740;
Luc Saillard2b455db2006-04-24 10:29:46 -0300953 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 default:
955 return -ENODEV;
956 break;
957 }
958 }
959 else if (vendor_id == 0x069A) {
960 switch(product_id) {
961 case 0x0001:
Luc Saillard2b455db2006-04-24 10:29:46 -0300962 PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 name = "Askey VC010 webcam";
964 type_id = 645;
965 break;
966 default:
967 return -ENODEV;
968 break;
969 }
970 }
971 else if (vendor_id == 0x046d) {
972 switch(product_id) {
973 case 0x08b0:
Luc Saillard2b455db2006-04-24 10:29:46 -0300974 PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 name = "Logitech QuickCam Pro 3000";
976 type_id = 740; /* CCD sensor */
977 break;
978 case 0x08b1:
Luc Saillard2b455db2006-04-24 10:29:46 -0300979 PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 name = "Logitech QuickCam Notebook Pro";
981 type_id = 740; /* CCD sensor */
982 break;
983 case 0x08b2:
Luc Saillard2b455db2006-04-24 10:29:46 -0300984 PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 name = "Logitech QuickCam Pro 4000";
986 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -0300987 if (my_power_save == -1)
988 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 break;
990 case 0x08b3:
Luc Saillard2b455db2006-04-24 10:29:46 -0300991 PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 name = "Logitech QuickCam Zoom";
993 type_id = 740; /* CCD sensor */
994 break;
995 case 0x08B4:
Luc Saillard2b455db2006-04-24 10:29:46 -0300996 PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 name = "Logitech QuickCam Zoom";
998 type_id = 740; /* CCD sensor */
Hans de Goede3b4d0ec2011-06-26 03:51:19 -0300999 if (my_power_save == -1)
1000 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 break;
1002 case 0x08b5:
Luc Saillard2b455db2006-04-24 10:29:46 -03001003 PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 name = "Logitech QuickCam Orbit";
1005 type_id = 740; /* CCD sensor */
Hans de Goede51886df2011-07-03 15:52:54 -03001006 if (my_power_save == -1)
1007 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 features |= FEATURE_MOTOR_PANTILT;
1009 break;
1010 case 0x08b6:
Jean Tourrilhesa63e1572007-03-21 16:29:16 -03001011 PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
1012 name = "Cisco VT Camera";
1013 type_id = 740; /* CCD sensor */
1014 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 case 0x08b7:
Mauro Carvalho Chehab6b1ce3c2007-03-21 16:35:28 -03001016 PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
1017 name = "Logitech ViewPort AV 100";
1018 type_id = 740; /* CCD sensor */
1019 break;
1020 case 0x08b8: /* Where this released? */
Luc Saillard2b455db2006-04-24 10:29:46 -03001021 PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 name = "Logitech QuickCam (res.)";
1023 type_id = 730; /* Assuming CMOS */
1024 break;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001025 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 return -ENODEV;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001027 break;
1028 }
1029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 else if (vendor_id == 0x055d) {
1031 /* I don't know the difference between the C10 and the C30;
1032 I suppose the difference is the sensor, but both cameras
1033 work equally well with a type_id of 675
1034 */
1035 switch(product_id) {
1036 case 0x9000:
Luc Saillard2b455db2006-04-24 10:29:46 -03001037 PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 name = "Samsung MPC-C10";
1039 type_id = 675;
1040 break;
1041 case 0x9001:
Luc Saillard2b455db2006-04-24 10:29:46 -03001042 PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 name = "Samsung MPC-C30";
1044 type_id = 675;
1045 break;
Luc Saillard2b455db2006-04-24 10:29:46 -03001046 case 0x9002:
1047 PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
1048 name = "Samsung MPC-C30";
1049 type_id = 740;
1050 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 default:
1052 return -ENODEV;
1053 break;
1054 }
1055 }
1056 else if (vendor_id == 0x041e) {
1057 switch(product_id) {
1058 case 0x400c:
Luc Saillard2b455db2006-04-24 10:29:46 -03001059 PWC_INFO("Creative Labs Webcam 5 detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 name = "Creative Labs Webcam 5";
1061 type_id = 730;
Hans de Goede51886df2011-07-03 15:52:54 -03001062 if (my_power_save == -1)
1063 my_power_save = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 break;
1065 case 0x4011:
Luc Saillard2b455db2006-04-24 10:29:46 -03001066 PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 name = "Creative Labs Webcam Pro Ex";
1068 type_id = 740;
1069 break;
1070 default:
1071 return -ENODEV;
1072 break;
1073 }
1074 }
1075 else if (vendor_id == 0x04cc) {
1076 switch(product_id) {
1077 case 0x8116:
Luc Saillard2b455db2006-04-24 10:29:46 -03001078 PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 name = "Sotec Afina Eye";
1080 type_id = 730;
1081 break;
1082 default:
1083 return -ENODEV;
1084 break;
1085 }
1086 }
1087 else if (vendor_id == 0x06be) {
1088 switch(product_id) {
1089 case 0x8116:
1090 /* This is essentially the same cam as the Sotec Afina Eye */
Luc Saillard2b455db2006-04-24 10:29:46 -03001091 PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 name = "AME Co. Afina Eye";
1093 type_id = 750;
1094 break;
1095 default:
1096 return -ENODEV;
1097 break;
1098 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 else if (vendor_id == 0x0d81) {
1102 switch(product_id) {
1103 case 0x1900:
Luc Saillard2b455db2006-04-24 10:29:46 -03001104 PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 name = "Visionite VCS-UC300";
1106 type_id = 740; /* CCD sensor */
1107 break;
1108 case 0x1910:
Luc Saillard2b455db2006-04-24 10:29:46 -03001109 PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 name = "Visionite VCS-UM100";
1111 type_id = 730; /* CMOS sensor */
1112 break;
1113 default:
1114 return -ENODEV;
1115 break;
1116 }
1117 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001118 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 return -ENODEV; /* Not any of the know types; but the list keeps growing. */
1120
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001121 if (my_power_save == -1)
1122 my_power_save = 0;
1123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 memset(serial_number, 0, 30);
1125 usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
Luc Saillard2b455db2006-04-24 10:29:46 -03001126 PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 if (udev->descriptor.bNumConfigurations > 1)
Luc Saillard2b455db2006-04-24 10:29:46 -03001129 PWC_WARNING("Warning: more than 1 configuration available.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
1131 /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01001132 pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 if (pdev == NULL) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001134 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 return -ENOMEM;
1136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 pdev->type = type_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 pdev->vframes = default_fps;
1139 strcpy(pdev->serial, serial_number);
1140 pdev->features = features;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001141 if (vendor_id == 0x046D && product_id == 0x08B5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 /* Logitech QuickCam Orbit
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001143 The ranges have been determined experimentally; they may differ from cam to cam.
1144 Also, the exact ranges left-right and up-down are different for my cam
1145 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 pdev->angle_range.pan_min = -7000;
1147 pdev->angle_range.pan_max = 7000;
1148 pdev->angle_range.tilt_min = -3000;
1149 pdev->angle_range.tilt_max = 2500;
1150 }
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001151 pwc_construct(pdev); /* set min/max sizes correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Hans de Goedec20d78c2011-10-09 09:16:46 -03001153 mutex_init(&pdev->capt_file_lock);
Hans de Goedec1127132011-07-03 11:50:51 -03001154 mutex_init(&pdev->udevlock);
Hans de Goede885fe182011-06-06 15:33:44 -03001155 spin_lock_init(&pdev->queued_bufs_lock);
1156 INIT_LIST_HEAD(&pdev->queued_bufs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
1158 pdev->udev = udev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 pdev->vcompression = pwc_preferred_compression;
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001160 pdev->power_save = my_power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Hans de Goede885fe182011-06-06 15:33:44 -03001162 /* Init videobuf2 queue structure */
1163 memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
1164 pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1165 pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1166 pdev->vb_queue.drv_priv = pdev;
1167 pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
1168 pdev->vb_queue.ops = &pwc_vb_queue_ops;
1169 pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
1170 vb2_queue_init(&pdev->vb_queue);
1171
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001172 /* Init video_device structure */
1173 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001174 strcpy(pdev->vdev.name, name);
Hans de Goede76ae8532011-07-19 07:14:22 -03001175 set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001176 video_set_drvdata(&pdev->vdev, pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
Luc Saillard2b455db2006-04-24 10:29:46 -03001179 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
1181 /* Now search device_hint[] table for a match, so we can hint a node number. */
1182 for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
1183 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
1184 (device_hint[hint].pdev == NULL)) {
1185 /* so far, so good... try serial number */
1186 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
Trent Piepho657de3c2006-06-20 00:30:57 -03001187 /* match! */
1188 video_nr = device_hint[hint].device_node;
1189 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1190 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
1192 }
1193 }
1194
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 /* occupy slot */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001196 if (hint < MAX_DEV_HINTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 device_hint[hint].pdev = pdev;
1198
Hans de Goede6eba9352011-06-26 06:49:59 -03001199#ifdef CONFIG_USB_PWC_DEBUG
1200 /* Query sensor type */
1201 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1202 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1203 pdev->vdev.name,
1204 pwc_sensor_type_to_string(rc), rc);
1205 }
1206#endif
1207
Luc Saillard2b455db2006-04-24 10:29:46 -03001208 /* Set the leds off */
1209 pwc_set_leds(pdev, 0, 0);
Hans de Goede6eba9352011-06-26 06:49:59 -03001210
1211 /* Setup intial videomode */
1212 rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
1213 pdev->vframes, pdev->vcompression, 0);
1214 if (rc)
1215 goto err_free_mem;
1216
Hans de Goede6c9cac82011-06-26 12:52:01 -03001217 /* Register controls (and read default values from camera */
1218 rc = pwc_init_controls(pdev);
1219 if (rc) {
1220 PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
1221 goto err_free_mem;
1222 }
1223
Hans de Goede6eba9352011-06-26 06:49:59 -03001224 /* And powerdown the camera until streaming starts */
Luc Saillard2b455db2006-04-24 10:29:46 -03001225 pwc_camera_power(pdev, 0);
1226
Hans de Goede76ae8532011-07-19 07:14:22 -03001227 /* Register the v4l2_device structure */
1228 pdev->v4l2_dev.release = pwc_video_release;
1229 rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
1230 if (rc) {
1231 PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
1232 goto err_free_controls;
1233 }
1234
1235 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
1236 pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
1237
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001238 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
Hans Verkuil479567c2010-09-12 17:05:11 -03001239 if (rc < 0) {
1240 PWC_ERROR("Failed to register as video device (%d).\n", rc);
Hans de Goede76ae8532011-07-19 07:14:22 -03001241 goto err_unregister_v4l2_dev;
Hans Verkuil479567c2010-09-12 17:05:11 -03001242 }
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001243 rc = pwc_create_sysfs_files(pdev);
Hans Verkuil479567c2010-09-12 17:05:11 -03001244 if (rc)
1245 goto err_video_unreg;
1246
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001247 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
Hans Verkuil479567c2010-09-12 17:05:11 -03001248
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001249#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1250 /* register webcam snapshot button input device */
1251 pdev->button_dev = input_allocate_device();
1252 if (!pdev->button_dev) {
1253 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001254 rc = -ENOMEM;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001255 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001256 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001257 }
1258
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001259 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1260 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1261
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001262 pdev->button_dev->name = "PWC snapshot button";
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001263 pdev->button_dev->phys = pdev->button_phys;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001264 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1265 pdev->button_dev->dev.parent = &pdev->udev->dev;
1266 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
Lennart Poetteringbcd3e4b2009-06-11 11:19:33 -03001267 pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001268
1269 rc = input_register_device(pdev->button_dev);
1270 if (rc) {
1271 input_free_device(pdev->button_dev);
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001272 pdev->button_dev = NULL;
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001273 pwc_remove_sysfs_files(pdev);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001274 goto err_video_unreg;
Nam Phạm Thànhe32a7ecc2009-01-12 02:50:17 -03001275 }
1276#endif
1277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return 0;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001279
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001280err_video_unreg:
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001281 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001282err_unregister_v4l2_dev:
1283 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede6c9cac82011-06-26 12:52:01 -03001284err_free_controls:
1285 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001286err_free_mem:
Hans de Goede32c67ec2011-07-19 09:05:49 -03001287 if (hint < MAX_DEV_HINTS)
1288 device_hint[hint].pdev = NULL;
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001289 kfree(pdev);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001290 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291}
1292
Dmitry Torokhov89dec012009-08-14 02:22:52 -03001293/* The user yanked out the cable... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294static void usb_pwc_disconnect(struct usb_interface *intf)
1295{
Hans de Goede76ae8532011-07-19 07:14:22 -03001296 struct v4l2_device *v = usb_get_intfdata(intf);
1297 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Hans de Goedec1127132011-07-03 11:50:51 -03001299 mutex_lock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001300 /* No need to keep the urbs around after disconnection */
1301 pwc_isoc_cleanup(pdev);
Hans de Goedeb824bb42011-06-25 17:39:19 -03001302 pdev->udev = NULL;
Hans de Goedec1127132011-07-03 11:50:51 -03001303 mutex_unlock(&pdev->udevlock);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001304
Hans de Goedec20d78c2011-10-09 09:16:46 -03001305 pwc_cleanup_queued_bufs(pdev);
1306
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001307 pwc_remove_sysfs_files(pdev);
1308 video_unregister_device(&pdev->vdev);
Hans de Goede76ae8532011-07-19 07:14:22 -03001309 v4l2_device_unregister(&pdev->v4l2_dev);
Hans de Goede9a7b2d12011-06-06 14:43:39 -03001310
1311#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1312 if (pdev->button_dev)
1313 input_unregister_device(pdev->button_dev);
1314#endif
Hans de Goede76ae8532011-07-19 07:14:22 -03001315
1316 v4l2_device_put(&pdev->v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317}
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001320/*
1321 * Initialization code & module stuff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 */
1323
Luc Saillard2b455db2006-04-24 10:29:46 -03001324static int fps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325static int compression = -1;
1326static int leds[2] = { -1, -1 };
Al Viro64a6f952007-10-14 19:35:30 +01001327static unsigned int leds_nargs;
Luc Saillard2b455db2006-04-24 10:29:46 -03001328static char *dev_hint[MAX_DEV_HINTS];
Al Viro64a6f952007-10-14 19:35:30 +01001329static unsigned int dev_hint_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Luc Saillard2b455db2006-04-24 10:29:46 -03001331module_param(fps, int, 0444);
Trent Piepho05ad3902007-01-30 23:26:01 -03001332#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001333module_param_named(trace, pwc_trace, int, 0644);
1334#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001335module_param(power_save, int, 0644);
Luc Saillard2b455db2006-04-24 10:29:46 -03001336module_param(compression, int, 0444);
1337module_param_array(leds, int, &leds_nargs, 0444);
1338module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
Andrea Odetti4315c412009-12-10 16:26:10 -03001341#ifdef CONFIG_USB_PWC_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342MODULE_PARM_DESC(trace, "For debugging purposes");
Andrea Odetti4315c412009-12-10 16:26:10 -03001343#endif
Hans de Goede3b4d0ec2011-06-26 03:51:19 -03001344MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347MODULE_PARM_DESC(dev_hint, "Device node hints");
1348
1349MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1350MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
1351MODULE_LICENSE("GPL");
Luc Saillard2b455db2006-04-24 10:29:46 -03001352MODULE_ALIAS("pwcx");
1353MODULE_VERSION( PWC_VERSION );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
1355static int __init usb_pwc_init(void)
1356{
Hans de Goede6eba9352011-06-26 06:49:59 -03001357 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Hans de Goede6eba9352011-06-26 06:49:59 -03001359#ifdef CONFIG_USB_PWC_DEBUG
Luc Saillard2b455db2006-04-24 10:29:46 -03001360 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1361 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1362 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1363 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 -07001364
Hans de Goede6eba9352011-06-26 06:49:59 -03001365 if (pwc_trace >= 0) {
1366 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1367 }
1368#endif
1369
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 if (fps) {
1371 if (fps < 4 || fps > 30) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001372 PWC_ERROR("Framerate out of bounds (4-30).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return -EINVAL;
1374 }
1375 default_fps = fps;
Luc Saillard2b455db2006-04-24 10:29:46 -03001376 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 }
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if (compression >= 0) {
1380 if (compression > 3) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001381 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 return -EINVAL;
1383 }
1384 pwc_preferred_compression = compression;
Luc Saillard2b455db2006-04-24 10:29:46 -03001385 PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 if (leds[0] >= 0)
1388 led_on = leds[0];
1389 if (leds[1] >= 0)
1390 led_off = leds[1];
1391
Steven Cole093cf722005-05-03 19:07:24 -06001392 /* Big device node whoopla. Basically, it allows you to assign a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 device node (/dev/videoX) to a camera, based on its type
1394 & serial number. The format is [type[.serialnumber]:]node.
1395
1396 Any camera that isn't matched by these rules gets the next
1397 available free device node.
1398 */
1399 for (i = 0; i < MAX_DEV_HINTS; i++) {
1400 char *s, *colon, *dot;
1401
1402 /* This loop also initializes the array */
1403 device_hint[i].pdev = NULL;
1404 s = dev_hint[i];
1405 if (s != NULL && *s != '\0') {
1406 device_hint[i].type = -1; /* wildcard */
1407 strcpy(device_hint[i].serial_number, "*");
1408
1409 /* parse string: chop at ':' & '/' */
1410 colon = dot = s;
1411 while (*colon != '\0' && *colon != ':')
1412 colon++;
1413 while (*dot != '\0' && *dot != '.')
1414 dot++;
1415 /* Few sanity checks */
1416 if (*dot != '\0' && dot > colon) {
Luc Saillard2b455db2006-04-24 10:29:46 -03001417 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return -EINVAL;
1419 }
1420
1421 if (*colon == '\0') {
1422 /* No colon */
1423 if (*dot != '\0') {
Luc Saillard2b455db2006-04-24 10:29:46 -03001424 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 return -EINVAL;
1426 }
1427 else {
1428 /* No type or serial number specified, just a number. */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001429 device_hint[i].device_node =
1430 simple_strtol(s, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 }
1432 }
1433 else {
1434 /* There's a colon, so we have at least a type and a device node */
Andy Shevchenko2d8d7762009-09-24 07:58:09 -03001435 device_hint[i].type =
1436 simple_strtol(s, NULL, 10);
1437 device_hint[i].device_node =
1438 simple_strtol(colon + 1, NULL, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 if (*dot != '\0') {
1440 /* There's a serial number as well */
1441 int k;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 dot++;
1444 k = 0;
1445 while (*dot != ':' && k < 29) {
1446 device_hint[i].serial_number[k++] = *dot;
1447 dot++;
1448 }
1449 device_hint[i].serial_number[k] = '\0';
1450 }
1451 }
Luc Saillard2b455db2006-04-24 10:29:46 -03001452 PWC_TRACE("device_hint[%d]:\n", i);
1453 PWC_TRACE(" type : %d\n", device_hint[i].type);
1454 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1455 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457 else
1458 device_hint[i].type = 0; /* not filled */
1459 } /* ..for MAX_DEV_HINTS */
1460
Luc Saillard2b455db2006-04-24 10:29:46 -03001461 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 return usb_register(&pwc_driver);
1463}
1464
1465static void __exit usb_pwc_exit(void)
1466{
Luc Saillard2b455db2006-04-24 10:29:46 -03001467 PWC_DEBUG_MODULE("Deregistering driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 usb_deregister(&pwc_driver);
Luc Saillard2b455db2006-04-24 10:29:46 -03001469 PWC_INFO("Philips webcam module removed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470}
1471
1472module_init(usb_pwc_init);
1473module_exit(usb_pwc_exit);
1474
Luc Saillard2b455db2006-04-24 10:29:46 -03001475/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */