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.