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);
61aa3e842d2c27acd3e73167eef5a347601639f2cbThomas PetazzoniMODULE_PARM_DESC(ntsc, "NTSC 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);
6998680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winklerstatic int field2frame(struct easycap *peasycap);
7098680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winklerstatic int redaub(struct easycap *peasycap,
7198680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winkler		void *pad, void *pex, int much, int more,
7298680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winkler		u8 mask, u8 margin, bool isuy);
73e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
745c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winklerconst char *strerror(int err)
755c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler{
765c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler#define ERRNOSTR(_e) case _e: return # _e
775c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	switch (err) {
785c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	case 0: return "OK";
795c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOMEM);
805c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENODEV);
815c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENXIO);
825c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EINVAL);
835c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EAGAIN);
845c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EFBIG);
855c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPIPE);
865c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EMSGSIZE);
875c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOSPC);
885c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EINPROGRESS);
895c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOSR);
905c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EOVERFLOW);
915c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPROTO);
925c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EILSEQ);
935c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ETIMEDOUT);
945c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EOPNOTSUPP);
955c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPFNOSUPPORT);
965c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EAFNOSUPPORT);
975c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EADDRINUSE);
985c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EADDRNOTAVAIL);
995c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOBUFS);
1005c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EISCONN);
1015c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOTCONN);
1025c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ESHUTDOWN);
1035c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ENOENT);
1045c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ECONNRESET);
1055c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ETIME);
1065c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(ECOMM);
1075c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EREMOTEIO);
1085c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EXDEV);
1095c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	ERRNOSTR(EPERM);
1105c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	default: return "unknown";
1115c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler	}
1125c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler
1135c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler#undef ERRNOSTR
1145c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler}
1155c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler
116702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/****************************************************************************/
117e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
119268dfede46e24eef55a2ef7a10a462617936771eMike Thomas *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
120e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
121e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
12296bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winklerint easycap_isdongle(struct easycap *peasycap)
123e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas{
124c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k;
1256888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap)
126c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -2;
127c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < DONGLE_MANY; k++) {
128c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (easycapdc60_dongle[k].peasycap == peasycap) {
129c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->isdongle = k;
130c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return k;
131c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
132e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas	}
133c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return -1;
134e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas}
135702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
136d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_open(struct inode *inode, struct file *file)
137702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
138c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct video_device *pvideo_device;
139c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
140c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc;
141702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
142c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "\n");
143c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("==========OPEN=========\n");
144702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
145c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pvideo_device = video_devdata(file);
1466888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvideo_device) {
147c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: pvideo_device is NULL.\n");
148c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
149c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
150c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
1516888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
152c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
157c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
159101dca425da49edb3093000d72490216fa322911Tomas Winkler
160101dca425da49edb3093000d72490216fa322911Tomas Winkler	JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
161101dca425da49edb3093000d72490216fa322911Tomas Winkler
162c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	file->private_data = peasycap;
16396bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	rc = easycap_wakeup_device(peasycap->pusb_device);
164101dca425da49edb3093000d72490216fa322911Tomas Winkler	if (rc) {
165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: wakeup_device() rc = %i\n", rc);
166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (-ENODEV == rc)
167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: wakeup_device() returned -ENODEV\n");
168c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		else
169c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: wakeup_device() rc = %i\n", rc);
170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return rc;
171c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
172101dca425da49edb3093000d72490216fa322911Tomas Winkler	JOM(8, "wakeup_device() OK\n");
173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = 0;
174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = reset(peasycap);
175c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
176c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: reset() rc = %i\n", rc);
177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
178c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
180f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas}
181d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
182f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*****************************************************************************/
183f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
184f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
185f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  RESET THE HARDWARE TO ITS REFERENCE STATE.
186f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
187f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
188f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  A BAD VIDEO FRAME SIZE.
189f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
190f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
191d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int reset(struct easycap *peasycap)
192f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas{
193c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap_standard const *peasycap_standard;
194fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	int fmtidx, input, rate;
195c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool ntsc, other;
196fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	int rc;
197f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
1986888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
199c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
200c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
201c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
202c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = peasycap->input;
203f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
204f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
205f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
206ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
207f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
208f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
209f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  A SWITCH BETWEEN PAL AND NTSC.
210f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
211f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
212f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
213f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
214f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
215c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	other = false;
216c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
217c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
218c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rate = ready_saa(peasycap->pusb_device);
219fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rate < 0) {
220c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
221fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		ntsc = !peasycap->ntsc;
222fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		JOM(8, "... trying  %s ..\n", ntsc ? "NTSC" : "PAL");
223fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rc = setup_stk(peasycap->pusb_device, ntsc);
224fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rc) {
225fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			SAM("ERROR: setup_stk() rc = %i\n", rc);
226fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			return -EFAULT;
227fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		}
228fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rc = setup_saa(peasycap->pusb_device, ntsc);
229fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rc) {
230fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			SAM("ERROR: setup_saa() rc = %i\n", rc);
231fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			return -EFAULT;
232fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		}
233fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler
234fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		rate = ready_saa(peasycap->pusb_device);
235fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler		if (rate < 0) {
236fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			JOM(8, "not ready to capture after %i ms\n", PATIENCE);
237fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			JOM(8, "... saa register 0x1F has 0x%02X\n",
238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					read_saa(peasycap->pusb_device, 0x1F));
239fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler			ntsc = peasycap->ntsc;
240c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
241c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "... success at second try:  %i=rate\n", rate);
242c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ntsc = (0 < (rate/2)) ? true : false ;
243c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			other = true;
244c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
245f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	} else {
246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "... success at first try:  %i=rate\n", rate);
247c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ntsc = (0 < rate/2) ? true : false ;
248c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
249c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "ntsc=%d\n", ntsc);
250c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
251c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
252c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = setup_stk(peasycap->pusb_device, ntsc);
253fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rc) {
254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: setup_stk() rc = %i\n", rc);
255c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
256c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = setup_saa(peasycap->pusb_device, ntsc);
258fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	if (rc) {
259c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: setup_saa() rc = %i\n", rc);
260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
261f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
262702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
263fd1b821c31f8a4588cc874721e3d17a47b460380Tomas Winkler	memset(peasycap->merit, 0, sizeof(peasycap->merit));
264c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
265c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_eof = 0;
266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_eof = 0;
267f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
268f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
269f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
270f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
271f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
272f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
273f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
274c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = -8192;
275c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->standard_offset = -8192;
276c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
277c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (other) {
278c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap_standard = &easycap_standard[0];
279c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		while (0xFFFF != peasycap_standard->mask) {
280c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (fmtidx == peasycap_standard->v4l2_standard.index) {
2811dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				peasycap->inputset[input].standard_offset =
282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap_standard - easycap_standard;
283f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				break;
284f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap_standard++;
286f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0xFFFF == peasycap_standard->mask) {
288c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: standard not found\n");
289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EINVAL;
290c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
291c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->inputset[input].standard_offset, input);
293f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->format_offset = -8192;
295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->brightness = -8192;
296c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->contrast = -8192;
297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->saturation = -8192;
298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->hue = -8192;
299f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
30096bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	rc = easycap_newinput(peasycap, input);
301702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
304c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
306f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	JOM(4, "restored input, standard and format\n");
307c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
308c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->input) {
311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
313c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
314c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->standard_offset) {
315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->standard_offset\n",
316c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->standard_offset);
317c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
319c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->format_offset) {
320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->format_offset\n",
321c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->format_offset);
322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
324c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->brightness) {
325c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->brightness\n",
326c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->brightness);
327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
328c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->contrast) {
330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
333c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->saturation) {
334c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->saturation\n",
335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->saturation);
336c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > peasycap->hue) {
339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
341c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
342c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
343f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas}
344f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*****************************************************************************/
345f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
346f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
347f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
348f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  OTHERWISE:
349f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
350f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *           _read AND _fill POINTERS.
351f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      SELECT THE NEW INPUT.
352f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
353f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
354f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
355f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *
356f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  NOTE:
357f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
358f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
359f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
360f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
36196bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winklerint easycap_newinput(struct easycap *peasycap, int input)
362f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas{
363c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, k, m, mood, off;
364c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int inputnow, video_idlenow, audio_idlenow;
365c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool resubmit;
366f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
3676888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
368c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
369c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
370c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
371c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "%i=input sought\n", input);
372702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
373c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 > input && INPUT_MANY <= input)
374c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
375c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	inputnow = peasycap->input;
376c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (input == inputnow)
377c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return 0;
378702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
379f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*
380f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
381f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
382f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
383f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *  ROUTINE.
384f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas*/
385f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
386c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	video_idlenow = peasycap->video_idle;
387c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	audio_idlenow = peasycap->audio_idle;
388f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
389c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_idle = 1;
390c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_idle = 1;
391c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_isoc_streaming) {
392c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		resubmit = true;
3938b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		easycap_video_kill_urbs(peasycap);
394c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
395c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		resubmit = false;
396c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
397f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
3986888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
399c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
400c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
401c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
402c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = usb_set_interface(peasycap->pusb_device,
403c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_interface,
404c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_altsetting_off);
405c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
406c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
408c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
409c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = stop_100(peasycap->pusb_device);
410c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
411c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: stop_100() rc = %i\n", rc);
412c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
413c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
414c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < FIELD_BUFFER_MANY; k++) {
415c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
416c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
417c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
418c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < FRAME_BUFFER_MANY; k++) {
419c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
420c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
421c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
422c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_page = 0;
423c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_read = 0;
424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->field_fill = 0;
425c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
426c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_read = 0;
427c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_fill = 0;
428c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0; k < peasycap->input; k++) {
429c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		(peasycap->frame_fill)++;
430c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->frame_buffer_many <= peasycap->frame_fill)
431c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->frame_fill = 0;
432c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
433c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->input = input;
434c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	select_input(peasycap->pusb_device, peasycap->input, 9);
435f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas/*---------------------------------------------------------------------------*/
436c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (input == peasycap->inputset[input].input) {
437c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		off = peasycap->inputset[input].standard_offset;
438c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (off != peasycap->standard_offset) {
439c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_standard(peasycap,
440f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				easycap_standard[off].v4l2_standard.id);
441c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
442c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_standard() rc = %i\n", rc);
443c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
444c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
445c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->standard_offset\n",
446c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->standard_offset);
447c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
448c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->standard_offset unchanged\n",
449f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas						peasycap->standard_offset);
450f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
451c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		off = peasycap->inputset[input].format_offset;
452c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (off != peasycap->format_offset) {
453c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			struct v4l2_pix_format *pix =
454c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				&easycap_format[off].v4l2_format.fmt.pix;
455c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_format(peasycap,
456c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pix->width, pix->height,
457c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pix->pixelformat, pix->field, false);
458c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 > rc) {
459c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_format() rc = %i\n", rc);
460c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
461c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
462c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->format_offset\n",
463c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->format_offset);
464c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
465c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->format_offset unchanged\n",
466c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->format_offset);
467f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
468c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].brightness;
469c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->brightness) {
470c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_brightness(peasycap, mood);
471c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
472c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_brightness rc = %i\n", rc);
473c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
474c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
475c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->brightness\n",
476c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->brightness);
477f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
478c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].contrast;
479c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->contrast) {
480c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_contrast(peasycap, mood);
481c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
482c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_contrast rc = %i\n", rc);
483c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
484c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
485c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
486f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
487c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].saturation;
488c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->saturation) {
489c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_saturation(peasycap, mood);
490c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
491c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_saturation rc = %i\n", rc);
492c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
493c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
494c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->saturation\n",
495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->saturation);
496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mood = peasycap->inputset[input].hue;
498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mood != peasycap->hue) {
499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = adjust_hue(peasycap, mood);
500c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
501c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: adjust_hue rc = %i\n", rc);
502c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EFAULT;
503c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
504c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->hue\n", peasycap->hue);
505f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
506c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
507c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
508c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENOENT;
509f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas	}
510702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
5116888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
512c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->pusb_device is NULL\n");
513c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
514c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
515c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = usb_set_interface(peasycap->pusb_device,
516c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_interface,
517c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_altsetting_on);
518c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
519c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
520c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
521c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
522c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = start_100(peasycap->pusb_device);
523c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc) {
524c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: start_100() rc = %i\n", rc);
525c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
526c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
52727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (resubmit)
52896bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler		easycap_video_submit_urbs(peasycap);
529f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
530c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
531c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_idle = video_idlenow;
532c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->audio_idle = audio_idlenow;
533c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_junk = 0;
534702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
535c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
536702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
537702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
53896bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winklerint easycap_video_submit_urbs(struct easycap *peasycap)
539702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
540c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
541c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct urb *purb;
542c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head;
543c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int j, isbad, nospc, m, rc;
544c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int isbuf;
545e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
5466888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
547c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
548c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
549c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
550c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
5516888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->purb_video_head) {
552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap->urb_video_head uninitialized\n");
553c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
554c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
5556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
556c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap->pusb_device is NULL\n");
557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ENODEV;
558c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
559c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->video_isoc_streaming) {
560c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "submission of all video urbs\n");
561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		isbad = 0;  nospc = 0;  m = 0;
562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each(plist_head, (peasycap->purb_video_head)) {
563c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
564c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
565c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb && pdata_urb->purb) {
566c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				purb = pdata_urb->purb;
567702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				isbuf = pdata_urb->isbuf;
568702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->interval = 1;
569702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->dev = peasycap->pusb_device;
5701dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->pipe =
5711dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					usb_rcvisocpipe(peasycap->pusb_device,
572702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_endpointnumber);
573702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->transfer_flags = URB_ISO_ASAP;
5741dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->transfer_buffer =
575702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_buffer[isbuf].pgo;
5761dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->transfer_buffer_length =
577702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_buffer_size;
578702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->complete = easycap_complete;
579702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->context = peasycap;
580702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				purb->start_frame = 0;
5811dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler				purb->number_of_packets =
582702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					peasycap->video_isoc_framesperdesc;
583702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
584c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
585c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					purb->iso_frame_desc[j]. offset =
586c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						j * peasycap->video_isoc_maxframesize;
587c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					purb->iso_frame_desc[j]. length =
588c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->video_isoc_maxframesize;
589c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
590702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
591702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				rc = usb_submit_urb(purb, GFP_KERNEL);
5925c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler				if (rc) {
593702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					isbad++;
5941dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					SAM("ERROR: usb_submit_urb() failed "
595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						"for urb with rc:-%s\n",
5965c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler							strerror(rc));
5975c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler					if (rc == -ENOSPC)
598e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						nospc++;
599702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				} else {
600702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					m++;
601702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
602702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			} else {
6035c0c6c395ea8ad2f831c0717f67f957ba84550adTomas Winkler				isbad++;
604702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
605702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
606c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (nospc) {
607c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
608c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM(".....  possibly inadequate USB bandwidth\n");
609c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
610c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
611e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
6128b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		if (isbad)
6138b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			easycap_video_kill_urbs(peasycap);
6148b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		else
615c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_streaming = 1;
616702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	} else {
617c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "already streaming video urbs\n");
618702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
619c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
620702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
621702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
6228b1fad2f046fb825046fee3a41885a70123de988Tomas Winklerint easycap_audio_kill_urbs(struct easycap *peasycap)
623702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
624c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int m;
625c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head;
626c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
627702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
6288b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	if (!peasycap->audio_isoc_streaming)
6298b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		return 0;
6308b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
6318b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	if (!peasycap->purb_audio_head) {
6328b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		SAM("ERROR: peasycap->purb_audio_head is NULL\n");
633c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
634c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
6358b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
6368b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	peasycap->audio_isoc_streaming = 0;
6378b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	m = 0;
6388b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	list_for_each(plist_head, peasycap->purb_audio_head) {
6398b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
6408b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		if (pdata_urb && pdata_urb->purb) {
6418b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			usb_kill_urb(pdata_urb->purb);
6428b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			m++;
6438b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		}
644c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
6458b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
6468b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	JOM(4, "%i audio urbs killed\n", m);
6478b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
6488b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	return 0;
6498b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler}
6508b1fad2f046fb825046fee3a41885a70123de988Tomas Winklerint easycap_video_kill_urbs(struct easycap *peasycap)
6518b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler{
6528b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	int m;
6538b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	struct list_head *plist_head;
6548b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	struct data_urb *pdata_urb;
6558b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
6568b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	if (!peasycap->video_isoc_streaming)
6578b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		return 0;
6588b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
659c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->purb_video_head) {
660e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas		SAM("ERROR: peasycap->purb_video_head is NULL\n");
661702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		return -EFAULT;
662702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
663c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_streaming = 0;
665c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "killing video urbs\n");
666c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = 0;
667c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	list_for_each(plist_head, (peasycap->purb_video_head)) {
668c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
669c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (pdata_urb && pdata_urb->purb) {
670c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			usb_kill_urb(pdata_urb->purb);
671c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m++;
672c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
673c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
674c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "%i video urbs killed\n", m);
675c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
676c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
677702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
678702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/****************************************************************************/
679702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
680702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
681d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_open_noinode(struct file *file)
682d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
683d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return easycap_open(NULL, file);
684d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler}
685d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
686d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int videodev_release(struct video_device *pvideo_device)
687702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
689702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = video_get_drvdata(pvideo_device);
6916888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap is NULL\n");
693c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ending unsuccessfully\n");
694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
695c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
6968b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	if (easycap_video_kill_urbs(peasycap)) {
6978b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		SAM("ERROR: easycap_video_kill_urbs() failed\n");
698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
699c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
700c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "ending successfully\n");
701c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
702702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
703e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
704e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*****************************************************************************/
705702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
706702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
707ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
708ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
709ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
710ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
711ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  peasycap->pusb_device IS NO LONGER VALID.
712702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
713702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
714d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_delete(struct kref *pkref)
715702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
717c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_urb *pdata_urb;
718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct list_head *plist_head, *plist_next;
719c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k, m, gone, kd;
720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_urb;
721c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_page;
722c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_video_struct;
723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_urb;
724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_page;
725c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int allocation_audio_struct;
726c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int registered_video, registered_audio;
727c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = container_of(pkref, struct easycap, kref);
7296888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
731c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
732c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
73396bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	kd = easycap_isdongle(peasycap);
734702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
735702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
736702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  FREE VIDEO.
737702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
738702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
7396888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (peasycap->purb_video_head) {
740c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
7418b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		list_for_each(plist_head, peasycap->purb_video_head) {
742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
743c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
7448b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			if (pdata_urb && pdata_urb->purb) {
7458b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				usb_free_urb(pdata_urb->purb);
7468b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				pdata_urb->purb = NULL;
7478b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				peasycap->allocation_video_urb--;
7488b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				m++;
749702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
750702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
751702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
752c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i video urbs freed\n", m);
753702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
754c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing video data_urb structures.\n");
755c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
756c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each_safe(plist_head, plist_next,
757c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->purb_video_head) {
758c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
759c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						struct data_urb, list_head);
760c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb) {
761c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_struct -=
762702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						sizeof(struct data_urb);
763c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				kfree(pdata_urb);
764c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				m++;
765c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
766702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
767c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i video data_urb structures freed\n", m);
768c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "setting peasycap->purb_video_head=NULL\n");
769c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->purb_video_head = NULL;
770702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
771702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
772c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video isoc buffers.\n");
773c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = 0;
774c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
775c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_isoc_buffer[k].pgo) {
776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			free_pages((unsigned long)
777c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				   peasycap->video_isoc_buffer[k].pgo,
778c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					VIDEO_ISOC_ORDER);
779c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_isoc_buffer[k].pgo = NULL;
780c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->allocation_video_page -=
781c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						BIT(VIDEO_ISOC_ORDER);
782c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m++;
783c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
784702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
785c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "isoc video buffers freed: %i pages\n",
786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			m * (0x01 << VIDEO_ISOC_ORDER));
787c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
788c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video field buffers.\n");
789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	gone = 0;
790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
791c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
7926888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (peasycap->field_buffer[k][m].pgo) {
793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				free_page((unsigned long)
794c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  peasycap->field_buffer[k][m].pgo);
795c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->field_buffer[k][m].pgo = NULL;
796c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_page -= 1;
797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				gone++;
798c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
799702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
800702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "video field buffers freed: %i pages\n", gone);
802c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
803c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing video frame buffers.\n");
804c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	gone = 0;
805c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
806c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
8076888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (peasycap->frame_buffer[k][m].pgo) {
808c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				free_page((unsigned long)
809c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  peasycap->frame_buffer[k][m].pgo);
810c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->frame_buffer[k][m].pgo = NULL;
811c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_video_page -= 1;
812c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				gone++;
813c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
814702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
815702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
816c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "video frame buffers freed: %i pages\n", gone);
817702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
818702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
819702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  FREE AUDIO.
820702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
821702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
8226888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (peasycap->purb_audio_head) {
823c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing audio urbs\n");
824c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
825c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each(plist_head, (peasycap->purb_audio_head)) {
826c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
827c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					struct data_urb, list_head);
8288b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			if (pdata_urb && pdata_urb->purb) {
8298b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				usb_free_urb(pdata_urb->purb);
8308b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				pdata_urb->purb = NULL;
8318b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				peasycap->allocation_audio_urb--;
8328b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler				m++;
833c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
834c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
835c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i audio urbs freed\n", m);
836c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
837c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "freeing audio data_urb structures.\n");
838c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		m = 0;
839c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		list_for_each_safe(plist_head, plist_next,
840c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->purb_audio_head) {
841c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			pdata_urb = list_entry(plist_head,
842c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					struct data_urb, list_head);
843c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (pdata_urb) {
844c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->allocation_audio_struct -=
845c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							sizeof(struct data_urb);
846c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				kfree(pdata_urb);
847702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				m++;
848702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
849702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
850c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "%i audio data_urb structures freed\n", m);
851c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "setting peasycap->purb_audio_head=NULL\n");
852c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->purb_audio_head = NULL;
853702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
854702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
855c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing audio isoc buffers.\n");
856702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	m = 0;
857c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
8586888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (peasycap->audio_isoc_buffer[k].pgo) {
859c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			free_pages((unsigned long)
860c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(peasycap->audio_isoc_buffer[k].pgo),
861c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					AUDIO_ISOC_ORDER);
862c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_isoc_buffer[k].pgo = NULL;
863c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->allocation_audio_page -=
864c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					BIT(AUDIO_ISOC_ORDER);
865702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			m++;
866702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
867702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
868c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
869702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					m * (0x01 << AUDIO_ISOC_ORDER));
870702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
871c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "freeing easycap structure.\n");
872c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_urb    = peasycap->allocation_video_urb;
873c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_page   = peasycap->allocation_video_page;
874c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_video_struct = peasycap->allocation_video_struct;
875c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	registered_video        = peasycap->registered_video;
876c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_urb    = peasycap->allocation_audio_urb;
877c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_page   = peasycap->allocation_audio_page;
878c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	allocation_audio_struct = peasycap->allocation_audio_struct;
879c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	registered_audio        = peasycap->registered_audio;
880c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
881c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
882c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&mutex_dongle)) {
883c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot down mutex_dongle\n");
884c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
885c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked mutex_dongle\n");
886c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			easycapdc60_dongle[kd].peasycap = NULL;
887c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&mutex_dongle);
888c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked mutex_dongle\n");
889c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOT(4, "   null-->dongle[%i].peasycap\n", kd);
890c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			allocation_video_struct -= sizeof(struct easycap);
891c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
892a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas	} else {
893c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: cannot purge dongle[].peasycap");
894c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
89538d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter
89638d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter	kfree(peasycap);
89738d0cffefd3daaad6bc58a6212d16edeaa8ee1f0Dan Carpenter
898702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
899c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
900c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video pages   after all deletions\n", allocation_video_page);
901c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video structs after all deletions\n", allocation_video_struct);
902c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=video devices after all deletions\n", registered_video);
903c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio urbs    after all deletions\n", allocation_audio_urb);
904c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio pages   after all deletions\n", allocation_audio_page);
905c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
906c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	SAY("%8i=audio devices after all deletions\n", registered_audio);
907c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
908c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "ending.\n");
909c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
910702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
911702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
912d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic unsigned int easycap_poll(struct file *file, poll_table *wait)
913702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
914c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
915c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, kd;
916702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
917c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "\n");
918702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
919c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (NULL == ((poll_table *)wait))
920c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
9216888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!file) {
922c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  file pointer is NULL\n");
923ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		return -ERESTARTSYS;
924ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
925ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	peasycap = file->private_data;
9266888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
927ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		SAY("ERROR:  peasycap is NULL\n");
928c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
929ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
9306888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
931c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap->pusb_device is NULL\n");
932c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
933ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
934c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
93596bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	kd = easycap_isdongle(peasycap);
936c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
937c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
938c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
939c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
940c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
941c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_video\n", kd);
942c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	/*
943c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
944c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
945c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 *  IF NECESSARY, BAIL OUT.
946c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	 */
94796bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler		if (kd != easycap_isdongle(peasycap)) {
94822f88fcf407933321d08c45520fbeffca70b05d1Alexey Khoroshilov			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
949c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
95022f88fcf407933321d08c45520fbeffca70b05d1Alexey Khoroshilov		}
9516888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!file) {
952c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR:  file is NULL\n");
953c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
954c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
955c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
956c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap = file->private_data;
9576888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
958c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR:  peasycap is NULL\n");
959c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
960c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
961c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
9626888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap->pusb_device) {
963c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: peasycap->pusb_device is NULL\n");
964c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
965c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -ERESTARTSYS;
966c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
967c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else
968ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	/*
969ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
970ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
971ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	 *  HAVE FAILED.  BAIL OUT.
972ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	*/
973c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -ERESTARTSYS;
974c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
97596bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	rc = easycap_video_dqbuf(peasycap, 0);
976c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->polled = 1;
977c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
978101dca425da49edb3093000d72490216fa322911Tomas Winkler	if (rc)
979c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return POLLERR;
980101dca425da49edb3093000d72490216fa322911Tomas Winkler
981101dca425da49edb3093000d72490216fa322911Tomas Winkler	return POLLIN | POLLRDNORM;
982101dca425da49edb3093000d72490216fa322911Tomas Winkler}
983702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
984702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
985702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
986702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
987702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
988702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
98996bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winklerint easycap_video_dqbuf(struct easycap *peasycap, int mode)
990702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
991c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int input, ifield, miss, rc;
992702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
993702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
9946888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
995c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap is NULL\n");
996c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
997c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
9986888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap->pusb_device) {
999c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR:  peasycap->pusb_device is NULL\n");
1000c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1001c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1002c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	ifield = 0;
1003c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "%i=ifield\n", ifield);
1004702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1005702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1006849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *  CHECK FOR LOST INPUT SIGNAL.
1007849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *
1008849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *  FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1009ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1010ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1011ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IS FLYWHEELING ON INPUT 0.  THE UPSHOT IS:
1012849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *
1013849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0   PLUGGED, INPUT 4   PLUGGED => SCREEN 0 OK,   SCREEN 4 OK
1014849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0   PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK,   SCREEN 4 BLACK
1015849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0 UNPLUGGED, INPUT 4   PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1016849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas *    INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1017849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas*/
1018849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*---------------------------------------------------------------------------*/
1019c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = peasycap->input;
1020c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= input && INPUT_MANY > input) {
1021c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		rc = read_saa(peasycap->pusb_device, 0x1F);
1022c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= rc) {
1023c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc & 0x40)
1024c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->lost[input] += 1;
1025c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			else
1026c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->lost[input] -= 2;
1027849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas
1028c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 > peasycap->lost[input])
1029c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->lost[input] = 0;
1030c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1031c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1032c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1033849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas	}
1034849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*---------------------------------------------------------------------------*/
1035849322a0f114e52d05e16fe8349843c980cff2c6Mike Thomas/*
103640b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
1037702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1038702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1039c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	miss = 0;
1040c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while ((peasycap->field_read == peasycap->field_fill) ||
1041c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	       (0 != (0xFF00 & peasycap->field_buffer
10421dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					[peasycap->field_read][0].kount)) ||
1043c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	      (ifield != (0x00FF & peasycap->field_buffer
1044702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					[peasycap->field_read][0].kount))) {
1045c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mode)
1046c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EAGAIN;
1047702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1048a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		JOM(8, "first wait  on wq_video, %i=field_read %i=field_fill\n",
1049a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->field_read, peasycap->field_fill);
1050c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1051c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != (wait_event_interruptible(peasycap->wq_video,
1052c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				(peasycap->video_idle || peasycap->video_eof  ||
1053c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				((peasycap->field_read != peasycap->field_fill) &&
1054a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				(0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1055a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				(ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1056c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("aborted by signal\n");
1057c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1058a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		}
1059c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_idle) {
1060c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1061c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_idle);
1062f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			return -EAGAIN;
1063f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
1064c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_eof) {
1065c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1066c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			#if defined(PERSEVERE)
1067c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (1 == peasycap->status) {
1068c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, "persevering ...\n");
1069c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_eof = 0;
1070c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->audio_eof = 0;
1071c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != reset(peasycap)) {
1072c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, " ... failed  returning -EIO\n");
1073c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_eof = 1;
1074c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->audio_eof = 1;
10758b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler					easycap_video_kill_urbs(peasycap);
1076c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EIO;
1077c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1078c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->status = 0;
1079c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, " ... OK  returning -EAGAIN\n");
1080c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EAGAIN;
1081c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1082c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			#endif /*PERSEVERE*/
1083c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
1084c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_eof = 1;
10858b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			easycap_video_kill_urbs(peasycap);
1086c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "returning -EIO\n");
1087c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1088c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1089a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		miss++;
1090702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1091c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "first awakening on wq_video after %i waits\n", miss);
1092702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1093c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = field2frame(peasycap);
1094c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc)
1095c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: field2frame() rc = %i\n", rc);
1096702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1097702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
109840b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WAIT FOR THE OTHER FIELD
1099702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1100702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1101c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (ifield)
1102c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ifield = 0;
1103c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1104c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		ifield = 1;
1105c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	miss = 0;
1106c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while ((peasycap->field_read == peasycap->field_fill) ||
1107a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	       (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1108a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	       (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1109c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mode)
1110c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EAGAIN;
1111702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1112c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "second wait on wq_video %i=field_read  %i=field_fill\n",
1113702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				peasycap->field_read, peasycap->field_fill);
1114c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != (wait_event_interruptible(peasycap->wq_video,
11151dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			(peasycap->video_idle || peasycap->video_eof  ||
11161dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			((peasycap->field_read != peasycap->field_fill) &&
1117a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1118a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1119c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("aborted by signal\n");
1120c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1121c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1122c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_idle) {
1123c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1124f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas							peasycap->video_idle);
1125f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			return -EAGAIN;
1126f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
1127c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_eof) {
1128c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1129a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler#if defined(PERSEVERE)
1130c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (1 == peasycap->status) {
1131c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, "persevering ...\n");
1132c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_eof = 0;
1133c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->audio_eof = 0;
1134c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != reset(peasycap)) {
1135c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, " ... failed returning -EIO\n");
1136c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_eof = 1;
1137c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->audio_eof = 1;
11388b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler					easycap_video_kill_urbs(peasycap);
1139c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EIO;
1140c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1141c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->status = 0;
1142c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOM(8, " ... OK ... returning -EAGAIN\n");
1143c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return -EAGAIN;
1144c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1145a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler#endif /*PERSEVERE*/
1146c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->video_eof = 1;
1147c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->audio_eof = 1;
11488b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler			easycap_video_kill_urbs(peasycap);
1149c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "returning -EIO\n");
1150c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return -EIO;
1151c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1152a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		miss++;
1153702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "second awakening on wq_video after %i waits\n", miss);
1155702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1156c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rc = field2frame(peasycap);
1157c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rc)
1158c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: field2frame() rc = %i\n", rc);
115940b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
116040b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*
116140b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas *  WASTE THIS FRAME
116240b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas*/
116340b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
1164a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler	if (peasycap->skip) {
1165c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->skipped++;
1166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->skip != peasycap->skipped)
1167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return peasycap->skip - peasycap->skipped;
1168a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler		else
1169a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->skipped = 0;
1170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
117140b8d50ac98f8c8779aea7459f805e5a69fdb726Mike Thomas/*---------------------------------------------------------------------------*/
1172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_read = peasycap->frame_fill;
1173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->queued[peasycap->frame_read] = 0;
1174c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
1175702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1176c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->frame_fill++;
1177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1178c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_fill = 0;
1179702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1181c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1182702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							V4L2_FIELD_TOP;
1183c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1184c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->frame_buffer[peasycap->frame_read][0].kount =
1185702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							V4L2_FIELD_BOTTOM;
1186702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1187702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1188c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
1189c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
1190c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1191c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
1192702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
1193702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
1194702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1195702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1196702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  BY DEFINITION, odd IS true  FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1197702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *                 odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1198702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1199702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1200702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1201702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1202702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1203702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
120498680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winklerstatic int field2frame(struct easycap *peasycap)
1205702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
1206c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1207c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	void *pex, *pad;
1208c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int kex, kad, mex, mad, rex, rad, rad2;
1209c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int c2, c3, w2, w3, cz, wz;
1210c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int rc, bytesperpixel, multiplier;
1211c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int  much, more, over, rump, caches, input;
1212c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 mask, margin;
1213a6ff0a06d8634a07db52dbc006fd9ce4c438c1e3Tomas Winkler	bool odd, isuy, decimatepixel, badinput;
1214c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
12156888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
1216c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
1217c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1218c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1219e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
1220c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	badinput = false;
1221c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1222f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
1223c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> "
1224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"frame buffer %i\n",
12251dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			peasycap->field_buffer[peasycap->field_read][0].kount,
12261dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			peasycap->field_buffer[peasycap->field_read][0].input,
1227702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			peasycap->field_read, peasycap->frame_fill);
1228c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
1229702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1230702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1231702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1232702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  REJECT OR CLEAN BAD FIELDS
1233702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1234702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1235c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->field_read == peasycap->field_fill) {
1236c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: on entry, still filling field buffer %i\n",
1237c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->field_read);
1238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return 0;
1239c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
12403fc0dae888ee216036ae1898fc9186f1dd04f185Tomas Winkler#ifdef EASYCAP_TESTCARD
1241c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	easycap_testcard(peasycap, peasycap->field_read);
1242702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas#else
1243c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= input && INPUT_MANY > input) {
1244c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1245c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			easycap_testcard(peasycap, peasycap->field_read);
1246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1247702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas#endif /*EASYCAP_TESTCARD*/
1248702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1249702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1250c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bytesperpixel = peasycap->bytesperpixel;
1251c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	decimatepixel = peasycap->decimatepixel;
1252702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1253c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((2 != bytesperpixel) &&
1254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	    (3 != bytesperpixel) &&
1255c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	    (4 != bytesperpixel)) {
1256c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1258c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
125927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (decimatepixel)
1260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier = 2;
1261c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1262c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier = 1;
1263702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1264c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	w2 = 2 * multiplier * (peasycap->width);
1265c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	w3 = bytesperpixel * multiplier * (peasycap->width);
1266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	wz = multiplier * (peasycap->height) *
1267c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		multiplier * (peasycap->width);
1268c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1269c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kex = peasycap->field_read;  mex = 0;
1270c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kad = peasycap->frame_fill;  mad = 0;
1271c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1272c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
1273c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
1274c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	odd = !!(peasycap->field_buffer[kex][0].kount);
1275c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1276febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler	if (odd && (!decimatepixel)) {
1277c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "initial skipping %4i bytes p.%4i\n",
1278c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					w3/multiplier, mad);
1279c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pad += (w3 / multiplier); rad -= (w3 / multiplier);
1280c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1281c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	isuy = true;
1282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	mask = 0;  rump = 0;  caches = 0;
1283c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1284c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	cz = 0;
1285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while (cz < wz) {
1286c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		/*
1287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1288c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  READ   w2   BYTES FROM FIELD BUFFER,
1289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 *  WRITE  w3   BYTES TO FRAME BUFFER
1290c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		 */
1291febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1293c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;  more = 0;
1295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				margin = 0;  mask = 0x00;
1296c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rump = 0;
1299c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1300c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (much % 2) {
1301c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: much is odd\n");
1302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1304702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = (bytesperpixel *
1306c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						much) / 2;
1307702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1308c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (1 < bytesperpixel) {
1309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad * 2 < much * bytesperpixel) {
1310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						/*
1311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * INJUDICIOUS ALTERATION OF
1312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * THIS STATEMENT BLOCK WILL
1313c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * CAUSE BREAKAGE.  BEWARE.
1314c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 */
1315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad2 = rad + bytesperpixel - 1;
1316a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1317a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						rump = ((bytesperpixel * much) / 2) - rad;
1318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1319a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					}
1320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mask = (u8)rump;
1321c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					margin = 0;
1322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much == rex) {
1323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mask |= 0x04;
1324a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1325a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1326a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						else
1327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							mask |= 0x08;
1328702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				} else {
1330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: %i=bytesperpixel\n",
1331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							bytesperpixel);
1332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1333702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1334c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rump)
1335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					caches++;
133627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (badinput) {
1337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1341c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1342c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1343c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1344c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rc = redaub(peasycap, pad, pex, much, more,
1345c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								mask, margin, isuy);
1346c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 > rc) {
1347c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: redaub() failed\n");
1348c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1349f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				}
1350a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				if (much % 4)
1351a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					isuy = !isuy;
1352a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler
1353c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;   cz += much;
1354c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;  rex -= much;
1355c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1356c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1357c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1358c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1359a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1360c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1361c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1362c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pad  += more;
1363c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rad -= more;
1364c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rad) {
1365c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mad++;
1366c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad = peasycap->frame_buffer[kad][mad].pgo;
1367c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad = PAGE_SIZE;
1368c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rump) {
1369c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad += rump;
1370c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad -= rump;
1371c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1372c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1373c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1374702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1375702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1376702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SKIP  w3 BYTES IN TARGET FRAME BUFFER,
1377702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1378702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1379702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1380febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!odd || (cz != wz)) {
1381c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over = w3;
1382c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				do {
1383c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (!rad) {
1384c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mad++;
1385c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad = peasycap->frame_buffer
1386c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kad][mad].pgo;
1387c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad = PAGE_SIZE;
1388c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1389c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					more = over;
1390c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad < more)
1391c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1392c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					over -= more;
1393c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad  += more;
1394c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad  -= more;
1395c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				} while (over);
1396c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1397702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1398702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1399702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1400702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ONLY IF false==odd,
1401702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  READ   w2   BYTES FROM FIELD BUFFER,
1402702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  WRITE  w3 / 2  BYTES TO FRAME BUFFER
1403702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1404702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1405febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		} else if (!odd) {
1406c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1408c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;  more = 0;  margin = 0;  mask = 0x00;
1409c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1410c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1411c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rump = 0;
1412702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1413c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (much % 2) {
1414c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("MISTAKE: much is odd\n");
1415c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1416c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1417702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1418c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = (bytesperpixel * much) / 4;
1419702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1420c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (1 < bytesperpixel) {
1421c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rad * 4 < much * bytesperpixel) {
1422c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						/*
1423c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * INJUDICIOUS ALTERATION OF
1424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * THIS STATEMENT BLOCK
1425c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * WILL CAUSE BREAKAGE.
1426c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 * BEWARE.
1427c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						 */
1428c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad2 = rad + bytesperpixel - 1;
1429a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1430a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						rump = ((bytesperpixel * much) / 4) - rad;
1431c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						more = rad;
1432702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1433c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mask = (u8)rump;
1434c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					margin = 0;
1435c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much == rex) {
1436c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						mask |= 0x04;
1437a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1438a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1439a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						else
1440c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							mask |= 0x08;
1441702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1442702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1443702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				} else {
14441dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler					SAM("MISTAKE: %i=bytesperpixel\n",
1445702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						bytesperpixel);
1446702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					return -EFAULT;
1447702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1448702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1449c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rump)
1450c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					caches++;
1451c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
145227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (badinput) {
1453c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1454c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1455c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1456c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1457c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1458c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1459c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1460c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rc = redaub(peasycap, pad, pex, much, more,
1461702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							mask, margin, isuy);
1462c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 > rc) {
1463c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: redaub() failed\n");
1464c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return -EFAULT;
1465702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1466c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;   cz += much;
1467c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;  rex -= much;
1468c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1469c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1470c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1471c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1472c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (peasycap->field_buffer[kex][mex].input !=
1473c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input))
1474c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1475c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1476c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pad  += more;
1477c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rad -= more;
1478c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rad) {
1479c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mad++;
1480c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pad = peasycap->frame_buffer[kad][mad].pgo;
1481c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rad = PAGE_SIZE;
1482c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (rump) {
1483c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pad += rump;
1484c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						rad -= rump;
1485c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1486c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
1487c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1488702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1489702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1490702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  OTHERWISE JUST
1491702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  READ   w2   BYTES FROM FIELD BUFFER AND DISCARD THEM
1492702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1493702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1494c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
1495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			over = w2;
1496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			do {
1497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (!rex) {
1498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					mex++;
1499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pex = peasycap->field_buffer[kex][mex].pgo;
1500c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					rex = PAGE_SIZE;
1501c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (peasycap->field_buffer[kex][mex].input !=
1502c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input)) {
1503c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "ERROR: 0x%02X=->field_buffer"
1504c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"[%i][%i].input, "
1505c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%02X=(0x08|->input)\n",
1506c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
1507c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[kex][mex].input, kex, mex,
1508c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x08|peasycap->input));
1509c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						badinput = true;
1510c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1511f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				}
1512c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				much = over;
1513c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (rex < much)
1514c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = rex;
1515c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				over -= much;
1516c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				cz += much;
1517c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pex  += much;
1518c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				rex -= much;
1519c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} while (over);
1520c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1521702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
1522702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1523702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1524702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SANITY CHECKS
1525702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1526702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1527c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	c2 = (mex + 1)*PAGE_SIZE - rex;
1528c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (cz != c2)
1529c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1530c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	c3 = (mad + 1)*PAGE_SIZE - rad;
1531c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1532febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler	if (!decimatepixel) {
1533c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (bytesperpixel * cz != c3)
15341dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler			SAM("ERROR: discrepancy %i in bytes written\n",
1535c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					c3 - (bytesperpixel * cz));
1536c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
1537febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!odd) {
1538c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (bytesperpixel *
1539c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				cz != (4 * c3))
1540c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: discrepancy %i in bytes written\n",
1541c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(2*c3)-(bytesperpixel * cz));
1542c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1543c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0 != c3)
1544c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: discrepancy %i "
1545c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					    "in bytes written\n", c3);
1546c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
1547c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1548c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rump)
1549c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1550702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1551c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
1553702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
155427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (odd)
1555c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
1556702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->field_read == peasycap->field_fill)
1558c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("WARNING: on exit, filling field buffer %i\n",
1559c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->field_read);
1560702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (caches)
1562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "%i=caches\n", caches);
1563c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
1564702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
1565702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1566702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1567702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DECIMATION AND COLOURSPACE CONVERSION.
1568702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1569702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1570702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1571702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1572702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ALSO ENSURE THAT much IS EVEN.
1573702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1574702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1575702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1576702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1577702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1578702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x03 & mask =  number of bytes to be written to cache instead of to
1579702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *                    frame buffer
1580702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x04 & mask => use argument margin to set the chrominance for last pixel
1581702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *     0x08 & mask => do not set the chrominance for last pixel
1582702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1583702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1584702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
1585702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1586702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INEFFICIENT SWITCHING INSIDE INNER LOOPS.  REARRANGING THE LOGIC TO
1587702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE.  BEWARE.
1588702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1589702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
159098680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winklerstatic int redaub(struct easycap *peasycap,
159198680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winkler		void *pad, void *pex, int much, int more,
159298680557f3ce7eadae0ceda4484fd6c7a13ba3beTomas Winkler		u8 mask, u8 margin, bool isuy)
1593702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
1594c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 *pcache;
1596c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1597c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int  bytesperpixel;
1598c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bool byteswaporder, decimatepixel, last;
1599c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int j, rump;
1600c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	s32 tmp;
1601c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1602c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (much % 2) {
1603c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: much is odd\n");
1604c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1605c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1606c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	bytesperpixel = peasycap->bytesperpixel;
1607c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	byteswaporder = peasycap->byteswaporder;
1608c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	decimatepixel = peasycap->decimatepixel;
1609c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1610c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler/*---------------------------------------------------------------------------*/
1611c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!bu[255]) {
1612c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 0; j < 112; j++) {
1613c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (453 * j)) >> 8;
1614c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j + 128] =  tmp; bu[127 - j] = -tmp;
1615c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (359 * j)) >> 8;
1616c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rv[j + 128] =  tmp; rv[127 - j] = -tmp;
1617c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (88 * j)) >> 8;
1618c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j + 128] =  tmp; gu[127 - j] = -tmp;
1619c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			tmp = (0xFF00 & (183 * j)) >> 8;
1620c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gv[j + 128] =  tmp; gv[127 - j] = -tmp;
1621c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1622c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 0; j < 16; j++) {
1623c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j] = bu[16]; rv[j] = rv[16];
1624c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j] = gu[16]; gv[j] = gv[16];
1625c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1626c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 240; j < 256; j++) {
1627c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bu[j] = bu[239]; rv[j] = rv[239];
1628c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			gu[j] = gu[239]; gv[j] = gv[239];
1629c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1630c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j =  16; j < 236; j++)
1631c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = j;
1632c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j =   0; j <  16; j++)
1633c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = ay[16];
1634c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (j = 236; j < 256; j++)
1635c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			ay[j] = ay[235];
1636c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(8, "lookup tables are prepared\n");
1637c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1638c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pcache = peasycap->pcache;
16396888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pcache)
1640c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pcache = &peasycap->cache[0];
1641702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1642702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
1643702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1644702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
1645702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1646c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!pcache) {
1647c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: pcache is NULL\n");
1648c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1649c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1650702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1651c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (pcache != &peasycap->cache[0])
1652c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1653c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2 = &peasycap->cache[0];
1654c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1655c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	while (p2 < pcache) {
1656c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		*p3++ = *p2;  p2++;
1657c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1658c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pcache = &peasycap->cache[0];
1659c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (p3 != pad) {
1660c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: pointer misalignment\n");
1661c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
1662c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
1663702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	rump = (int)(0x03 & mask);
1665c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u = 0; v = 0;
1666c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2 = (u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
1667c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	p2++;
1668702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
166927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler	if (isuy)
1670c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		u = *(p2 - 1);
1671c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
1672c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v = *(p2 - 1);
1673702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1674c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (rump)
1675c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
1676702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
1677702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
1678c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	switch (bytesperpixel) {
1679c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 2: {
1680febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1681c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			memcpy(pad, pex, (size_t)much);
1682febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1683c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* UYVY */
1684c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1685c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1686c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* YUYV */
1687c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p3 = (u8 *)pad;  pz = p3 + much;
1688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while  (pz > p3) {
1689c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					c = *p3;
1690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *(p3 + 1);
1691c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = c;
1692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 2;
1693702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1695702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
1696702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		} else {
1697febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*  UYVY DECIMATED */
1699c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1700c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1701c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *p2;
1702c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = *(p2 + 1);
1703c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 2) = *(p2 + 2);
1704c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 3) = *(p2 + 3);
1705c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 4;  p2 += 8;
1706702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1707c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1708c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1709c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* YUYV DECIMATED */
1710c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
1711c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1712c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*p3 = *(p2 + 1);
1713c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 1) = *p2;
1714c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 2) = *(p2 + 3);
1715c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					*(p3 + 3) = *(p2 + 2);
1716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += 4;  p2 += 8;
1717702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1719702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
1720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1721c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
1722c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
1723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 3:
1724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		{
1725febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
1726febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1727c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* RGB */
1728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1729c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1731c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1732c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1733c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
173427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1735c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
173627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1737c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1738c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1739c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1740c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
1741c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
1742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
1743c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
174427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1745c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1746702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
1747c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1748c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1749702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
175027d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
175127d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1752055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
1753c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
175427d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1755055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
175627d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
175727d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1758055e3a3a2cdcb7d39d14857e2fb2175c11168ee7Tomas Winkler								0 : (u8)tmp);
1759702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
176027d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
1761e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
1762702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
1763702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
1764702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
1765702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
1766702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
1767702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1768702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1769702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
1770702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
1771702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
1772702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
1773702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1774702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1775702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
1776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
1777c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1778702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
1779702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1780702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1781702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
1782702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = r;
1783702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
1784702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = b;
1785702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
178727d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
1788c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1791702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
1792702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1794c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1795c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* BGR */
1796c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1798c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1799c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1800c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
180227d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1803c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
180427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1805c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1806c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1807c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1808c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
1809c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1810702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						if (0x08 & mask)
1811702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							;
1812c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
181327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1814c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1815c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
1816c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1817c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
1818702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
181927d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
182027d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
1821c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1822c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
182327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
1824c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
182527d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
182627d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
1827c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1828702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
182927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
1830e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
1831702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
1832702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
1833702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
1834702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
1835702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
1836702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1837702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1838702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
1839702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
1840702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
1841702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
1842702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
1843702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1844702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
1845c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
1846c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1847702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
1848702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1849702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1850702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
1851702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = b;
1852702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
1853702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = r;
1854702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
1855c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
185627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
1857c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1858c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1859c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1860702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
1861702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1862702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1863702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			return 0;
1864c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
1865febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
1866c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*  RGB DECIMATED */
1867c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1868c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1869c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1870c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1871c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1872c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
187327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1874c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
187527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1876c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1877c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1878c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1879c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
1880c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
1881c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
1882c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
188327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1884c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1885702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
1886c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1887702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1888c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
188927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
1890c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
1891c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
1892c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1893c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
1894c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
1895c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
1896c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1897c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
1898c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
1899c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1900c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
190127d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
1902c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
1903c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
1904c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
1905c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
1906c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
1907c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
1908c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1909c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1910c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
1911c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
1912c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
1913c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
1914c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1915c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1916c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
1917c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
1918c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
1919c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1920c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
1921c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1922c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1923c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
1924c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = r;
1925c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
1926c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = b;
1927c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
1928c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
1929c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
1930c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
1931c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
1932702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1933c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
1934702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
1935c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
1936c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
1937c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* BGR DECIMATED */
1938c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
1939c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
1940c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
1941c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
1942c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
1943c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
194427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
1945c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
194627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
1947c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
1948c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
1949c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
1950c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
1951c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
1952c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
1953c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
195427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
1955c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
1956702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
1957c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
1958702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
1959c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
196027d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
1961c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
1962c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
1963c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
1964c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1965c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
1966c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
1967c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
1968c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1969c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
1970c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
1971c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
1972c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
197327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
1974c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
1975c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
1976c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
1977c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
1978c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
1979c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
1980c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1981c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1982c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
1983c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
1984c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
1985c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
1986c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
1987c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1988c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
1989c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
1990c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
1991c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
1992c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
1993c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1994c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
1995c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
1996c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = b;
1997c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
1998c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = r;
1999c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2000c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2001c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2002c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2003c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2004c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2005c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
2006702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
2007c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2008702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2009702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2010c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
2011702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2012c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 4:
2013c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		{
2014febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler		if (!decimatepixel) {
2015febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
2016c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* RGBA */
2017c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2018c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2019c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2020c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2021c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2022c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
202327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2024c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
202527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2026c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2027c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2028c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2029c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2030c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							 if (0x08 & mask)
2031c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2032c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
203327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2034c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2035702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						else
2036c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2037c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2038702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
203927d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
204027d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2041c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2042c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
204327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2044c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
204527d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
204627d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2047c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2048702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
204927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
2050e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
2051702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
2052702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
2053702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2054702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
2055702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
2056702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2057702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2058702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2059702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
2060702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2061702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2062702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = b;
2063702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2064702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2065702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2066702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 3: {
2067702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = r;
2068702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2069702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 2) = b;
2070702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2071702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2072702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2073702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						default: {
2074c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
2075c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2076702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
2077c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2078702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2079702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
2080702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = r;
2081702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
2082702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = b;
2083702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 3) = 0;
2084c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2085c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
208627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
2087c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2088702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					else
2089c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2090c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p3 += bytesperpixel;
2091702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2092c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2093c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
2094c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2095c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  BGRA
2096c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2097c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2098c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2099c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2100c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2101c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2102c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
210327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2104c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
210527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2106c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2107c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2108c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2109c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2110c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							 if (0x08 & mask)
2111c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2112c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
211327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2114c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2115c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2116c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2117c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2118702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
211927d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + rv[(int)v];
212027d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					r = (255 < tmp) ? 255 : ((0 > tmp) ?
2121c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2122c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
212327d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					g = (255 < tmp) ? 255 : ((0 > tmp) ?
2124c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
212527d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					tmp = ay[(int)y] + bu[(int)u];
212627d1766927372bf1410a44e8a22132757b0948b0Tomas Winkler					b = (255 < tmp) ? 255 : ((0 > tmp) ?
2127c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2128702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
212927d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && rump) {
2130e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas						pcache = &peasycap->cache[0];
2131702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						switch (bytesperpixel - rump) {
2132702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 1: {
2133702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2134702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = g;
2135702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
2136702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2137702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2138702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2139702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 2: {
2140702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2141702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2142702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = r;
2143702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2144702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2145702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2146702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						case 3: {
2147702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*p3 = b;
2148702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 1) = g;
2149702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*(p3 + 2) = r;
2150702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							*pcache++ = 0;
2151702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							break;
2152702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2153c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						default:
2154c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							SAM("MISTAKE: %i=rump\n",
2155c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2156702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							return -EFAULT;
2157702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						}
2158702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					} else {
2159702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*p3 = b;
2160702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 1) = g;
2161702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 2) = r;
2162702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						*(p3 + 3) = 0;
2163702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
2164c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					p2 += 2;
216527d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy)
2166c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2167c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2168c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2169702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p3 += bytesperpixel;
2170c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2171c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
2172c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return 0;
2173c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
2174febd32bcfd09aeb543b229fd2896814a26d74d20Tomas Winkler			if (!byteswaporder) {
2175c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2176c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  RGBA DECIMATED
2177c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2178c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2179c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2180c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2181c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2182c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2183c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
218427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2185c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
218627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2187c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2188c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2189c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2190c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2191c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
2192c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2193c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
219427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2195c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2196c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2197c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2198c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2199c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
220027d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
2201c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2202c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
2203c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2204c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2205c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
2206c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
2207c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2208c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2209c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
2210c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2211c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2212c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
221327d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
2214c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
2215c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
2216c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
2217c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2218c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
2219c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
2220c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2221c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2222c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2223c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
2224c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2225c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2226c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = b;
2227c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2228c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2229c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2230c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 3: {
2231c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = r;
2232c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2233c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 2) = b;
2234c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2235c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2236c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2237c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
2238c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
2239c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
2240c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel -
2241c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								rump);
2242c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
2243c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								}
2244c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2245c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2246c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = r;
2247c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
2248c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = b;
2249c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 3) = 0;
2250c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2251c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2252c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2253c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else
2254c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2255702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					p2 += 2;
2256702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2257c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return 0;
2258c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			} else {
2259c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/*
2260c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 *  BGRA DECIMATED
2261c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				 */
2262c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (pz > p2) {
2263c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (pr <= (p3 + bytesperpixel))
2264c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = true;
2265c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					else
2266c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last = false;
2267c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					y = *p2;
226827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (last && (0x0C & mask)) {
2269c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x04 & mask) {
227027d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler							if (isuy)
2271c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								v = margin;
2272c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							else
2273c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								u = margin;
2274c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2275c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (0x08 & mask)
2276c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								;
2277c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else {
227827d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (isuy)
2279c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							v = *(p2 + 1);
2280c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2281c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							u = *(p2 + 1);
2282c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2283c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
228427d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler					if (isuy) {
2285c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + rv[(int)v];
2286c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						r = (255 < tmp) ? 255 : ((0 > tmp) ?
2287c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2288c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] - gu[(int)u] -
2289c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									gv[(int)v];
2290c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						g = (255 < tmp) ? 255 : ((0 > tmp) ?
2291c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2292c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						tmp = ay[(int)y] + bu[(int)u];
2293c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						b = (255 < tmp) ? 255 : ((0 > tmp) ?
2294c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									0 : (u8)tmp);
2295c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
229627d683ab79a408a6a48cb01a200af9abf82cca5aTomas Winkler						if (last && rump) {
2297c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pcache = &peasycap->cache[0];
2298c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							switch (bytesperpixel - rump) {
2299c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 1: {
2300c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2301c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = g;
2302c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2303c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2304c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2305c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2306c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 2: {
2307c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2308c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2309c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = r;
2310c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2311c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2312c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2313c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							case 3: {
2314c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*p3 = b;
2315c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 1) = g;
2316c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*(p3 + 2) = r;
2317c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								*pcache++ = 0;
2318c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								break;
2319c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2320c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							default: {
2321c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								SAM("MISTAKE: "
2322c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=rump\n",
2323c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								bytesperpixel - rump);
2324c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								return -EFAULT;
2325c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2326c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							}
2327c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2328c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*p3 = b;
2329c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 1) = g;
2330c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 2) = r;
2331c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							*(p3 + 3) = 0;
2332c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2333c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = false;
2334c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p3 += bytesperpixel;
2335c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					} else
2336c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						isuy = true;
2337c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						p2 += 2;
2338c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2339c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return 0;
2340c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2341702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2342c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
2343c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2344c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	default: {
2345c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2346c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return -EFAULT;
2347702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2348702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2349c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return 0;
2350702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2351702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2352702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2353702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2354702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2355702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2356d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_vma_open(struct vm_area_struct *pvma)
2357702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2358c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2359702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2360c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
23616888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2362c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2363c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2364c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2365c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->vma_many++;
2366c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2367268dfede46e24eef55a2ef7a10a462617936771eMike Thomas	return;
2368268dfede46e24eef55a2ef7a10a462617936771eMike Thomas}
2369702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2370d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_vma_close(struct vm_area_struct *pvma)
2371702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2372c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2373702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2374c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
23756888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2376c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2377c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2378c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2379c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->vma_many--;
2380c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2381268dfede46e24eef55a2ef7a10a462617936771eMike Thomas	return;
2382702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2383702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2384d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2385702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2386c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int k, m, retcode;
2387c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	void *pbuf;
2388c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct page *page;
2389c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2390702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2391c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	retcode = VM_FAULT_NOPAGE;
2392702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
23936888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvma) {
2394c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("pvma is NULL\n");
2395c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2396c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
23976888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pvmf) {
2398c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("pvmf is NULL\n");
2399c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2400c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2401702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2402c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2403c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2404702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2405c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!m)
2406c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "%4i=k, %4i=m\n", k, m);
2407c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	else
2408c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(16, "%4i=k, %4i=m\n", k, m);
2409702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2410c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2411c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: buffer index %i out of range\n", k);
2412c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2413c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2414c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2415c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: page number  %i out of range\n", m);
2416c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2417c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2418c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = pvma->vm_private_data;
24196888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2420c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
2421c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2422c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2423702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2424c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	pbuf = peasycap->frame_buffer[k][m].pgo;
24256888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pbuf) {
2426c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  pbuf is NULL\n");
2427c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2428c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2429c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	page = virt_to_page(pbuf);
24306888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!page) {
2431c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  page is NULL\n");
2432c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return retcode;
2433c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2434c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	get_page(page);
2435702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
24366888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!page) {
2437c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR:  page is NULL after get_page(page)\n");
2438c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
2439c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		pvmf->page = page;
2440c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		retcode = VM_FAULT_MINOR;
2441c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2442c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return retcode;
2443702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
2444d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2445d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct vm_operations_struct easycap_vm_ops = {
2446d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.open  = easycap_vma_open,
2447d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.close = easycap_vma_close,
2448d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.fault = easycap_vma_fault,
2449d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
2450d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2451d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2452d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
2453d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	JOT(8, "\n");
2454d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
2455d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	pvma->vm_ops = &easycap_vm_ops;
2456d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	pvma->vm_flags |= VM_RESERVED;
24576888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (file)
2458d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		pvma->vm_private_data = file->private_data;
2459d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	easycap_vma_open(pvma);
2460d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return 0;
2461d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler}
2462702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
2463702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2464702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2465702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2466ce36cedab3f865969653bf4360f7e364ab0937e4Mike Thomas *  PROVIDED peasycap->video_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
2467702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2468702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2469702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2470702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2471702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2472702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  STORED IN THE TWO-BYTE STATUS PARAMETER
2473702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        peasycap->field_buffer[peasycap->field_fill][0].kount
2474702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2475702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2476702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2477702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  CHIP.
2478702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2479702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2480702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
2481702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
2482702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
2483f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
2484ce36cedab3f865969653bf4360f7e364ab0937e4Mike Thomas *      0 != (kount & 0x0400)   => RESERVED
2485702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
2486702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
2487702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2488702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2489d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_complete(struct urb *purb)
2490702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
2491c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct easycap *peasycap;
2492c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	struct data_buffer *pfield_buffer;
2493c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	char errbuf[16];
2494c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int i, more, much, leap, rc, last;
2495c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int videofieldamount;
2496c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	unsigned int override, bad;
2497c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	int framestatus, framelength, frameactual, frameoffset;
2498c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	u8 *pu;
2499c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
25006888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!purb) {
2501c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: easycap_complete(): purb is NULL\n");
2502c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2503c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2504c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap = purb->context;
25056888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
2506c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2507c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2508c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2509c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_eof)
2510c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2511c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2512c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2513c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			break;
2514c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(16, "%2i=urb\n", i);
2515c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	last = peasycap->video_isoc_sequence;
2516c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2517c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	     (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2518c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2519c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						last, i);
2520c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2521c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	peasycap->video_isoc_sequence = i;
2522702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2523c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_idle) {
2524c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(16, "%i=video_idle  %i=video_isoc_streaming\n",
2525c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_idle, peasycap->video_isoc_streaming);
2526c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (peasycap->video_isoc_streaming) {
2527c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			rc = usb_submit_urb(purb, GFP_ATOMIC);
2528c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (rc) {
2529c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2530c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (-ENODEV != rc)
2531c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: while %i=video_idle, "
2532c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"usb_submit_urb() "
2533c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"failed with rc:\n",
2534c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_idle);
2535c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
2536702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2537c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
2538702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2539c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	override = 0;
2540702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2541c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2542c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: bad peasycap->field_fill\n");
2543702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		return;
2544702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2545c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (purb->status) {
2546c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2547c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2548c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
2549c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2550702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2551c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2552c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: bad urb status -%s: %d\n",
2553c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				strerror(purb->status), purb->status);
2554702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2555c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	} else {
2556c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		for (i = 0;  i < purb->number_of_packets; i++) {
2557c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 != purb->iso_frame_desc[i].status) {
2558c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				(peasycap->field_buffer
2559c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][0].kount) |= 0x8000 ;
2560c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				/* FIXME: 1. missing '-' check boundaries */
2561c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				strcpy(&errbuf[0],
2562c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					strerror(purb->iso_frame_desc[i].status));
2563702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2564c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			framestatus = purb->iso_frame_desc[i].status;
2565c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			framelength = purb->iso_frame_desc[i].length;
2566c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			frameactual = purb->iso_frame_desc[i].actual_length;
2567c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			frameoffset = purb->iso_frame_desc[i].offset;
2568c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2569c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(16, "frame[%2i]:"
2570c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=status "
2571c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=actual "
2572c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%4i=length "
2573c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"%5i=offset\n",
2574c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				i, framestatus, frameactual, framelength, frameoffset);
2575c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (!purb->iso_frame_desc[i].status) {
2576c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more = purb->iso_frame_desc[i].actual_length;
2577c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2578c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					  [peasycap->field_fill][peasycap->field_page];
2579c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				videofieldamount = (peasycap->field_page *
2580c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					PAGE_SIZE) +
2581c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(int)(pfield_buffer->pto - pfield_buffer->pgo);
2582c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (4 == more)
2583c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				peasycap->video_mt++;
2584c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (4 < more) {
2585c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (peasycap->video_mt) {
2586c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					JOM(8, "%4i empty video urb frames\n",
2587c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_mt);
2588c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_mt = 0;
2589c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2590c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2591c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_fill\n");
2592c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2593c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2594c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2595c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_page) {
2596c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_page\n");
2597c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2598c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2599c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2600c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][peasycap->field_page];
2601c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pu = (u8 *)(purb->transfer_buffer +
2602c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						purb->iso_frame_desc[i].offset);
2603c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (0x80 & *pu)
2604c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					leap = 8;
2605c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				else
2606c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					leap = 4;
2607702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
2608702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2609702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2610702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTE:  A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2611702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *         CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2612702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2613702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2614702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  BYTE OF
2615702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *        peasycap->field_buffer[peasycap->field_fill][0].kount
2616702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2617702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  UPDATED AND field_fill IS BUMPED.  IF THE FIELD BUFFER CONTAINS BAD DATA
2618702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  NOTHING IS OFFERED TO dqbuf().
2619702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2620702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2621702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  RESTS WITH dqbuf().
2622702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2623702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2624c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if ((8 == more) || override) {
2625c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (videofieldamount >
2626c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->videofieldamount) {
2627c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (2 == videofieldamount -
2628c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->
2629c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount) {
2630c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2631c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2632c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x0100;
2633c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_junk += (1 +
2634c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								VIDEO_JUNK_TOLERATE);
2635c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else
2636c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2637c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2638c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x4000;
2639c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else if (videofieldamount <
2640c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->
2641c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount) {
2642c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2643c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2644c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0].kount) |= 0x2000;
2645c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2646c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						bad = 0xFF00 & peasycap->field_buffer
2647c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2648c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[0].kount;
2649c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (!bad) {
2650c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->video_junk)--;
2651c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (-VIDEO_JUNK_TOLERATE >
2652c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_junk)
2653c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->video_junk =
2654c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								-VIDEO_JUNK_TOLERATE;
2655c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_read =
2656c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								(peasycap->
2657c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill)++;
2658c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							if (FIELD_BUFFER_MANY <=
2659c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									peasycap->
2660c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill)
26611dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler								peasycap->
2662c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									field_fill = 0;
2663c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_page = 0;
2664c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer = &peasycap->
2665c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2666c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2667c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_fill]
2668c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2669c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_page];
2670c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->pto =
2671c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo;
2672c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "bumped to: %i="
2673c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"peasycap->"
2674c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"field_fill  %i="
2675c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"parity\n",
2676c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill,
2677c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								0x00FF &
2678c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->kount);
2679c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "field buffer %i has "
2680c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i bytes fit to be "
2681c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"read\n",
2682c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_read,
2683c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								videofieldamount);
2684c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(8, "wakeup call to "
2685c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"wq_video, "
2686c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=field_read "
2687c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=field_fill "
2688c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"%i=parity\n",
2689c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_read,
2690c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill,
2691c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								0x00FF & peasycap->
2692c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2693c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->
2694c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_read][0].kount);
2695c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							wake_up_interruptible
2696c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								(&(peasycap->
2697c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									 wq_video));
2698c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						} else {
2699c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						peasycap->video_junk++;
2700c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (bad & 0x0010)
2701c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->video_junk +=
2702c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(1 + VIDEO_JUNK_TOLERATE/2);
2703c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "field buffer %i had %i "
2704c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"bytes, now discarded: "
2705c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"0x%04X\n",
2706c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_fill,
2707c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							videofieldamount,
2708c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0xFF00 &
2709c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_buffer
2710c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill][0].
2711c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							kount));
2712c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(peasycap->field_fill)++;
2713c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2714c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (FIELD_BUFFER_MANY <=
2715c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_fill)
2716c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_fill = 0;
2717f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas						peasycap->field_page = 0;
2718c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer =
2719c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							&peasycap->field_buffer
2720c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_fill]
2721c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							[peasycap->field_page];
27221dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler						pfield_buffer->pto =
2723c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo;
2724c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
2725c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "bumped to: %i=peasycap->"
2726c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"field_fill  %i=parity\n",
27271dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler							peasycap->field_fill,
2728c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							0x00FF & pfield_buffer->kount);
2729c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2730c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (8 == more) {
2731c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "end-of-field: received "
2732c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"parity byte 0x%02X\n",
2733c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0xFF & *pu));
2734c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (0x40 & *pu)
2735c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->kount = 0x0000;
2736c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						else
2737c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							pfield_buffer->kount = 0x0001;
2738c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->input = 0x08 |
2739c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x07 & peasycap->input);
2740c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						JOM(8, "end-of-field: 0x%02X=kount\n",
2741c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							0xFF & pfield_buffer->kount);
2742c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2743702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2744702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2745702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2746702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2747702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2748702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2749c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pu += leap;
2750c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				more -= leap;
2751702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2752c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2753c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_fill\n");
2754702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					return;
2755702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2756c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2757c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					SAM("ERROR: bad peasycap->field_page\n");
2758c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					return;
2759c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				}
2760c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				pfield_buffer = &peasycap->field_buffer
2761c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					[peasycap->field_fill][peasycap->field_page];
2762c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				while (more) {
2763c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pfield_buffer = &peasycap->field_buffer
27641dc6e41825aa270cfc0166beb54afb1c235dc803Tomas Winkler							[peasycap->field_fill]
2765702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							[peasycap->field_page];
2766c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (PAGE_SIZE < (pfield_buffer->pto -
2767c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo)) {
2768c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						SAM("ERROR: bad pfield_buffer->pto\n");
2769c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						return;
2770c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2771c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (PAGE_SIZE == (pfield_buffer->pto -
2772c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->pgo)) {
2773c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(peasycap->field_page)++;
2774c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2775c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								peasycap->field_page) {
2776c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							JOM(16, "wrapping peasycap->"
2777c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								"field_page\n");
2778c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							peasycap->field_page = 0;
2779c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						}
2780c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer = &peasycap->
2781c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_buffer
2782c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_fill]
2783c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_page];
2784c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->pto = pfield_buffer->pgo;
2785c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						pfield_buffer->input = 0x08 |
2786c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(0x07 & peasycap->input);
2787c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						if ((peasycap->field_buffer[peasycap->
2788c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								field_fill][0]).
2789c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler									input !=
2790c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								pfield_buffer->input)
2791c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							(peasycap->field_buffer
2792c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[peasycap->field_fill]
2793c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler								[0]).kount |= 0x1000;
2794c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2795702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2796c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					much = PAGE_SIZE -
2797c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						(int)(pfield_buffer->pto -
2798702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas							pfield_buffer->pgo);
2799702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
2800c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					if (much > more)
2801c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						much = more;
2802c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					memcpy(pfield_buffer->pto, pu, much);
2803c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					pu += much;
2804c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					(pfield_buffer->pto) += much;
2805c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					more -= much;
2806c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					}
2807702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
2808702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
2809702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
2810702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2811702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2812702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
2813702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2814702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *
2815702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2816702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2817702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
2818702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
2819c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2820c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("easycap driver shutting down on condition green\n");
2821c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->status = 1;
2822c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->video_eof = 1;
2823c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->video_junk = 0;
2824c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		wake_up_interruptible(&peasycap->wq_video);
2825f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas#if !defined(PERSEVERE)
2826c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->audio_eof = 1;
2827c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		wake_up_interruptible(&peasycap->wq_audio);
2828f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas#endif /*PERSEVERE*/
2829c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		return;
2830702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
2831c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (peasycap->video_isoc_streaming) {
2832c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		rc = usb_submit_urb(purb, GFP_ATOMIC);
2833c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (rc) {
2834c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("%s: %d\n", strerror(rc), rc);
2835c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (-ENODEV != rc)
2836c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAM("ERROR: while %i=video_idle, "
2837c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"usb_submit_urb() "
2838c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					"failed with rc:\n",
2839c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler					peasycap->video_idle);
2840c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
2841c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
2842c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
2843702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
28440b217d2125acc039d2f3a94f01821472fbbb75b6Tomas Winkler
2845d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic const struct v4l2_file_operations v4l2_fops = {
2846d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.owner		= THIS_MODULE,
2847d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.open		= easycap_open_noinode,
2848f2b3c685b9b1c048cfa8bef98dac037275b9d20dTomas Winkler	.unlocked_ioctl	= easycap_unlocked_ioctl,
2849d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.poll		= easycap_poll,
2850d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.mmap		= easycap_mmap,
2851d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
28522bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
2853702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
28542bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García * When the device is plugged, this function is called three times,
28552bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García * one for each interface.
2856702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
285711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winklerstatic int easycap_usb_probe(struct usb_interface *intf,
285811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			    const struct usb_device_id *id)
2859702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
286011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_device *usbdev;
286111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_host_interface *alt;
286211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_endpoint_descriptor *ep;
286311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	struct usb_interface_descriptor *interface;
28647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct urb *purb;
28657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap *peasycap;
28667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int ndong;
28677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct data_urb *pdata_urb;
28681d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler	int i, j, k, m, rc;
28697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceNumber;
28707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceClass;
28717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u8 bInterfaceSubClass;
28727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	void *pbuf;
28737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okalt[8], isokalt;
28747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okepn[8];
28757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int okmps[8];
28767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	int maxpacketsize;
28777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	u16 mask;
28787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	s32 value;
28797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap_format *peasycap_format;
2880b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler	int fmtidx;
2881b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler	struct inputset *inputset;
2882702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
288311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	usbdev = interface_to_usbdev(intf);
2884ee99aa4928129d4aad9087988db6b7815ecdc1d5Tomas Winkler
288511ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	alt = usb_altnum_to_altsetting(intf, 0);
288611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	if (!alt) {
288711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		SAY("ERROR: usb_host_interface not found\n");
28887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return -EFAULT;
28897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
2890101dca425da49edb3093000d72490216fa322911Tomas Winkler
289111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	interface = &alt->desc;
289211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	if (!interface) {
289311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		SAY("ERROR: intf_descriptor is NULL\n");
28947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return -EFAULT;
28957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
28962bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
28972bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* Get properties of probed interface */
289811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceNumber = interface->bInterfaceNumber;
289911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceClass = interface->bInterfaceClass;
290011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	bInterfaceSubClass = interface->bInterfaceSubClass;
29017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
2902e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: num_altsetting=%i\n",
290311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			bInterfaceNumber, intf->num_altsetting);
2904e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
2905e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		bInterfaceNumber,
290611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		(long int)(intf->cur_altsetting - intf->altsetting));
2907e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
2908e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
29092bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
29102bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/*
29112bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * A new struct easycap is always allocated when interface 0 is probed.
29122bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * It is not possible here to free any existing struct easycap.
29132bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * This should have been done by easycap_delete() when the device was
29142bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * physically unplugged.
29152bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * The allocated struct easycap is saved for later usage when
29162bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * interfaces 1 and 2 are probed.
29172bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 */
29187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if (0 == bInterfaceNumber) {
29197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
29206888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
29217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: Could not allocate peasycap\n");
29227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOMEM;
29237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
29242bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
29252bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Perform urgent initializations */
29267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->minor = -1;
29277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		kref_init(&peasycap->kref);
29287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(8, "intf[%i]: after kref_init(..._video) "
29297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				"%i=peasycap->kref.refcount.counter\n",
29307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				bInterfaceNumber, peasycap->kref.refcount.counter);
2931702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
29327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		/* module params */
29337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
29342a9a05c43294d703e351753da49231c47e0aad0dTomas Winkler
29357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_video);
29367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_audio);
29377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		init_waitqueue_head(&peasycap->wq_trigger);
2938e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
29397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (mutex_lock_interruptible(&mutex_dongle)) {
2940dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler			SAY("ERROR: cannot down mutex_dongle\n");
29417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ERESTARTSYS;
2942101dca425da49edb3093000d72490216fa322911Tomas Winkler		}
2943101dca425da49edb3093000d72490216fa322911Tomas Winkler
2944101dca425da49edb3093000d72490216fa322911Tomas Winkler		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
2945101dca425da49edb3093000d72490216fa322911Tomas Winkler			if ((!easycapdc60_dongle[ndong].peasycap) &&
2946101dca425da49edb3093000d72490216fa322911Tomas Winkler					(!mutex_is_locked(&easycapdc60_dongle
2947101dca425da49edb3093000d72490216fa322911Tomas Winkler						[ndong].mutex_video)) &&
2948101dca425da49edb3093000d72490216fa322911Tomas Winkler					(!mutex_is_locked(&easycapdc60_dongle
2949101dca425da49edb3093000d72490216fa322911Tomas Winkler						[ndong].mutex_audio))) {
2950101dca425da49edb3093000d72490216fa322911Tomas Winkler				easycapdc60_dongle[ndong].peasycap = peasycap;
2951101dca425da49edb3093000d72490216fa322911Tomas Winkler				peasycap->isdongle = ndong;
2952101dca425da49edb3093000d72490216fa322911Tomas Winkler				JOM(8, "intf[%i]: peasycap-->easycap"
2953101dca425da49edb3093000d72490216fa322911Tomas Winkler						"_dongle[%i].peasycap\n",
2954101dca425da49edb3093000d72490216fa322911Tomas Winkler						bInterfaceNumber, ndong);
2955101dca425da49edb3093000d72490216fa322911Tomas Winkler				break;
2956ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas			}
2957101dca425da49edb3093000d72490216fa322911Tomas Winkler		}
2958101dca425da49edb3093000d72490216fa322911Tomas Winkler
2959101dca425da49edb3093000d72490216fa322911Tomas Winkler		if (DONGLE_MANY <= ndong) {
2960101dca425da49edb3093000d72490216fa322911Tomas Winkler			SAM("ERROR: too many dongles\n");
2961a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas			mutex_unlock(&mutex_dongle);
2962101dca425da49edb3093000d72490216fa322911Tomas Winkler			return -ENOMEM;
2963a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		}
2964101dca425da49edb3093000d72490216fa322911Tomas Winkler		mutex_unlock(&mutex_dongle);
2965101dca425da49edb3093000d72490216fa322911Tomas Winkler
29667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->allocation_video_struct = sizeof(struct easycap);
2967e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
29682bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* and further initialize the structure */
296911ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		peasycap->pusb_device = usbdev;
297011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		peasycap->pusb_interface = intf;
2971702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
29727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->microphone = false;
2973702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
29747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_interface = -1;
29757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_altsetting_on = -1;
29767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_altsetting_off = -1;
29777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_endpointnumber = -1;
29787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_maxframesize = -1;
29797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_buffer_size = -1;
2980702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
29817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_interface = -1;
29827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_altsetting_on = -1;
29837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_altsetting_off = -1;
29847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_endpointnumber = -1;
29857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_maxframesize = -1;
29867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_buffer_size = -1;
2987702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
29887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
2989e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
29902bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Dynamically fill in the available formats */
299196bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler		rc = easycap_video_fillin_formats();
29927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 > rc) {
2993c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: fillin_formats() rc = %i\n", rc);
29947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
29957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
29967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i formats available\n", rc);
29977dfdae8e32a26ef3b3aa8d114d2fed93d7680169Tomas Winkler
29982bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Populate easycap.inputset[] */
2999b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		inputset = peasycap->inputset;
3000b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3001b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		m = 0;
3002b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		mask = 0;
3003b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3004b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3005b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				m++;
3006b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3007b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].standard_offset = i;
3008b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler
30097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				mask = easycap_standard[i].mask;
3010f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
3011f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
30127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (1 != m) {
3013b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: "
3014b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    "inputset->standard_offset unpopulated, %i=m\n", m);
30157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
30167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
30177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
30187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap_format = &easycap_format[0];
3019f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		m = 0;
3020b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3021b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			struct v4l2_pix_format *pix =
3022b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler				&peasycap_format->v4l2_format.fmt.pix;
30237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3024b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->field == V4L2_FIELD_NONE &&
3025b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3026b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			    pix->width  == 640 && pix->height == 480) {
3027f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas				m++;
30287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3029b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].format_offset = i;
30307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				break;
3031f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas			}
3032e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap_format++;
3033f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
30347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (1 != m) {
3035b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: inputset[]->format_offset unpopulated\n");
3036e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			return -ENOENT;
3037f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
3038f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas
30397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		m = 0;
3040b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
30417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			value = easycap_control[i].default_value;
30427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
30437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
30447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3045b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].brightness = value;
30467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
30477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
30487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3049b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].contrast = value;
30507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
30517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
30527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3053b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].saturation = value;
30547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			} else if (V4L2_CID_HUE == easycap_control[i].id) {
30557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				m++;
30567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				for (k = 0; k < INPUT_MANY; k++)
3057b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler					inputset[k].hue = value;
30587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3059f36bc37a48148f31f936557b811431b98dbfe347Mike Thomas		}
3060e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
30617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (4 != m) {
3062b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			SAM("ERROR: inputset[]->brightness underpopulated\n");
30637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
30647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
30657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0; k < INPUT_MANY; k++)
3066b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler			inputset[k].input = k;
3067b4a5916e6bdbd5585a961179799a59871d8722ccTomas Winkler		JOM(4, "populated inputset[]\n");
30687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "finished initialization\n");
30697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	} else {
30702bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
30712bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/*
30722bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * FIXME: Identify the appropriate pointer
30732bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * peasycap for interfaces 1 and 2.
30742bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * The address of peasycap->pusb_device
30752bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * is reluctantly used for this purpose.
30762bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 */
30777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
307811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (usbdev == easycapdc60_dongle[ndong].peasycap->
30797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									pusb_device) {
30807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap = easycapdc60_dongle[ndong].peasycap;
3081c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3082c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler						bInterfaceNumber, ndong);
30837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				break;
30847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
30857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
30867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (DONGLE_MANY <= ndong) {
30877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: peasycap is unknown when probing interface %i\n",
30887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								bInterfaceNumber);
30897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
30907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
30916888393c43c95a40d551989e89cbf572423619e6Tomas Winkler		if (!peasycap) {
30927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAY("ERROR: peasycap is NULL when probing interface %i\n",
30937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								bInterfaceNumber);
30947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
3095a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas		}
3096dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
30972bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
30987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3099dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	    (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
31007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_interface) {
31017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_interface = bInterfaceNumber;
31027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "setting peasycap->video_interface=%i\n",
31037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->video_interface);
31047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
31057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (peasycap->video_interface != bInterfaceNumber) {
31067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: attempting to reset "
31077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"peasycap->video_interface\n");
31087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... continuing with "
31097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"%i=peasycap->video_interface\n",
3110702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas						peasycap->video_interface);
31117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3112702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
31137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	} else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3114fc3cc2caa07568de92cc84780b89b5cf9fbf28b7Tomas Winkler		   (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
31157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_interface) {
31167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_interface = bInterfaceNumber;
31177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			JOM(4, "setting peasycap->audio_interface=%i\n",
31187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							 peasycap->audio_interface);
31197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
31207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (peasycap->audio_interface != bInterfaceNumber) {
31217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: attempting to reset "
31227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"peasycap->audio_interface\n");
31237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... continuing with "
31247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"%i=peasycap->audio_interface\n",
31257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_interface);
31267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3127702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3128702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
3129702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
31302bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/*
31312bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * Investigate all altsettings. This is done in detail
31322bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 * because USB device 05e1:0408 has disparate incarnations.
31332bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	 */
31342bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	isokalt = 0;
313511ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler	for (i = 0; i < intf->num_altsetting; i++) {
313611ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		alt = usb_altnum_to_altsetting(intf, i);
313711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (!alt) {
313811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			SAM("ERROR: alt is NULL\n");
31397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
3140702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
314111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		interface = &alt->desc;
314211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (!interface) {
314311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			SAM("ERROR: intf_descriptor is NULL\n");
31447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
3145702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
31467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
314711ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		if (0 == interface->bNumEndpoints)
3148e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3149e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler						bInterfaceNumber, i);
315011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		for (j = 0; j < interface->bNumEndpoints; j++) {
315111ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			ep = &alt->endpoint[j].desc;
315211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (!ep) {
315311ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler				SAM("ERROR:  ep is NULL.\n");
31547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("...... skipping\n");
31557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				continue;
31567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
31571d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler
31581d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			if (!usb_endpoint_is_isoc_in(ep)) {
31591d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
31601d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bInterfaceNumber,
31611d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						i, j, ep->bmAttributes);
31621d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (usb_endpoint_dir_out(ep)) {
31631d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("ERROR: OUT endpoint unexpected\n");
31641d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("...... continuing\n");
31651d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
31661d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				continue;
31677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
31681d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			switch (bInterfaceClass) {
31691d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_VIDEO:
31701d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_VENDOR_SPEC: {
31711d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (ep->wMaxPacketSize) {
31721d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (8 > isokalt) {
31731d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt] = i;
31741d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
31751d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okalt[%i]\n",
31761d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt],
31771d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
31781d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt] =
31791d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						ep->
31801d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bEndpointAddress &
31811d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						0x0F;
31821d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
31831d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okepn[%i]\n",
31841d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt],
31851d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
31861d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt] =
31871d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						le16_to_cpu(ep->
31881d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						wMaxPacketSize);
31891d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
31901d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okmps[%i]\n",
31911d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt],
31921d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
31931d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt++;
3194702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
31951d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				} else {
31961d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (-1 == peasycap->
31971d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off) {
31981d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
31991d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off =
32001d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler								 i;
32011d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4, "%i=video_"
32021d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off "
32031d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler							"<====\n",
32041d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
32051d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off);
32061d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					} else {
32071d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("ERROR: peasycap"
32081d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"->video_altsetting_"
32091d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off already set\n");
32101d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("...... "
32111d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"continuing with "
32121d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=peasycap->video_"
32131d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off\n",
32141d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
32151d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						video_altsetting_off);
32161d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					}
32171d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
32181d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				break;
32191d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			}
32201d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			case USB_CLASS_AUDIO: {
32211d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (bInterfaceSubClass !=
32221d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				    USB_SUBCLASS_AUDIOSTREAMING)
3223702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					break;
32241d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (!peasycap) {
32251d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					SAM("MISTAKE: "
32261d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					"peasycap is NULL\n");
32271d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					return -EFAULT;
32281d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				}
32291d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				if (ep->wMaxPacketSize) {
32301d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (8 > isokalt) {
32311d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt] = i ;
32321d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
32331d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okalt[%i]\n",
32341d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okalt[isokalt],
32351d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
32361d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt] =
32371d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						ep->
32381d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						bEndpointAddress &
32391d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						0x0F;
32401d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
32411d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okepn[%i]\n",
32421d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okepn[isokalt],
32431d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
32441d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt] =
32451d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						le16_to_cpu(ep->
32461d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						wMaxPacketSize);
32471d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4,
32481d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=okmps[%i]\n",
32491d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						okmps[isokalt],
32501d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt);
32511d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						isokalt++;
32527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
32531d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				} else {
32541d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					if (-1 == peasycap->
32551d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off) {
32561d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
32571d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off =
32581d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler								 i;
32591d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						JOM(4, "%i=audio_"
32601d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"altsetting_off "
32611d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"<====\n",
32621d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
32631d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off);
32641d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler					} else {
32651d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("ERROR: peasycap"
32661d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"->audio_altsetting_"
32671d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off already set\n");
32681d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						SAM("...... "
32691d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"continuing with "
32701d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"%i=peasycap->"
32711d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"audio_altsetting_"
32721d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						"off\n",
32731d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						peasycap->
32741d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler						audio_altsetting_off);
32757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					}
3276702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas				}
32771d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			break;
32781d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			}
32791d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler			default:
32801d243c2e18a6070f4029b774966c51967c3240e0Tomas Winkler				break;
32817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
328211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler			if (0 == ep->wMaxPacketSize) {
32837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "intf[%i]alt[%i]end[%i] "
32847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							"has zero packet size\n",
32857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							bInterfaceNumber, i, j);
3286702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
3287702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3288702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
32892bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
32902bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* Perform initialization of the probed interface */
32917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOM(4, "initialization begins for interface %i\n",
329211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		interface->bInterfaceNumber);
32937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	switch (bInterfaceNumber) {
32942bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* 0: Video interface */
32957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 0: {
32967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
32977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
32987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
32997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!isokalt) {
33017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  no viable video_altsetting_on\n");
33027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
33037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3304101dca425da49edb3093000d72490216fa322911Tomas Winkler		peasycap->video_altsetting_on = okalt[isokalt - 1];
3305101dca425da49edb3093000d72490216fa322911Tomas Winkler		JOM(4, "%i=video_altsetting_on <====\n",
3306101dca425da49edb3093000d72490216fa322911Tomas Winkler					peasycap->video_altsetting_on);
33072bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
33082bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Decide video streaming parameters */
33097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_endpointnumber = okepn[isokalt - 1];
33107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
33117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		maxpacketsize = okmps[isokalt - 1];
3312e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
3313e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		peasycap->video_isoc_maxframesize =
3314e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler				min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
33157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->video_isoc_maxframesize) {
33167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad video_isoc_maxframesize\n");
33177dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("        possibly because port is USB 1.1\n");
33187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
33197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3320e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler		JOM(4, "%i=video_isoc_maxframesize\n",
3321e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler					peasycap->video_isoc_maxframesize);
3322e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler
33237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
33247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_isoc_framesperdesc\n",
33257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_framesperdesc);
33267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->video_isoc_framesperdesc) {
33277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad video_isoc_framesperdesc\n");
33287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
33297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_isoc_buffer_size =
33317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_maxframesize *
33327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_framesperdesc;
33337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=video_isoc_buffer_size\n",
33347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_buffer_size);
33357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
33367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->video_isoc_buffer_size) {
33377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
33387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33397dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_interface) {
33417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_interface is unset\n");
33427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_altsetting_on) {
33457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_altsetting_on is unset\n");
33467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33477dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_altsetting_off) {
33497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_interface_off is unset\n");
33507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_endpointnumber) {
33537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_endpointnumber is unset\n");
33547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_isoc_maxframesize) {
33577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
33587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->video_isoc_buffer_size) {
33617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
33627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
33637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
33642bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
33652bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/*
33662bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * Allocate memory for video buffers.
33672bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * Lists must be initialized first.
33682bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 */
33697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		INIT_LIST_HEAD(&(peasycap->urb_video_head));
33707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->purb_video_head = &(peasycap->urb_video_head);
33717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i frame buffers of size %li\n",
33727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
33737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each scattered over %li pages\n",
33747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							FRAME_BUFFER_SIZE/PAGE_SIZE);
33757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
33767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
33777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
33786888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (peasycap->frame_buffer[k][m].pgo)
33797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					SAM("attempting to reallocate frame "
33807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									" buffers\n");
33817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				else {
33827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					pbuf = (void *)__get_free_page(GFP_KERNEL);
33836888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (!pbuf) {
33847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						SAM("ERROR: Could not allocate frame "
33857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							"buffer %i page %i\n", k, m);
33867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						return -ENOMEM;
3387101dca425da49edb3093000d72490216fa322911Tomas Winkler					}
3388101dca425da49edb3093000d72490216fa322911Tomas Winkler
3389101dca425da49edb3093000d72490216fa322911Tomas Winkler					peasycap->allocation_video_page += 1;
33907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->frame_buffer[k][m].pgo = pbuf;
33917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				}
33927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->frame_buffer[k][m].pto =
33937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->frame_buffer[k][m].pgo;
3394702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas			}
3395702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
3396702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
33977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_fill = 0;
33987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->frame_read = 0;
33997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of frame buffers done:  %i pages\n", k *
34007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									m);
34017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i field buffers of size %li\n",
34027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
34037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each scattered over %li pages\n",
34047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						FIELD_BUFFER_SIZE/PAGE_SIZE);
34057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
34067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
34077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
34086888393c43c95a40d551989e89cbf572423619e6Tomas Winkler				if (peasycap->field_buffer[k][m].pgo) {
34097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					SAM("ERROR: attempting to reallocate "
34107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"field buffers\n");
34117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				} else {
34127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					pbuf = (void *) __get_free_page(GFP_KERNEL);
34136888393c43c95a40d551989e89cbf572423619e6Tomas Winkler					if (!pbuf) {
34147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						SAM("ERROR: Could not allocate field"
34157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							" buffer %i page %i\n", k, m);
34167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						return -ENOMEM;
3417702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas					}
3418101dca425da49edb3093000d72490216fa322911Tomas Winkler
3419101dca425da49edb3093000d72490216fa322911Tomas Winkler					peasycap->allocation_video_page += 1;
3420101dca425da49edb3093000d72490216fa322911Tomas Winkler					peasycap->field_buffer[k][m].pgo = pbuf;
3421101dca425da49edb3093000d72490216fa322911Tomas Winkler				}
34227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				peasycap->field_buffer[k][m].pto =
34237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->field_buffer[k][m].pgo;
34247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
34257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->field_buffer[k][0].kount = 0x0200;
3426702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
34277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_fill = 0;
34287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_page = 0;
34297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->field_read = 0;
34307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of field buffers done:  %i pages\n", k *
34317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									m);
34327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i isoc video buffers of size %i\n",
34337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						VIDEO_ISOC_BUFFER_MANY,
34347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
34357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each occupying contiguous memory pages\n");
34367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
34377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
3438a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			pbuf = (void *)__get_free_pages(GFP_KERNEL,
3439a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							VIDEO_ISOC_ORDER);
34406888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pbuf) {
34417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate isoc video buffer "
34427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									"%i\n", k);
34437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3444101dca425da49edb3093000d72490216fa322911Tomas Winkler			}
3445101dca425da49edb3093000d72490216fa322911Tomas Winkler			peasycap->allocation_video_page +=
3446101dca425da49edb3093000d72490216fa322911Tomas Winkler						BIT(VIDEO_ISOC_ORDER);
3447702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
34487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_isoc_buffer[k].pgo = pbuf;
3449a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->video_isoc_buffer[k].pto =
3450a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				pbuf + peasycap->video_isoc_buffer_size;
34517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->video_isoc_buffer[k].kount = k;
34527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
34537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of isoc video buffers done: %i pages\n",
34547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						k * (0x01 << VIDEO_ISOC_ORDER));
34552bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
34562bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Allocate and initialize multiple struct usb */
34577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
34587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
34597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
34607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
34617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
34627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
34637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
34647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
34657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
34667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
34677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									GFP_KERNEL);
34686888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!purb) {
34697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
34707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler									"%i\n", k);
34717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3472101dca425da49edb3093000d72490216fa322911Tomas Winkler			}
3473101dca425da49edb3093000d72490216fa322911Tomas Winkler
3474101dca425da49edb3093000d72490216fa322911Tomas Winkler			peasycap->allocation_video_urb += 1;
34757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
34766888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb) {
34777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate struct data_urb.\n");
34787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3479101dca425da49edb3093000d72490216fa322911Tomas Winkler			}
3480101dca425da49edb3093000d72490216fa322911Tomas Winkler
3481101dca425da49edb3093000d72490216fa322911Tomas Winkler			peasycap->allocation_video_struct +=
34827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							sizeof(struct data_urb);
3483702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
34847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->purb = purb;
34857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->isbuf = k;
34867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->length = 0;
34877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			list_add_tail(&(pdata_urb->list_head),
34887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->purb_video_head);
34892bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
34902bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García			/* Initialize allocated urbs */
34917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (!k) {
34927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "initializing video urbs thus:\n");
34937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->interval = 1;\n");
34947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
34957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->pipe = usb_rcvisocpipe"
34967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"(peasycap->pusb_device,%i);\n",
34977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_endpointnumber);
34987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
34997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer = peasycap->"
35007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"video_isoc_buffer[.].pgo;\n");
35017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer_length = %i;\n",
35027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size);
35037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->complete = easycap_complete;\n");
35047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->context = peasycap;\n");
35057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->start_frame = 0;\n");
35067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->number_of_packets = %i;\n",
35077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
35087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  for (j = 0; j < %i; j++)\n",
35097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_framesperdesc);
35107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    {\n");
35117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
35127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
35137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
35147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize);
35157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    }\n");
35167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3517702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
35187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->interval = 1;
35197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->dev = peasycap->pusb_device;
35207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
35217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_endpointnumber);
35227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_flags = URB_ISO_ASAP;
35237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
35247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer_length =
35257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_buffer_size;
35267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->complete = easycap_complete;
35277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->context = peasycap;
35287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->start_frame = 0;
35297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->number_of_packets = peasycap->video_isoc_framesperdesc;
35307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
35317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].offset = j *
35327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize;
35337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].length =
35347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->video_isoc_maxframesize;
35357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3536702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
35377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of %i struct urb done.\n", k);
35382bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
35392bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Save pointer peasycap in this interface */
354011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
35412bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
35422bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/*
35432bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * It is essential to initialize the hardware before,
35442bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * rather than after, the device is registered,
3545d994c46d4309df85aea86049024cadfcbf523116Ezequiel García		 * because some udev rules triggers easycap_open()
3546d994c46d4309df85aea86049024cadfcbf523116Ezequiel García		 * immediately after registration, causing a clash.
35472bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 */
35488d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler		peasycap->ntsc = easycap_ntsc;
35498d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler		JOM(8, "defaulting initially to %s\n",
35508d6139547ca349f9acea6536dd6b7f6140d3507fTomas Winkler			easycap_ntsc ? "NTSC" : "PAL");
35517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		rc = reset(peasycap);
35527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (rc) {
3553c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: reset() rc = %i\n", rc);
35547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
35557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
35562bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
35572bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* The video device can now be registered */
3558cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler		if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
35597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("v4l2_device_register() failed\n");
35607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
35617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3562cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler		JOM(4, "registered device instance: %s\n",
3563cdaa898b5efcc598ab1004e8f913061dc7005091Tomas Winkler			peasycap->v4l2_device.name);
35642bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
35652bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/*
35662bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * FIXME: This is believed to be harmless,
35672bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * but may well be unnecessary or wrong.
35682bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 */
35697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.v4l2_dev = NULL;
3570702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
3571e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
35727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		strcpy(&peasycap->video_device.name[0], "easycapdc60");
35737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.fops = &v4l2_fops;
35747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.minor = -1;
35757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->video_device.release = (void *)(&videodev_release);
3576702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
35777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3578702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
35797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 != (video_register_device(&(peasycap->video_device),
35807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							VFL_TYPE_GRABBER, -1))) {
35817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			err("Not able to register with videodev");
35827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			videodev_release(&(peasycap->video_device));
35837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
35847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3585101dca425da49edb3093000d72490216fa322911Tomas Winkler
3586101dca425da49edb3093000d72490216fa322911Tomas Winkler		peasycap->registered_video++;
3587101dca425da49edb3093000d72490216fa322911Tomas Winkler		SAM("registered with videodev: %i=minor\n",
3588101dca425da49edb3093000d72490216fa322911Tomas Winkler						peasycap->video_device.minor);
3589101dca425da49edb3093000d72490216fa322911Tomas Winkler		peasycap->minor = peasycap->video_device.minor;
3590a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
35917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3592dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
35932bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* 1: Audio control */
35947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 1: {
35957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
35967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
35977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
35987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
35992bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Save pointer peasycap in this interface */
360011ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
36017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "no initialization required for interface %i\n",
360211ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler					interface->bInterfaceNumber);
36037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3604702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas	}
36052bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* 2: Audio streaming */
36067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	case 2: {
36077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!peasycap) {
36087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE: peasycap is NULL\n");
36097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (!isokalt) {
36127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  no viable audio_altsetting_on\n");
36137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
36147dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3615101dca425da49edb3093000d72490216fa322911Tomas Winkler		peasycap->audio_altsetting_on = okalt[isokalt - 1];
3616101dca425da49edb3093000d72490216fa322911Tomas Winkler		JOM(4, "%i=audio_altsetting_on <====\n",
3617101dca425da49edb3093000d72490216fa322911Tomas Winkler						peasycap->audio_altsetting_on);
3618e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
36197dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_endpointnumber = okepn[isokalt - 1];
36207dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3621e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
36227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
36237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_maxframesize\n",
36247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize);
36257dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->audio_isoc_maxframesize) {
36267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad audio_isoc_maxframesize\n");
36277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
36287dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (9 == peasycap->audio_isoc_maxframesize) {
36307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->ilk |= 0x02;
36317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("audio hardware is microphone\n");
36327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->microphone = true;
3633a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_pages_per_fragment =
3634a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					PAGES_PER_AUDIO_FRAGMENT;
36357dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else if (256 == peasycap->audio_isoc_maxframesize) {
36367dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->ilk &= ~0x02;
36377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("audio hardware is AC'97\n");
36387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->microphone = false;
3639a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_pages_per_fragment =
3640a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					PAGES_PER_AUDIO_FRAGMENT;
36417dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		} else {
36427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("hardware is unidentified:\n");
36437dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("%i=audio_isoc_maxframesize\n",
3644a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_isoc_maxframesize);
36457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
36467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3647702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
36487dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_bytes_per_fragment =
3649a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_pages_per_fragment * PAGE_SIZE;
36507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3651a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler				peasycap->audio_pages_per_fragment);
36527dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
36537dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
36547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_pages_per_fragment\n",
36557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_pages_per_fragment);
36567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_bytes_per_fragment\n",
36577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_bytes_per_fragment);
36587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%6i=audio_buffer_page_many\n",
36597dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_buffer_page_many);
36607dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
36617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
36627dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
36637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_framesperdesc\n",
36647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
36657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (0 >= peasycap->audio_isoc_framesperdesc) {
36667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("ERROR:  bad audio_isoc_framesperdesc\n");
36677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENOENT;
36687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3669702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
36707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->audio_isoc_buffer_size =
36717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->audio_isoc_maxframesize *
36727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					peasycap->audio_isoc_framesperdesc;
36737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "%i=audio_isoc_buffer_size\n",
36747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_buffer_size);
36757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
36767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("MISTAKE:  audio_isoc_buffer_size bigger "
36777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				"than %li=AUDIO_ISOC_BUFFER_SIZE\n",
36787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							AUDIO_ISOC_BUFFER_SIZE);
36797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_interface) {
36827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_interface is unset\n");
36837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_altsetting_on) {
36867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_altsetting_on is unset\n");
36877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_altsetting_off) {
36907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_interface_off is unset\n");
36917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_endpointnumber) {
36947dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_endpointnumber is unset\n");
36957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
36967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
36977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_isoc_maxframesize) {
36987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
36997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
37007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
37017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (-1 == peasycap->audio_isoc_buffer_size) {
37027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
37037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -EFAULT;
37047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
37052bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
37062bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/*
37072bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * Allocate memory for audio buffers.
37082bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 * Lists must be initialized first.
37092bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		 */
37107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		INIT_LIST_HEAD(&(peasycap->urb_audio_head));
37117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3712702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i isoc audio buffers of size %i\n",
3714a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			AUDIO_ISOC_BUFFER_MANY,
3715a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			peasycap->audio_isoc_buffer_size);
37167dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, ".... each occupying contiguous memory pages\n");
3717702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37187dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
3719a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler			pbuf = (void *)__get_free_pages(GFP_KERNEL,
3720a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler							AUDIO_ISOC_ORDER);
37216888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pbuf) {
37227dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate isoc audio buffer "
37237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"%i\n", k);
37247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3725101dca425da49edb3093000d72490216fa322911Tomas Winkler			}
3726101dca425da49edb3093000d72490216fa322911Tomas Winkler			peasycap->allocation_audio_page +=
3727a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler						BIT(AUDIO_ISOC_ORDER);
3728702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37297dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].pgo = pbuf;
37307dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].pto = pbuf +
37317dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer_size;
37327dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			peasycap->audio_isoc_buffer[k].kount = k;
37337dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
37347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of isoc audio buffers done.\n");
37352bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
37362bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Allocate and initialize urbs */
37377dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
37387dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
3739a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_framesperdesc);
37407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
3741a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
37427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
3743a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_buffer_size);
37447dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler
37457dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
37467dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
3747a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler								GFP_KERNEL);
37486888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!purb) {
37497dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
37507dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler								"%i\n", k);
37517dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3752e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			}
3753e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap->allocation_audio_urb += 1 ;
37547dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
37556888393c43c95a40d551989e89cbf572423619e6Tomas Winkler			if (!pdata_urb) {
37569fa728ea35501fb5cd56880839ad867265c61822Jesper Juhl				usb_free_urb(purb);
37577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				SAM("ERROR: Could not allocate struct data_urb.\n");
37587dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				return -ENOMEM;
3759e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			}
3760e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler			peasycap->allocation_audio_struct +=
3761e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler						sizeof(struct data_urb);
3762702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->purb = purb;
37647dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->isbuf = k;
37657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			pdata_urb->length = 0;
37667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			list_add_tail(&(pdata_urb->list_head),
37677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler							peasycap->purb_audio_head);
37682bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
37697dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			if (!k) {
37707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "initializing audio urbs thus:\n");
37717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->interval = 1;\n");
37727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
37737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->"
37747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						"pusb_device,%i);\n",
37757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_endpointnumber);
37767dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
37777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer = "
37787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler					"peasycap->audio_isoc_buffer[.].pgo;\n");
37797dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->transfer_buffer_length = %i;\n",
3780a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_buffer_size);
37817dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->complete = easycap_alsa_complete;\n");
37827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->context = peasycap;\n");
37837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->start_frame = 0;\n");
37847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  purb->number_of_packets = %i;\n",
37857dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
37867dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "  for (j = 0; j < %i; j++)\n",
37877dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_framesperdesc);
37887dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    {\n");
37897dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
3790a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
37917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
3792a90f36206f0af9d6e2378a5f9c02dea081a04ae5Tomas Winkler					peasycap->audio_isoc_maxframesize);
37937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				JOM(4, "    }\n");
3794dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler			}
3795702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
37967dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->interval = 1;
37977dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->dev = peasycap->pusb_device;
37987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
37997dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_endpointnumber);
38007dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_flags = URB_ISO_ASAP;
38017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
38027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->transfer_buffer_length =
38037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_buffer_size;
38047dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->complete = easycap_alsa_complete;
38057dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->context = peasycap;
38067dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->start_frame = 0;
38077dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
38087dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
38097dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].offset = j *
38107dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize;
38117dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler				purb->iso_frame_desc[j].length =
38127dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler						peasycap->audio_isoc_maxframesize;
38137dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			}
3814702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas		}
38157dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "allocation of %i struct urb done.\n", k);
38162bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
38172bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* Save pointer peasycap in this interface */
381811ff12feb40dc663cad0f2da86729f1af9d1356eTomas Winkler		usb_set_intfdata(intf, peasycap);
38192bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García
38202bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García		/* The audio device can now be registered */
38217dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOM(4, "initializing ALSA card\n");
3822a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
38237dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		rc = easycap_alsa_probe(peasycap);
38247dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		if (rc) {
3825c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			err("easycap_alsa_probe() rc = %i\n", rc);
38267dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler			return -ENODEV;
38277dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		}
3828a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
3829a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
3830ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		JOM(8, "kref_get() with %i=kref.refcount.counter\n",
3831ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler				peasycap->kref.refcount.counter);
3832ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		kref_get(&peasycap->kref);
3833ad30d7af14c778a63304e42acdcedc365b26e8d8Tomas Winkler		peasycap->registered_audio++;
38347dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3835dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	}
38362bc1e212b3f1f783cae9adc5d16aa1a899dc2f82Ezequiel García	/* Interfaces other than 0,1,2 are unexpected */
3837dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler	default:
3838dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler		JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
3839dfcce7bf0913cc81d57a41d8da3175b201ec1664Tomas Winkler		return -EINVAL;
38407dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
3841e03da5e2b77dee7d0535c036a09e9f613dce7c48Tomas Winkler	SAM("ends successfully for interface %i\n", bInterfaceNumber);
38427dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	return 0;
3843702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
3844702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
3845702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3846702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3847ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
3848ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  UNPLUGGED.  HENCE peasycap->pusb_device IS NO LONGER VALID.
3849a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *
385073019286cddc8bba1773944a7b6b603137fd66ffTomas Winkler *  THIS FUNCTION AFFECTS ALSA.  BEWARE.
3851702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3852702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3853d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic void easycap_usb_disconnect(struct usb_interface *pusb_interface)
3854702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
38557dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct usb_host_interface *pusb_host_interface;
38567dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct usb_interface_descriptor *pusb_interface_descriptor;
38577dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	struct easycap *peasycap;
38588b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	int minor, kd;
38598b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	u8 bInterfaceNumber;
3860702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38617dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOT(4, "\n");
3862702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38637dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	pusb_host_interface = pusb_interface->cur_altsetting;
38646888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pusb_host_interface) {
38657dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOT(4, "ERROR: pusb_host_interface is NULL\n");
38667dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
38677dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
38687dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	pusb_interface_descriptor = &(pusb_host_interface->desc);
38696888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!pusb_interface_descriptor) {
38707dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
38717dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
38727dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
38737dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
38747dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	minor = pusb_interface->minor;
38757dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
3876702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
38777dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	if (1 == bInterfaceNumber)
38787dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
3879e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas
38807dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap = usb_get_intfdata(pusb_interface);
38816888393c43c95a40d551989e89cbf572423619e6Tomas Winkler	if (!peasycap) {
38827dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		SAY("ERROR: peasycap is NULL\n");
38837dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		return;
38847dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	}
3885e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
3886268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*
3887e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas *  IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE.  BEWARE.
3888e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas*/
3889e68703cfe8dd2f5605c53b46fae6c9c027e7ef50Mike Thomas/*---------------------------------------------------------------------------*/
38907dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap->video_eof = 1;
38917dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	peasycap->audio_eof = 1;
38927dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	wake_up_interruptible(&(peasycap->wq_video));
38937dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	wake_up_interruptible(&(peasycap->wq_audio));
38948b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler
38957dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	switch (bInterfaceNumber) {
38968b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	case 0:
38978b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		easycap_video_kill_urbs(peasycap);
38987dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
38998b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler	case 2:
39008b1fad2f046fb825046fee3a41885a70123de988Tomas Winkler		easycap_audio_kill_urbs(peasycap);
39017dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
39027dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler	default:
39037dcef374d17fd20ecd96b1aeccafe8a4a8c15740Tomas Winkler		break;
3904c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
3905702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
3906702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3907702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  DEREGISTER
3908ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *
3909ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
3910ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  IOCTL ARE ALL UNLOCKED.  IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
3911ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas *  AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING.  BEWARE.
3912702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3913702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*--------------------------------------------------------------------------*/
391496bec7dd72511e3c16588d9af52da2cc937f7ea1Tomas Winkler	kd = easycap_isdongle(peasycap);
3915c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	switch (bInterfaceNumber) {
3916c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 0: {
3917c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
3918c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			wake_up_interruptible(&peasycap->wq_video);
3919c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
3920c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
3921ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas								mutex_video)) {
3922c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAY("ERROR: "
3923c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				    "cannot lock dongle[%i].mutex_video\n", kd);
3924c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return;
3925c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
3926c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked dongle[%i].mutex_video\n", kd);
3927c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
3928c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
3929ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		}
3930ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas/*---------------------------------------------------------------------------*/
3931c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (!peasycap->v4l2_device.name[0]) {
3932c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ERROR: peasycap->v4l2_device.name is empty\n");
3933c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (0 <= kd && DONGLE_MANY > kd)
3934c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
3935c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
3936c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
3937c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v4l2_device_disconnect(&peasycap->v4l2_device);
3938c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "v4l2_device_disconnect() OK\n");
3939c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		v4l2_device_unregister(&peasycap->v4l2_device);
3940c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "v4l2_device_unregister() OK\n");
3941c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler
3942c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		video_unregister_device(&peasycap->video_device);
3943c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
3944c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				bInterfaceNumber, minor);
3945c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		peasycap->registered_video--;
3946268dfede46e24eef55a2ef7a10a462617936771eMike Thomas/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3947268dfede46e24eef55a2ef7a10a462617936771eMike Thomas
3948c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
3949c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
3950c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
3951c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
3952c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
3953ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
3954c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	case 2: {
3955c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
3956c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			wake_up_interruptible(&peasycap->wq_audio);
3957c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
3958c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
3959ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas								mutex_audio)) {
3960c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				SAY("ERROR: "
3961c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				    "cannot lock dongle[%i].mutex_audio\n", kd);
3962c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler				return;
3963c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			}
3964c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "locked dongle[%i].mutex_audio\n", kd);
3965c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else
3966c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
3967c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 != snd_card_free(peasycap->psnd_card)) {
3968c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: snd_card_free() failed\n");
3969c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		} else {
3970c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			peasycap->psnd_card = NULL;
3971c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			(peasycap->registered_audio)--;
3972c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
3973c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (0 <= kd && DONGLE_MANY > kd) {
3974c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
3975c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
3976c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
3977c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
3978c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
3979c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	default:
3980c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		break;
3981ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
3982702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3983702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
3984702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas *  CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
3985a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas *  (ALSO WHEN ALSA HAS BEEN IN USE)
3986702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
3987702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
3988c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (!peasycap->kref.refcount.counter) {
3989c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		SAM("ERROR: peasycap->kref.refcount.counter is zero "
3990c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler							"so cannot call kref_put()\n");
3991ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		SAM("ending unsuccessfully: may cause memory leak\n");
3992ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas		return;
3993ae59dad4fef271222d65ac6afe2889eb12ea6ca9Mike Thomas	}
3994c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
3995c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
3996c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
3997c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
3998c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ending unsuccessfully: may cause memory leak\n");
3999c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
4000c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4001c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_video\n", kd);
4002c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4003c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4004c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4005c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4006c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4007c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			SAM("ending unsuccessfully: may cause memory leak\n");
4008c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			return;
4009c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		}
4010c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4011c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4012c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4013c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler			bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4014c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	kref_put(&peasycap->kref, easycap_delete);
4015c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4016c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	if (0 <= kd && DONGLE_MANY > kd) {
4017c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4018c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4019c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4020c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler		JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4021c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	}
4022702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4023c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	JOM(4, "ends\n");
4024c750665850dfed34d3ff0f73ddf367cc7b729b77Tomas Winkler	return;
4025702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4026702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4027a9855917290fc40dbfd67d3ee06c190667d6c5b5Mike Thomas
4028702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4029702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*
4030d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler *  PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4031702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas */
4032702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*---------------------------------------------------------------------------*/
4033d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic struct usb_device_id easycap_usb_device_id_table[] = {
4034d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	{USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4035d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	{ }
4036d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
4037d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4038d090bf57492bde9cb6281246c92963476c40b512Tomas WinklerMODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
40394329f3c6a5fb4ed2332c7552894e7e4b8efef194Tomas Winklerstatic struct usb_driver easycap_usb_driver = {
4040d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.name = "easycap",
4041d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.id_table = easycap_usb_device_id_table,
4042d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.probe = easycap_usb_probe,
4043d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	.disconnect = easycap_usb_disconnect,
4044d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler};
4045702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4046d090bf57492bde9cb6281246c92963476c40b512Tomas Winklerstatic int __init easycap_module_init(void)
4047d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler{
4048d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	int k, rc;
4049d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4050aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler	printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4051aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler
4052d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	JOT(4, "begins.  %i=debug %i=bars %i=gain\n",
4053d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		easycap_debug, easycap_bars, easycap_gain);
4054d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4055d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	mutex_init(&mutex_dongle);
4056d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	for (k = 0; k < DONGLE_MANY; k++) {
40573c1fb66ede917d54079a959a95f79777e95920bdTomas Winkler		easycapdc60_dongle[k].peasycap = NULL;
4058d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		mutex_init(&easycapdc60_dongle[k].mutex_video);
4059d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler		mutex_init(&easycapdc60_dongle[k].mutex_audio);
4060d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	}
4061d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	rc = usb_register(&easycap_usb_driver);
40626911e7e4a6bed8ac7989137387f6a33ef65c2b56Tomas Winkler	if (rc)
4063aff512c8a4582c7f74af57bb09a9979edf92b6d8Tomas Winkler		printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4064d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler
4065d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	return rc;
4066702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4067702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4068dbf4805ee6a850e941110b0df1e96049287ecf75Tomas Winklerstatic void __exit easycap_module_exit(void)
4069702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas{
4070d090bf57492bde9cb6281246c92963476c40b512Tomas Winkler	usb_deregister(&easycap_usb_driver);
4071702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas}
4072702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4073702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4074702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasmodule_init(easycap_module_init);
4075702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomasmodule_exit(easycap_module_exit);
4076702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas
4077702422bd2d3f44e454a97ca7054edde84cc18126R.M. Thomas/*****************************************************************************/
4078