struct pvr2_v4l2_dev { struct video_device devbase; /* MUST be first! */ struct pvr2_v4l2 *v4lp; struct pvr2_context_stream *stream; /* Information about this device: */ enum pvr2_config config; /* Expected stream format */ int v4l_type; /* V4L defined type for this device node */ enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
};
struct pvr2_v4l2_fh { struct v4l2_fh fh; struct pvr2_channel channel; struct pvr2_v4l2_dev *pdi; struct pvr2_ioread *rhp; struct file *file;
wait_queue_head_t wait_data; int fw_mode_flag; /* Map contiguous ordinal value to input id */ unsignedchar *input_map; unsignedint input_cnt;
};
struct pvr2_v4l2 { struct pvr2_channel channel;
/* streams - Note that these must be separately, individually, * allocated pointers. This is because the v4l core is going to
* manage their deletion - separately, individually... */ struct pvr2_v4l2_dev *dev_video; struct pvr2_v4l2_dev *dev_radio;
};
staticint video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor"); staticint radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
module_param_array(radio_nr, int, NULL, 0444);
MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor"); staticint vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
module_param_array(vbi_nr, int, NULL, 0444);
MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
/* Don't bother with audioset, since this driver currently always switches the audio whenever the video is
switched. */
/* Handling std is a tougher problem. It doesn't make sense in cases where a device might be multi-standard. We could just copy out the current value for the standard, but it can change over time. For now just
leave it zero. */
*vi = tmp; return 0;
}
if (inp >= fh->input_cnt) return -EINVAL;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
fh->input_map[inp]);
pvr2_hdw_commit_ctl(hdw); return ret;
}
staticint pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
{ /* pkt: FIXME: We are returning one "fake" input here which could very well be called "whatever_we_like". This is for apps that want to see an audio input just to feel comfortable, as well as to test if it can do stereo or sth. There is actually no guarantee that the actual audio input cannot change behind the app's back, but most applications should not mind that either.
Hopefully, mplayer people will work with us on this (this whole mess is to support mplayer pvr://), or Hans will come up with a more standard way to say "we have inputs but we don 't want you to change them independent of video" which will sort this mess.
*/
ret = pvr2_hdw_get_tuner_status(hdw, &vt); if (ret != 0) return ret;
ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
ret = pvr2_ctrl_get_value(ctrlp, &cur_input); if (ret != 0) return ret; if (vf->type == V4L2_TUNER_RADIO) { if (cur_input != PVR2_CVAL_INPUT_RADIO)
pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
} else { if (cur_input == PVR2_CVAL_INPUT_RADIO)
pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
}
fv = vf->frequency; if (vt.capability & V4L2_TUNER_CAP_LOW)
fv = (fv * 125) / 2; else
fv = fv * 62500;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
pvr2_hdw_commit_ctl(hdw); return ret;
}
staticint pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
{ struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int val = 0; int cur_input; struct v4l2_tuner vt; int ret;
ret = pvr2_hdw_get_tuner_status(hdw, &vt); if (ret != 0) return ret;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
&val); if (ret != 0) return ret;
pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
&cur_input); if (cur_input == PVR2_CVAL_INPUT_RADIO)
vf->type = V4L2_TUNER_RADIO; else
vf->type = V4L2_TUNER_ANALOG_TV; if (vt.capability & V4L2_TUNER_CAP_LOW)
val = (val * 2) / 125; else
val /= 62500;
vf->frequency = val; return 0;
}
staticint pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
{ /* Only one format is supported: MPEG. */ if (fd->index) return -EINVAL;
if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from
this node. */ return -EPERM;
}
ret = pvr2_hdw_set_stream_type(hdw, pdi->config); if (ret < 0) return ret; return pvr2_hdw_set_streaming(hdw, !0);
}
if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from
this node. */ return -EPERM;
} return pvr2_hdw_set_streaming(hdw, 0);
}
ret = 0; for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id); if (cptr) { if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
pvr2_ctrl_get_def(cptr, &val); else
ret = pvr2_ctrl_get_value(cptr, &val);
} else
ret = -EINVAL;
if (ret) {
ctls->error_idx = idx; return ret;
} /* Ensure that if read as a 64 bit value, the user
will still get a hopefully sane value */
ctrl->value64 = 0;
ctrl->value = val;
} return 0;
}
/* For the moment just validate that the requested control
actually exists. */ for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id); if (!pctl) {
ctls->error_idx = idx; return -EINVAL;
}
} return 0;
}
staticint pvr2_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f)
{ struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_cropcap cap = { .type = type }; int ret;
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL;
ret = pvr2_hdw_get_cropcap(hdw, &cap); if (!ret)
*f = cap.pixelaspect; return ret;
}
staticint pvr2_g_selection(struct file *file, void *priv, struct v4l2_selection *sel)
{ struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_cropcap cap; int val = 0; int ret;
if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL;
cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
switch (sel->target) { case V4L2_SEL_TGT_CROP:
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); if (ret != 0) return -EINVAL;
sel->r.left = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); if (ret != 0) return -EINVAL;
sel->r.top = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); if (ret != 0) return -EINVAL;
sel->r.width = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); if (ret != 0) return -EINVAL;
sel->r.height = val; break; case V4L2_SEL_TGT_CROP_DEFAULT:
ret = pvr2_hdw_get_cropcap(hdw, &cap);
sel->r = cap.defrect; break; case V4L2_SEL_TGT_CROP_BOUNDS:
ret = pvr2_hdw_get_cropcap(hdw, &cap);
sel->r = cap.bounds; break; default: return -EINVAL;
} return ret;
}
/* Construct the unregistration message *before* we actually perform the unregistration step. By doing it this way we don't
have to worry about potentially touching deleted resources. */
mcnt = scnprintf(msg, sizeof(msg) - 1, "pvrusb2: unregistered device %s [%s]",
video_device_node_name(&dip->devbase),
pvr2_config_get_name(cfg));
msg[mcnt] = 0;
staticint pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
{ int ret; struct pvr2_stream *sp; struct pvr2_hdw *hdw; if (fh->rhp) return 0;
if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're
not currently allowed to stream from this node. */ return -EPERM;
}
/* First read() attempt. Try to claim the stream and start
it... */ if ((ret = pvr2_channel_claim_stream(&fh->channel,
fh->pdi->stream)) != 0) { /* Someone else must already have it */ return ret;
}
fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream); if (!fh->rhp) {
pvr2_channel_claim_stream(&fh->channel,NULL); return -ENOMEM;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.