📄 ivtv-ioctl.c
字号:
"Stereo", "Left", "Right", "Mono", "Swapped" }; static const char * const alpha_mode[4] = { "None", "Global", "Local", "Global and Local" }; static const char * const pixel_format[16] = { "ARGB Indexed", "RGB 5:6:5", "ARGB 1:5:5:5", "ARGB 1:4:4:4", "ARGB 8:8:8:8", "5", "6", "7", "AYUV Indexed", "YUV 5:6:5", "AYUV 1:5:5:5", "AYUV 1:4:4:4", "AYUV 8:8:8:8", "13", "14", "15", }; ivtv_get_output(itv, itv->active_output, &vidout); ivtv_get_audio_output(itv, 0, &audout); IVTV_INFO("Video Output: %s\n", vidout.name); IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, audio_modes[itv->audio_stereo_mode], audio_modes[itv->audio_bilingual_mode]); if (mode < 0 || mode > OUT_PASSTHROUGH) mode = OUT_NONE; IVTV_INFO("Output Mode: %s\n", output_modes[mode]); ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); data[0] |= (read_reg(0x2a00) >> 7) & 0x40; IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n", data[0] & 1 ? "On" : "Off", alpha_mode[(data[0] >> 1) & 0x3], pixel_format[(data[0] >> 3) & 0xf]); } IVTV_INFO("Tuner: %s\n", test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); cx2341x_log_status(&itv->params, itv->name); IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); for (i = 0; i < IVTV_MAX_STREAMS; i++) { struct ivtv_stream *s = &itv->streams[i]; if (s->v4l2dev == NULL || s->buffers == 0) continue; IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, (s->buffers - s->q_free.buffers) * 100 / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); break; } default: return -EINVAL; } return 0;}static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg){ struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; struct ivtv *itv = id->itv; int nonblocking = filp->f_flags & O_NONBLOCK; struct ivtv_stream *s = &itv->streams[id->type]; switch (cmd) { case IVTV_IOC_DMA_FRAME: { struct ivtv_dma_frame *args = arg; IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n"); if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) return 0; if (ivtv_claim_stream(id, id->type)) { return -EBUSY; } if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { ivtv_release_stream(s); return -EBUSY; } /* Mark that this file handle started the UDMA_YUV mode */ id->yuv_frames = 1; if (args->y_source == NULL) return 0; return ivtv_yuv_prep_frame(itv, args); } case VIDEO_GET_PTS: { u32 data[CX2341X_MBOX_MAX_DATA]; u64 *pts = arg; IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { *pts = s->dma_pts; break; } if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | (u64)itv->last_dec_timing[1]; break; } *pts = 0; if (atomic_read(&itv->decoding)) { if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); return -EIO; } memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ } break; } case VIDEO_GET_FRAME_COUNT: { u32 data[CX2341X_MBOX_MAX_DATA]; u64 *frame = arg; IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { *frame = 0; break; } if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { *frame = itv->last_dec_timing[0]; break; } *frame = 0; if (atomic_read(&itv->decoding)) { if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); return -EIO; } memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); *frame = data[0]; } break; } case VIDEO_PLAY: { struct video_command vc; IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); memset(&vc, 0, sizeof(vc)); vc.cmd = VIDEO_CMD_PLAY; return ivtv_video_command(itv, id, &vc, 0); } case VIDEO_STOP: { struct video_command vc; IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); memset(&vc, 0, sizeof(vc)); vc.cmd = VIDEO_CMD_STOP; vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; return ivtv_video_command(itv, id, &vc, 0); } case VIDEO_FREEZE: { struct video_command vc; IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); memset(&vc, 0, sizeof(vc)); vc.cmd = VIDEO_CMD_FREEZE; return ivtv_video_command(itv, id, &vc, 0); } case VIDEO_CONTINUE: { struct video_command vc; IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); memset(&vc, 0, sizeof(vc)); vc.cmd = VIDEO_CMD_CONTINUE; return ivtv_video_command(itv, id, &vc, 0); } case VIDEO_COMMAND: case VIDEO_TRY_COMMAND: { struct video_command *vc = arg; int try = (cmd == VIDEO_TRY_COMMAND); if (try) IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); else IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); return ivtv_video_command(itv, id, vc, try); } case VIDEO_GET_EVENT: { struct video_event *ev = arg; DEFINE_WAIT(wait); IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n"); if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; memset(ev, 0, sizeof(*ev)); set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); while (1) { if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) ev->type = VIDEO_EVENT_DECODER_STOPPED; else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) { ev->type = VIDEO_EVENT_VSYNC; ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ? VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN; if (itv->output_mode == OUT_UDMA_YUV && (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) == IVTV_YUV_MODE_PROGRESSIVE) { ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE; } } if (ev->type) return 0; if (nonblocking) return -EAGAIN; /* Wait for event. Note that serialize_lock is locked, so to allow other processes to access the driver while we are waiting unlock first and later lock again. */ mutex_unlock(&itv->serialize_lock); prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) schedule(); finish_wait(&itv->event_waitq, &wait); mutex_lock(&itv->serialize_lock); if (signal_pending(current)) { /* return if a signal was received */ IVTV_DEBUG_INFO("User stopped wait for event\n"); return -EINTR; } } break; } default: return -EINVAL; } return 0;}static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg){ struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; struct ivtv *itv = id->itv; int ret; /* check priority */ switch (cmd) { case VIDIOC_S_CTRL: case VIDIOC_S_STD: case VIDIOC_S_INPUT: case VIDIOC_S_OUTPUT: case VIDIOC_S_TUNER: case VIDIOC_S_FREQUENCY: case VIDIOC_S_FMT: case VIDIOC_S_CROP: case VIDIOC_S_AUDIO: case VIDIOC_S_AUDOUT: case VIDIOC_S_EXT_CTRLS: case VIDIOC_S_FBUF: case VIDIOC_OVERLAY: ret = v4l2_prio_check(&itv->prio, &id->prio); if (ret) return ret; } switch (cmd) { case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_S_REGISTER: case VIDIOC_G_CHIP_IDENT: case VIDIOC_INT_S_AUDIO_ROUTING: case VIDIOC_INT_RESET: if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); } return ivtv_debug_ioctls(filp, cmd, arg); case VIDIOC_G_PRIORITY: case VIDIOC_S_PRIORITY: case VIDIOC_QUERYCAP: case VIDIOC_ENUMINPUT: case VIDIOC_G_INPUT: case VIDIOC_S_INPUT: case VIDIOC_ENUMOUTPUT: case VIDIOC_G_OUTPUT: case VIDIOC_S_OUTPUT: case VIDIOC_G_FMT: case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: case VIDIOC_ENUM_FMT: case VIDIOC_CROPCAP: case VIDIOC_G_CROP: case VIDIOC_S_CROP: case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: case VIDIOC_ENUMSTD: case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_S_TUNER: case VIDIOC_G_TUNER: case VIDIOC_ENUMAUDIO: case VIDIOC_S_AUDIO: case VIDIOC_G_AUDIO: case VIDIOC_ENUMAUDOUT: case VIDIOC_S_AUDOUT: case VIDIOC_G_AUDOUT: case VIDIOC_G_SLICED_VBI_CAP: case VIDIOC_LOG_STATUS: case VIDIOC_G_ENC_INDEX: case VIDIOC_ENCODER_CMD: case VIDIOC_TRY_ENCODER_CMD: case VIDIOC_G_FBUF: case VIDIOC_S_FBUF: case VIDIOC_OVERLAY: if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); } return ivtv_v4l2_ioctls(itv, filp, cmd, arg); case VIDIOC_QUERYMENU: case VIDIOC_QUERYCTRL: case VIDIOC_S_CTRL: case VIDIOC_G_CTRL: case VIDIOC_S_EXT_CTRLS: case VIDIOC_G_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); } return ivtv_control_ioctls(itv, cmd, arg); case IVTV_IOC_DMA_FRAME: case VIDEO_GET_PTS: case VIDEO_GET_FRAME_COUNT: case VIDEO_GET_EVENT: case VIDEO_PLAY: case VIDEO_STOP: case VIDEO_FREEZE: case VIDEO_CONTINUE: case VIDEO_COMMAND: case VIDEO_TRY_COMMAND: return ivtv_decoder_ioctls(filp, cmd, arg); case 0x00005401: /* Handle isatty() calls */ return -EINVAL; default: return v4l_compat_translate_ioctl(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); } return 0;}static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ /* Filter dvb ioctls that cannot be handled by video_usercopy */ switch (cmd) { case VIDEO_SELECT_SOURCE: IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX); case AUDIO_SET_MUTE: IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); itv->speed_mute_audio = arg; return 0; case AUDIO_CHANNEL_SELECT: IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); if (arg > AUDIO_STEREO_SWAPPED) return -EINVAL; itv->audio_stereo_mode = arg; ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); return 0; case AUDIO_BILINGUAL_CHANNEL_SELECT: IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); if (arg > AUDIO_STEREO_SWAPPED) return -EINVAL; itv->audio_bilingual_mode = arg; ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); return 0; default: break; } return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);}int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; struct ivtv *itv = id->itv; int res; mutex_lock(&itv->serialize_lock); res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg); mutex_unlock(&itv->serialize_lock); return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -