Enscript Output

extractedLnx/linux-2.6.38/drivers/staging/easycap/easycap_ioctl.c_easycap_ioctl.c

int
easycap_ioctl(struct inode *inode, struct file *file,
					unsigned int cmd, unsigned long arg)
{
struct easycap *peasycap;
struct usb_device *p;
int kd;

if (NULL == file) {
	SAY("ERROR:  file is NULL\n");
	return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
	SAY("ERROR:  peasycap is NULL\n");
	return -1;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
	SAY("ERROR: bad peasycap\n");
	return -EFAULT;
}
p = peasycap->pusb_device;
if (NULL == p) {
	SAM("ERROR: peasycap->pusb_device is NULL\n");
	return -EFAULT;
}
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
		return -ERESTARTSYS;
	}
	JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
/*---------------------------------------------------------------------------*/
/*
 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
 *  IF NECESSARY, BAIL OUT.
*/
/*---------------------------------------------------------------------------*/
	if (kd != isdongle(peasycap))
		return -ERESTARTSYS;
	if (NULL == file) {
		SAY("ERROR:  file is NULL\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ERESTARTSYS;
	}
	peasycap = file->private_data;
	if (NULL == peasycap) {
		SAY("ERROR:  peasycap is NULL\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ERESTARTSYS;
	}
	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
		SAY("ERROR: bad peasycap\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	p = peasycap->pusb_device;
	if (NULL == peasycap->pusb_device) {
		SAM("ERROR: peasycap->pusb_device is NULL\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ERESTARTSYS;
	}
} else {
/*---------------------------------------------------------------------------*/
/*
 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
 *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
*/
/*---------------------------------------------------------------------------*/
	return -ERESTARTSYS;
}
/*---------------------------------------------------------------------------*/
switch (cmd) {
case VIDIOC_QUERYCAP: {
	struct v4l2_capability v4l2_capability;
	char version[16], *p1, *p2;
	int i, rc, k[3];
	long lng;

	JOM(8, "VIDIOC_QUERYCAP\n");

	if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
		SAM("ERROR: bad driver version string\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	strcpy(&version[0], EASYCAP_DRIVER_VERSION);
	for (i = 0; i < 3; i++)
		k[i] = 0;
	p2 = &version[0];  i = 0;
	while (*p2) {
		p1 = p2;
		while (*p2 && ('.' != *p2))
			p2++;
		if (*p2)
			*p2++ = 0;
		if (3 > i) {
			rc = (int) strict_strtol(p1, 10, &lng);
			if (0 != rc) {
				SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
								rc, p1);
				mutex_unlock(&easycap_dongle[kd].mutex_video);
				return -EINVAL;
			}
			k[i] = (int)lng;
		}
		i++;
	}

	memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
	strlcpy(&v4l2_capability.driver[0], "easycap", \
					sizeof(v4l2_capability.driver));

	v4l2_capability.capabilities = \
				V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
				V4L2_CAP_AUDIO         | V4L2_CAP_READWRITE;

	v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
	JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);

	strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \
		sizeof(v4l2_capability.card));

	if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\
				sizeof(v4l2_capability.bus_info)) < 0) {
		strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \
					sizeof(v4l2_capability.bus_info));
		JOM(8, "%s=v4l2_capability.bus_info\n", \
					&v4l2_capability.bus_info[0]);
	}
	if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
					sizeof(struct v4l2_capability))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUMINPUT: {
	struct v4l2_input v4l2_input;
	__u32 index;

	JOM(8, "VIDIOC_ENUMINPUT\n");

	if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
					sizeof(struct v4l2_input))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	index = v4l2_input.index;
	memset(&v4l2_input, 0, sizeof(struct v4l2_input));

	switch (index) {
	case 0: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "CVBS0");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	case 1: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "CVBS1");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	case 2: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "CVBS2");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	case 3: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "CVBS3");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	case 4: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "CVBS4");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	case 5: {
		v4l2_input.index = index;
		strcpy(&v4l2_input.name[0], "S-VIDEO");
		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
		v4l2_input.audioset = 0x01;
		v4l2_input.tuner = 0;
		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
				V4L2_STD_NTSC ;
		v4l2_input.status = 0;
		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
		break;
	}
	default: {
		JOM(8, "%i=index: exhausts inputs\n", index);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	}

	if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
						sizeof(struct v4l2_input))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_INPUT: {
	__u32 index;

	JOM(8, "VIDIOC_G_INPUT\n");
	index = (__u32)peasycap->input;
	JOM(8, "user is told: %i\n", index);
	if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_INPUT:
	{
	__u32 index;
	int rc;

	JOM(8, "VIDIOC_S_INPUT\n");

	if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	JOM(8, "user requests input %i\n", index);

	if ((int)index == peasycap->input) {
		SAM("requested input already in effect\n");
		break;
	}

	if ((0 > index) || (INPUT_MANY <= index)) {
		JOM(8, "ERROR:  bad requested input: %i\n", index);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}

	rc = newinput(peasycap, (int)index);
	if (0 == rc) {
		JOM(8, "newinput(.,%i) OK\n", (int)index);
	} else {
		SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUMAUDIO: {
	JOM(8, "VIDIOC_ENUMAUDIO\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUMAUDOUT: {
	struct v4l2_audioout v4l2_audioout;

	JOM(8, "VIDIOC_ENUMAUDOUT\n");

	if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
					sizeof(struct v4l2_audioout))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (0 != v4l2_audioout.index) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
	v4l2_audioout.index = 0;
	strcpy(&v4l2_audioout.name[0], "Soundtrack");

	if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
					sizeof(struct v4l2_audioout))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYCTRL: {
	int i1;
	struct v4l2_queryctrl v4l2_queryctrl;

	JOM(8, "VIDIOC_QUERYCTRL\n");

	if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
					sizeof(struct v4l2_queryctrl))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	i1 = 0;
	while (0xFFFFFFFF != easycap_control[i1].id) {
		if (easycap_control[i1].id == v4l2_queryctrl.id) {
			JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]" \
				".name\n", &easycap_control[i1].name[0], i1);
			memcpy(&v4l2_queryctrl, &easycap_control[i1], \
						sizeof(struct v4l2_queryctrl));
			break;
		}
		i1++;
	}
	if (0xFFFFFFFF == easycap_control[i1].id) {
		JOM(8, "%i=index: exhausts controls\n", i1);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
					sizeof(struct v4l2_queryctrl))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYMENU: {
	JOM(8, "VIDIOC_QUERYMENU unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_CTRL: {
	struct v4l2_control *pv4l2_control;

	JOM(8, "VIDIOC_G_CTRL\n");
	pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
	if (!pv4l2_control) {
		SAM("ERROR: out of memory\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOMEM;
	}
	if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
					sizeof(struct v4l2_control))) {
		kfree(pv4l2_control);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	switch (pv4l2_control->id) {
	case V4L2_CID_BRIGHTNESS: {
		pv4l2_control->value = peasycap->brightness;
		JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
		break;
	}
	case V4L2_CID_CONTRAST: {
		pv4l2_control->value = peasycap->contrast;
		JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
		break;
	}
	case V4L2_CID_SATURATION: {
		pv4l2_control->value = peasycap->saturation;
		JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
		break;
	}
	case V4L2_CID_HUE: {
		pv4l2_control->value = peasycap->hue;
		JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
		break;
	}
	case V4L2_CID_AUDIO_VOLUME: {
		pv4l2_control->value = peasycap->volume;
		JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
		break;
	}
	case V4L2_CID_AUDIO_MUTE: {
		if (1 == peasycap->mute)
			pv4l2_control->value = true;
		else
			pv4l2_control->value = false;
		JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
		break;
	}
	default: {
		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
							pv4l2_control->id);
		kfree(pv4l2_control);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	}
	if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
					sizeof(struct v4l2_control))) {
		kfree(pv4l2_control);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	kfree(pv4l2_control);
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(VIDIOC_S_CTRL_OLD)
case VIDIOC_S_CTRL_OLD: {
	JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
}
#endif /*VIDIOC_S_CTRL_OLD*/
case VIDIOC_S_CTRL:
	{
	struct v4l2_control v4l2_control;

	JOM(8, "VIDIOC_S_CTRL\n");

	if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
					sizeof(struct v4l2_control))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	switch (v4l2_control.id) {
	case V4L2_CID_BRIGHTNESS: {
		JOM(8, "user requests brightness %i\n", v4l2_control.value);
		if (0 != adjust_brightness(peasycap, v4l2_control.value))
			;
		break;
	}
	case V4L2_CID_CONTRAST: {
		JOM(8, "user requests contrast %i\n", v4l2_control.value);
		if (0 != adjust_contrast(peasycap, v4l2_control.value))
			;
		break;
	}
	case V4L2_CID_SATURATION: {
		JOM(8, "user requests saturation %i\n", v4l2_control.value);
		if (0 != adjust_saturation(peasycap, v4l2_control.value))
			;
		break;
	}
	case V4L2_CID_HUE: {
		JOM(8, "user requests hue %i\n", v4l2_control.value);
		if (0 != adjust_hue(peasycap, v4l2_control.value))
			;
		break;
	}
	case V4L2_CID_AUDIO_VOLUME: {
		JOM(8, "user requests volume %i\n", v4l2_control.value);
		if (0 != adjust_volume(peasycap, v4l2_control.value))
			;
		break;
	}
	case V4L2_CID_AUDIO_MUTE: {
		int mute;

		JOM(8, "user requests mute %i\n", v4l2_control.value);
		if (true == v4l2_control.value)
			mute = 1;
		else
			mute = 0;

		if (0 != adjust_mute(peasycap, mute))
			SAM("WARNING: failed to adjust mute to %i\n", mute);
		break;
	}
	default: {
		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
							v4l2_control.id);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_EXT_CTRLS: {
	JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUM_FMT: {
	__u32 index;
	struct v4l2_fmtdesc v4l2_fmtdesc;

	JOM(8, "VIDIOC_ENUM_FMT\n");

	if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
					sizeof(struct v4l2_fmtdesc))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	index = v4l2_fmtdesc.index;
	memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));

	v4l2_fmtdesc.index = index;
	v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

	switch (index) {
	case 0: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "uyvy");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	case 1: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "yuy2");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	case 2: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "rgb24");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	case 3: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "rgb32");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	case 4: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "bgr24");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	case 5: {
		v4l2_fmtdesc.flags = 0;
		strcpy(&v4l2_fmtdesc.description[0], "bgr32");
		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
		break;
	}
	default: {
		JOM(8, "%i=index: exhausts formats\n", index);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	}
	if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
					sizeof(struct v4l2_fmtdesc))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUM_FRAMESIZES: {
	__u32 index;
	struct v4l2_frmsizeenum v4l2_frmsizeenum;

	JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");

	if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
					sizeof(struct v4l2_frmsizeenum))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	index = v4l2_frmsizeenum.index;

	v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;

	if (true == peasycap->ntsc) {
		switch (index) {
		case 0: {
			v4l2_frmsizeenum.discrete.width = 640;
			v4l2_frmsizeenum.discrete.height = 480;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						 discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 1: {
			v4l2_frmsizeenum.discrete.width = 320;
			v4l2_frmsizeenum.discrete.height = 240;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 2: {
			v4l2_frmsizeenum.discrete.width = 720;
			v4l2_frmsizeenum.discrete.height = 480;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 3: {
			v4l2_frmsizeenum.discrete.width = 360;
			v4l2_frmsizeenum.discrete.height = 240;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		default: {
			JOM(8, "%i=index: exhausts framesizes\n", index);
			mutex_unlock(&easycap_dongle[kd].mutex_video);
			return -EINVAL;
		}
		}
	} else {
		switch (index) {
		case 0: {
			v4l2_frmsizeenum.discrete.width = 640;
			v4l2_frmsizeenum.discrete.height = 480;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 1: {
			v4l2_frmsizeenum.discrete.width = 320;
			v4l2_frmsizeenum.discrete.height = 240;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 2: {
			v4l2_frmsizeenum.discrete.width = 704;
			v4l2_frmsizeenum.discrete.height = 576;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 3: {
			v4l2_frmsizeenum.discrete.width = 720;
			v4l2_frmsizeenum.discrete.height = 576;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		case 4: {
			v4l2_frmsizeenum.discrete.width = 360;
			v4l2_frmsizeenum.discrete.height = 288;
			JOM(8, "%i=index: %ix%i\n", index, \
					(int)(v4l2_frmsizeenum.\
						discrete.width), \
					(int)(v4l2_frmsizeenum.\
						discrete.height));
			break;
		}
		default: {
			JOM(8, "%i=index: exhausts framesizes\n", index);
			mutex_unlock(&easycap_dongle[kd].mutex_video);
			return -EINVAL;
		}
		}
	}
	if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
					sizeof(struct v4l2_frmsizeenum))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUM_FRAMEINTERVALS: {
	__u32 index;
	int denominator;
	struct v4l2_frmivalenum v4l2_frmivalenum;

	JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");

	if (peasycap->fps)
		denominator = peasycap->fps;
	else {
		if (true == peasycap->ntsc)
			denominator = 30;
		else
			denominator = 25;
	}

	if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
					sizeof(struct v4l2_frmivalenum))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	index = v4l2_frmivalenum.index;

	v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;

	switch (index) {
	case 0: {
		v4l2_frmivalenum.discrete.numerator = 1;
		v4l2_frmivalenum.discrete.denominator = denominator;
		JOM(8, "%i=index: %i/%i\n", index, \
			(int)(v4l2_frmivalenum.discrete.numerator), \
			(int)(v4l2_frmivalenum.discrete.denominator));
		break;
	}
	case 1: {
		v4l2_frmivalenum.discrete.numerator = 1;
		v4l2_frmivalenum.discrete.denominator = denominator/5;
		JOM(8, "%i=index: %i/%i\n", index, \
			(int)(v4l2_frmivalenum.discrete.numerator), \
			(int)(v4l2_frmivalenum.discrete.denominator));
		break;
	}
	default: {
		JOM(8, "%i=index: exhausts frameintervals\n", index);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	}
	if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
					sizeof(struct v4l2_frmivalenum))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_FMT: {
	struct v4l2_format *pv4l2_format;
	struct v4l2_pix_format *pv4l2_pix_format;

	JOM(8, "VIDIOC_G_FMT\n");
	pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
	if (!pv4l2_format) {
		SAM("ERROR: out of memory\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOMEM;
	}
	pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
	if (!pv4l2_pix_format) {
		SAM("ERROR: out of memory\n");
		kfree(pv4l2_format);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOMEM;
	}
	if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
					sizeof(struct v4l2_format))) {
		kfree(pv4l2_format);
		kfree(pv4l2_pix_format);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		kfree(pv4l2_format);
		kfree(pv4l2_pix_format);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}

	memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
	pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	memcpy(&pv4l2_format->fmt.pix, \
			 &easycap_format[peasycap->format_offset]\
			.v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
	JOM(8, "user is told: %s\n", \
			&easycap_format[peasycap->format_offset].name[0]);

	if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
					sizeof(struct v4l2_format))) {
		kfree(pv4l2_format);
		kfree(pv4l2_pix_format);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	kfree(pv4l2_format);
	kfree(pv4l2_pix_format);
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_TRY_FMT:
case VIDIOC_S_FMT: {
	struct v4l2_format v4l2_format;
	struct v4l2_pix_format v4l2_pix_format;
	bool try;
	int best_format;

	if (VIDIOC_TRY_FMT == cmd) {
		JOM(8, "VIDIOC_TRY_FMT\n");
		try = true;
	} else {
		JOM(8, "VIDIOC_S_FMT\n");
		try = false;
	}

	if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
					sizeof(struct v4l2_format))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	best_format = adjust_format(peasycap, \
					v4l2_format.fmt.pix.width, \
					v4l2_format.fmt.pix.height, \
					v4l2_format.fmt.pix.pixelformat, \
					v4l2_format.fmt.pix.field, \
					try);
	if (0 > best_format) {
		if (-EBUSY == best_format) {
			mutex_unlock(&easycap_dongle[kd].mutex_video);
			return -EBUSY;
		}
		JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOENT;
	}
/*...........................................................................*/
	memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
	v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

	memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
			.v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
	JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);

	if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
					sizeof(struct v4l2_format))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_CROPCAP: {
	struct v4l2_cropcap v4l2_cropcap;

	JOM(8, "VIDIOC_CROPCAP\n");

	if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
					sizeof(struct v4l2_cropcap))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");

	memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
	v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	v4l2_cropcap.bounds.left      = 0;
	v4l2_cropcap.bounds.top       = 0;
	v4l2_cropcap.bounds.width     = peasycap->width;
	v4l2_cropcap.bounds.height    = peasycap->height;
	v4l2_cropcap.defrect.left     = 0;
	v4l2_cropcap.defrect.top      = 0;
	v4l2_cropcap.defrect.width    = peasycap->width;
	v4l2_cropcap.defrect.height   = peasycap->height;
	v4l2_cropcap.pixelaspect.numerator = 1;
	v4l2_cropcap.pixelaspect.denominator = 1;

	JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);

	if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
					sizeof(struct v4l2_cropcap))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_CROP:
case VIDIOC_S_CROP: {
	JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYSTD: {
	JOM(8, "VIDIOC_QUERYSTD: " \
			"EasyCAP is incapable of detecting standard\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*---------------------------------------------------------------------------*/
/*
 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
 *  FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
 */
/*---------------------------------------------------------------------------*/
case VIDIOC_ENUMSTD: {
	int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
	struct v4l2_standard v4l2_standard;
	__u32 index;
	struct easycap_standard const *peasycap_standard;

	JOM(8, "VIDIOC_ENUMSTD\n");

	if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
					sizeof(struct v4l2_standard))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	index = v4l2_standard.index;

	last3 = last2; last2 = last1; last1 = last0; last0 = index;
	if ((index == last3) && (index == last2) && \
			(index == last1) && (index == last0)) {
		index++;
		last3 = last2; last2 = last1; last1 = last0; last0 = index;
	}

	memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));

	peasycap_standard = &easycap_standard[0];
	while (0xFFFF != peasycap_standard->mask) {
		if ((int)(peasycap_standard - &easycap_standard[0]) == index)
			break;
		peasycap_standard++;
	}
	if (0xFFFF == peasycap_standard->mask) {
		JOM(8, "%i=index: exhausts standards\n", index);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	JOM(8, "%i=index: %s\n", index, \
				&(peasycap_standard->v4l2_standard.name[0]));
	memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
					sizeof(struct v4l2_standard));

	v4l2_standard.index = index;

	if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
					sizeof(struct v4l2_standard))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_STD: {
	v4l2_std_id std_id;
	struct easycap_standard const *peasycap_standard;

	JOM(8, "VIDIOC_G_STD\n");

	if (0 > peasycap->standard_offset) {
		JOM(8, "%i=peasycap->standard_offset\n", \
					peasycap->standard_offset);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EBUSY;
	}

	if (0 != copy_from_user(&std_id, (void __user *)arg, \
						sizeof(v4l2_std_id))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	peasycap_standard = &easycap_standard[peasycap->standard_offset];
	std_id = peasycap_standard->v4l2_standard.id;

	JOM(8, "user is told: %s\n", \
				&peasycap_standard->v4l2_standard.name[0]);

	if (0 != copy_to_user((void __user *)arg, &std_id, \
						sizeof(v4l2_std_id))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_STD: {
	v4l2_std_id std_id;
	int rc;

	JOM(8, "VIDIOC_S_STD\n");

	if (0 != copy_from_user(&std_id, (void __user *)arg, \
						sizeof(v4l2_std_id))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	JOM(8, "User requests standard: 0x%08X%08X\n", \
		(int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
		(int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));

	rc = adjust_standard(peasycap, std_id);
	if (0 > rc) {
		JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOENT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_REQBUFS: {
	int nbuffers;
	struct v4l2_requestbuffers v4l2_requestbuffers;

	JOM(8, "VIDIOC_REQBUFS\n");

	if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
				sizeof(struct v4l2_requestbuffers))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	nbuffers = v4l2_requestbuffers.count;
	JOM(8, "                   User requests %i buffers ...\n", nbuffers);
	if (nbuffers < 2)
		nbuffers = 2;
	if (nbuffers > FRAME_BUFFER_MANY)
		nbuffers = FRAME_BUFFER_MANY;
	if (v4l2_requestbuffers.count == nbuffers) {
		JOM(8, "                   ... agree to  %i buffers\n", \
								nbuffers);
	} else {
		JOM(8, "                  ... insist on  %i buffers\n", \
								nbuffers);
		v4l2_requestbuffers.count = nbuffers;
	}
	peasycap->frame_buffer_many = nbuffers;

	if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
				sizeof(struct v4l2_requestbuffers))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYBUF: {
	__u32 index;
	struct v4l2_buffer v4l2_buffer;

	JOM(8, "VIDIOC_QUERYBUF\n");

	if (peasycap->video_eof) {
		JOM(8, "returning -EIO because  %i=video_eof\n", \
							peasycap->video_eof);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EIO;
	}

	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
					sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	index = v4l2_buffer.index;
	if (index < 0 || index >= peasycap->frame_buffer_many)
		return -EINVAL;
	memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
	v4l2_buffer.index = index;
	v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	v4l2_buffer.bytesused = peasycap->frame_buffer_used;
	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
						peasycap->done[index] | \
						peasycap->queued[index];
	v4l2_buffer.field = V4L2_FIELD_NONE;
	v4l2_buffer.memory = V4L2_MEMORY_MMAP;
	v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
	v4l2_buffer.length = FRAME_BUFFER_SIZE;

	JOM(16, "  %10i=index\n", v4l2_buffer.index);
	JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
	JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
	JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
	JOM(16, "  %10i=field\n", v4l2_buffer.field);
	JOM(16, "  %10li=timestamp.tv_usec\n", \
					 (long)v4l2_buffer.timestamp.tv_usec);
	JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
	JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
	JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
	JOM(16, "  %10i=length\n", v4l2_buffer.length);

	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
					sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QBUF: {
	struct v4l2_buffer v4l2_buffer;

	JOM(8, "VIDIOC_QBUF\n");

	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
					sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	if (v4l2_buffer.index < 0 || \
		 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;

	peasycap->done[v4l2_buffer.index]   = 0;
	peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;

	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
					sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	JOM(8, ".....   user queueing frame buffer %i\n", \
						(int)v4l2_buffer.index);

	peasycap->frame_lock = 0;

	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_DQBUF:
	{
#if defined(AUDIOTIME)
	struct signed_div_result sdr;
	long long int above, below, dnbydt, fudge, sll;
	unsigned long long int ull;
	struct timeval timeval8;
	struct timeval timeval1;
#endif /*AUDIOTIME*/
	struct timeval timeval, timeval2;
	int i, j;
	struct v4l2_buffer v4l2_buffer;
	int rcdq;
	__u16 input;

	JOM(8, "VIDIOC_DQBUF\n");

	if ((peasycap->video_idle) || (peasycap->video_eof)) {
		JOM(8, "returning -EIO because  " \
				"%i=video_idle  %i=video_eof\n", \
				peasycap->video_idle, peasycap->video_eof);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EIO;
	}

	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
					sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}

	if (true == peasycap->offerfields) {
		/*-----------------------------------------------------------*/
		/*
		 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
		 *  V4L2_FIELD_BOTTOM
		*/
		/*-----------------------------------------------------------*/
		if (V4L2_FIELD_TOP == v4l2_buffer.field)
			JOM(8, "user wants V4L2_FIELD_TOP\n");
		else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
			JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
		else if (V4L2_FIELD_ANY == v4l2_buffer.field)
			JOM(8, "user wants V4L2_FIELD_ANY\n");
		else
			JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
							v4l2_buffer.field);
	}

	if (!peasycap->video_isoc_streaming) {
		JOM(16, "returning -EIO because video urbs not streaming\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EIO;
	}
/*---------------------------------------------------------------------------*/
/*
 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
 *  THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE.  IN THIS
 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
 */
/*---------------------------------------------------------------------------*/

	if (!peasycap->polled) {
		do {
			rcdq = easycap_dqbuf(peasycap, 0);
			if (-EIO == rcdq) {
				JOM(8, "returning -EIO because " \
						"dqbuf() returned -EIO\n");
				mutex_unlock(&easycap_dongle[kd].mutex_video);
				return -EIO;
			}
		} while (0 != rcdq);
	} else {
		if (peasycap->video_eof) {
			mutex_unlock(&easycap_dongle[kd].mutex_video);
			return -EIO;
		}
	}
	if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
		SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
					peasycap->done[peasycap->frame_read]);
	}
	peasycap->polled = 0;

	if (!(peasycap->isequence % 10)) {
		for (i = 0; i < 179; i++)
			peasycap->merit[i] = peasycap->merit[i+1];
		peasycap->merit[179] = merit_saa(peasycap->pusb_device);
		j = 0;
		for (i = 0; i < 180; i++)
			j += peasycap->merit[i];
		if (90 < j) {
			SAM("easycap driver shutting down " \
							"on condition blue\n");
			peasycap->video_eof = 1; peasycap->audio_eof = 1;
		}
	}

	v4l2_buffer.index = peasycap->frame_read;
	v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	v4l2_buffer.bytesused = peasycap->frame_buffer_used;
	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
	if (true == peasycap->offerfields)
		v4l2_buffer.field = V4L2_FIELD_BOTTOM;
	else
		v4l2_buffer.field = V4L2_FIELD_NONE;
	do_gettimeofday(&timeval);
	timeval2 = timeval;

#if defined(AUDIOTIME)
	if (!peasycap->timeval0.tv_sec) {
		timeval8 = timeval;
		timeval1 = timeval;
		timeval2 = timeval;
		dnbydt = 192000;
		peasycap->timeval0 = timeval8;
	} else {
		dnbydt = peasycap->dnbydt;
		timeval1 = peasycap->timeval1;
		above = dnbydt * MICROSECONDS(timeval, timeval1);
		below = 192000;
		sdr = signed_div(above, below);

		above = sdr.quotient + timeval1.tv_usec - 350000;

		below = 1000000;
		sdr = signed_div(above, below);
		timeval2.tv_usec = sdr.remainder;
		timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
	}
	if (!(peasycap->isequence % 500)) {
		fudge = ((long long int)(1000000)) * \
				((long long int)(timeval.tv_sec - \
						timeval2.tv_sec)) + \
				(long long int)(timeval.tv_usec - \
						timeval2.tv_usec);
		sdr = signed_div(fudge, 1000);
		sll = sdr.quotient;
		ull = sdr.remainder;

		SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
	}
#endif /*AUDIOTIME*/

	v4l2_buffer.timestamp = timeval2;
	v4l2_buffer.sequence = peasycap->isequence++;
	v4l2_buffer.memory = V4L2_MEMORY_MMAP;
	v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
	v4l2_buffer.length = FRAME_BUFFER_SIZE;

	JOM(16, "  %10i=index\n", v4l2_buffer.index);
	JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
	JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
	JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
	JOM(16, "  %10i=field\n", v4l2_buffer.field);
	JOM(16, "  %10li=timestamp.tv_sec\n", \
					(long)v4l2_buffer.timestamp.tv_sec);
	JOM(16, "  %10li=timestamp.tv_usec\n", \
					(long)v4l2_buffer.timestamp.tv_usec);
	JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
	JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
	JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
	JOM(16, "  %10i=length\n", v4l2_buffer.length);

	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
						sizeof(struct v4l2_buffer))) {
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	input = peasycap->frame_buffer[peasycap->frame_read][0].input;
	if (0x08 & input) {
		JOM(8, "user is offered frame buffer %i, input %i\n", \
					peasycap->frame_read, (0x07 & input));
	} else {
		JOM(8, "user is offered frame buffer %i\n", \
							peasycap->frame_read);
	}
	peasycap->frame_lock = 1;
	JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
	if (peasycap->frame_read == peasycap->frame_fill) {
		if (peasycap->frame_lock) {
			JOM(8, "WORRY:  filling frame buffer " \
						"while offered to user\n");
		}
	}
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_STREAMON: {
	int i;

	JOM(8, "VIDIOC_STREAMON\n");

	peasycap->isequence = 0;
	for (i = 0; i < 180; i++)
		peasycap->merit[i] = 0;
	if ((struct usb_device *)NULL == peasycap->pusb_device) {
		SAM("ERROR: peasycap->pusb_device is NULL\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	submit_video_urbs(peasycap);
	peasycap->video_idle = 0;
	peasycap->audio_idle = 0;
	peasycap->video_eof = 0;
	peasycap->audio_eof = 0;
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_STREAMOFF: {
	JOM(8, "VIDIOC_STREAMOFF\n");

	if ((struct usb_device *)NULL == peasycap->pusb_device) {
		SAM("ERROR: peasycap->pusb_device is NULL\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	peasycap->video_idle = 1;
	peasycap->audio_idle = 1;  peasycap->timeval0.tv_sec = 0;
/*---------------------------------------------------------------------------*/
/*
 *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
 *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
 */
/*---------------------------------------------------------------------------*/
	JOM(8, "calling wake_up on wq_video and wq_audio\n");
	wake_up_interruptible(&(peasycap->wq_video));
	wake_up_interruptible(&(peasycap->wq_audio));
/*---------------------------------------------------------------------------*/
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_PARM: {
	struct v4l2_streamparm *pv4l2_streamparm;

	JOM(8, "VIDIOC_G_PARM\n");
	pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
	if (!pv4l2_streamparm) {
		SAM("ERROR: out of memory\n");
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -ENOMEM;
	}
	if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
					sizeof(struct v4l2_streamparm))) {
		kfree(pv4l2_streamparm);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}

	if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		kfree(pv4l2_streamparm);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EINVAL;
	}
	pv4l2_streamparm->parm.capture.capability = 0;
	pv4l2_streamparm->parm.capture.capturemode = 0;
	pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;

	if (peasycap->fps) {
		pv4l2_streamparm->parm.capture.timeperframe.\
						denominator = peasycap->fps;
	} else {
		if (true == peasycap->ntsc) {
			pv4l2_streamparm->parm.capture.timeperframe.\
						denominator = 30;
		} else {
			pv4l2_streamparm->parm.capture.timeperframe.\
						denominator = 25;
		}
	}

	pv4l2_streamparm->parm.capture.readbuffers = \
						peasycap->frame_buffer_many;
	pv4l2_streamparm->parm.capture.extendedmode = 0;
	if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
					sizeof(struct v4l2_streamparm))) {
		kfree(pv4l2_streamparm);
		mutex_unlock(&easycap_dongle[kd].mutex_video);
		return -EFAULT;
	}
	kfree(pv4l2_streamparm);
	break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_PARM: {
	JOM(8, "VIDIOC_S_PARM unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_AUDIO: {
	JOM(8, "VIDIOC_G_AUDIO unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_AUDIO: {
	JOM(8, "VIDIOC_S_AUDIO unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_TUNER: {
	JOM(8, "VIDIOC_S_TUNER unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_FBUF:
case VIDIOC_S_FBUF:
case VIDIOC_OVERLAY: {
	JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_TUNER: {
	JOM(8, "VIDIOC_G_TUNER unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY: {
	JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
default: {
	JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
	mutex_unlock(&easycap_dongle[kd].mutex_video);
	return -ENOIOCTLCMD;
}
}
mutex_unlock(&easycap_dongle[kd].mutex_video);
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
return 0;
}

Generated by GNU enscript 1.6.4.