easycap_main.c revision 73019286cddc8bba1773944a7b6b603137fd66ff
1702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/******************************************************************************
2702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*                                                                             *
3702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*  easycap_main.c                                                             *
4702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*                                                                             *
5702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*  Video driver for EasyCAP USB2.0 Video Capture Device DC60                  *
6702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*                                                                             *
7702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*                                                                             *
8702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas******************************************************************************/
9702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
10702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
11702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
12702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
13702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
14702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  This is free software; you can redistribute it and/or modify
15702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  it under the terms of the GNU General Public License as published by
16702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  the Free Software Foundation; either version 2 of the License, or
17702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  (at your option) any later version.
18702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
19702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  The software is distributed in the hope that it will be useful,
20702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  GNU General Public License for more details.
23702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
24702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  You should have received a copy of the GNU General Public License
25702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  along with this software; if not, write to the Free Software
26702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
28702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas*/
29702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
30702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
31702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas#include "easycap.h"
32fc3cc2caa07568de92cc84780b89b5cf9fbf28b7Tomas Winkler#include <linux/usb/audio.h>
33702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
3402149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler
3502149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_LICENSE("GPL");
3602149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
3702149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
3802149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_VERSION(EASYCAP_DRIVER_VERSION);
3902149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler
4002149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler#ifdef CONFIG_EASYCAP_DEBUG
4118545cfd3623e5cd8960f5155f95e0a9c790a54cMike Thomasint easycap_debug;
4262af33ec6e73d658720ea1190861c8c0609a94b3Randy Dunlapmodule_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
4302149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
4402149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler#endif /* CONFIG_EASYCAP_DEBUG */
4502149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler
462ef0c05e80cf59315f6f0a4e5a950899f169f2d0Tomas Winklerbool easycap_readback;
472ef0c05e80cf59315f6f0a4e5a950899f169f2d0Tomas Winklermodule_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
482ef0c05e80cf59315f6f0a4e5a950899f169f2d0Tomas WinklerMODULE_PARM_DESC(readback, "read back written registers: (default false)");
492ef0c05e80cf59315f6f0a4e5a950899f169f2d0Tomas Winkler
5002149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winklerstatic int easycap_bars = 1;
5162af33ec6e73d658720ea1190861c8c0609a94b3Randy Dunlapmodule_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
5202149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_PARM_DESC(bars,
5302149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winkler	"Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
54702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
5502149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winklerstatic int easycap_gain = 16;
5602149cf7c7fd1ece5ada28f5a95914f4348df44fTomas Winklermodule_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
5702149cf7c7fd1ece5ada28f5a95914f4348df44fTomas WinklerMODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
58d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
598d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winklerstatic bool easycap_ntsc;
608d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winklermodule_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
618d6139547ca349f9acea6536dd6b7f6140d3507fTomas WinklerMODULE_PARM_DESC(ntsc, "NTCS default encoding (default PAL)");
628d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler
63d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
64d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
65a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomasstruct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
66a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomasstatic struct mutex mutex_dongle;
67d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_complete(struct urb *purb);
68d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int reset(struct easycap *peasycap);
69e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
705c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winklerconst char *strerror(int err)
715c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler{
725c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler#define ERRNOSTR(_e) case _e: return # _e
735c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	switch (err) {
745c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	case 0: return "OK";
755c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOMEM);
765c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENODEV);
775c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENXIO);
785c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EINVAL);
795c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EAGAIN);
805c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EFBIG);
815c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPIPE);
825c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EMSGSIZE);
835c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOSPC);
845c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EINPROGRESS);
855c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOSR);
865c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EOVERFLOW);
875c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPROTO);
885c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EILSEQ);
895c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ETIMEDOUT);
905c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EOPNOTSUPP);
915c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPFNOSUPPORT);
925c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EAFNOSUPPORT);
935c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EADDRINUSE);
945c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EADDRNOTAVAIL);
955c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOBUFS);
965c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EISCONN);
975c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOTCONN);
985c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ESHUTDOWN);
995c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOENT);
1005c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ECONNRESET);
1015c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ETIME);
1025c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ECOMM);
1035c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EREMOTEIO);
1045c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EXDEV);
1055c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPERM);
1065c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	default: return "unknown";
1075c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	}
1085c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler
1095c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler#undef ERRNOSTR
1105c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler}
1115c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler
112e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
113e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*
114702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
115702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
116702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
117702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        THIS IS THE CASE FOR OpenSUSE.
119702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
120702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
121702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
122702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/****************************************************************************/
123e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
124702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
125268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
126e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
127e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
128c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winklerint isdongle(struct easycap *peasycap)
129e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas{
130c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k;
1316888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap)
132c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -2;
133c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < DONGLE_MANY; k++) {
134c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (easycapdc60_dongle[k].peasycap == peasycap) {
135c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->isdongle = k;
136c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return k;
137c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
138e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas	}
139c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return -1;
140e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas}
141702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
142d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_open(struct inode *inode, struct file *file)
143702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
144c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct video_device *pvideo_device;
145c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
146c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc;
147702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
148c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "\n");
149c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("==========OPEN=========\n");
150702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
151c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pvideo_device = video_devdata(file);
1526888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvideo_device) {
153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: pvideo_device is NULL.\n");
154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
155c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
1576888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
159c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
160c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1616888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
162c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
163c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
164c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	file->private_data = peasycap;
168c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = wakeup_device(peasycap->pusb_device);
169c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 == rc)
170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "wakeup_device() OK\n");
171c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else {
172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: wakeup_device() rc = %i\n", rc);
173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (-ENODEV == rc)
174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: wakeup_device() returned -ENODEV\n");
175c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		else
176c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: wakeup_device() rc = %i\n", rc);
177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return rc;
178c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = 0;
180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = reset(peasycap);
181c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
182c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: reset() rc = %i\n", rc);
183c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
184c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
185c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
186f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas}
187d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
188f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*****************************************************************************/
189f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
190f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
191f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  RESET THE HARDWARE TO ITS REFERENCE STATE.
192f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
193f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
194f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  A BAD VIDEO FRAME SIZE.
195f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
196f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
197d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int reset(struct easycap *peasycap)
198f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas{
199c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap_standard const *peasycap_standard;
200fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	int fmtidx, input, rate;
201c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool ntsc, other;
202fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	int rc;
203f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
2046888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
205c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
206c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
207c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
208c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = peasycap->input;
209f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
210f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
211f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
212ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
213f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
214f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
215f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  A SWITCH BETWEEN PAL AND NTSC.
216f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
217f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
218f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
219f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
220f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
221c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	other = false;
222c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
223c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rate = ready_saa(peasycap->pusb_device);
225fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rate < 0) {
226c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
227fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		ntsc = !peasycap->ntsc;
228fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		JOM(8, "... trying  %s ..\n", ntsc ? "NTSC" : "PAL");
229fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rc = setup_stk(peasycap->pusb_device, ntsc);
230fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rc) {
231fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			SAM("ERROR: setup_stk() rc = %i\n", rc);
232fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			return -EFAULT;
233fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		}
234fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rc = setup_saa(peasycap->pusb_device, ntsc);
235fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rc) {
236fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			SAM("ERROR: setup_saa() rc = %i\n", rc);
237fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			return -EFAULT;
238fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		}
239fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler
240fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rate = ready_saa(peasycap->pusb_device);
241fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rate < 0) {
242fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			JOM(8, "not ready to capture after %i ms\n", PATIENCE);
243fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			JOM(8, "... saa register 0x1F has 0x%02X\n",
244c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					read_saa(peasycap->pusb_device, 0x1F));
245fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			ntsc = peasycap->ntsc;
246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
247c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "... success at second try:  %i=rate\n", rate);
248c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ntsc = (0 < (rate/2)) ? true : false ;
249c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			other = true;
250c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
251f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	} else {
252c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "... success at first try:  %i=rate\n", rate);
253c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ntsc = (0 < rate/2) ? true : false ;
254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
255c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "ntsc=%d\n", ntsc);
256c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
258c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = setup_stk(peasycap->pusb_device, ntsc);
259fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rc) {
260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: setup_stk() rc = %i\n", rc);
261c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
262c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
263c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = setup_saa(peasycap->pusb_device, ntsc);
264fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rc) {
265c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: setup_saa() rc = %i\n", rc);
266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
267f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
268702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
269fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	memset(peasycap->merit, 0, sizeof(peasycap->merit));
270c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
271c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_eof = 0;
272c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_eof = 0;
273c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	do_gettimeofday(&peasycap->timeval7);
274f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
275f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
276f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
277f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
278f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
279f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
280f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
281c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = -8192;
282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->standard_offset = -8192;
283c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
284c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (other) {
285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap_standard = &easycap_standard[0];
286c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		while (0xFFFF != peasycap_standard->mask) {
287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (fmtidx == peasycap_standard->v4l2_standard.index) {
2881dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				peasycap->inputset[input].standard_offset =
289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap_standard - easycap_standard;
290f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				break;
291f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap_standard++;
293f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0xFFFF == peasycap_standard->mask) {
295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: standard not found\n");
296c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EINVAL;
297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
299c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->inputset[input].standard_offset, input);
300f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
301c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->format_offset = -8192;
302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->brightness = -8192;
303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->contrast = -8192;
304c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->saturation = -8192;
305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->hue = -8192;
306f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
307c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = newinput(peasycap, input);
308702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
313f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	JOM(4, "restored input, standard and format\n");
314c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
316c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
317c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->input) {
318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
319c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
321c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->standard_offset) {
322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->standard_offset\n",
323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->standard_offset);
324c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
325c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
326c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->format_offset) {
327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->format_offset\n",
328c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->format_offset);
329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->brightness) {
332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->brightness\n",
333c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->brightness);
334c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
336c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->contrast) {
337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->saturation) {
341c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->saturation\n",
342c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->saturation);
343c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
344c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
345c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->hue) {
346c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
347c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
348c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
349c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
350f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas}
351f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*****************************************************************************/
352f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
353f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
354f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
355f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  OTHERWISE:
356f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
357f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *           _read AND _fill POINTERS.
358f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      SELECT THE NEW INPUT.
359f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
360f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
361f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
362f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
363f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  NOTE:
364f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
365f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
366f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
367f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
368f36bc37a48148f31f936557b811431b98dbfe347Mike Thomasint
369f36bc37a48148f31f936557b811431b98dbfe347Mike Thomasnewinput(struct easycap *peasycap, int input)
370f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas{
371c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, k, m, mood, off;
372c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int inputnow, video_idlenow, audio_idlenow;
373c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool resubmit;
374f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
3756888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
376c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
377c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
378c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
379c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "%i=input sought\n", input);
380702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
381c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > input && INPUT_MANY <= input)
382c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
383c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	inputnow = peasycap->input;
384c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (input == inputnow)
385c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return 0;
386702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
387f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
388f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
389f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
390f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
391f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  ROUTINE.
392f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
393f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
394c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	video_idlenow = peasycap->video_idle;
395c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	audio_idlenow = peasycap->audio_idle;
396f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
397c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_idle = 1;
398c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_idle = 1;
399c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_isoc_streaming) {
400c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		resubmit = true;
401c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		kill_video_urbs(peasycap);
402c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
403c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		resubmit = false;
404c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
405f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
4066888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
408c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
409c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
410c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = usb_set_interface(peasycap->pusb_device,
411c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_interface,
412c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_altsetting_off);
413c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
414c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
415c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
416c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
417c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = stop_100(peasycap->pusb_device);
418c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
419c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: stop_100() rc = %i\n", rc);
420c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
421c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
422c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < FIELD_BUFFER_MANY; k++) {
423c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
425c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
426c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < FRAME_BUFFER_MANY; k++) {
427c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
428c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
429c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
430c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_page = 0;
431c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_read = 0;
432c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_fill = 0;
433c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
434c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_read = 0;
435c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_fill = 0;
436c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < peasycap->input; k++) {
437c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		(peasycap->frame_fill)++;
438c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->frame_buffer_many <= peasycap->frame_fill)
439c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->frame_fill = 0;
440c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
441c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = input;
442c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	select_input(peasycap->pusb_device, peasycap->input, 9);
443f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
444c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (input == peasycap->inputset[input].input) {
445c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		off = peasycap->inputset[input].standard_offset;
446c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (off != peasycap->standard_offset) {
447c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_standard(peasycap,
448f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				easycap_standard[off].v4l2_standard.id);
449c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
450c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_standard() rc = %i\n", rc);
451c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
452c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
453c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->standard_offset\n",
454c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->standard_offset);
455c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
456c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->standard_offset unchanged\n",
457f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas						peasycap->standard_offset);
458f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
459c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		off = peasycap->inputset[input].format_offset;
460c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (off != peasycap->format_offset) {
461c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			struct v4l2_pix_format *pix =
462c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				&easycap_format[off].v4l2_format.fmt.pix;
463c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_format(peasycap,
464c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pix->width, pix->height,
465c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pix->pixelformat, pix->field, false);
466c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 > rc) {
467c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_format() rc = %i\n", rc);
468c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
469c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
470c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->format_offset\n",
471c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->format_offset);
472c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
473c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->format_offset unchanged\n",
474c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->format_offset);
475f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
476c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].brightness;
477c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->brightness) {
478c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_brightness(peasycap, mood);
479c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
480c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_brightness rc = %i\n", rc);
481c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
482c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
483c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->brightness\n",
484c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->brightness);
485f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
486c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].contrast;
487c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->contrast) {
488c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_contrast(peasycap, mood);
489c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
490c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_contrast rc = %i\n", rc);
491c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
492c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
493c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
494f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].saturation;
496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->saturation) {
497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_saturation(peasycap, mood);
498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_saturation rc = %i\n", rc);
500c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
501c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
502c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->saturation\n",
503c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->saturation);
504c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
505c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].hue;
506c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->hue) {
507c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_hue(peasycap, mood);
508c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
509c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_hue rc = %i\n", rc);
510c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
511c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
512c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->hue\n", peasycap->hue);
513f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
514c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
515c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
516c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
517f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
518702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
5196888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
520c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
521c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
522c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
523c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = usb_set_interface(peasycap->pusb_device,
524c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_interface,
525c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_altsetting_on);
526c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
527c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
528c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
529c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
530c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = start_100(peasycap->pusb_device);
531c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
532c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: start_100() rc = %i\n", rc);
533c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
534c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
53527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (resubmit)
536c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		submit_video_urbs(peasycap);
537f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
538c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
539c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_idle = video_idlenow;
540c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_idle = audio_idlenow;
541c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_junk = 0;
542702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
543c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
544702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
545702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
546d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerint submit_video_urbs(struct easycap *peasycap)
547702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
548c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
549c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct urb *purb;
550c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head;
551c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int j, isbad, nospc, m, rc;
552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int isbuf;
553e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
5546888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
555c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
556c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
558c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
5596888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->purb_video_head) {
560c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap->urb_video_head uninitialized\n");
561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
5636888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
564c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap->pusb_device is NULL\n");
565c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
566c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
567c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->video_isoc_streaming) {
568c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "submission of all video urbs\n");
569c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		isbad = 0;  nospc = 0;  m = 0;
570c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each(plist_head, (peasycap->purb_video_head)) {
571c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
572c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
573c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb && pdata_urb->purb) {
574c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				purb = pdata_urb->purb;
575702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				isbuf = pdata_urb->isbuf;
576702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->interval = 1;
577702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->dev = peasycap->pusb_device;
5781dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->pipe =
5791dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					usb_rcvisocpipe(peasycap->pusb_device,
580702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_endpointnumber);
581702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->transfer_flags = URB_ISO_ASAP;
5821dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->transfer_buffer =
583702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_buffer[isbuf].pgo;
5841dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->transfer_buffer_length =
585702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_buffer_size;
586702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->complete = easycap_complete;
587702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->context = peasycap;
588702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->start_frame = 0;
5891dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->number_of_packets =
590702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_framesperdesc;
591702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
592c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
593c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					purb->iso_frame_desc[j]. offset =
594c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						j * peasycap->video_isoc_maxframesize;
595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					purb->iso_frame_desc[j]. length =
596c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->video_isoc_maxframesize;
597c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
598702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
599702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				rc = usb_submit_urb(purb, GFP_KERNEL);
6005c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler				if (rc) {
601702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					isbad++;
6021dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					SAM("ERROR: usb_submit_urb() failed "
603c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						"for urb with rc:-%s\n",
6045c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler							strerror(rc));
6055c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler					if (rc == -ENOSPC)
606e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						nospc++;
607702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				} else {
608702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					m++;
609702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
610702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			} else {
6115c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler				isbad++;
612702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
613702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
614c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (nospc) {
615c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
616c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM(".....  possibly inadequate USB bandwidth\n");
617c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
618c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
619e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
620c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (isbad) {
621c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "attempting cleanup instead of submitting\n");
622c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			list_for_each(plist_head, (peasycap->purb_video_head)) {
623c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pdata_urb = list_entry(plist_head,
624c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
6256888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (pdata_urb) {
626c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					purb = pdata_urb->purb;
6276888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (purb)
628c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						usb_kill_urb(purb);
629c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
630702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
631c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_streaming = 0;
632c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
633c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_streaming = 1;
634c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "submitted %i video urbs\n", m);
635702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
636702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	} else {
637c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "already streaming video urbs\n");
638702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
639c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
640702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
641702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
642c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winklerint kill_video_urbs(struct easycap *peasycap)
643702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
644c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int m;
645c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head;
646c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
647702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
6486888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
649c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
650c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
651c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
652c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->video_isoc_streaming) {
653c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
654c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_streaming);
655c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return 0;
656c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
657c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->purb_video_head) {
658e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas		SAM("ERROR: peasycap->purb_video_head is NULL\n");
659702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		return -EFAULT;
660702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
661c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
662c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_streaming = 0;
663c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "killing video urbs\n");
664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = 0;
665c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	list_for_each(plist_head, (peasycap->purb_video_head)) {
666c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
667c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (pdata_urb && pdata_urb->purb) {
668c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			usb_kill_urb(pdata_urb->purb);
669c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m++;
670c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
671c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
672c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "%i video urbs killed\n", m);
673c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
674c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
675702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
676702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/****************************************************************************/
677702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
678702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
679d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_open_noinode(struct file *file)
680d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
681d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return easycap_open(NULL, file);
682d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler}
683d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
684d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int videodev_release(struct video_device *pvideo_device)
685702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
686c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
687702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = video_get_drvdata(pvideo_device);
6896888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap is NULL\n");
691c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ending unsuccessfully\n");
692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
693c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 != kill_video_urbs(peasycap)) {
695c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: kill_video_urbs() failed\n");
696c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
697c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "ending successfully\n");
699c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
700702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
701e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
702e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*****************************************************************************/
703702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
704702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
705ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
706ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
707ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
708ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
709ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  peasycap->pusb_device IS NO LONGER VALID.
710702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
711702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
712d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_delete(struct kref *pkref)
713702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
714c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
715c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head, *plist_next;
717c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k, m, gone, kd;
718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_urb;
719c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_page;
720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_struct;
721c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_urb;
722c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_page;
723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_struct;
724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int registered_video, registered_audio;
725c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
726c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = container_of(pkref, struct easycap, kref);
7276888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
729c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
731c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kd = isdongle(peasycap);
732702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
733702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
734702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  FREE VIDEO.
735702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
736702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
7376888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (peasycap->purb_video_head) {
738c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing video urbs\n");
739c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
740c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each(plist_head, (peasycap->purb_video_head)) {
741c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
7436888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb) {
744c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(4, "ERROR: pdata_urb is NULL\n");
745c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
7466888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (pdata_urb->purb) {
747c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					usb_free_urb(pdata_urb->purb);
748c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pdata_urb->purb = NULL;
749c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->allocation_video_urb -= 1;
750c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					m++;
751c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
752702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
753702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
754702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
755c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i video urbs freed\n", m);
756702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
757c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing video data_urb structures.\n");
758c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
759c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each_safe(plist_head, plist_next,
760c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->purb_video_head) {
761c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
762c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
763c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb) {
764c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_struct -=
765702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						sizeof(struct data_urb);
766c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				kfree(pdata_urb);
767c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pdata_urb = NULL;
768c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				m++;
769c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
770702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
771c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i video data_urb structures freed\n", m);
772c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "setting peasycap->purb_video_head=NULL\n");
773c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->purb_video_head = NULL;
774702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
775702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video isoc buffers.\n");
777c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = 0;
778c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
779c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_isoc_buffer[k].pgo) {
780c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			free_pages((unsigned long)
781c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				   peasycap->video_isoc_buffer[k].pgo,
782c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					VIDEO_ISOC_ORDER);
783c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_buffer[k].pgo = NULL;
784c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->allocation_video_page -=
785c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						BIT(VIDEO_ISOC_ORDER);
786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m++;
787c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
788702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "isoc video buffers freed: %i pages\n",
790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m * (0x01 << VIDEO_ISOC_ORDER));
791c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
792c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video field buffers.\n");
793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	gone = 0;
794c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
795c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
7966888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (peasycap->field_buffer[k][m].pgo) {
797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				free_page((unsigned long)
798c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  peasycap->field_buffer[k][m].pgo);
799c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->field_buffer[k][m].pgo = NULL;
800c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_page -= 1;
801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				gone++;
802c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
803702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
804702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
805c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "video field buffers freed: %i pages\n", gone);
806c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
807c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video frame buffers.\n");
808c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	gone = 0;
809c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
810c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
8116888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (peasycap->frame_buffer[k][m].pgo) {
812c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				free_page((unsigned long)
813c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  peasycap->frame_buffer[k][m].pgo);
814c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->frame_buffer[k][m].pgo = NULL;
815c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_page -= 1;
816c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				gone++;
817c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
818702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
819702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
820c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "video frame buffers freed: %i pages\n", gone);
821702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
822702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
823702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  FREE AUDIO.
824702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
825702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
8266888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (peasycap->purb_audio_head) {
827c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing audio urbs\n");
828c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
829c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each(plist_head, (peasycap->purb_audio_head)) {
830c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
831c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					struct data_urb, list_head);
8326888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb)
833c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(4, "ERROR: pdata_urb is NULL\n");
834c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			else {
8356888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (pdata_urb->purb) {
836c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					usb_free_urb(pdata_urb->purb);
837c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pdata_urb->purb = NULL;
838c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->allocation_audio_urb -= 1;
839c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					m++;
840c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
841c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
842c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
843c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i audio urbs freed\n", m);
844c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
845c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing audio data_urb structures.\n");
846c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
847c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each_safe(plist_head, plist_next,
848c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->purb_audio_head) {
849c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
850c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					struct data_urb, list_head);
851c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb) {
852c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_audio_struct -=
853c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							sizeof(struct data_urb);
854c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				kfree(pdata_urb);
855c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pdata_urb = NULL;
856702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				m++;
857702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
858702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
859c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i audio data_urb structures freed\n", m);
860c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "setting peasycap->purb_audio_head=NULL\n");
861c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->purb_audio_head = NULL;
862702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
863702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
864c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing audio isoc buffers.\n");
865702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	m = 0;
866c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
8676888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (peasycap->audio_isoc_buffer[k].pgo) {
868c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			free_pages((unsigned long)
869c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(peasycap->audio_isoc_buffer[k].pgo),
870c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					AUDIO_ISOC_ORDER);
871c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_isoc_buffer[k].pgo = NULL;
872c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->allocation_audio_page -=
873c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					BIT(AUDIO_ISOC_ORDER);
874702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			m++;
875702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
876702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
877c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
878702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					m * (0x01 << AUDIO_ISOC_ORDER));
879702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
880c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing easycap structure.\n");
881c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_urb    = peasycap->allocation_video_urb;
882c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_page   = peasycap->allocation_video_page;
883c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_struct = peasycap->allocation_video_struct;
884c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	registered_video        = peasycap->registered_video;
885c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_urb    = peasycap->allocation_audio_urb;
886c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_page   = peasycap->allocation_audio_page;
887c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_struct = peasycap->allocation_audio_struct;
888c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	registered_audio        = peasycap->registered_audio;
889c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
890c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
891c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&mutex_dongle)) {
892c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot down mutex_dongle\n");
893c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
894c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked mutex_dongle\n");
895c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			easycapdc60_dongle[kd].peasycap = NULL;
896c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&mutex_dongle);
897c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked mutex_dongle\n");
898c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOT(4, "   null-->dongle[%i].peasycap\n", kd);
899c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			allocation_video_struct -= sizeof(struct easycap);
900c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
901a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas	} else {
902c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: cannot purge dongle[].peasycap");
903c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
90438d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter
90538d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter	kfree(peasycap);
90638d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter
907702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
908c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
909c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video pages   after all deletions\n", allocation_video_page);
910c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video structs after all deletions\n", allocation_video_struct);
911c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video devices after all deletions\n", registered_video);
912c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio urbs    after all deletions\n", allocation_audio_urb);
913c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio pages   after all deletions\n", allocation_audio_page);
914c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
915c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio devices after all deletions\n", registered_audio);
916c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
917c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "ending.\n");
918c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
919702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
920702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
921d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic unsigned int easycap_poll(struct file *file, poll_table *wait)
922702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
923c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
924c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, kd;
925702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
926c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "\n");
927702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
928c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (NULL == ((poll_table *)wait))
929c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
9306888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!file) {
931c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  file pointer is NULL\n");
932ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		return -ERESTARTSYS;
933ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
934ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	peasycap = file->private_data;
9356888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
936ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		SAY("ERROR:  peasycap is NULL\n");
937c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
938ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
9396888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
940c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap->pusb_device is NULL\n");
941c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
942ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
943c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
944c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kd = isdongle(peasycap);
945c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
946c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
947c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
948c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
949c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
950c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_video\n", kd);
951c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	/*
952c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
953c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
954c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  IF NECESSARY, BAIL OUT.
955c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 */
956c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (kd != isdongle(peasycap))
957c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
9586888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!file) {
959c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR:  file is NULL\n");
960c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
961c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
962c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
963c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap = file->private_data;
9646888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
965c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR:  peasycap is NULL\n");
966c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
967c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
968c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
9696888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap->pusb_device) {
970c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: peasycap->pusb_device is NULL\n");
971c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
972c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
973c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
974c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else
975ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	/*
976ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
977ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
978ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  HAVE FAILED.  BAIL OUT.
979ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	*/
980c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ERESTARTSYS;
981c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
982c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = easycap_dqbuf(peasycap, 0);
983c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->polled = 1;
984c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
985c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 == rc)
986c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return POLLIN | POLLRDNORM;
987c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
988c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return POLLERR;
989c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
990702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
991702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
992702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
993702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
994702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
995702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
996c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winklerint easycap_dqbuf(struct easycap *peasycap, int mode)
997702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
998c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int input, ifield, miss, rc;
999702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1000702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
10016888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
1002c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap is NULL\n");
1003c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1004c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
10056888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
1006c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap->pusb_device is NULL\n");
1007c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1008c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1009c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	ifield = 0;
1010c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "%i=ifield\n", ifield);
1011702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1012702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1013849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *  CHECK FOR LOST INPUT SIGNAL.
1014849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *
1015849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *  FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1016ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1017ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1018ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IS FLYWHEELING ON INPUT 0.  THE UPSHOT IS:
1019849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *
1020849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0   PLUGGED, INPUT 4   PLUGGED => SCREEN 0 OK,   SCREEN 4 OK
1021849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0   PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK,   SCREEN 4 BLACK
1022849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0 UNPLUGGED, INPUT 4   PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1023849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1024849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas*/
1025849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*---------------------------------------------------------------------------*/
1026c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = peasycap->input;
1027c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= input && INPUT_MANY > input) {
1028c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		rc = read_saa(peasycap->pusb_device, 0x1F);
1029c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= rc) {
1030c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc & 0x40)
1031c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->lost[input] += 1;
1032c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			else
1033c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->lost[input] -= 2;
1034849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas
1035c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 > peasycap->lost[input])
1036c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->lost[input] = 0;
1037c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1038c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1039c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1040849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas	}
1041849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*---------------------------------------------------------------------------*/
1042849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*
104340b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
1044702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1045702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1046c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	miss = 0;
1047c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while ((peasycap->field_read == peasycap->field_fill) ||
1048c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	       (0 != (0xFF00 & peasycap->field_buffer
10491dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					[peasycap->field_read][0].kount)) ||
1050c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	      (ifield != (0x00FF & peasycap->field_buffer
1051702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					[peasycap->field_read][0].kount))) {
1052c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mode)
1053c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EAGAIN;
1054702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1055a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		JOM(8, "first wait  on wq_video, %i=field_read %i=field_fill\n",
1056a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->field_read, peasycap->field_fill);
1057c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1058c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != (wait_event_interruptible(peasycap->wq_video,
1059c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				(peasycap->video_idle || peasycap->video_eof  ||
1060c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				((peasycap->field_read != peasycap->field_fill) &&
1061a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				(0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1062a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				(ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1063c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("aborted by signal\n");
1064c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1065a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		}
1066c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_idle) {
1067c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1068c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_idle);
1069f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			return -EAGAIN;
1070f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
1071c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_eof) {
1072c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1073c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			#if defined(PERSEVERE)
1074c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (1 == peasycap->status) {
1075c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, "persevering ...\n");
1076c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_eof = 0;
1077c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->audio_eof = 0;
1078c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != reset(peasycap)) {
1079c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, " ... failed  returning -EIO\n");
1080c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_eof = 1;
1081c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->audio_eof = 1;
1082c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					kill_video_urbs(peasycap);
1083c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EIO;
1084c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1085c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->status = 0;
1086c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, " ... OK  returning -EAGAIN\n");
1087c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EAGAIN;
1088c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1089c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			#endif /*PERSEVERE*/
1090c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
1091c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_eof = 1;
1092c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			kill_video_urbs(peasycap);
1093c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "returning -EIO\n");
1094c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1095c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1096a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		miss++;
1097702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1098c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "first awakening on wq_video after %i waits\n", miss);
1099702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1100c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = field2frame(peasycap);
1101c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc)
1102c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: field2frame() rc = %i\n", rc);
1103702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1104702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
110540b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WAIT FOR THE OTHER FIELD
1106702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1107702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1108c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (ifield)
1109c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ifield = 0;
1110c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1111c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ifield = 1;
1112c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	miss = 0;
1113c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while ((peasycap->field_read == peasycap->field_fill) ||
1114a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	       (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1115a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	       (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1116c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mode)
1117c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EAGAIN;
1118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1119c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "second wait on wq_video %i=field_read  %i=field_fill\n",
1120702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				peasycap->field_read, peasycap->field_fill);
1121c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != (wait_event_interruptible(peasycap->wq_video,
11221dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			(peasycap->video_idle || peasycap->video_eof  ||
11231dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			((peasycap->field_read != peasycap->field_fill) &&
1124a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1125a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1126c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("aborted by signal\n");
1127c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1128c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1129c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_idle) {
1130c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1131f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas							peasycap->video_idle);
1132f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			return -EAGAIN;
1133f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
1134c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_eof) {
1135c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1136a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler#if defined(PERSEVERE)
1137c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (1 == peasycap->status) {
1138c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, "persevering ...\n");
1139c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_eof = 0;
1140c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->audio_eof = 0;
1141c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != reset(peasycap)) {
1142c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, " ... failed returning -EIO\n");
1143c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_eof = 1;
1144c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->audio_eof = 1;
1145c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					kill_video_urbs(peasycap);
1146c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EIO;
1147c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1148c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->status = 0;
1149c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, " ... OK ... returning -EAGAIN\n");
1150c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EAGAIN;
1151c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1152a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler#endif /*PERSEVERE*/
1153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
1154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_eof = 1;
1155c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			kill_video_urbs(peasycap);
1156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "returning -EIO\n");
1157c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1159a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		miss++;
1160702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1161c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "second awakening on wq_video after %i waits\n", miss);
1162702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1163c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = field2frame(peasycap);
1164c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc)
1165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: field2frame() rc = %i\n", rc);
116640b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
116740b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*
116840b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WASTE THIS FRAME
116940b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas*/
117040b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
1171a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	if (peasycap->skip) {
1172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->skipped++;
1173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->skip != peasycap->skipped)
1174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return peasycap->skip - peasycap->skipped;
1175a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		else
1176a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->skipped = 0;
1177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
117840b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
1179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_read = peasycap->frame_fill;
1180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->queued[peasycap->frame_read] = 0;
1181c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
1182702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1183c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_fill++;
1184c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1185c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_fill = 0;
1186702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1187c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1188c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1189702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							V4L2_FIELD_TOP;
1190c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1191c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1192702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							V4L2_FIELD_BOTTOM;
1193702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1194702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1195c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
1196c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
1197c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1198c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
1199702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
1200702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
1201702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1202702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1203702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  BY DEFINITION, odd IS true  FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1204702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *                 odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1205702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1206702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1207702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1208702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1209702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
121040b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1211702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1212702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1213702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasint
1214702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasfield2frame(struct easycap *peasycap)
1215702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
1216c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct timeval timeval;
1217c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	long long int above, below;
1218c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u32 remainder;
1219c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct signed_div_result sdr;
1220c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1221c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	void *pex, *pad;
1222c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int kex, kad, mex, mad, rex, rad, rad2;
1223c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int c2, c3, w2, w3, cz, wz;
1224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, bytesperpixel, multiplier;
1225c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int  much, more, over, rump, caches, input;
1226c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 mask, margin;
1227c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool odd, isuy, decimatepixel, offerfields, badinput;
1228c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
12296888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
1230c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
1231c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1232c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1233e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
1234c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	badinput = false;
1235c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1236f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
1237c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> "
1238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"frame buffer %i\n",
12391dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			peasycap->field_buffer[peasycap->field_read][0].kount,
12401dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			peasycap->field_buffer[peasycap->field_read][0].input,
1241702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			peasycap->field_read, peasycap->frame_fill);
1242c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
124327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (peasycap->offerfields)
1244c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "===== offerfields\n");
1245702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1246702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1247702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1248702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  REJECT OR CLEAN BAD FIELDS
1249702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1250702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1251c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->field_read == peasycap->field_fill) {
1252c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: on entry, still filling field buffer %i\n",
1253c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->field_read);
1254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return 0;
1255c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
12563fc0dae888ee216036ae1898fc9186f1dd04f185Tomas Winkler#ifdef EASYCAP_TESTCARD
1257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	easycap_testcard(peasycap, peasycap->field_read);
1258702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas#else
1259c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= input && INPUT_MANY > input) {
1260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1261c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			easycap_testcard(peasycap, peasycap->field_read);
1262c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1263702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas#endif /*EASYCAP_TESTCARD*/
1264702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1265702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	offerfields = peasycap->offerfields;
1267c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bytesperpixel = peasycap->bytesperpixel;
1268c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	decimatepixel = peasycap->decimatepixel;
1269702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1270c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((2 != bytesperpixel) &&
1271c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	    (3 != bytesperpixel) &&
1272c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	    (4 != bytesperpixel)) {
1273c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1274c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1275c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
127627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (decimatepixel)
1277c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier = 2;
1278c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1279c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier = 1;
1280702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1281c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	w2 = 2 * multiplier * (peasycap->width);
1282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	w3 = bytesperpixel * multiplier * (peasycap->width);
1283c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	wz = multiplier * (peasycap->height) *
1284c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier * (peasycap->width);
1285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1286c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kex = peasycap->field_read;  mex = 0;
1287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kad = peasycap->frame_fill;  mad = 0;
1288c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
1290c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
1291c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	odd = !!(peasycap->field_buffer[kex][0].kount);
1292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1293febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler	if (odd && (!decimatepixel)) {
1294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "initial skipping %4i bytes p.%4i\n",
1295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					w3/multiplier, mad);
1296c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pad += (w3 / multiplier); rad -= (w3 / multiplier);
1297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	isuy = true;
1299c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	mask = 0;  rump = 0;  caches = 0;
1300c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1301c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	cz = 0;
1302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while (cz < wz) {
1303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		/*
1304c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  READ   w2   BYTES FROM FIELD BUFFER,
1306c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  WRITE  w3   BYTES TO FRAME BUFFER
1307c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 */
1308febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;  more = 0;
1312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				margin = 0;  mask = 0x00;
1313c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1314c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rump = 0;
1316c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1317c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (much % 2) {
1318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: much is odd\n");
1319c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1321702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = (bytesperpixel *
1323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						much) / 2;
1324702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (1 < bytesperpixel) {
1326c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad * 2 < much * bytesperpixel) {
1327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						/*
1328c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * INJUDICIOUS ALTERATION OF
1329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * THIS STATEMENT BLOCK WILL
1330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * CAUSE BREAKAGE.  BEWARE.
1331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 */
1332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad2 = rad + bytesperpixel - 1;
1333a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1334a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						rump = ((bytesperpixel * much) / 2) - rad;
1335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1336a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					}
1337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mask = (u8)rump;
1338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					margin = 0;
1339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much == rex) {
1340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mask |= 0x04;
1341a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1342a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1343a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						else
1344c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							mask |= 0x08;
1345702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1346c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				} else {
1347c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: %i=bytesperpixel\n",
1348c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							bytesperpixel);
1349c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1350702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1351c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rump)
1352c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					caches++;
135327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (badinput) {
1354c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1355c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1356c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1357c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1358c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1359c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1360c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1361c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rc = redaub(peasycap, pad, pex, much, more,
1362c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								mask, margin, isuy);
1363c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 > rc) {
1364c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: redaub() failed\n");
1365c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1366f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				}
1367a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				if (much % 4)
1368a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					isuy = !isuy;
1369a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler
1370c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;   cz += much;
1371c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;  rex -= much;
1372c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1373c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1374c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1375c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1376a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1377c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1378c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1379c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pad  += more;
1380c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rad -= more;
1381c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rad) {
1382c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mad++;
1383c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad = peasycap->frame_buffer[kad][mad].pgo;
1384c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad = PAGE_SIZE;
1385c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rump) {
1386c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad += rump;
1387c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad -= rump;
1388c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1389c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1390c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1391702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1392702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1393702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SKIP  w3 BYTES IN TARGET FRAME BUFFER,
1394702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1395702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1396702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1397febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!odd || (cz != wz)) {
1398c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over = w3;
1399c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				do {
1400c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (!rad) {
1401c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mad++;
1402c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad = peasycap->frame_buffer
1403c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kad][mad].pgo;
1404c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad = PAGE_SIZE;
1405c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1406c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					more = over;
1407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad < more)
1408c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1409c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					over -= more;
1410c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad  += more;
1411c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad  -= more;
1412c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				} while (over);
1413c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1414702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1415702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1416702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1417702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ONLY IF false==odd,
1418702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  READ   w2   BYTES FROM FIELD BUFFER,
1419702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  WRITE  w3 / 2  BYTES TO FRAME BUFFER
1420702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1421702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1422febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		} else if (!odd) {
1423c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1425c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;  more = 0;  margin = 0;  mask = 0x00;
1426c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1427c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1428c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rump = 0;
1429702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1430c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (much % 2) {
1431c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: much is odd\n");
1432c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1433c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1434702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1435c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = (bytesperpixel * much) / 4;
1436702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1437c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (1 < bytesperpixel) {
1438c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad * 4 < much * bytesperpixel) {
1439c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						/*
1440c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * INJUDICIOUS ALTERATION OF
1441c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * THIS STATEMENT BLOCK
1442c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * WILL CAUSE BREAKAGE.
1443c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * BEWARE.
1444c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 */
1445c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad2 = rad + bytesperpixel - 1;
1446a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1447a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						rump = ((bytesperpixel * much) / 4) - rad;
1448c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1449702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1450c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mask = (u8)rump;
1451c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					margin = 0;
1452c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much == rex) {
1453c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mask |= 0x04;
1454a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1455a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1456a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						else
1457c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							mask |= 0x08;
1458702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1459702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1460702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				} else {
14611dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					SAM("MISTAKE: %i=bytesperpixel\n",
1462702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						bytesperpixel);
1463702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					return -EFAULT;
1464702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1465702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1466c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rump)
1467c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					caches++;
1468c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
146927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (badinput) {
1470c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1471c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1472c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1473c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1474c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1475c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1476c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1477c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rc = redaub(peasycap, pad, pex, much, more,
1478702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							mask, margin, isuy);
1479c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 > rc) {
1480c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: redaub() failed\n");
1481c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1482702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1483c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;   cz += much;
1484c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;  rex -= much;
1485c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1486c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1487c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1488c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1489c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (peasycap->field_buffer[kex][mex].input !=
1490c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input))
1491c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1492c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1493c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pad  += more;
1494c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rad -= more;
1495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rad) {
1496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mad++;
1497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad = peasycap->frame_buffer[kad][mad].pgo;
1498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad = PAGE_SIZE;
1499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rump) {
1500c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad += rump;
1501c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad -= rump;
1502c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1503c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1504c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1505702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1506702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1507702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  OTHERWISE JUST
1508702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  READ   w2   BYTES FROM FIELD BUFFER AND DISCARD THEM
1509702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1510702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1511c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
1512c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1513c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1514c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1515c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1516c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1517c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1518c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (peasycap->field_buffer[kex][mex].input !=
1519c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input)) {
1520c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1521c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1522c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1523c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1524c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1525c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1526c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1527c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1528f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				}
1529c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;
1530c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1531c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1532c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;
1533c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				cz += much;
1534c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;
1535c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rex -= much;
1536c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1537c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1538702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1539702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1540702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1541702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SANITY CHECKS
1542702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1543702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1544c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	c2 = (mex + 1)*PAGE_SIZE - rex;
1545c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (cz != c2)
1546c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1547c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	c3 = (mad + 1)*PAGE_SIZE - rad;
1548c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1549febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler	if (!decimatepixel) {
1550c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (bytesperpixel * cz != c3)
15511dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			SAM("ERROR: discrepancy %i in bytes written\n",
1552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					c3 - (bytesperpixel * cz));
1553c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
1554febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!odd) {
1555c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (bytesperpixel *
1556c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				cz != (4 * c3))
1557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: discrepancy %i in bytes written\n",
1558c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(2*c3)-(bytesperpixel * cz));
1559c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1560c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != c3)
1561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: discrepancy %i "
1562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					    "in bytes written\n", c3);
1563c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1564c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1565c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rump)
1566c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1567702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1568c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1569c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
1570702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
157127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (odd)
1572c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
1573702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1574c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->field_read == peasycap->field_fill)
1575c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("WARNING: on exit, filling field buffer %i\n",
1576c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->field_read);
1577702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1578702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1579702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  CALCULATE VIDEO STREAMING RATE
1580702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1581702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1582c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	do_gettimeofday(&timeval);
1583c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->timeval6.tv_sec) {
1584c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		below = ((long long int)(1000000)) *
1585c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			((long long int)(timeval.tv_sec -
1586c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->timeval6.tv_sec)) +
1587c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1588c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		above = (long long int)1000000;
1589702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1590c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		sdr = signed_div(above, below);
1591c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		above = sdr.quotient;
1592c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		remainder = (u32)sdr.remainder;
1593702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1594c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "video streaming at %3lli.%03i fields per second\n",
1595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				above, (remainder/1000));
1596c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1597c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->timeval6 = timeval;
1598702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1599c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (caches)
1600c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "%i=caches\n", caches);
1601c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
1602702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
1603702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
1604702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasstruct signed_div_result
1605702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomassigned_div(long long int above, long long int below)
1606702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
1607c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct signed_div_result sdr;
1608c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1609c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (((0 <= above) && (0 <= below)) || ((0  > above) && (0  > below))) {
1610c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		sdr.remainder = (unsigned long long int) do_div(above, below);
1611c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		sdr.quotient  = (long long int) above;
1612c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
1613c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 > above)
1614c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			above = -above;
1615c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 > below)
1616c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			below = -below;
1617c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		sdr.remainder = (unsigned long long int) do_div(above, below);
1618c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		sdr.quotient  = -((long long int) above);
1619c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1620c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return sdr;
1621702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
1622702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
1623702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1624702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1625702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DECIMATION AND COLOURSPACE CONVERSION.
1626702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1627702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1628702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1629702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1630702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALSO ENSURE THAT much IS EVEN.
1631702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1632702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1633702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1634702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1635702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1636702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x03 & mask =  number of bytes to be written to cache instead of to
1637702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *                    frame buffer
1638702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x04 & mask => use argument margin to set the chrominance for last pixel
1639702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x08 & mask => do not set the chrominance for last pixel
1640702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1641702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1642702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1643702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1644702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INEFFICIENT SWITCHING INSIDE INNER LOOPS.  REARRANGING THE LOGIC TO
1645702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE.  BEWARE.
1646702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1647702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1648702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasint
16491dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winklerredaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1650055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler					u8 mask, u8 margin, bool isuy)
1651702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
1652c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1653c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 *pcache;
1654c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1655c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int  bytesperpixel;
1656c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool byteswaporder, decimatepixel, last;
1657c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int j, rump;
1658c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	s32 tmp;
1659c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1660c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (much % 2) {
1661c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: much is odd\n");
1662c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1663c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bytesperpixel = peasycap->bytesperpixel;
1665c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	byteswaporder = peasycap->byteswaporder;
1666c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	decimatepixel = peasycap->decimatepixel;
1667c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1668c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
1669c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!bu[255]) {
1670c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 0; j < 112; j++) {
1671c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (453 * j)) >> 8;
1672c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j + 128] =  tmp; bu[127 - j] = -tmp;
1673c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (359 * j)) >> 8;
1674c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rv[j + 128] =  tmp; rv[127 - j] = -tmp;
1675c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (88 * j)) >> 8;
1676c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j + 128] =  tmp; gu[127 - j] = -tmp;
1677c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (183 * j)) >> 8;
1678c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gv[j + 128] =  tmp; gv[127 - j] = -tmp;
1679c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1680c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 0; j < 16; j++) {
1681c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j] = bu[16]; rv[j] = rv[16];
1682c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j] = gu[16]; gv[j] = gv[16];
1683c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1684c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 240; j < 256; j++) {
1685c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j] = bu[239]; rv[j] = rv[239];
1686c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j] = gu[239]; gv[j] = gv[239];
1687c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j =  16; j < 236; j++)
1689c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = j;
1690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j =   0; j <  16; j++)
1691c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = ay[16];
1692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 236; j < 256; j++)
1693c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = ay[235];
1694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "lookup tables are prepared\n");
1695c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1696c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pcache = peasycap->pcache;
16976888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pcache)
1698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pcache = &peasycap->cache[0];
1699702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1700702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1701702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1702702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1703702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1704c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!pcache) {
1705c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: pcache is NULL\n");
1706c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1707c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1708702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1709c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (pcache != &peasycap->cache[0])
1710c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1711c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2 = &peasycap->cache[0];
1712c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1713c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while (p2 < pcache) {
1714c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		*p3++ = *p2;  p2++;
1715c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pcache = &peasycap->cache[0];
1717c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (p3 != pad) {
1718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: pointer misalignment\n");
1719c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1721702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1722c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rump = (int)(0x03 & mask);
1723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u = 0; v = 0;
1724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2 = (u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
1725c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2++;
1726702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
172727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (isuy)
1728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		u = *(p2 - 1);
1729c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v = *(p2 - 1);
1731702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1732c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rump)
1733c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
1734702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1735702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1736c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	switch (bytesperpixel) {
1737c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 2: {
1738febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1739c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memcpy(pad, pex, (size_t)much);
1740febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1741c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* UYVY */
1742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1743c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1744c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* YUYV */
1745c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p3 = (u8 *)pad;  pz = p3 + much;
1746c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while  (pz > p3) {
1747c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					c = *p3;
1748c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *(p3 + 1);
1749c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = c;
1750c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 2;
1751702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1752c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1753702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
1754702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		} else {
1755febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1756c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*  UYVY DECIMATED */
1757c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1758c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1759c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *p2;
1760c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = *(p2 + 1);
1761c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 2) = *(p2 + 2);
1762c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 3) = *(p2 + 3);
1763c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 4;  p2 += 8;
1764702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1765c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1766c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1767c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* YUYV DECIMATED */
1768c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1769c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1770c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *(p2 + 1);
1771c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = *p2;
1772c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 2) = *(p2 + 3);
1773c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 3) = *(p2 + 2);
1774c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 4;  p2 += 8;
1775702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1777702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
1778c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1779c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
1780c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1781c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 3:
1782c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		{
1783febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1784febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1785c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* RGB */
1786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1787c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1788c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1791c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
179227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
179427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1795c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1796c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1798c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
1799c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
1800c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
1801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
180227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1803c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1804702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
1805c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1806c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1807702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
180827d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
180927d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1810055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
1811c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
181227d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1813055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
181427d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
181527d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1816055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
1817702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
181827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
1819e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
1820702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
1821702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
1822702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
1823702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
1824702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
1825702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1826702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1827702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
1828702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
1829702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
1830702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
1831702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1832702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1833702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
1834c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
1835c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1836702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
1837702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1838702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1839702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
1840702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = r;
1841702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
1842702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = b;
1843702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1844c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
184527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
1846c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1847c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1848c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1849702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
1850702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1851c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1852c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1853c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* BGR */
1854c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1855c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1856c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1857c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1858c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1859c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
186027d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1861c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
186227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1863c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1864c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1865c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1866c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
1867c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1868702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						if (0x08 & mask)
1869702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							;
1870c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
187127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1872c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1873c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
1874c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1875c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1876702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
187727d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
187827d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1879c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1880c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
188127d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1882c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
188327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
188427d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1885c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1886702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
188727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
1888e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
1889702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
1890702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
1891702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
1892702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
1893702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
1894702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1895702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1896702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
1897702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
1898702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
1899702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
1900702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1901702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1902702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
1903c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
1904c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1905702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
1906702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1907702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1908702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
1909702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = b;
1910702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
1911702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = r;
1912702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1913c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
191427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
1915c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1916c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1917c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1918702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
1919702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1920702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1921702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			return 0;
1922c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
1923febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1924c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*  RGB DECIMATED */
1925c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1926c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1927c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1928c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1929c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1930c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
193127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1932c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
193327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1934c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1935c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1936c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1937c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
1938c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
1939c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
1940c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
194127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1942c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1943702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
1944c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1945702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1946c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
194727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
1948c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
1949c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
1950c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1951c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
1952c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
1953c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
1954c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1955c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
1956c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
1957c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1958c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
195927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
1960c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
1961c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
1962c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
1963c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
1964c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
1965c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
1966c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1967c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1968c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
1969c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
1970c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
1971c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
1972c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1973c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1974c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
1975c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
1976c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
1977c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1978c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
1979c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1980c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1981c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
1982c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = r;
1983c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
1984c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = b;
1985c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
1986c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1987c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
1988c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
1989c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1990702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1991c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
1992702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1993c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1994c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1995c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* BGR DECIMATED */
1996c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1997c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1998c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1999c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2000c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2001c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
200227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2003c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
200427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2005c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2006c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2007c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2008c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2009c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
2010c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2011c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
201227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2013c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2014702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
2015c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2016702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
2017c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
201827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
2019c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2020c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
2021c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2022c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2023c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
2024c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
2025c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2026c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2027c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
2028c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2029c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2030c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
203127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
2032c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
2033c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
2034c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
2035c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2036c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
2037c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2038c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2039c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2040c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
2041c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2042c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2043c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2044c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2045c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2046c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
2047c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
2048c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
2049c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2050c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
2051c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2052c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2053c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2054c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = b;
2055c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
2056c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = r;
2057c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2058c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2059c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2060c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2061c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2062c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2063c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
2064702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
2065c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2066702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2067702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2068c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
2069702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2070c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 4:
2071c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		{
2072febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
2073febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
2074c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* RGBA */
2075c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2076c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2077c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2078c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2079c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2080c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
208127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2082c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
208327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2084c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2085c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2086c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2087c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2088c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							 if (0x08 & mask)
2089c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2090c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
209127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2092c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2093702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
2094c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2095c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2096702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
209727d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
209827d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2099c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2100c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
210127d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2102c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
210327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
210427d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2105c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2106702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
210727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
2108e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
2109702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
2110702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
2111702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2112702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
2113702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
2114702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2115702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2116702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2117702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
2118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2119702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2120702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
2121702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2122702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2123702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2124702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 3: {
2125702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2126702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2127702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 2) = b;
2128702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2129702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2130702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2131702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
2132c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
2133c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2134702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
2135c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2136702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2137702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
2138702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = r;
2139702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
2140702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = b;
2141702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 3) = 0;
2142c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2143c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
214427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
2145c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2146702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					else
2147c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2148c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += bytesperpixel;
2149702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2150c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2151c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
2152c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  BGRA
2154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2155c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2157c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2159c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2160c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
216127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2162c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
216327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2164c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2168c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							 if (0x08 & mask)
2169c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
217127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2175c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2176702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
217727d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
217827d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
218127d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2182c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
218327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
218427d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2185c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2186702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
218727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
2188e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
2189702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
2190702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
2191702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2192702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
2193702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
2194702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2195702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2196702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2197702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
2198702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2199702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2200702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
2201702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2202702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2203702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2204702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 3: {
2205702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2206702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2207702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 2) = r;
2208702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2209702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2210702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2211c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						default:
2212c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
2213c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2214702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
2215702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2216702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
2217702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = b;
2218702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
2219702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = r;
2220702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 3) = 0;
2221702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
2222c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
222327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
2224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2225c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2226c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2227702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
2228c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2229c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
2230c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return 0;
2231c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
2232febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
2233c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2234c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  RGBA DECIMATED
2235c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2236c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2237c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2239c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2240c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2241c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
224227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2243c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
224427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2245c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2247c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2248c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2249c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
2250c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2251c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
225227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2253c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2255c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2256c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
225827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
2259c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
2261c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2262c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2263c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
2264c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
2265c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2267c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
2268c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2269c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2270c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
227127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
2272c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
2273c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
2274c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
2275c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2276c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
2277c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
2278c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2279c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2280c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2281c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
2282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2283c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2284c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
2285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2286c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2288c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 3: {
2289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2290c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2291c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 2) = b;
2292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2293c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
2296c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
2297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
2298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel -
2299c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								rump);
2300c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
2301c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								}
2302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2304c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = r;
2305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
2306c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = b;
2307c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 3) = 0;
2308c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else
2312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2313702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p2 += 2;
2314702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2316c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
2317c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  BGRA DECIMATED
2319c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2321c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2324c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2325c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
232627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
232827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2333c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
2334c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
233627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2341c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
234227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
2343c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
2344c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2345c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2346c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
2347c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
2348c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2349c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2350c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
2351c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2352c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2353c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
235427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
2355c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
2356c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
2357c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
2358c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2359c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
2360c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2361c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2362c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2363c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2364c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
2365c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2366c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2367c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2368c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2369c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2370c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2371c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 3: {
2372c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2373c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2374c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 2) = r;
2375c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2376c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2377c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2378c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
2379c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
2380c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
2381c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2382c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
2383c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2384c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2385c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2386c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = b;
2387c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
2388c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = r;
2389c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 3) = 0;
2390c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2391c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2392c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2393c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else
2394c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2395c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p2 += 2;
2396c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2397c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return 0;
2398c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2399702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2400c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
2401c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2402c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	default: {
2403c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2404c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
2405702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2406702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
2408702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2409702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2410702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2411702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2412702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2413702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2414d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_vma_open(struct vm_area_struct *pvma)
2415702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2416c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2417702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2418c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
24196888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2420c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2421c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2422c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2423c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->vma_many++;
2424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2425268dfede46e24eef55a2ef7a10a462617936771eMike Thomas	return;
2426268dfede46e24eef55a2ef7a10a462617936771eMike Thomas}
2427702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2428d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_vma_close(struct vm_area_struct *pvma)
2429702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2430c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2431702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2432c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
24336888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2434c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2435c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2436c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2437c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->vma_many--;
2438c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2439268dfede46e24eef55a2ef7a10a462617936771eMike Thomas	return;
2440702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2441702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2442d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2443702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2444c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k, m, retcode;
2445c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	void *pbuf;
2446c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct page *page;
2447c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2448702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2449c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	retcode = VM_FAULT_NOPAGE;
2450702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
24516888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvma) {
2452c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("pvma is NULL\n");
2453c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2454c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
24556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvmf) {
2456c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("pvmf is NULL\n");
2457c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2458c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2459702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2460c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2461c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2462702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2463c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!m)
2464c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "%4i=k, %4i=m\n", k, m);
2465c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
2466c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(16, "%4i=k, %4i=m\n", k, m);
2467702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2468c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2469c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: buffer index %i out of range\n", k);
2470c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2471c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2472c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2473c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: page number  %i out of range\n", m);
2474c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2475c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2476c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
24776888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2478c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2479c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2480c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2481702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2482c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pbuf = peasycap->frame_buffer[k][m].pgo;
24836888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pbuf) {
2484c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  pbuf is NULL\n");
2485c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2486c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2487c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	page = virt_to_page(pbuf);
24886888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!page) {
2489c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  page is NULL\n");
2490c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2491c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2492c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	get_page(page);
2493702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
24946888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!page) {
2495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  page is NULL after get_page(page)\n");
2496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
2497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pvmf->page = page;
2498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		retcode = VM_FAULT_MINOR;
2499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2500c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return retcode;
2501702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2502d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2503d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct vm_operations_struct easycap_vm_ops = {
2504d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.open  = easycap_vma_open,
2505d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.close = easycap_vma_close,
2506d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.fault = easycap_vma_fault,
2507d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
2508d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2509d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2510d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
2511d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	JOT(8, "\n");
2512d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2513d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	pvma->vm_ops = &easycap_vm_ops;
2514d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	pvma->vm_flags |= VM_RESERVED;
25156888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (file)
2516d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		pvma->vm_private_data = file->private_data;
2517d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	easycap_vma_open(pvma);
2518d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return 0;
2519d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler}
2520702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2521702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2522702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2523702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2524ce36cedab3f865969653bf4360f7e364ab0937e4Mike Thomas *  PROVIDED peasycap->video_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
2525702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2526702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2527702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2528702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2529702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2530702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  STORED IN THE TWO-BYTE STATUS PARAMETER
2531702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        peasycap->field_buffer[peasycap->field_fill][0].kount
2532702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2533702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2534702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2535702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  CHIP.
2536702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2537702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2538702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
2539702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
2540702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
2541f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
2542ce36cedab3f865969653bf4360f7e364ab0937e4Mike Thomas *      0 != (kount & 0x0400)   => RESERVED
2543702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
2544702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
2545702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2546702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2547d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_complete(struct urb *purb)
2548702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2549c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2550c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_buffer *pfield_buffer;
2551c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	char errbuf[16];
2552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int i, more, much, leap, rc, last;
2553c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int videofieldamount;
2554c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	unsigned int override, bad;
2555c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int framestatus, framelength, frameactual, frameoffset;
2556c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 *pu;
2557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
25586888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!purb) {
2559c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: easycap_complete(): purb is NULL\n");
2560c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = purb->context;
25636888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2564c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2565c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2566c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2567c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_eof)
2568c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2569c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2570c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2571c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			break;
2572c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(16, "%2i=urb\n", i);
2573c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	last = peasycap->video_isoc_sequence;
2574c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2575c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	     (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2576c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2577c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last, i);
2578c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2579c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_sequence = i;
2580702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2581c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_idle) {
2582c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "%i=video_idle  %i=video_isoc_streaming\n",
2583c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_idle, peasycap->video_isoc_streaming);
2584c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_isoc_streaming) {
2585c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = usb_submit_urb(purb, GFP_ATOMIC);
2586c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
2587c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2588c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (-ENODEV != rc)
2589c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: while %i=video_idle, "
2590c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"usb_submit_urb() "
2591c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"failed with rc:\n",
2592c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_idle);
2593c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
2594702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
2596702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2597c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	override = 0;
2598702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2599c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2600c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: bad peasycap->field_fill\n");
2601702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		return;
2602702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2603c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (purb->status) {
2604c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2605c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2606c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
2607c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2608702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2609c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2610c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: bad urb status -%s: %d\n",
2611c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				strerror(purb->status), purb->status);
2612702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2613c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
2614c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (i = 0;  i < purb->number_of_packets; i++) {
2615c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 != purb->iso_frame_desc[i].status) {
2616c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				(peasycap->field_buffer
2617c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][0].kount) |= 0x8000 ;
2618c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* FIXME: 1. missing '-' check boundaries */
2619c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				strcpy(&errbuf[0],
2620c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					strerror(purb->iso_frame_desc[i].status));
2621702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2622c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			framestatus = purb->iso_frame_desc[i].status;
2623c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			framelength = purb->iso_frame_desc[i].length;
2624c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			frameactual = purb->iso_frame_desc[i].actual_length;
2625c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			frameoffset = purb->iso_frame_desc[i].offset;
2626c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2627c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(16, "frame[%2i]:"
2628c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=status "
2629c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=actual "
2630c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=length "
2631c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%5i=offset\n",
2632c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				i, framestatus, frameactual, framelength, frameoffset);
2633c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (!purb->iso_frame_desc[i].status) {
2634c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = purb->iso_frame_desc[i].actual_length;
2635c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2636c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  [peasycap->field_fill][peasycap->field_page];
2637c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				videofieldamount = (peasycap->field_page *
2638c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					PAGE_SIZE) +
2639c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(int)(pfield_buffer->pto - pfield_buffer->pgo);
2640c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (4 == more)
2641c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_mt++;
2642c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (4 < more) {
2643c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (peasycap->video_mt) {
2644c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, "%4i empty video urb frames\n",
2645c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_mt);
2646c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_mt = 0;
2647c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2648c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2649c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_fill\n");
2650c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2651c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2652c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2653c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_page) {
2654c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_page\n");
2655c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2656c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2657c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2658c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][peasycap->field_page];
2659c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pu = (u8 *)(purb->transfer_buffer +
2660c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						purb->iso_frame_desc[i].offset);
2661c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0x80 & *pu)
2662c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					leap = 8;
2663c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				else
2664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					leap = 4;
2665702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
2666702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2667702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2668702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTE:  A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2669702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *         CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2670702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2671702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2672702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  BYTE OF
2673702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        peasycap->field_buffer[peasycap->field_fill][0].kount
2674702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2675702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  UPDATED AND field_fill IS BUMPED.  IF THE FIELD BUFFER CONTAINS BAD DATA
2676702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTHING IS OFFERED TO dqbuf().
2677702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2678702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2679702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  RESTS WITH dqbuf().
2680702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2681702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2682c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if ((8 == more) || override) {
2683c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (videofieldamount >
2684c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->videofieldamount) {
2685c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (2 == videofieldamount -
2686c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->
2687c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount) {
2688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2689c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x0100;
2691c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_junk += (1 +
2692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								VIDEO_JUNK_TOLERATE);
2693c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2695c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2696c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x4000;
2697c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else if (videofieldamount <
2698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->
2699c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount) {
2700c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2701c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2702c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x2000;
2703c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2704c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						bad = 0xFF00 & peasycap->field_buffer
2705c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2706c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[0].kount;
2707c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (!bad) {
2708c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->video_junk)--;
2709c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (-VIDEO_JUNK_TOLERATE >
2710c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_junk)
2711c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_junk =
2712c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								-VIDEO_JUNK_TOLERATE;
2713c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_read =
2714c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								(peasycap->
2715c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill)++;
2716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (FIELD_BUFFER_MANY <=
2717c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									peasycap->
2718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill)
27191dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler								peasycap->
2720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill = 0;
2721c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_page = 0;
2722c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer = &peasycap->
2723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2725c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_fill]
2726c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2727c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_page];
2728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->pto =
2729c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo;
2730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "bumped to: %i="
2731c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"peasycap->"
2732c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"field_fill  %i="
2733c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"parity\n",
2734c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill,
2735c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								0x00FF &
2736c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->kount);
2737c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "field buffer %i has "
2738c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i bytes fit to be "
2739c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"read\n",
2740c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_read,
2741c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount);
2742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "wakeup call to "
2743c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"wq_video, "
2744c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=field_read "
2745c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=field_fill "
2746c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=parity\n",
2747c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_read,
2748c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill,
2749c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								0x00FF & peasycap->
2750c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2751c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2752c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_read][0].kount);
2753c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							wake_up_interruptible
2754c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								(&(peasycap->
2755c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									 wq_video));
2756c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							do_gettimeofday
2757c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								(&peasycap->timeval7);
2758c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2759c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->video_junk++;
2760c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (bad & 0x0010)
2761c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_junk +=
2762c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(1 + VIDEO_JUNK_TOLERATE/2);
2763c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "field buffer %i had %i "
2764c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"bytes, now discarded: "
2765c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%04X\n",
2766c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_fill,
2767c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							videofieldamount,
2768c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0xFF00 &
2769c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
2770c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill][0].
2771c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							kount));
2772c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(peasycap->field_fill)++;
2773c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2774c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (FIELD_BUFFER_MANY <=
2775c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill)
2776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_fill = 0;
2777f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas						peasycap->field_page = 0;
2778c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer =
2779c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							&peasycap->field_buffer
2780c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2781c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_page];
27821dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler						pfield_buffer->pto =
2783c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo;
2784c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2785c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "bumped to: %i=peasycap->"
2786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"field_fill  %i=parity\n",
27871dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler							peasycap->field_fill,
2788c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							0x00FF & pfield_buffer->kount);
2789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (8 == more) {
2791c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "end-of-field: received "
2792c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"parity byte 0x%02X\n",
2793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0xFF & *pu));
2794c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x40 & *pu)
2795c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->kount = 0x0000;
2796c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->kount = 0x0001;
2798c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->input = 0x08 |
2799c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x07 & peasycap->input);
2800c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "end-of-field: 0x%02X=kount\n",
2801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							0xFF & pfield_buffer->kount);
2802c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2803702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2804702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2805702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2806702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2807702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2808702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2809c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pu += leap;
2810c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more -= leap;
2811702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2812c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2813c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_fill\n");
2814702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					return;
2815702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2816c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2817c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_page\n");
2818c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2819c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2820c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2821c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][peasycap->field_page];
2822c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (more) {
2823c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pfield_buffer = &peasycap->field_buffer
28241dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler							[peasycap->field_fill]
2825702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							[peasycap->field_page];
2826c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (PAGE_SIZE < (pfield_buffer->pto -
2827c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo)) {
2828c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						SAM("ERROR: bad pfield_buffer->pto\n");
2829c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						return;
2830c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2831c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (PAGE_SIZE == (pfield_buffer->pto -
2832c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo)) {
2833c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(peasycap->field_page)++;
2834c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2835c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_page) {
2836c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(16, "wrapping peasycap->"
2837c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"field_page\n");
2838c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_page = 0;
2839c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2840c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer = &peasycap->
2841c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2842c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_fill]
2843c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_page];
2844c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->pto = pfield_buffer->pgo;
2845c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->input = 0x08 |
2846c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x07 & peasycap->input);
2847c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if ((peasycap->field_buffer[peasycap->
2848c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_fill][0]).
2849c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									input !=
2850c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->input)
2851c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2852c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_fill]
2853c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0]).kount |= 0x1000;
2854c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2855702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2856c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = PAGE_SIZE -
2857c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(int)(pfield_buffer->pto -
2858702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							pfield_buffer->pgo);
2859702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2860c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much > more)
2861c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						much = more;
2862c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					memcpy(pfield_buffer->pto, pu, much);
2863c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pu += much;
2864c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(pfield_buffer->pto) += much;
2865c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					more -= much;
2866c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2867702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2868702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2869702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2870702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2871702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2872702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2873702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2874702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2875702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2876702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2877702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2878702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2879c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2880c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("easycap driver shutting down on condition green\n");
2881c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->status = 1;
2882c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->video_eof = 1;
2883c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->video_junk = 0;
2884c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		wake_up_interruptible(&peasycap->wq_video);
2885f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas#if !defined(PERSEVERE)
2886c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->audio_eof = 1;
2887c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		wake_up_interruptible(&peasycap->wq_audio);
2888f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas#endif /*PERSEVERE*/
2889c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2890702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2891c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_isoc_streaming) {
2892c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		rc = usb_submit_urb(purb, GFP_ATOMIC);
2893c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (rc) {
2894c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("%s: %d\n", strerror(rc), rc);
2895c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (-ENODEV != rc)
2896c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: while %i=video_idle, "
2897c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"usb_submit_urb() "
2898c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"failed with rc:\n",
2899c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_idle);
2900c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2901c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2902c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
2903702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2904d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct file_operations easycap_fops = {
2905d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.owner		= THIS_MODULE,
2906d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.open		= easycap_open,
2907f2b3c685b9b1c048cfa8bef98dac037275b9d20dTomas Winkler	.unlocked_ioctl	= easycap_unlocked_ioctl,
2908d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.poll		= easycap_poll,
2909d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.mmap		= easycap_mmap,
2910d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.llseek		= no_llseek,
2911d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
2912d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct usb_class_driver easycap_class = {
2913d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.name = "usb/easycap%d",
2914d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.fops = &easycap_fops,
2915d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.minor_base = USB_SKEL_MINOR_BASE,
2916d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
2917d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2918d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct v4l2_file_operations v4l2_fops = {
2919d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.owner		= THIS_MODULE,
2920d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.open		= easycap_open_noinode,
2921f2b3c685b9b1c048cfa8bef98dac037275b9d20dTomas Winkler	.unlocked_ioctl	= easycap_unlocked_ioctl,
2922d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.poll		= easycap_poll,
2923d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.mmap		= easycap_mmap,
2924d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
2925702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2926702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2927702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2928a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
2929a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  TIMES, ONCE FOR EACH OF THE THREE INTERFACES.  BEWARE.
2930702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2931702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
293211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winklerstatic int easycap_usb_probe(struct usb_interface *intf,
293311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			    const struct usb_device_id *id)
2934702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
293511ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_device *usbdev;
293611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_host_interface *alt;
293711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_endpoint_descriptor *ep;
293811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_interface_descriptor *interface;
29397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct urb *purb;
29407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap *peasycap;
29417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int ndong;
29427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct data_urb *pdata_urb;
29431d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler	int i, j, k, m, rc;
29447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceNumber;
29457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceClass;
29467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceSubClass;
29477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	void *pbuf;
29487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okalt[8], isokalt;
29497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okepn[8];
29507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okmps[8];
29517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int maxpacketsize;
29527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u16 mask;
29537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	s32 value;
29547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap_format *peasycap_format;
2955b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler	int fmtidx;
2956b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler	struct inputset *inputset;
2957702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
295811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	usbdev = interface_to_usbdev(intf);
2959ee99aa4928129d4aad9087988db6b7815ecdc1d5Tomas Winkler
2960702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
296111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	alt = usb_altnum_to_altsetting(intf, 0);
296211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	if (!alt) {
296311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		SAY("ERROR: usb_host_interface not found\n");
29647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return -EFAULT;
29657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
296611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	interface = &alt->desc;
296711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	if (!interface) {
296811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		SAY("ERROR: intf_descriptor is NULL\n");
29697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return -EFAULT;
29707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
2971702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2972702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2973702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  GET PROPERTIES OF PROBED INTERFACE
2974702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2975702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
297611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceNumber = interface->bInterfaceNumber;
297711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceClass = interface->bInterfaceClass;
297811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceSubClass = interface->bInterfaceSubClass;
29797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
2980e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: num_altsetting=%i\n",
298111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			bInterfaceNumber, intf->num_altsetting);
2982e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
2983e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		bInterfaceNumber,
298411ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		(long int)(intf->cur_altsetting - intf->altsetting));
2985e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
2986e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
2987702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2988702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2989702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
2990702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap.  THIS
2991e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
2992e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  PHYSICALLY UNPLUGGED.
2993e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *
2994e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
2995e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  INTERFACES 1 AND 2 ARE PROBED.
2996e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
2997702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
29987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if (0 == bInterfaceNumber) {
29997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
30006888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
30017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: Could not allocate peasycap\n");
30027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOMEM;
30037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3004702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3005702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3006e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  PERFORM URGENT INTIALIZATIONS ...
3007e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
3008702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
30097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->minor = -1;
30107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		kref_init(&peasycap->kref);
30117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(8, "intf[%i]: after kref_init(..._video) "
30127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				"%i=peasycap->kref.refcount.counter\n",
30137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				bInterfaceNumber, peasycap->kref.refcount.counter);
3014702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
30157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		/* module params */
30167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
30172a9a05c43294d703e351753da49231c47e0aad0dTomas Winkler
30187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_video);
30197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_audio);
30207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_trigger);
3021e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
30227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (mutex_lock_interruptible(&mutex_dongle)) {
3023dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler			SAY("ERROR: cannot down mutex_dongle\n");
30247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ERESTARTSYS;
30257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
3026a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas/*---------------------------------------------------------------------------*/
3027a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		/*
3028a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *  FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3029a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *  TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3030a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *
3031a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *  NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3032a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *  PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3033a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		 *  EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3034a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		*/
3035a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas/*---------------------------------------------------------------------------*/
30367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
30376888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if ((!easycapdc60_dongle[ndong].peasycap) &&
30387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						(!mutex_is_locked(&easycapdc60_dongle
30397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							[ndong].mutex_video)) &&
30407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						(!mutex_is_locked(&easycapdc60_dongle
30417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							[ndong].mutex_audio))) {
30427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					easycapdc60_dongle[ndong].peasycap = peasycap;
30437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->isdongle = ndong;
30447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					JOM(8, "intf[%i]: peasycap-->easycap"
30457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							"_dongle[%i].peasycap\n",
30467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							bInterfaceNumber, ndong);
30477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					break;
30487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				}
30497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
30507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (DONGLE_MANY <= ndong) {
30517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: too many dongles\n");
30527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				mutex_unlock(&mutex_dongle);
30537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3054ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas			}
3055a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas			mutex_unlock(&mutex_dongle);
3056a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		}
30577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_video_struct = sizeof(struct easycap);
30587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_video_page = 0;
30597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_video_urb = 0;
30607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_audio_struct = 0;
30617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_audio_page = 0;
30627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_audio_urb = 0;
3063e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
3064e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
3065e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*
3066e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  ... AND FURTHER INITIALIZE THE STRUCTURE
3067e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
3068e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
306911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		peasycap->pusb_device = usbdev;
307011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		peasycap->pusb_interface = intf;
3071702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
30727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->ilk = 0;
30737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->microphone = false;
3074702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
30757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_interface = -1;
30767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_altsetting_on = -1;
30777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_altsetting_off = -1;
30787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_endpointnumber = -1;
30797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_maxframesize = -1;
30807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_buffer_size = -1;
3081702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
30827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_interface = -1;
30837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_altsetting_on = -1;
30847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_altsetting_off = -1;
30857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_endpointnumber = -1;
30867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_maxframesize = -1;
30877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_buffer_size = -1;
3088702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
30897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3090e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
30917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0; k < INPUT_MANY; k++)
30927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->lost[k] = 0;
30937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->skip = 0;
30947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->skipped = 0;
30957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->offerfields = 0;
3096702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3097702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3098f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3099702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3100702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
31017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		rc = fillin_formats();
31027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 > rc) {
3103c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: fillin_formats() rc = %i\n", rc);
31047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
31057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
31067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i formats available\n", rc);
3107f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
3108f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
3109f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  ... AND POPULATE easycap.inputset[]
3110f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
3111f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
3112b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		/* FIXME: maybe we just use memset 0 */
3113b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		inputset = peasycap->inputset;
31147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0; k < INPUT_MANY; k++) {
3115b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].input_ok = 0;
3116b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].standard_offset_ok = 0;
3117b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].format_offset_ok = 0;
3118b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].brightness_ok = 0;
3119b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].contrast_ok = 0;
3120b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].saturation_ok = 0;
3121b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].hue_ok = 0;
31227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3123b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler
3124b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3125b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		m = 0;
3126b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		mask = 0;
3127b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3128b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3129b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				m++;
3130b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3131b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].standard_offset = i;
3132b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler
31337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				mask = easycap_standard[i].mask;
3134f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
3135f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
31367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
31377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (1 != m) {
3138b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: "
3139b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    "inputset->standard_offset unpopulated, %i=m\n", m);
31407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
31417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
31427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
31437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap_format = &easycap_format[0];
3144f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		m = 0;
3145b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3146b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			struct v4l2_pix_format *pix =
3147b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				&peasycap_format->v4l2_format.fmt.pix;
31487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3149b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->field == V4L2_FIELD_NONE &&
3150b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3151b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->width  == 640 && pix->height == 480) {
3152f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				m++;
31537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3154b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].format_offset = i;
31557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				break;
3156f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
3157e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap_format++;
3158f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
31597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (1 != m) {
3160b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: inputset[]->format_offset unpopulated\n");
3161e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			return -ENOENT;
3162f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
3163f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
31647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		m = 0;
3165b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
31667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			value = easycap_control[i].default_value;
31677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
31687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
31697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3170b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].brightness = value;
31717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
31727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
31737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3174b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].contrast = value;
31757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
31767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
31777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3178b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].saturation = value;
31797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_HUE == easycap_control[i].id) {
31807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
31817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3182b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].hue = value;
31837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3184f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
3185e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
31867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (4 != m) {
3187b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: inputset[]->brightness underpopulated\n");
31887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
31897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
31907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0; k < INPUT_MANY; k++)
3191b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].input = k;
3192b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		JOM(4, "populated inputset[]\n");
31937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "finished initialization\n");
31947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	} else {
3195702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3196a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas/*
3197a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *                                 FIXME
3198a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *
3199a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3200a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3201a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas */
3202e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
32037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
320411ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (usbdev == easycapdc60_dongle[ndong].peasycap->
32057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									pusb_device) {
32067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap = easycapdc60_dongle[ndong].peasycap;
3207c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3208c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						bInterfaceNumber, ndong);
32097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				break;
32107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
32117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
32127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (DONGLE_MANY <= ndong) {
32137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: peasycap is unknown when probing interface %i\n",
32147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								bInterfaceNumber);
32157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
32167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
32176888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
32187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: peasycap is NULL when probing interface %i\n",
32197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								bInterfaceNumber);
32207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
3221a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		}
3222dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
3223702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
32247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3225dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	    (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
32267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_interface) {
32277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_interface = bInterfaceNumber;
32287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "setting peasycap->video_interface=%i\n",
32297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->video_interface);
32307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
32317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (peasycap->video_interface != bInterfaceNumber) {
32327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: attempting to reset "
32337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"peasycap->video_interface\n");
32347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... continuing with "
32357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"%i=peasycap->video_interface\n",
3236702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						peasycap->video_interface);
32377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3238702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
32397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	} else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3240fc3cc2caa07568de92cc84780b89b5cf9fbf28b7Tomas Winkler		   (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
32417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_interface) {
32427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_interface = bInterfaceNumber;
32437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "setting peasycap->audio_interface=%i\n",
32447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							 peasycap->audio_interface);
32457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
32467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (peasycap->audio_interface != bInterfaceNumber) {
32477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: attempting to reset "
32487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"peasycap->audio_interface\n");
32497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... continuing with "
32507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"%i=peasycap->audio_interface\n",
32517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_interface);
32527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3253702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3254702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
3255702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3256702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3257702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INVESTIGATE ALL ALTSETTINGS.
3258702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3259702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3260702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
32617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	isokalt = 0;
3262702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
326311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	for (i = 0; i < intf->num_altsetting; i++) {
326411ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		alt = usb_altnum_to_altsetting(intf, i);
326511ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (!alt) {
326611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			SAM("ERROR: alt is NULL\n");
32677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
3268702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
326911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		interface = &alt->desc;
327011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (!interface) {
327111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			SAM("ERROR: intf_descriptor is NULL\n");
32727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
3273702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
32747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
327511ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (0 == interface->bNumEndpoints)
3276e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3277e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler						bInterfaceNumber, i);
32787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler/*---------------------------------------------------------------------------*/
327911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		for (j = 0; j < interface->bNumEndpoints; j++) {
328011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			ep = &alt->endpoint[j].desc;
328111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (!ep) {
328211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler				SAM("ERROR:  ep is NULL.\n");
32837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... skipping\n");
32847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				continue;
32857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
32861d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler
32871d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			if (!usb_endpoint_is_isoc_in(ep)) {
32881d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
32891d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bInterfaceNumber,
32901d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						i, j, ep->bmAttributes);
32911d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (usb_endpoint_dir_out(ep)) {
32921d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("ERROR: OUT endpoint unexpected\n");
32931d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("...... continuing\n");
32941d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
32951d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				continue;
32967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
32971d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			switch (bInterfaceClass) {
32981d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_VIDEO:
32991d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_VENDOR_SPEC: {
33001d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (ep->wMaxPacketSize) {
33011d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (8 > isokalt) {
33021d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt] = i;
33031d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33041d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okalt[%i]\n",
33051d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt],
33061d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33071d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt] =
33081d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						ep->
33091d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bEndpointAddress &
33101d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						0x0F;
33111d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33121d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okepn[%i]\n",
33131d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt],
33141d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33151d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt] =
33161d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						le16_to_cpu(ep->
33171d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						wMaxPacketSize);
33181d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33191d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okmps[%i]\n",
33201d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt],
33211d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33221d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt++;
3323702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
33241d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				} else {
33251d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (-1 == peasycap->
33261d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off) {
33271d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
33281d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off =
33291d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler								 i;
33301d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4, "%i=video_"
33311d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off "
33321d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler							"<====\n",
33331d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
33341d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off);
33351d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					} else {
33361d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("ERROR: peasycap"
33371d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"->video_altsetting_"
33381d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off already set\n");
33391d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("...... "
33401d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"continuing with "
33411d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=peasycap->video_"
33421d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off\n",
33431d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
33441d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off);
33451d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					}
33461d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
33471d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				break;
33481d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			}
33491d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_AUDIO: {
33501d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (bInterfaceSubClass !=
33511d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				    USB_SUBCLASS_AUDIOSTREAMING)
3352702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					break;
33531d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (!peasycap) {
33541d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("MISTAKE: "
33551d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					"peasycap is NULL\n");
33561d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					return -EFAULT;
33571d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
33581d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (ep->wMaxPacketSize) {
33591d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (8 > isokalt) {
33601d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt] = i ;
33611d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33621d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okalt[%i]\n",
33631d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt],
33641d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33651d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt] =
33661d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						ep->
33671d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bEndpointAddress &
33681d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						0x0F;
33691d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33701d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okepn[%i]\n",
33711d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt],
33721d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33731d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt] =
33741d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						le16_to_cpu(ep->
33751d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						wMaxPacketSize);
33761d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
33771d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okmps[%i]\n",
33781d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt],
33791d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
33801d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt++;
33817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
33821d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				} else {
33831d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (-1 == peasycap->
33841d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off) {
33851d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
33861d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off =
33871d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler								 i;
33881d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4, "%i=audio_"
33891d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off "
33901d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"<====\n",
33911d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
33921d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off);
33931d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					} else {
33941d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("ERROR: peasycap"
33951d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"->audio_altsetting_"
33961d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off already set\n");
33971d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("...... "
33981d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"continuing with "
33991d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=peasycap->"
34001d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"audio_altsetting_"
34011d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off\n",
34021d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
34031d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off);
34047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
3405702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
34061d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			break;
34071d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			}
34081d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			default:
34091d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				break;
34107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
341111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (0 == ep->wMaxPacketSize) {
34127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "intf[%i]alt[%i]end[%i] "
34137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							"has zero packet size\n",
34147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							bInterfaceNumber, i, j);
3415702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
3416702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3417702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
3418702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3419702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3420702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PERFORM INITIALIZATION OF THE PROBED INTERFACE
3421702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3422702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
34237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOM(4, "initialization begins for interface %i\n",
342411ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		interface->bInterfaceNumber);
34257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	switch (bInterfaceNumber) {
3426702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3427702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3428702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INTERFACE 0 IS THE VIDEO INTERFACE
3429702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3430702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
34317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 0: {
34327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
34337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
34347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!isokalt) {
34377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  no viable video_altsetting_on\n");
34387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
34397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
34407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_altsetting_on = okalt[isokalt - 1];
34417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "%i=video_altsetting_on <====\n",
34427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_altsetting_on);
34437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3444702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3445702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3446702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DECIDE THE VIDEO STREAMING PARAMETERS
3447702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3448702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
34497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_endpointnumber = okepn[isokalt - 1];
34507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
34517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		maxpacketsize = okmps[isokalt - 1];
3452e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
3453e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		peasycap->video_isoc_maxframesize =
3454e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler				min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
34557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->video_isoc_maxframesize) {
34567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad video_isoc_maxframesize\n");
34577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("        possibly because port is USB 1.1\n");
34587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
34597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3460e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		JOM(4, "%i=video_isoc_maxframesize\n",
3461e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler					peasycap->video_isoc_maxframesize);
3462e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
34637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
34647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_isoc_framesperdesc\n",
34657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_framesperdesc);
34667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->video_isoc_framesperdesc) {
34677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad video_isoc_framesperdesc\n");
34687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
34697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_buffer_size =
34717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_maxframesize *
34727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_framesperdesc;
34737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_isoc_buffer_size\n",
34747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_buffer_size);
34757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
34767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_buffer_size) {
34777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
34787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3480702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
34817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_interface) {
34827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_interface is unset\n");
34837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_altsetting_on) {
34867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_altsetting_on is unset\n");
34877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_altsetting_off) {
34907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_interface_off is unset\n");
34917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_endpointnumber) {
34947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_endpointnumber is unset\n");
34957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
34967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_isoc_maxframesize) {
34987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
34997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
35007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
35017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_isoc_buffer_size) {
35027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
35037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
35047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3505702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3506702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3507702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALLOCATE MEMORY FOR VIDEO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
3508702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3509702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
35107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		INIT_LIST_HEAD(&(peasycap->urb_video_head));
35117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->purb_video_head = &(peasycap->urb_video_head);
35127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler/*---------------------------------------------------------------------------*/
35137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i frame buffers of size %li\n",
35147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
35157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each scattered over %li pages\n",
35167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							FRAME_BUFFER_SIZE/PAGE_SIZE);
35177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
35187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
35197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
35206888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (peasycap->frame_buffer[k][m].pgo)
35217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					SAM("attempting to reallocate frame "
35227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									" buffers\n");
35237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				else {
35247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					pbuf = (void *)__get_free_page(GFP_KERNEL);
35256888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (!pbuf) {
35267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						SAM("ERROR: Could not allocate frame "
35277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							"buffer %i page %i\n", k, m);
35287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						return -ENOMEM;
35297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					} else
35307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->allocation_video_page += 1;
35317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->frame_buffer[k][m].pgo = pbuf;
35327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				}
35337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->frame_buffer[k][m].pto =
35347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->frame_buffer[k][m].pgo;
3535702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
3536702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3537702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
35387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_fill = 0;
35397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_read = 0;
35407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of frame buffers done:  %i pages\n", k *
35417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									m);
35427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler/*---------------------------------------------------------------------------*/
35437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i field buffers of size %li\n",
35447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
35457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each scattered over %li pages\n",
35467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						FIELD_BUFFER_SIZE/PAGE_SIZE);
35477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
35487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
35497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
35506888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (peasycap->field_buffer[k][m].pgo) {
35517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					SAM("ERROR: attempting to reallocate "
35527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"field buffers\n");
35537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				} else {
35547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					pbuf = (void *) __get_free_page(GFP_KERNEL);
35556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (!pbuf) {
35567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						SAM("ERROR: Could not allocate field"
35577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							" buffer %i page %i\n", k, m);
35587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						return -ENOMEM;
35597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						}
35607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					else
35617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->allocation_video_page += 1;
35627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->field_buffer[k][m].pgo = pbuf;
3563702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
35647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->field_buffer[k][m].pto =
35657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->field_buffer[k][m].pgo;
35667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
35677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->field_buffer[k][0].kount = 0x0200;
3568702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
35697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_fill = 0;
35707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_page = 0;
35717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_read = 0;
35727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of field buffers done:  %i pages\n", k *
35737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									m);
35747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler/*---------------------------------------------------------------------------*/
35757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i isoc video buffers of size %i\n",
35767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						VIDEO_ISOC_BUFFER_MANY,
35777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
35787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each occupying contiguous memory pages\n");
35797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
35807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
3581a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			pbuf = (void *)__get_free_pages(GFP_KERNEL,
3582a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							VIDEO_ISOC_ORDER);
35836888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pbuf) {
35847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate isoc video buffer "
35857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									"%i\n", k);
35867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
35877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else
35887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->allocation_video_page +=
3589a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					BIT(VIDEO_ISOC_ORDER);
3590702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
35917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_isoc_buffer[k].pgo = pbuf;
3592a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->video_isoc_buffer[k].pto =
3593a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				pbuf + peasycap->video_isoc_buffer_size;
35947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_isoc_buffer[k].kount = k;
35957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
35967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of isoc video buffers done: %i pages\n",
35977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						k * (0x01 << VIDEO_ISOC_ORDER));
3598702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3599702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3600702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3601702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3602702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
36037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
36047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
36057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
36067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
36077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
36087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
36097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
36107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
36117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
36127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
36137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									GFP_KERNEL);
36146888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!purb) {
36157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
36167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									"%i\n", k);
36177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
36187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else
36197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->allocation_video_urb += 1;
3620702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
36226888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb) {
36237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate struct data_urb.\n");
36247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
36257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else
36267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->allocation_video_struct +=
36277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							sizeof(struct data_urb);
3628702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
36297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->purb = purb;
36307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->isbuf = k;
36317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->length = 0;
36327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			list_add_tail(&(pdata_urb->list_head),
36337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->purb_video_head);
3634702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3635702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3636702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ... AND INITIALIZE THEM
3637702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3638702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
36397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (!k) {
36407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "initializing video urbs thus:\n");
36417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->interval = 1;\n");
36427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
36437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->pipe = usb_rcvisocpipe"
36447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"(peasycap->pusb_device,%i);\n",
36457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_endpointnumber);
36467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
36477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer = peasycap->"
36487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"video_isoc_buffer[.].pgo;\n");
36497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer_length = %i;\n",
36507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
36517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->complete = easycap_complete;\n");
36527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->context = peasycap;\n");
36537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->start_frame = 0;\n");
36547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->number_of_packets = %i;\n",
36557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
36567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  for (j = 0; j < %i; j++)\n",
36577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
36587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    {\n");
36597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
36607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
36617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
36627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
36637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    }\n");
36647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3665702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
36667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->interval = 1;
36677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->dev = peasycap->pusb_device;
36687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
36697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_endpointnumber);
36707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_flags = URB_ISO_ASAP;
36717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
36727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer_length =
36737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size;
36747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->complete = easycap_complete;
36757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->context = peasycap;
36767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->start_frame = 0;
36777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->number_of_packets = peasycap->video_isoc_framesperdesc;
36787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
36797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].offset = j *
36807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize;
36817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].length =
36827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize;
36837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3684702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
36857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of %i struct urb done.\n", k);
3686702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3687702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3688702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SAVE POINTER peasycap IN THIS INTERFACE.
3689702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3690702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
369111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
3692268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*---------------------------------------------------------------------------*/
3693268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*
3694268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3695268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3696268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3697268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  BEWARE.
3698268dfede46e24eef55a2ef7a10a462617936771eMike Thomas*/
3699268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*---------------------------------------------------------------------------*/
37008d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler		peasycap->ntsc = easycap_ntsc;
37018d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler		JOM(8, "defaulting initially to %s\n",
37028d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler			easycap_ntsc ? "NTSC" : "PAL");
37037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		rc = reset(peasycap);
37047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (rc) {
3705c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: reset() rc = %i\n", rc);
37067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
37077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3708702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3709702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3710702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3711702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3712702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3713cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler		if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
37147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("v4l2_device_register() failed\n");
37157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
37167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3717cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler		JOM(4, "registered device instance: %s\n",
3718cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler			peasycap->v4l2_device.name);
3719e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
3720e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*
3721a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *                                 FIXME
3722ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
3723ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
3724e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3725e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
3726e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
37277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.v4l2_dev = NULL;
3728e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
3729702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
3730e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
37317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		strcpy(&peasycap->video_device.name[0], "easycapdc60");
37327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.fops = &v4l2_fops;
37337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.minor = -1;
37347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.release = (void *)(&videodev_release);
3735702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3737702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 != (video_register_device(&(peasycap->video_device),
37397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							VFL_TYPE_GRABBER, -1))) {
37407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			err("Not able to register with videodev");
37417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			videodev_release(&(peasycap->video_device));
37427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
37437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
37447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			(peasycap->registered_video)++;
37457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("registered with videodev: %i=minor\n",
37467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->video_device.minor);
37477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->minor = peasycap->video_device.minor;
37487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3749e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3750a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
37517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3752dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
3753702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3754702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3755702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3756702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3757702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3758702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
37597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 1: {
37607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
37617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
37627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
37637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3764702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3765702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3766702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SAVE POINTER peasycap IN INTERFACE 1
3767702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3768702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
376911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
37707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "no initialization required for interface %i\n",
377111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler					interface->bInterfaceNumber);
37727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3773702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
3774c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*--------------------------------------------------------------------------*/
37757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 2: {
37767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
37777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
37787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
37797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
37807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!isokalt) {
37817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  no viable audio_altsetting_on\n");
37827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
37837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
37847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_altsetting_on = okalt[isokalt - 1];
37857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "%i=audio_altsetting_on <====\n",
37867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->audio_altsetting_on);
37877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3788e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
37897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_endpointnumber = okepn[isokalt - 1];
37907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3791e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
37927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
37937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_maxframesize\n",
37947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize);
37957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->audio_isoc_maxframesize) {
37967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad audio_isoc_maxframesize\n");
37977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
37987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
37997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (9 == peasycap->audio_isoc_maxframesize) {
38007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->ilk |= 0x02;
38017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("audio hardware is microphone\n");
38027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->microphone = true;
3803a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_pages_per_fragment =
3804a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					PAGES_PER_AUDIO_FRAGMENT;
38057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else if (256 == peasycap->audio_isoc_maxframesize) {
38067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->ilk &= ~0x02;
38077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("audio hardware is AC'97\n");
38087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->microphone = false;
3809a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_pages_per_fragment =
3810a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					PAGES_PER_AUDIO_FRAGMENT;
38117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
38127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("hardware is unidentified:\n");
38137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("%i=audio_isoc_maxframesize\n",
3814a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_isoc_maxframesize);
38157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
38167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3817702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_bytes_per_fragment =
3819a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_pages_per_fragment * PAGE_SIZE;
38207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3821a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_pages_per_fragment);
38227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
38237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
38247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_pages_per_fragment\n",
38257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_pages_per_fragment);
38267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_bytes_per_fragment\n",
38277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_bytes_per_fragment);
38287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_buffer_page_many\n",
38297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_buffer_page_many);
38307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
38317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
38327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
38337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_framesperdesc\n",
38347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
38357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->audio_isoc_framesperdesc) {
38367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad audio_isoc_framesperdesc\n");
38377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
38387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3839702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_buffer_size =
38417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->audio_isoc_maxframesize *
38427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->audio_isoc_framesperdesc;
38437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_buffer_size\n",
38447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_buffer_size);
38457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
38467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("MISTAKE:  audio_isoc_buffer_size bigger "
38477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				"than %li=AUDIO_ISOC_BUFFER_SIZE\n",
38487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							AUDIO_ISOC_BUFFER_SIZE);
38497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_interface) {
38527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_interface is unset\n");
38537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_altsetting_on) {
38567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_altsetting_on is unset\n");
38577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_altsetting_off) {
38607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_interface_off is unset\n");
38617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_endpointnumber) {
38647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_endpointnumber is unset\n");
38657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_isoc_maxframesize) {
38687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
38697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
38717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_isoc_buffer_size) {
38727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
38737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
38747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3875702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3876702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3877702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALLOCATE MEMORY FOR AUDIO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
3878702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3879702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
38807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		INIT_LIST_HEAD(&(peasycap->urb_audio_head));
38817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3882702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
3883702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
38847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i isoc audio buffers of size %i\n",
3885a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			AUDIO_ISOC_BUFFER_MANY,
3886a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_isoc_buffer_size);
38877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each occupying contiguous memory pages\n");
3888702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
3890a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			pbuf = (void *)__get_free_pages(GFP_KERNEL,
3891a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							AUDIO_ISOC_ORDER);
38926888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pbuf) {
38937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate isoc audio buffer "
38947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"%i\n", k);
38957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
38967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else
38977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->allocation_audio_page +=
3898a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						BIT(AUDIO_ISOC_ORDER);
3899702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
39007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].pgo = pbuf;
39017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].pto = pbuf +
39027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer_size;
39037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].kount = k;
39047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
39057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of isoc audio buffers done.\n");
3906702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3907702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3908702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3909702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3910702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
39117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
39127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
3913a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_framesperdesc);
39147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
3915a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
39167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
3917a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_buffer_size);
39187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
39197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
39207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
3921a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler								GFP_KERNEL);
39226888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!purb) {
39237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
39247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"%i\n", k);
39257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3926e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			}
3927e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap->allocation_audio_urb += 1 ;
3928702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
39297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
39306888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb) {
39317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate struct data_urb.\n");
39327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3933e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			}
3934e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap->allocation_audio_struct +=
3935e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler						sizeof(struct data_urb);
3936702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
39377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->purb = purb;
39387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->isbuf = k;
39397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->length = 0;
39407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			list_add_tail(&(pdata_urb->list_head),
39417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->purb_audio_head);
3942702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3943702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3944702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ... AND INITIALIZE THEM
3945702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3946702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
39477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (!k) {
39487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "initializing audio urbs thus:\n");
39497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->interval = 1;\n");
39507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
39517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->"
39527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"pusb_device,%i);\n",
39537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_endpointnumber);
39547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
39557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer = "
39567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					"peasycap->audio_isoc_buffer[.].pgo;\n");
39577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer_length = %i;\n",
3958a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_buffer_size);
39597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->complete = easycap_alsa_complete;\n");
39607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->context = peasycap;\n");
39617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->start_frame = 0;\n");
39627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->number_of_packets = %i;\n",
39637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
39647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  for (j = 0; j < %i; j++)\n",
39657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
39667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    {\n");
39677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
3968a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
39697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
3970a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
39717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    }\n");
3972dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler			}
3973702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
39747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->interval = 1;
39757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->dev = peasycap->pusb_device;
39767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
39777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_endpointnumber);
39787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_flags = URB_ISO_ASAP;
39797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
39807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer_length =
39817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_buffer_size;
39827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->complete = easycap_alsa_complete;
39837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->context = peasycap;
39847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->start_frame = 0;
39857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
39867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
39877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].offset = j *
39887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize;
39897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].length =
39907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize;
39917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3992702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
39937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of %i struct urb done.\n", k);
3994702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3995702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3996702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SAVE POINTER peasycap IN THIS INTERFACE.
3997702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3998702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
399911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
4000702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4001702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4002702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4003702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4004702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
40057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "initializing ALSA card\n");
4006a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
40077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		rc = easycap_alsa_probe(peasycap);
40087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (rc) {
4009c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			err("easycap_alsa_probe() rc = %i\n", rc);
40107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
40117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
4012a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
4013a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
4014ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4015ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler				peasycap->kref.refcount.counter);
4016ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		kref_get(&peasycap->kref);
4017ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		peasycap->registered_audio++;
40187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
4019dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
4020702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4021702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4022702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4023702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4024702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4025dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	default:
4026dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler		JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4027dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler		return -EINVAL;
40287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
4029e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	SAM("ends successfully for interface %i\n", bInterfaceNumber);
40307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	return 0;
4031702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4032702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4033702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4034702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4035ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4036ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  UNPLUGGED.  HENCE peasycap->pusb_device IS NO LONGER VALID.
4037a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *
403873019286cddc8bba1773944a7b6b603137fd66ffTomas Winkler *  THIS FUNCTION AFFECTS ALSA.  BEWARE.
4039702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4040702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4041d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4042702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
40437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct usb_host_interface *pusb_host_interface;
40447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct usb_interface_descriptor *pusb_interface_descriptor;
40457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceNumber;
40467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap *peasycap;
40477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
40487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct list_head *plist_head;
40497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct data_urb *pdata_urb;
40507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int minor, m, kd;
4051702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
40527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOT(4, "\n");
4053702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
40547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	pusb_host_interface = pusb_interface->cur_altsetting;
40556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pusb_host_interface) {
40567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOT(4, "ERROR: pusb_host_interface is NULL\n");
40577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
40587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
40597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	pusb_interface_descriptor = &(pusb_host_interface->desc);
40606888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pusb_interface_descriptor) {
40617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
40627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
40637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
40647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
40657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	minor = pusb_interface->minor;
40667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4067702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
40687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if (1 == bInterfaceNumber)
40697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
4070e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
40717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap = usb_get_intfdata(pusb_interface);
40726888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
40737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
40747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
40757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
4076e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
4077268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*
4078e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE.  BEWARE.
4079e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
4080e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
40817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap->video_eof = 1;
40827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap->audio_eof = 1;
40837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	wake_up_interruptible(&(peasycap->wq_video));
40847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	wake_up_interruptible(&(peasycap->wq_audio));
40857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler/*---------------------------------------------------------------------------*/
40867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	switch (bInterfaceNumber) {
40877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 0: {
40886888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (peasycap->purb_video_head) {
40897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "killing video urbs\n");
40907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			m = 0;
4091a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			list_for_each(plist_head, peasycap->purb_video_head) {
40927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				pdata_urb = list_entry(plist_head,
40937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						struct data_urb, list_head);
40946888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (pdata_urb) {
40956888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (pdata_urb->purb) {
40967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						usb_kill_urb(pdata_urb->purb);
40977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						m++;
40987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
4099702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
4100702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
41017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "%i video urbs killed\n", m);
4102e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas		}
41037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
4104702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
4105702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
41067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 2: {
41076888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (peasycap->purb_audio_head) {
41087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "killing audio urbs\n");
41097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			m = 0;
4110a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			list_for_each(plist_head, peasycap->purb_audio_head) {
41117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				pdata_urb = list_entry(plist_head,
41127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						struct data_urb, list_head);
41136888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (pdata_urb) {
41146888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (pdata_urb->purb) {
41157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						usb_kill_urb(pdata_urb->purb);
41167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						m++;
41177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
4118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
4119702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
41207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "%i audio urbs killed\n", m);
4121e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas		}
41227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
4123702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
41247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	default:
41257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
4126c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4127702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
4128702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4129702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DEREGISTER
4130ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
4131ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4132ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IOCTL ARE ALL UNLOCKED.  IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4133ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING.  BEWARE.
4134702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4135702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
4136c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kd = isdongle(peasycap);
4137c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	switch (bInterfaceNumber) {
4138c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 0: {
4139c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
4140c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			wake_up_interruptible(&peasycap->wq_video);
4141c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4142c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4143ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas								mutex_video)) {
4144c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAY("ERROR: "
4145c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				    "cannot lock dongle[%i].mutex_video\n", kd);
4146c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return;
4147c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
4148c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked dongle[%i].mutex_video\n", kd);
4149c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
4150c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4151ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		}
4152ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas/*---------------------------------------------------------------------------*/
4153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (!peasycap->v4l2_device.name[0]) {
4154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4155c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 <= kd && DONGLE_MANY > kd)
4156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4157c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
4158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4159c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v4l2_device_disconnect(&peasycap->v4l2_device);
4160c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "v4l2_device_disconnect() OK\n");
4161c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v4l2_device_unregister(&peasycap->v4l2_device);
4162c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "v4l2_device_unregister() OK\n");
4163c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
4164c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		video_unregister_device(&peasycap->video_device);
4165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				bInterfaceNumber, minor);
4167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->registered_video--;
4168268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4169268dfede46e24eef55a2ef7a10a462617936771eMike Thomas
4170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
4171c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
4175ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
4176c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 2: {
4177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
4178c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			wake_up_interruptible(&peasycap->wq_audio);
4179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4181ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas								mutex_audio)) {
4182c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAY("ERROR: "
4183c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				    "cannot lock dongle[%i].mutex_audio\n", kd);
4184c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return;
4185c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
4186c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4187c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else
4188c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4189c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != snd_card_free(peasycap->psnd_card)) {
4190c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: snd_card_free() failed\n");
4191c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
4192c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->psnd_card = NULL;
4193c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			(peasycap->registered_audio)--;
4194c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4195c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
4196c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4197c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4198c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4199c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
4200c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4201c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	default:
4202c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
4203ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
4204702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4205702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4206702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4207a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  (ALSO WHEN ALSA HAS BEEN IN USE)
4208702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4209702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4210c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->kref.refcount.counter) {
4211c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->kref.refcount.counter is zero "
4212c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"so cannot call kref_put()\n");
4213ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		SAM("ending unsuccessfully: may cause memory leak\n");
4214ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		return;
4215ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
4216c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
4217c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4218c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4219c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4220c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ending unsuccessfully: may cause memory leak\n");
4221c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
4222c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4223c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_video\n", kd);
4224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4225c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4226c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4227c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4228c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4229c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ending unsuccessfully: may cause memory leak\n");
4230c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
4231c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4232c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4233c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4234c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4235c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4236c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kref_put(&peasycap->kref, easycap_delete);
4237c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
4239c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4240c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4241c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4242c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4243c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4244702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4245c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "ends\n");
4246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
4247702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4248702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4249a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
4250702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4251702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4252d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler *  PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4253702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4254702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4255d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic struct usb_device_id easycap_usb_device_id_table[] = {
4256d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	{USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4257d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	{ }
4258d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
4259d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4260d090bf57492bde9cb6281246c92963476c40b512Tomas WinklerMODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4261d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstruct usb_driver easycap_usb_driver = {
4262d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.name = "easycap",
4263d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.id_table = easycap_usb_device_id_table,
4264d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.probe = easycap_usb_probe,
4265d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.disconnect = easycap_usb_disconnect,
4266d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
4267702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4268d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int __init easycap_module_init(void)
4269d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
4270d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	int k, rc;
4271d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4272aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler	printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4273aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler
4274d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	JOT(4, "begins.  %i=debug %i=bars %i=gain\n",
4275d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		easycap_debug, easycap_bars, easycap_gain);
4276d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4277d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	mutex_init(&mutex_dongle);
4278d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	for (k = 0; k < DONGLE_MANY; k++) {
42793c1fb66ede917d54079a959a95f79777e95920bdTomas Winkler		easycapdc60_dongle[k].peasycap = NULL;
4280d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		mutex_init(&easycapdc60_dongle[k].mutex_video);
4281d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		mutex_init(&easycapdc60_dongle[k].mutex_audio);
4282d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	}
4283d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	rc = usb_register(&easycap_usb_driver);
42846911e7e4a6bed8ac7989137387f6a33ef65c2b56Tomas Winkler	if (rc)
4285aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler		printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4286d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4287d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return rc;
4288702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4289702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4290dbf4805ee6a850e941110b0df1e96049287ecf75Tomas Winklerstatic void __exit easycap_module_exit(void)
4291702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
4292d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	usb_deregister(&easycap_usb_driver);
4293702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4294702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4295702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4296702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasmodule_init(easycap_module_init);
4297702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasmodule_exit(easycap_module_exit);
4298702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4299702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4300