📄 cx23885-417.c
字号:
{ int index; index = f->index; if (index != 0) return -EINVAL; memset(f, 0, sizeof(*f)); f->index = index; strlcpy(f->description, "MPEG", sizeof(f->description)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0;}static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; memset(f, 0, sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; f->fmt.pix.colorspace = 0; f->fmt.pix.width = dev->ts1.width; f->fmt.pix.height = dev->ts1.height; f->fmt.pix.field = fh->mpegq.field; dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", dev->ts1.width, dev->ts1.height, fh->mpegq.field); return 0;}static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; f->fmt.pix.sizeimage = f->fmt.pix.colorspace = 0; dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->ts1.width, dev->ts1.height, fh->mpegq.field); return 0;}static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; f->fmt.pix.colorspace = 0; dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); return 0;}static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p){ struct cx23885_fh *fh = file->private_data; return videobuf_reqbufs(&fh->mpegq, p);}static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p){ struct cx23885_fh *fh = file->private_data; return videobuf_querybuf(&fh->mpegq, p);}static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p){ struct cx23885_fh *fh = file->private_data; return videobuf_qbuf(&fh->mpegq, p);}static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b){ struct cx23885_fh *fh = priv; return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);}static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx23885_fh *fh = file->private_data; return videobuf_streamon(&fh->mpegq);}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx23885_fh *fh = file->private_data; return videobuf_streamoff(&fh->mpegq);}static int vidioc_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);}static int vidioc_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; struct cx2341x_mpeg_params p; int err; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; p = dev->mpeg_params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); if (err == 0) { err = cx2341x_update(dev, cx23885_mbox_func, &dev->mpeg_params, &p); dev->mpeg_params = p; } return err;}static int vidioc_try_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; struct cx2341x_mpeg_params p; int err; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; p = dev->mpeg_params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); return err;}static int vidioc_log_status(struct file *file, void *priv){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; char name[32 + 2]; snprintf(name, sizeof(name), "%s/2", dev->name); printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS, NULL); cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS, NULL); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS, NULL); cx2341x_log_status(&dev->mpeg_params, name); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); return 0;}static int vidioc_querymenu(struct file *file, void *priv, struct v4l2_querymenu *a){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; return cx23885_querymenu(dev, a);}static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; return cx23885_queryctrl(dev, c);}static int mpeg_open(struct inode *inode, struct file *file){ int minor = iminor(inode); struct cx23885_dev *h, *dev = NULL; struct list_head *list; struct cx23885_fh *fh; dprintk(2, "%s()\n", __func__); lock_kernel(); list_for_each(list, &cx23885_devlist) { h = list_entry(list, struct cx23885_dev, devlist); if (h->v4l_device->minor == minor) { dev = h; break; } } if (dev == NULL) { unlock_kernel(); return -ENODEV; } /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { unlock_kernel(); return -ENOMEM; } file->private_data = fh; fh->dev = dev; videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops, &dev->pci->dev, &dev->ts1.slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), fh); unlock_kernel(); return 0;}static int mpeg_release(struct inode *inode, struct file *file){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; dprintk(2, "%s()\n", __func__); /* FIXME: Review this crap */ /* Shut device down on last close */ if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { if (atomic_dec_return(&dev->v4l_reader_count) == 0) { /* stop mpeg capture */ cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, CX23885_END_NOW, CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); msleep(500); cx23885_417_check_encoder(dev); cx23885_cancel_buffers(&fh->dev->ts1); } } if (fh->mpegq.streaming) videobuf_streamoff(&fh->mpegq); if (fh->mpegq.reading) videobuf_read_stop(&fh->mpegq); videobuf_mmap_free(&fh->mpegq); file->private_data = NULL; kfree(fh); return 0;}static ssize_t mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; dprintk(2, "%s()\n", __func__); /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ /* Start mpeg encoder on first read. */ if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&dev->v4l_reader_count) == 1) { if (cx23885_initialize_codec(dev) < 0) return -EINVAL; } } return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, file->f_flags & O_NONBLOCK);}static unsigned int mpeg_poll(struct file *file, struct poll_table_struct *wait){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; dprintk(2, "%s\n", __func__); return videobuf_poll_stream(file, &fh->mpegq, wait);}static int mpeg_mmap(struct file *file, struct vm_area_struct *vma){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; dprintk(2, "%s()\n", __func__); return videobuf_mmap_mapper(&fh->mpegq, vma);}static struct file_operations mpeg_fops = { .owner = THIS_MODULE, .open = mpeg_open, .release = mpeg_release, .read = mpeg_read, .poll = mpeg_poll, .mmap = mpeg_mmap, .ioctl = video_ioctl2, .llseek = no_llseek,};static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_reqbufs = vidioc_reqbufs, .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_log_status = vidioc_log_status, .vidioc_querymenu = vidioc_querymenu, .vidioc_queryctrl = vidioc_queryctrl,};static struct video_device cx23885_mpeg_template = { .name = "cx23885", .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, .minor = -1,};void cx23885_417_unregister(struct cx23885_dev *dev){ dprintk(1, "%s()\n", __func__); if (dev->v4l_device) { if (-1 != dev->v4l_device->minor) video_unregister_device(dev->v4l_device); else video_device_release(dev->v4l_device); dev->v4l_device = NULL; }}static struct video_device *cx23885_video_dev_alloc( struct cx23885_tsport *tsport, struct pci_dev *pci, struct video_device *template, char *type){ struct video_device *vfd; struct cx23885_dev *dev = tsport->dev; dprintk(1, "%s()\n", __func__); vfd = video_device_alloc(); if (NULL == vfd) return NULL; *vfd = *template; vfd->minor = -1; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx23885_boards[tsport->dev->board].name); vfd->parent = &pci->dev; vfd->release = video_device_release; return vfd;}int cx23885_417_register(struct cx23885_dev *dev){ /* FIXME: Port1 hardcoded here */ int err = -ENODEV; struct cx23885_tsport *tsport = &dev->ts1; dprintk(1, "%s()\n", __func__); if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER) return err; /* Set default TV standard */ dev->encodernorm = cx23885_tvnorms[0]; if (dev->encodernorm.id & V4L2_STD_525_60) tsport->height = 480; else tsport->height = 576; tsport->width = 720; cx2341x_fill_defaults(&dev->mpeg_params); dev->mpeg_params.port = CX2341X_PORT_SERIAL; /* Allocate and initialize V4L video device */ dev->v4l_device = cx23885_video_dev_alloc(tsport, dev->pci, &cx23885_mpeg_template, "mpeg"); err = video_register_device(dev->v4l_device, VFL_TYPE_GRABBER, -1); if (err < 0) { printk(KERN_INFO "%s: can't register mpeg device\n", dev->name); return err; } /* Initialize MC417 registers */ cx23885_mc417_init(dev); printk(KERN_INFO "%s: registered device video%d [mpeg]\n", dev->name, dev->v4l_device->num); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -