| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | cx231xx-video.c - driver for Conexant Cx23100/101/102 |
|---|
| 3 | 4 | USB video capture devices |
|---|
| .. | .. |
|---|
| 7 | 8 | Based on cx23885 driver |
|---|
| 8 | 9 | Based on cx88 driver |
|---|
| 9 | 10 | |
|---|
| 10 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - (at your option) any later version. |
|---|
| 14 | | - |
|---|
| 15 | | - This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - GNU General Public License for more details. |
|---|
| 19 | | - |
|---|
| 20 | | - You should have received a copy of the GNU General Public License |
|---|
| 21 | | - along with this program; if not, write to the Free Software |
|---|
| 22 | | - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 23 | 11 | */ |
|---|
| 24 | 12 | |
|---|
| 25 | 13 | #include "cx231xx.h" |
|---|
| .. | .. |
|---|
| 70 | 58 | MODULE_LICENSE("GPL"); |
|---|
| 71 | 59 | MODULE_VERSION(CX231XX_VERSION); |
|---|
| 72 | 60 | |
|---|
| 73 | | -static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; |
|---|
| 74 | | -static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; |
|---|
| 75 | | -static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; |
|---|
| 76 | | -static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; |
|---|
| 61 | +static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; |
|---|
| 62 | +static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; |
|---|
| 63 | +static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; |
|---|
| 64 | +static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U }; |
|---|
| 77 | 65 | |
|---|
| 78 | 66 | module_param_array(card, int, NULL, 0444); |
|---|
| 79 | 67 | module_param_array(video_nr, int, NULL, 0444); |
|---|
| .. | .. |
|---|
| 92 | 80 | /* supported video standards */ |
|---|
| 93 | 81 | static struct cx231xx_fmt format[] = { |
|---|
| 94 | 82 | { |
|---|
| 95 | | - .name = "16bpp YUY2, 4:2:2, packed", |
|---|
| 96 | 83 | .fourcc = V4L2_PIX_FMT_YUYV, |
|---|
| 97 | 84 | .depth = 16, |
|---|
| 98 | 85 | .reg = 0, |
|---|
| .. | .. |
|---|
| 179 | 166 | struct cx231xx_buffer *buf) |
|---|
| 180 | 167 | { |
|---|
| 181 | 168 | /* Advice that buffer was filled */ |
|---|
| 182 | | - cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); |
|---|
| 183 | | - buf->vb.state = VIDEOBUF_DONE; |
|---|
| 184 | | - buf->vb.field_count++; |
|---|
| 185 | | - v4l2_get_timestamp(&buf->vb.ts); |
|---|
| 169 | + cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.vb2_buf.index); |
|---|
| 170 | + buf->vb.sequence = dma_q->sequence++; |
|---|
| 171 | + buf->vb.field = V4L2_FIELD_INTERLACED; |
|---|
| 172 | + buf->vb.vb2_buf.timestamp = ktime_get_ns(); |
|---|
| 173 | + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, dev->size); |
|---|
| 186 | 174 | |
|---|
| 187 | 175 | if (dev->USE_ISO) |
|---|
| 188 | 176 | dev->video_mode.isoc_ctl.buf = NULL; |
|---|
| 189 | 177 | else |
|---|
| 190 | 178 | dev->video_mode.bulk_ctl.buf = NULL; |
|---|
| 191 | 179 | |
|---|
| 192 | | - list_del(&buf->vb.queue); |
|---|
| 193 | | - wake_up(&buf->vb.done); |
|---|
| 180 | + list_del(&buf->list); |
|---|
| 181 | + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); |
|---|
| 194 | 182 | } |
|---|
| 195 | 183 | |
|---|
| 196 | 184 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) |
|---|
| .. | .. |
|---|
| 254 | 242 | } |
|---|
| 255 | 243 | |
|---|
| 256 | 244 | /* Get the next buffer */ |
|---|
| 257 | | - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); |
|---|
| 245 | + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); |
|---|
| 258 | 246 | |
|---|
| 259 | 247 | /* Cleans up buffer - Useful for testing for frame/URB loss */ |
|---|
| 260 | | - outp = videobuf_to_vmalloc(&(*buf)->vb); |
|---|
| 261 | | - memset(outp, 0, (*buf)->vb.size); |
|---|
| 248 | + outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); |
|---|
| 249 | + memset(outp, 0, dev->size); |
|---|
| 262 | 250 | |
|---|
| 263 | 251 | if (dev->USE_ISO) |
|---|
| 264 | 252 | dev->video_mode.isoc_ctl.buf = *buf; |
|---|
| .. | .. |
|---|
| 666 | 654 | if (buf == NULL) |
|---|
| 667 | 655 | return -1; |
|---|
| 668 | 656 | |
|---|
| 669 | | - p_out_buffer = videobuf_to_vmalloc(&buf->vb); |
|---|
| 657 | + p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); |
|---|
| 670 | 658 | |
|---|
| 671 | 659 | current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; |
|---|
| 672 | 660 | |
|---|
| .. | .. |
|---|
| 685 | 673 | lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? |
|---|
| 686 | 674 | bytes_to_copy : dma_q->bytes_left_in_line; |
|---|
| 687 | 675 | |
|---|
| 688 | | - if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size)) |
|---|
| 676 | + if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + dev->size)) |
|---|
| 689 | 677 | return 0; |
|---|
| 690 | 678 | |
|---|
| 691 | 679 | /* The below copies the UYVY data straight into video buffer */ |
|---|
| .. | .. |
|---|
| 721 | 709 | Videobuf operations |
|---|
| 722 | 710 | ------------------------------------------------------------------*/ |
|---|
| 723 | 711 | |
|---|
| 724 | | -static int |
|---|
| 725 | | -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) |
|---|
| 712 | +static int queue_setup(struct vb2_queue *vq, |
|---|
| 713 | + unsigned int *nbuffers, unsigned int *nplanes, |
|---|
| 714 | + unsigned int sizes[], struct device *alloc_devs[]) |
|---|
| 726 | 715 | { |
|---|
| 727 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 728 | | - struct cx231xx *dev = fh->dev; |
|---|
| 716 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 729 | 717 | |
|---|
| 730 | | - *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3; |
|---|
| 731 | | - if (0 == *count) |
|---|
| 732 | | - *count = CX231XX_DEF_BUF; |
|---|
| 718 | + dev->size = (dev->width * dev->height * dev->format->depth + 7) >> 3; |
|---|
| 733 | 719 | |
|---|
| 734 | | - if (*count < CX231XX_MIN_BUF) |
|---|
| 735 | | - *count = CX231XX_MIN_BUF; |
|---|
| 720 | + if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF) |
|---|
| 721 | + *nbuffers = CX231XX_MIN_BUF - vq->num_buffers; |
|---|
| 736 | 722 | |
|---|
| 737 | | - |
|---|
| 738 | | - cx231xx_enable_analog_tuner(dev); |
|---|
| 723 | + if (*nplanes) |
|---|
| 724 | + return sizes[0] < dev->size ? -EINVAL : 0; |
|---|
| 725 | + *nplanes = 1; |
|---|
| 726 | + sizes[0] = dev->size; |
|---|
| 739 | 727 | |
|---|
| 740 | 728 | return 0; |
|---|
| 741 | 729 | } |
|---|
| 742 | 730 | |
|---|
| 743 | | -/* This is called *without* dev->slock held; please keep it that way */ |
|---|
| 744 | | -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) |
|---|
| 731 | +static void buffer_queue(struct vb2_buffer *vb) |
|---|
| 745 | 732 | { |
|---|
| 746 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 747 | | - struct cx231xx *dev = fh->dev; |
|---|
| 748 | | - unsigned long flags = 0; |
|---|
| 733 | + struct cx231xx_buffer *buf = |
|---|
| 734 | + container_of(vb, struct cx231xx_buffer, vb.vb2_buf); |
|---|
| 735 | + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); |
|---|
| 736 | + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; |
|---|
| 737 | + unsigned long flags; |
|---|
| 749 | 738 | |
|---|
| 750 | | - BUG_ON(in_interrupt()); |
|---|
| 751 | | - |
|---|
| 752 | | - /* We used to wait for the buffer to finish here, but this didn't work |
|---|
| 753 | | - because, as we were keeping the state as VIDEOBUF_QUEUED, |
|---|
| 754 | | - videobuf_queue_cancel marked it as finished for us. |
|---|
| 755 | | - (Also, it could wedge forever if the hardware was misconfigured.) |
|---|
| 756 | | - |
|---|
| 757 | | - This should be safe; by the time we get here, the buffer isn't |
|---|
| 758 | | - queued anymore. If we ever start marking the buffers as |
|---|
| 759 | | - VIDEOBUF_ACTIVE, it won't be, though. |
|---|
| 760 | | - */ |
|---|
| 761 | 739 | spin_lock_irqsave(&dev->video_mode.slock, flags); |
|---|
| 762 | | - if (dev->USE_ISO) { |
|---|
| 763 | | - if (dev->video_mode.isoc_ctl.buf == buf) |
|---|
| 764 | | - dev->video_mode.isoc_ctl.buf = NULL; |
|---|
| 765 | | - } else { |
|---|
| 766 | | - if (dev->video_mode.bulk_ctl.buf == buf) |
|---|
| 767 | | - dev->video_mode.bulk_ctl.buf = NULL; |
|---|
| 740 | + list_add_tail(&buf->list, &vidq->active); |
|---|
| 741 | + spin_unlock_irqrestore(&dev->video_mode.slock, flags); |
|---|
| 742 | +} |
|---|
| 743 | + |
|---|
| 744 | +static void return_all_buffers(struct cx231xx *dev, |
|---|
| 745 | + enum vb2_buffer_state state) |
|---|
| 746 | +{ |
|---|
| 747 | + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; |
|---|
| 748 | + struct cx231xx_buffer *buf, *node; |
|---|
| 749 | + unsigned long flags; |
|---|
| 750 | + |
|---|
| 751 | + spin_lock_irqsave(&dev->video_mode.slock, flags); |
|---|
| 752 | + if (dev->USE_ISO) |
|---|
| 753 | + dev->video_mode.isoc_ctl.buf = NULL; |
|---|
| 754 | + else |
|---|
| 755 | + dev->video_mode.bulk_ctl.buf = NULL; |
|---|
| 756 | + list_for_each_entry_safe(buf, node, &vidq->active, list) { |
|---|
| 757 | + list_del(&buf->list); |
|---|
| 758 | + vb2_buffer_done(&buf->vb.vb2_buf, state); |
|---|
| 768 | 759 | } |
|---|
| 769 | 760 | spin_unlock_irqrestore(&dev->video_mode.slock, flags); |
|---|
| 770 | | - |
|---|
| 771 | | - videobuf_vmalloc_free(&buf->vb); |
|---|
| 772 | | - buf->vb.state = VIDEOBUF_NEEDS_INIT; |
|---|
| 773 | 761 | } |
|---|
| 774 | 762 | |
|---|
| 775 | | -static int |
|---|
| 776 | | -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
|---|
| 777 | | - enum v4l2_field field) |
|---|
| 763 | +static int start_streaming(struct vb2_queue *vq, unsigned int count) |
|---|
| 778 | 764 | { |
|---|
| 779 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 780 | | - struct cx231xx_buffer *buf = |
|---|
| 781 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 782 | | - struct cx231xx *dev = fh->dev; |
|---|
| 783 | | - int rc = 0, urb_init = 0; |
|---|
| 784 | | - |
|---|
| 785 | | - /* The only currently supported format is 16 bits/pixel */ |
|---|
| 786 | | - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth |
|---|
| 787 | | - + 7) >> 3; |
|---|
| 788 | | - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
|---|
| 789 | | - return -EINVAL; |
|---|
| 790 | | - |
|---|
| 791 | | - buf->vb.width = dev->width; |
|---|
| 792 | | - buf->vb.height = dev->height; |
|---|
| 793 | | - buf->vb.field = field; |
|---|
| 794 | | - |
|---|
| 795 | | - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
|---|
| 796 | | - rc = videobuf_iolock(vq, &buf->vb, NULL); |
|---|
| 797 | | - if (rc < 0) |
|---|
| 798 | | - goto fail; |
|---|
| 799 | | - } |
|---|
| 800 | | - |
|---|
| 801 | | - if (dev->USE_ISO) { |
|---|
| 802 | | - if (!dev->video_mode.isoc_ctl.num_bufs) |
|---|
| 803 | | - urb_init = 1; |
|---|
| 804 | | - } else { |
|---|
| 805 | | - if (!dev->video_mode.bulk_ctl.num_bufs) |
|---|
| 806 | | - urb_init = 1; |
|---|
| 807 | | - } |
|---|
| 808 | | - dev_dbg(dev->dev, |
|---|
| 809 | | - "urb_init=%d dev->video_mode.max_pkt_size=%d\n", |
|---|
| 810 | | - urb_init, dev->video_mode.max_pkt_size); |
|---|
| 811 | | - if (urb_init) { |
|---|
| 812 | | - dev->mode_tv = 0; |
|---|
| 813 | | - if (dev->USE_ISO) |
|---|
| 814 | | - rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, |
|---|
| 815 | | - CX231XX_NUM_BUFS, |
|---|
| 816 | | - dev->video_mode.max_pkt_size, |
|---|
| 817 | | - cx231xx_isoc_copy); |
|---|
| 818 | | - else |
|---|
| 819 | | - rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS, |
|---|
| 820 | | - CX231XX_NUM_BUFS, |
|---|
| 821 | | - dev->video_mode.max_pkt_size, |
|---|
| 822 | | - cx231xx_bulk_copy); |
|---|
| 823 | | - if (rc < 0) |
|---|
| 824 | | - goto fail; |
|---|
| 825 | | - } |
|---|
| 826 | | - |
|---|
| 827 | | - buf->vb.state = VIDEOBUF_PREPARED; |
|---|
| 828 | | - |
|---|
| 829 | | - return 0; |
|---|
| 830 | | - |
|---|
| 831 | | -fail: |
|---|
| 832 | | - free_buffer(vq, buf); |
|---|
| 833 | | - return rc; |
|---|
| 834 | | -} |
|---|
| 835 | | - |
|---|
| 836 | | -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
|---|
| 837 | | -{ |
|---|
| 838 | | - struct cx231xx_buffer *buf = |
|---|
| 839 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 840 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 841 | | - struct cx231xx *dev = fh->dev; |
|---|
| 765 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 842 | 766 | struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; |
|---|
| 767 | + int ret = 0; |
|---|
| 843 | 768 | |
|---|
| 844 | | - buf->vb.state = VIDEOBUF_QUEUED; |
|---|
| 845 | | - list_add_tail(&buf->vb.queue, &vidq->active); |
|---|
| 769 | + vidq->sequence = 0; |
|---|
| 770 | + dev->mode_tv = 0; |
|---|
| 846 | 771 | |
|---|
| 772 | + cx231xx_enable_analog_tuner(dev); |
|---|
| 773 | + if (dev->USE_ISO) |
|---|
| 774 | + ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, |
|---|
| 775 | + CX231XX_NUM_BUFS, |
|---|
| 776 | + dev->video_mode.max_pkt_size, |
|---|
| 777 | + cx231xx_isoc_copy); |
|---|
| 778 | + else |
|---|
| 779 | + ret = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS, |
|---|
| 780 | + CX231XX_NUM_BUFS, |
|---|
| 781 | + dev->video_mode.max_pkt_size, |
|---|
| 782 | + cx231xx_bulk_copy); |
|---|
| 783 | + if (ret) |
|---|
| 784 | + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); |
|---|
| 785 | + call_all(dev, video, s_stream, 1); |
|---|
| 786 | + return ret; |
|---|
| 847 | 787 | } |
|---|
| 848 | 788 | |
|---|
| 849 | | -static void buffer_release(struct videobuf_queue *vq, |
|---|
| 850 | | - struct videobuf_buffer *vb) |
|---|
| 789 | +static void stop_streaming(struct vb2_queue *vq) |
|---|
| 851 | 790 | { |
|---|
| 852 | | - struct cx231xx_buffer *buf = |
|---|
| 853 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 854 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 855 | | - struct cx231xx *dev = (struct cx231xx *)fh->dev; |
|---|
| 791 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 856 | 792 | |
|---|
| 857 | | - cx231xx_isocdbg("cx231xx: called buffer_release\n"); |
|---|
| 858 | | - |
|---|
| 859 | | - free_buffer(vq, buf); |
|---|
| 793 | + call_all(dev, video, s_stream, 0); |
|---|
| 794 | + return_all_buffers(dev, VB2_BUF_STATE_ERROR); |
|---|
| 860 | 795 | } |
|---|
| 861 | 796 | |
|---|
| 862 | | -static const struct videobuf_queue_ops cx231xx_video_qops = { |
|---|
| 863 | | - .buf_setup = buffer_setup, |
|---|
| 864 | | - .buf_prepare = buffer_prepare, |
|---|
| 865 | | - .buf_queue = buffer_queue, |
|---|
| 866 | | - .buf_release = buffer_release, |
|---|
| 797 | +static struct vb2_ops cx231xx_video_qops = { |
|---|
| 798 | + .queue_setup = queue_setup, |
|---|
| 799 | + .buf_queue = buffer_queue, |
|---|
| 800 | + .start_streaming = start_streaming, |
|---|
| 801 | + .stop_streaming = stop_streaming, |
|---|
| 802 | + .wait_prepare = vb2_ops_wait_prepare, |
|---|
| 803 | + .wait_finish = vb2_ops_wait_finish, |
|---|
| 867 | 804 | }; |
|---|
| 868 | 805 | |
|---|
| 869 | 806 | /********************* v4l2 interface **************************************/ |
|---|
| .. | .. |
|---|
| 885 | 822 | cx231xx_do_mode_ctrl_overrides(dev); |
|---|
| 886 | 823 | } |
|---|
| 887 | 824 | |
|---|
| 888 | | -/* Usage lock check functions */ |
|---|
| 889 | | -static int res_get(struct cx231xx_fh *fh) |
|---|
| 890 | | -{ |
|---|
| 891 | | - struct cx231xx *dev = fh->dev; |
|---|
| 892 | | - int rc = 0; |
|---|
| 893 | | - |
|---|
| 894 | | - /* This instance already has stream_on */ |
|---|
| 895 | | - if (fh->stream_on) |
|---|
| 896 | | - return rc; |
|---|
| 897 | | - |
|---|
| 898 | | - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
|---|
| 899 | | - if (dev->stream_on) |
|---|
| 900 | | - return -EBUSY; |
|---|
| 901 | | - dev->stream_on = 1; |
|---|
| 902 | | - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
|---|
| 903 | | - if (dev->vbi_stream_on) |
|---|
| 904 | | - return -EBUSY; |
|---|
| 905 | | - dev->vbi_stream_on = 1; |
|---|
| 906 | | - } else |
|---|
| 907 | | - return -EINVAL; |
|---|
| 908 | | - |
|---|
| 909 | | - fh->stream_on = 1; |
|---|
| 910 | | - |
|---|
| 911 | | - return rc; |
|---|
| 912 | | -} |
|---|
| 913 | | - |
|---|
| 914 | | -static int res_check(struct cx231xx_fh *fh) |
|---|
| 915 | | -{ |
|---|
| 916 | | - return fh->stream_on; |
|---|
| 917 | | -} |
|---|
| 918 | | - |
|---|
| 919 | | -static void res_free(struct cx231xx_fh *fh) |
|---|
| 920 | | -{ |
|---|
| 921 | | - struct cx231xx *dev = fh->dev; |
|---|
| 922 | | - |
|---|
| 923 | | - fh->stream_on = 0; |
|---|
| 924 | | - |
|---|
| 925 | | - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 926 | | - dev->stream_on = 0; |
|---|
| 927 | | - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) |
|---|
| 928 | | - dev->vbi_stream_on = 0; |
|---|
| 929 | | -} |
|---|
| 930 | | - |
|---|
| 931 | | -static int check_dev(struct cx231xx *dev) |
|---|
| 932 | | -{ |
|---|
| 933 | | - if (dev->state & DEV_DISCONNECTED) { |
|---|
| 934 | | - dev_err(dev->dev, "v4l2 ioctl: device not present\n"); |
|---|
| 935 | | - return -ENODEV; |
|---|
| 936 | | - } |
|---|
| 937 | | - return 0; |
|---|
| 938 | | -} |
|---|
| 939 | | - |
|---|
| 940 | 825 | /* ------------------------------------------------------------------ |
|---|
| 941 | 826 | IOCTL vidioc handling |
|---|
| 942 | 827 | ------------------------------------------------------------------*/ |
|---|
| .. | .. |
|---|
| 944 | 829 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 945 | 830 | struct v4l2_format *f) |
|---|
| 946 | 831 | { |
|---|
| 947 | | - struct cx231xx_fh *fh = priv; |
|---|
| 948 | | - struct cx231xx *dev = fh->dev; |
|---|
| 832 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 949 | 833 | |
|---|
| 950 | 834 | f->fmt.pix.width = dev->width; |
|---|
| 951 | 835 | f->fmt.pix.height = dev->height; |
|---|
| .. | .. |
|---|
| 973 | 857 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 974 | 858 | struct v4l2_format *f) |
|---|
| 975 | 859 | { |
|---|
| 976 | | - struct cx231xx_fh *fh = priv; |
|---|
| 977 | | - struct cx231xx *dev = fh->dev; |
|---|
| 860 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 978 | 861 | unsigned int width = f->fmt.pix.width; |
|---|
| 979 | 862 | unsigned int height = f->fmt.pix.height; |
|---|
| 980 | 863 | unsigned int maxw = norm_maxw(dev); |
|---|
| .. | .. |
|---|
| 1006 | 889 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 1007 | 890 | struct v4l2_format *f) |
|---|
| 1008 | 891 | { |
|---|
| 1009 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1010 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1011 | | - int rc; |
|---|
| 1012 | | - struct cx231xx_fmt *fmt; |
|---|
| 892 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1013 | 893 | struct v4l2_subdev_format format = { |
|---|
| 1014 | 894 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, |
|---|
| 1015 | 895 | }; |
|---|
| 896 | + int rc; |
|---|
| 1016 | 897 | |
|---|
| 1017 | | - rc = check_dev(dev); |
|---|
| 1018 | | - if (rc < 0) |
|---|
| 898 | + rc = vidioc_try_fmt_vid_cap(file, priv, f); |
|---|
| 899 | + if (rc) |
|---|
| 1019 | 900 | return rc; |
|---|
| 1020 | 901 | |
|---|
| 1021 | | - vidioc_try_fmt_vid_cap(file, priv, f); |
|---|
| 1022 | | - |
|---|
| 1023 | | - fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
|---|
| 1024 | | - if (!fmt) |
|---|
| 1025 | | - return -EINVAL; |
|---|
| 1026 | | - |
|---|
| 1027 | | - if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
|---|
| 902 | + if (vb2_is_busy(&dev->vidq)) { |
|---|
| 1028 | 903 | dev_err(dev->dev, "%s: queue busy\n", __func__); |
|---|
| 1029 | | - return -EBUSY; |
|---|
| 1030 | | - } |
|---|
| 1031 | | - |
|---|
| 1032 | | - if (dev->stream_on && !fh->stream_on) { |
|---|
| 1033 | | - dev_err(dev->dev, |
|---|
| 1034 | | - "%s: device in use by another fh\n", __func__); |
|---|
| 1035 | 904 | return -EBUSY; |
|---|
| 1036 | 905 | } |
|---|
| 1037 | 906 | |
|---|
| 1038 | 907 | /* set new image size */ |
|---|
| 1039 | 908 | dev->width = f->fmt.pix.width; |
|---|
| 1040 | 909 | dev->height = f->fmt.pix.height; |
|---|
| 1041 | | - dev->format = fmt; |
|---|
| 910 | + dev->format = format_by_fourcc(f->fmt.pix.pixelformat); |
|---|
| 1042 | 911 | |
|---|
| 1043 | 912 | v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED); |
|---|
| 1044 | 913 | call_all(dev, pad, set_fmt, NULL, &format); |
|---|
| .. | .. |
|---|
| 1049 | 918 | |
|---|
| 1050 | 919 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) |
|---|
| 1051 | 920 | { |
|---|
| 1052 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1053 | | - struct cx231xx *dev = fh->dev; |
|---|
| 921 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1054 | 922 | |
|---|
| 1055 | 923 | *id = dev->norm; |
|---|
| 1056 | 924 | return 0; |
|---|
| .. | .. |
|---|
| 1058 | 926 | |
|---|
| 1059 | 927 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) |
|---|
| 1060 | 928 | { |
|---|
| 1061 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1062 | | - struct cx231xx *dev = fh->dev; |
|---|
| 929 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1063 | 930 | struct v4l2_subdev_format format = { |
|---|
| 1064 | 931 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, |
|---|
| 1065 | 932 | }; |
|---|
| 1066 | | - int rc; |
|---|
| 1067 | | - |
|---|
| 1068 | | - rc = check_dev(dev); |
|---|
| 1069 | | - if (rc < 0) |
|---|
| 1070 | | - return rc; |
|---|
| 1071 | 933 | |
|---|
| 1072 | 934 | if (dev->norm == norm) |
|---|
| 1073 | 935 | return 0; |
|---|
| 1074 | 936 | |
|---|
| 1075 | | - if (videobuf_queue_is_busy(&fh->vb_vidq)) |
|---|
| 937 | + if (vb2_is_busy(&dev->vidq)) |
|---|
| 1076 | 938 | return -EBUSY; |
|---|
| 1077 | 939 | |
|---|
| 1078 | 940 | dev->norm = norm; |
|---|
| .. | .. |
|---|
| 1134 | 996 | /* The DVB core will handle it */ |
|---|
| 1135 | 997 | if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 1136 | 998 | continue; |
|---|
| 1137 | | - /* fall through */ |
|---|
| 999 | + fallthrough; |
|---|
| 1138 | 1000 | default: /* just to shut up a gcc warning */ |
|---|
| 1139 | 1001 | ent->function = MEDIA_ENT_F_CONN_RF; |
|---|
| 1140 | 1002 | break; |
|---|
| .. | .. |
|---|
| 1154 | 1016 | int cx231xx_enum_input(struct file *file, void *priv, |
|---|
| 1155 | 1017 | struct v4l2_input *i) |
|---|
| 1156 | 1018 | { |
|---|
| 1157 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1158 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1019 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1159 | 1020 | u32 gen_stat; |
|---|
| 1160 | 1021 | unsigned int n; |
|---|
| 1161 | 1022 | int ret; |
|---|
| .. | .. |
|---|
| 1169 | 1030 | i->index = n; |
|---|
| 1170 | 1031 | i->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 1171 | 1032 | |
|---|
| 1172 | | - strcpy(i->name, iname[INPUT(n)->type]); |
|---|
| 1033 | + strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name)); |
|---|
| 1173 | 1034 | |
|---|
| 1174 | 1035 | if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || |
|---|
| 1175 | 1036 | (CX231XX_VMUX_CABLE == INPUT(n)->type)) |
|---|
| .. | .. |
|---|
| 1194 | 1055 | |
|---|
| 1195 | 1056 | int cx231xx_g_input(struct file *file, void *priv, unsigned int *i) |
|---|
| 1196 | 1057 | { |
|---|
| 1197 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1198 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1058 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1199 | 1059 | |
|---|
| 1200 | 1060 | *i = dev->video_input; |
|---|
| 1201 | 1061 | |
|---|
| .. | .. |
|---|
| 1204 | 1064 | |
|---|
| 1205 | 1065 | int cx231xx_s_input(struct file *file, void *priv, unsigned int i) |
|---|
| 1206 | 1066 | { |
|---|
| 1207 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1208 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1209 | | - int rc; |
|---|
| 1067 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1210 | 1068 | |
|---|
| 1211 | 1069 | dev->mode_tv = 0; |
|---|
| 1212 | | - rc = check_dev(dev); |
|---|
| 1213 | | - if (rc < 0) |
|---|
| 1214 | | - return rc; |
|---|
| 1215 | 1070 | |
|---|
| 1216 | 1071 | if (i >= MAX_CX231XX_INPUT) |
|---|
| 1217 | 1072 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1233 | 1088 | |
|---|
| 1234 | 1089 | int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
|---|
| 1235 | 1090 | { |
|---|
| 1236 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1237 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1238 | | - int rc; |
|---|
| 1239 | | - |
|---|
| 1240 | | - rc = check_dev(dev); |
|---|
| 1241 | | - if (rc < 0) |
|---|
| 1242 | | - return rc; |
|---|
| 1091 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1243 | 1092 | |
|---|
| 1244 | 1093 | if (0 != t->index) |
|---|
| 1245 | 1094 | return -EINVAL; |
|---|
| 1246 | 1095 | |
|---|
| 1247 | | - strcpy(t->name, "Tuner"); |
|---|
| 1096 | + strscpy(t->name, "Tuner", sizeof(t->name)); |
|---|
| 1248 | 1097 | |
|---|
| 1249 | 1098 | t->type = V4L2_TUNER_ANALOG_TV; |
|---|
| 1250 | 1099 | t->capability = V4L2_TUNER_CAP_NORM; |
|---|
| .. | .. |
|---|
| 1257 | 1106 | |
|---|
| 1258 | 1107 | int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) |
|---|
| 1259 | 1108 | { |
|---|
| 1260 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1261 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1262 | | - int rc; |
|---|
| 1263 | | - |
|---|
| 1264 | | - rc = check_dev(dev); |
|---|
| 1265 | | - if (rc < 0) |
|---|
| 1266 | | - return rc; |
|---|
| 1267 | | - |
|---|
| 1268 | 1109 | if (0 != t->index) |
|---|
| 1269 | 1110 | return -EINVAL; |
|---|
| 1270 | | -#if 0 |
|---|
| 1271 | | - call_all(dev, tuner, s_tuner, t); |
|---|
| 1272 | | -#endif |
|---|
| 1273 | 1111 | return 0; |
|---|
| 1274 | 1112 | } |
|---|
| 1275 | 1113 | |
|---|
| 1276 | 1114 | int cx231xx_g_frequency(struct file *file, void *priv, |
|---|
| 1277 | 1115 | struct v4l2_frequency *f) |
|---|
| 1278 | 1116 | { |
|---|
| 1279 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1280 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1117 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1281 | 1118 | |
|---|
| 1282 | 1119 | if (f->tuner) |
|---|
| 1283 | 1120 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1290 | 1127 | int cx231xx_s_frequency(struct file *file, void *priv, |
|---|
| 1291 | 1128 | const struct v4l2_frequency *f) |
|---|
| 1292 | 1129 | { |
|---|
| 1293 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1294 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1130 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1295 | 1131 | struct v4l2_frequency new_freq = *f; |
|---|
| 1296 | | - int rc; |
|---|
| 1132 | + int rc, need_if_freq = 0; |
|---|
| 1297 | 1133 | u32 if_frequency = 5400000; |
|---|
| 1298 | 1134 | |
|---|
| 1299 | 1135 | dev_dbg(dev->dev, |
|---|
| 1300 | 1136 | "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n", |
|---|
| 1301 | 1137 | f->frequency, f->type); |
|---|
| 1302 | | - |
|---|
| 1303 | | - rc = check_dev(dev); |
|---|
| 1304 | | - if (rc < 0) |
|---|
| 1305 | | - return rc; |
|---|
| 1306 | 1138 | |
|---|
| 1307 | 1139 | if (0 != f->tuner) |
|---|
| 1308 | 1140 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1310 | 1142 | /* set pre channel change settings in DIF first */ |
|---|
| 1311 | 1143 | rc = cx231xx_tuner_pre_channel_change(dev); |
|---|
| 1312 | 1144 | |
|---|
| 1313 | | - call_all(dev, tuner, s_frequency, f); |
|---|
| 1314 | | - call_all(dev, tuner, g_frequency, &new_freq); |
|---|
| 1315 | | - dev->ctl_freq = new_freq.frequency; |
|---|
| 1145 | + switch (dev->model) { /* i2c device tuners */ |
|---|
| 1146 | + case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: |
|---|
| 1147 | + case CX231XX_BOARD_HAUPPAUGE_935C: |
|---|
| 1148 | + case CX231XX_BOARD_HAUPPAUGE_955Q: |
|---|
| 1149 | + case CX231XX_BOARD_HAUPPAUGE_975: |
|---|
| 1150 | + case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: |
|---|
| 1151 | + if (dev->cx231xx_set_analog_freq) |
|---|
| 1152 | + dev->cx231xx_set_analog_freq(dev, f->frequency); |
|---|
| 1153 | + dev->ctl_freq = f->frequency; |
|---|
| 1154 | + need_if_freq = 1; |
|---|
| 1155 | + break; |
|---|
| 1156 | + default: |
|---|
| 1157 | + call_all(dev, tuner, s_frequency, f); |
|---|
| 1158 | + call_all(dev, tuner, g_frequency, &new_freq); |
|---|
| 1159 | + dev->ctl_freq = new_freq.frequency; |
|---|
| 1160 | + break; |
|---|
| 1161 | + } |
|---|
| 1162 | + |
|---|
| 1163 | + pr_debug("%s() %u : %u\n", __func__, f->frequency, dev->ctl_freq); |
|---|
| 1316 | 1164 | |
|---|
| 1317 | 1165 | /* set post channel change settings in DIF first */ |
|---|
| 1318 | 1166 | rc = cx231xx_tuner_post_channel_change(dev); |
|---|
| 1319 | 1167 | |
|---|
| 1320 | | - if (dev->tuner_type == TUNER_NXP_TDA18271) { |
|---|
| 1168 | + if (need_if_freq || dev->tuner_type == TUNER_NXP_TDA18271) { |
|---|
| 1321 | 1169 | if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443)) |
|---|
| 1322 | 1170 | if_frequency = 5400000; /*5.4MHz */ |
|---|
| 1323 | 1171 | else if (dev->norm & V4L2_STD_B) |
|---|
| .. | .. |
|---|
| 1354 | 1202 | case 0: /* Cx231xx - internal registers */ |
|---|
| 1355 | 1203 | return 0; |
|---|
| 1356 | 1204 | case 1: /* AFE - read byte */ |
|---|
| 1357 | | - strlcpy(chip->name, "AFE (byte)", sizeof(chip->name)); |
|---|
| 1205 | + strscpy(chip->name, "AFE (byte)", sizeof(chip->name)); |
|---|
| 1358 | 1206 | return 0; |
|---|
| 1359 | 1207 | case 2: /* Video Block - read byte */ |
|---|
| 1360 | | - strlcpy(chip->name, "Video (byte)", sizeof(chip->name)); |
|---|
| 1208 | + strscpy(chip->name, "Video (byte)", sizeof(chip->name)); |
|---|
| 1361 | 1209 | return 0; |
|---|
| 1362 | 1210 | case 3: /* I2S block - read byte */ |
|---|
| 1363 | | - strlcpy(chip->name, "I2S (byte)", sizeof(chip->name)); |
|---|
| 1211 | + strscpy(chip->name, "I2S (byte)", sizeof(chip->name)); |
|---|
| 1364 | 1212 | return 0; |
|---|
| 1365 | 1213 | case 4: /* AFE - read dword */ |
|---|
| 1366 | | - strlcpy(chip->name, "AFE (dword)", sizeof(chip->name)); |
|---|
| 1214 | + strscpy(chip->name, "AFE (dword)", sizeof(chip->name)); |
|---|
| 1367 | 1215 | return 0; |
|---|
| 1368 | 1216 | case 5: /* Video Block - read dword */ |
|---|
| 1369 | | - strlcpy(chip->name, "Video (dword)", sizeof(chip->name)); |
|---|
| 1217 | + strscpy(chip->name, "Video (dword)", sizeof(chip->name)); |
|---|
| 1370 | 1218 | return 0; |
|---|
| 1371 | 1219 | case 6: /* I2S Block - read dword */ |
|---|
| 1372 | | - strlcpy(chip->name, "I2S (dword)", sizeof(chip->name)); |
|---|
| 1220 | + strscpy(chip->name, "I2S (dword)", sizeof(chip->name)); |
|---|
| 1373 | 1221 | return 0; |
|---|
| 1374 | 1222 | } |
|---|
| 1375 | 1223 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1378 | 1226 | int cx231xx_g_register(struct file *file, void *priv, |
|---|
| 1379 | 1227 | struct v4l2_dbg_register *reg) |
|---|
| 1380 | 1228 | { |
|---|
| 1381 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1382 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1229 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1383 | 1230 | int ret; |
|---|
| 1384 | 1231 | u8 value[4] = { 0, 0, 0, 0 }; |
|---|
| 1385 | 1232 | u32 data = 0; |
|---|
| .. | .. |
|---|
| 1437 | 1284 | int cx231xx_s_register(struct file *file, void *priv, |
|---|
| 1438 | 1285 | const struct v4l2_dbg_register *reg) |
|---|
| 1439 | 1286 | { |
|---|
| 1440 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1441 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1287 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1442 | 1288 | int ret; |
|---|
| 1443 | 1289 | u8 data[4] = { 0, 0, 0, 0 }; |
|---|
| 1444 | 1290 | |
|---|
| .. | .. |
|---|
| 1482 | 1328 | } |
|---|
| 1483 | 1329 | #endif |
|---|
| 1484 | 1330 | |
|---|
| 1485 | | -static int vidioc_cropcap(struct file *file, void *priv, |
|---|
| 1486 | | - struct v4l2_cropcap *cc) |
|---|
| 1331 | +static int vidioc_g_pixelaspect(struct file *file, void *priv, |
|---|
| 1332 | + int type, struct v4l2_fract *f) |
|---|
| 1487 | 1333 | { |
|---|
| 1488 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1489 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1334 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1490 | 1335 | bool is_50hz = dev->norm & V4L2_STD_625_50; |
|---|
| 1491 | 1336 | |
|---|
| 1492 | | - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 1337 | + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 1493 | 1338 | return -EINVAL; |
|---|
| 1494 | 1339 | |
|---|
| 1495 | | - cc->bounds.left = 0; |
|---|
| 1496 | | - cc->bounds.top = 0; |
|---|
| 1497 | | - cc->bounds.width = dev->width; |
|---|
| 1498 | | - cc->bounds.height = dev->height; |
|---|
| 1499 | | - cc->defrect = cc->bounds; |
|---|
| 1500 | | - cc->pixelaspect.numerator = is_50hz ? 54 : 11; |
|---|
| 1501 | | - cc->pixelaspect.denominator = is_50hz ? 59 : 10; |
|---|
| 1340 | + f->numerator = is_50hz ? 54 : 11; |
|---|
| 1341 | + f->denominator = is_50hz ? 59 : 10; |
|---|
| 1502 | 1342 | |
|---|
| 1503 | 1343 | return 0; |
|---|
| 1504 | 1344 | } |
|---|
| 1505 | 1345 | |
|---|
| 1506 | | -static int vidioc_streamon(struct file *file, void *priv, |
|---|
| 1507 | | - enum v4l2_buf_type type) |
|---|
| 1346 | +static int vidioc_g_selection(struct file *file, void *priv, |
|---|
| 1347 | + struct v4l2_selection *s) |
|---|
| 1508 | 1348 | { |
|---|
| 1509 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1510 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1511 | | - int rc; |
|---|
| 1349 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1512 | 1350 | |
|---|
| 1513 | | - rc = check_dev(dev); |
|---|
| 1514 | | - if (rc < 0) |
|---|
| 1515 | | - return rc; |
|---|
| 1516 | | - |
|---|
| 1517 | | - rc = res_get(fh); |
|---|
| 1518 | | - |
|---|
| 1519 | | - if (likely(rc >= 0)) |
|---|
| 1520 | | - rc = videobuf_streamon(&fh->vb_vidq); |
|---|
| 1521 | | - |
|---|
| 1522 | | - call_all(dev, video, s_stream, 1); |
|---|
| 1523 | | - |
|---|
| 1524 | | - return rc; |
|---|
| 1525 | | -} |
|---|
| 1526 | | - |
|---|
| 1527 | | -static int vidioc_streamoff(struct file *file, void *priv, |
|---|
| 1528 | | - enum v4l2_buf_type type) |
|---|
| 1529 | | -{ |
|---|
| 1530 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1531 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1532 | | - int rc; |
|---|
| 1533 | | - |
|---|
| 1534 | | - rc = check_dev(dev); |
|---|
| 1535 | | - if (rc < 0) |
|---|
| 1536 | | - return rc; |
|---|
| 1537 | | - |
|---|
| 1538 | | - if (type != fh->type) |
|---|
| 1351 | + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 1539 | 1352 | return -EINVAL; |
|---|
| 1540 | 1353 | |
|---|
| 1541 | | - cx25840_call(dev, video, s_stream, 0); |
|---|
| 1542 | | - |
|---|
| 1543 | | - videobuf_streamoff(&fh->vb_vidq); |
|---|
| 1544 | | - res_free(fh); |
|---|
| 1545 | | - |
|---|
| 1354 | + switch (s->target) { |
|---|
| 1355 | + case V4L2_SEL_TGT_CROP_BOUNDS: |
|---|
| 1356 | + case V4L2_SEL_TGT_CROP_DEFAULT: |
|---|
| 1357 | + s->r.left = 0; |
|---|
| 1358 | + s->r.top = 0; |
|---|
| 1359 | + s->r.width = dev->width; |
|---|
| 1360 | + s->r.height = dev->height; |
|---|
| 1361 | + break; |
|---|
| 1362 | + default: |
|---|
| 1363 | + return -EINVAL; |
|---|
| 1364 | + } |
|---|
| 1546 | 1365 | return 0; |
|---|
| 1547 | 1366 | } |
|---|
| 1548 | 1367 | |
|---|
| 1549 | 1368 | int cx231xx_querycap(struct file *file, void *priv, |
|---|
| 1550 | 1369 | struct v4l2_capability *cap) |
|---|
| 1551 | 1370 | { |
|---|
| 1552 | | - struct video_device *vdev = video_devdata(file); |
|---|
| 1553 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1554 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1371 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1555 | 1372 | |
|---|
| 1556 | | - strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); |
|---|
| 1557 | | - strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); |
|---|
| 1373 | + strscpy(cap->driver, "cx231xx", sizeof(cap->driver)); |
|---|
| 1374 | + strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); |
|---|
| 1558 | 1375 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); |
|---|
| 1559 | | - |
|---|
| 1560 | | - if (vdev->vfl_type == VFL_TYPE_RADIO) |
|---|
| 1561 | | - cap->device_caps = V4L2_CAP_RADIO; |
|---|
| 1562 | | - else { |
|---|
| 1563 | | - cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; |
|---|
| 1564 | | - if (vdev->vfl_type == VFL_TYPE_VBI) |
|---|
| 1565 | | - cap->device_caps |= V4L2_CAP_VBI_CAPTURE; |
|---|
| 1566 | | - else |
|---|
| 1567 | | - cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; |
|---|
| 1568 | | - } |
|---|
| 1569 | | - if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1570 | | - cap->device_caps |= V4L2_CAP_TUNER; |
|---|
| 1571 | | - cap->capabilities = cap->device_caps | V4L2_CAP_READWRITE | |
|---|
| 1376 | + cap->capabilities = V4L2_CAP_READWRITE | |
|---|
| 1572 | 1377 | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 1573 | 1378 | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; |
|---|
| 1574 | 1379 | if (video_is_registered(&dev->radio_dev)) |
|---|
| 1575 | 1380 | cap->capabilities |= V4L2_CAP_RADIO; |
|---|
| 1576 | 1381 | |
|---|
| 1382 | + switch (dev->model) { |
|---|
| 1383 | + case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: |
|---|
| 1384 | + case CX231XX_BOARD_HAUPPAUGE_935C: |
|---|
| 1385 | + case CX231XX_BOARD_HAUPPAUGE_955Q: |
|---|
| 1386 | + case CX231XX_BOARD_HAUPPAUGE_975: |
|---|
| 1387 | + case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: |
|---|
| 1388 | + cap->capabilities |= V4L2_CAP_TUNER; |
|---|
| 1389 | + break; |
|---|
| 1390 | + default: |
|---|
| 1391 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1392 | + cap->capabilities |= V4L2_CAP_TUNER; |
|---|
| 1393 | + break; |
|---|
| 1394 | + } |
|---|
| 1577 | 1395 | return 0; |
|---|
| 1578 | 1396 | } |
|---|
| 1579 | 1397 | |
|---|
| .. | .. |
|---|
| 1583 | 1401 | if (unlikely(f->index >= ARRAY_SIZE(format))) |
|---|
| 1584 | 1402 | return -EINVAL; |
|---|
| 1585 | 1403 | |
|---|
| 1586 | | - strlcpy(f->description, format[f->index].name, sizeof(f->description)); |
|---|
| 1587 | 1404 | f->pixelformat = format[f->index].fourcc; |
|---|
| 1588 | 1405 | |
|---|
| 1589 | 1406 | return 0; |
|---|
| .. | .. |
|---|
| 1594 | 1411 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, |
|---|
| 1595 | 1412 | struct v4l2_format *f) |
|---|
| 1596 | 1413 | { |
|---|
| 1597 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1598 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1414 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1599 | 1415 | |
|---|
| 1600 | 1416 | f->fmt.vbi.sampling_rate = 6750000 * 4; |
|---|
| 1601 | 1417 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; |
|---|
| .. | .. |
|---|
| 1617 | 1433 | static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, |
|---|
| 1618 | 1434 | struct v4l2_format *f) |
|---|
| 1619 | 1435 | { |
|---|
| 1620 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1621 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1436 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1622 | 1437 | |
|---|
| 1623 | 1438 | f->fmt.vbi.sampling_rate = 6750000 * 4; |
|---|
| 1624 | 1439 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; |
|---|
| .. | .. |
|---|
| 1641 | 1456 | static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, |
|---|
| 1642 | 1457 | struct v4l2_format *f) |
|---|
| 1643 | 1458 | { |
|---|
| 1644 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1645 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1646 | | - |
|---|
| 1647 | | - if (dev->vbi_stream_on && !fh->stream_on) { |
|---|
| 1648 | | - dev_err(dev->dev, |
|---|
| 1649 | | - "%s device in use by another fh\n", __func__); |
|---|
| 1650 | | - return -EBUSY; |
|---|
| 1651 | | - } |
|---|
| 1652 | 1459 | return vidioc_try_fmt_vbi_cap(file, priv, f); |
|---|
| 1653 | | -} |
|---|
| 1654 | | - |
|---|
| 1655 | | -static int vidioc_reqbufs(struct file *file, void *priv, |
|---|
| 1656 | | - struct v4l2_requestbuffers *rb) |
|---|
| 1657 | | -{ |
|---|
| 1658 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1659 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1660 | | - int rc; |
|---|
| 1661 | | - |
|---|
| 1662 | | - rc = check_dev(dev); |
|---|
| 1663 | | - if (rc < 0) |
|---|
| 1664 | | - return rc; |
|---|
| 1665 | | - |
|---|
| 1666 | | - return videobuf_reqbufs(&fh->vb_vidq, rb); |
|---|
| 1667 | | -} |
|---|
| 1668 | | - |
|---|
| 1669 | | -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) |
|---|
| 1670 | | -{ |
|---|
| 1671 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1672 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1673 | | - int rc; |
|---|
| 1674 | | - |
|---|
| 1675 | | - rc = check_dev(dev); |
|---|
| 1676 | | - if (rc < 0) |
|---|
| 1677 | | - return rc; |
|---|
| 1678 | | - |
|---|
| 1679 | | - return videobuf_querybuf(&fh->vb_vidq, b); |
|---|
| 1680 | | -} |
|---|
| 1681 | | - |
|---|
| 1682 | | -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
|---|
| 1683 | | -{ |
|---|
| 1684 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1685 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1686 | | - int rc; |
|---|
| 1687 | | - |
|---|
| 1688 | | - rc = check_dev(dev); |
|---|
| 1689 | | - if (rc < 0) |
|---|
| 1690 | | - return rc; |
|---|
| 1691 | | - |
|---|
| 1692 | | - return videobuf_qbuf(&fh->vb_vidq, b); |
|---|
| 1693 | | -} |
|---|
| 1694 | | - |
|---|
| 1695 | | -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
|---|
| 1696 | | -{ |
|---|
| 1697 | | - struct cx231xx_fh *fh = priv; |
|---|
| 1698 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1699 | | - int rc; |
|---|
| 1700 | | - |
|---|
| 1701 | | - rc = check_dev(dev); |
|---|
| 1702 | | - if (rc < 0) |
|---|
| 1703 | | - return rc; |
|---|
| 1704 | | - |
|---|
| 1705 | | - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); |
|---|
| 1706 | 1460 | } |
|---|
| 1707 | 1461 | |
|---|
| 1708 | 1462 | /* ----------------------------------------------------------- */ |
|---|
| .. | .. |
|---|
| 1711 | 1465 | |
|---|
| 1712 | 1466 | static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
|---|
| 1713 | 1467 | { |
|---|
| 1714 | | - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; |
|---|
| 1468 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1715 | 1469 | |
|---|
| 1716 | 1470 | if (t->index) |
|---|
| 1717 | 1471 | return -EINVAL; |
|---|
| 1718 | 1472 | |
|---|
| 1719 | | - strcpy(t->name, "Radio"); |
|---|
| 1473 | + strscpy(t->name, "Radio", sizeof(t->name)); |
|---|
| 1720 | 1474 | |
|---|
| 1721 | 1475 | call_all(dev, tuner, g_tuner, t); |
|---|
| 1722 | 1476 | |
|---|
| .. | .. |
|---|
| 1724 | 1478 | } |
|---|
| 1725 | 1479 | static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) |
|---|
| 1726 | 1480 | { |
|---|
| 1727 | | - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; |
|---|
| 1481 | + struct cx231xx *dev = video_drvdata(file); |
|---|
| 1728 | 1482 | |
|---|
| 1729 | 1483 | if (t->index) |
|---|
| 1730 | 1484 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1740 | 1494 | */ |
|---|
| 1741 | 1495 | static int cx231xx_v4l2_open(struct file *filp) |
|---|
| 1742 | 1496 | { |
|---|
| 1743 | | - int radio = 0; |
|---|
| 1744 | 1497 | struct video_device *vdev = video_devdata(filp); |
|---|
| 1745 | 1498 | struct cx231xx *dev = video_drvdata(filp); |
|---|
| 1746 | | - struct cx231xx_fh *fh; |
|---|
| 1747 | | - enum v4l2_buf_type fh_type = 0; |
|---|
| 1499 | + int ret; |
|---|
| 1748 | 1500 | |
|---|
| 1749 | | - switch (vdev->vfl_type) { |
|---|
| 1750 | | - case VFL_TYPE_GRABBER: |
|---|
| 1751 | | - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|---|
| 1752 | | - break; |
|---|
| 1753 | | - case VFL_TYPE_VBI: |
|---|
| 1754 | | - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; |
|---|
| 1755 | | - break; |
|---|
| 1756 | | - case VFL_TYPE_RADIO: |
|---|
| 1757 | | - radio = 1; |
|---|
| 1758 | | - break; |
|---|
| 1759 | | - default: |
|---|
| 1760 | | - return -EINVAL; |
|---|
| 1761 | | - } |
|---|
| 1762 | | - |
|---|
| 1763 | | - cx231xx_videodbg("open dev=%s type=%s users=%d\n", |
|---|
| 1764 | | - video_device_node_name(vdev), v4l2_type_names[fh_type], |
|---|
| 1765 | | - dev->users); |
|---|
| 1766 | | - |
|---|
| 1767 | | -#if 0 |
|---|
| 1768 | | - errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); |
|---|
| 1769 | | - if (errCode < 0) { |
|---|
| 1770 | | - dev_err(dev->dev, |
|---|
| 1771 | | - "Device locked on digital mode. Can't open analog\n"); |
|---|
| 1772 | | - return -EBUSY; |
|---|
| 1773 | | - } |
|---|
| 1774 | | -#endif |
|---|
| 1775 | | - |
|---|
| 1776 | | - fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); |
|---|
| 1777 | | - if (!fh) |
|---|
| 1778 | | - return -ENOMEM; |
|---|
| 1779 | | - if (mutex_lock_interruptible(&dev->lock)) { |
|---|
| 1780 | | - kfree(fh); |
|---|
| 1501 | + if (mutex_lock_interruptible(&dev->lock)) |
|---|
| 1781 | 1502 | return -ERESTARTSYS; |
|---|
| 1782 | | - } |
|---|
| 1783 | | - fh->dev = dev; |
|---|
| 1784 | | - fh->type = fh_type; |
|---|
| 1785 | | - filp->private_data = fh; |
|---|
| 1786 | | - v4l2_fh_init(&fh->fh, vdev); |
|---|
| 1787 | 1503 | |
|---|
| 1788 | | - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { |
|---|
| 1504 | + ret = v4l2_fh_open(filp); |
|---|
| 1505 | + if (ret) { |
|---|
| 1506 | + mutex_unlock(&dev->lock); |
|---|
| 1507 | + return ret; |
|---|
| 1508 | + } |
|---|
| 1509 | + |
|---|
| 1510 | + if (dev->users++ == 0) { |
|---|
| 1789 | 1511 | /* Power up in Analog TV mode */ |
|---|
| 1790 | 1512 | if (dev->board.external_av) |
|---|
| 1791 | 1513 | cx231xx_set_power_mode(dev, |
|---|
| 1792 | 1514 | POLARIS_AVMODE_ENXTERNAL_AV); |
|---|
| 1793 | 1515 | else |
|---|
| 1794 | 1516 | cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); |
|---|
| 1795 | | - |
|---|
| 1796 | | -#if 0 |
|---|
| 1797 | | - cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); |
|---|
| 1798 | | -#endif |
|---|
| 1799 | 1517 | |
|---|
| 1800 | 1518 | /* set video alternate setting */ |
|---|
| 1801 | 1519 | cx231xx_set_video_alternate(dev); |
|---|
| .. | .. |
|---|
| 1806 | 1524 | |
|---|
| 1807 | 1525 | /* device needs to be initialized before isoc transfer */ |
|---|
| 1808 | 1526 | dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; |
|---|
| 1809 | | - |
|---|
| 1810 | 1527 | } |
|---|
| 1811 | | - if (radio) { |
|---|
| 1528 | + |
|---|
| 1529 | + if (vdev->vfl_type == VFL_TYPE_RADIO) { |
|---|
| 1812 | 1530 | cx231xx_videodbg("video_open: setting radio device\n"); |
|---|
| 1813 | 1531 | |
|---|
| 1814 | 1532 | /* cx231xx_start_radio(dev); */ |
|---|
| 1815 | 1533 | |
|---|
| 1816 | 1534 | call_all(dev, tuner, s_radio); |
|---|
| 1817 | 1535 | } |
|---|
| 1818 | | - |
|---|
| 1819 | | - dev->users++; |
|---|
| 1820 | | - |
|---|
| 1821 | | - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 1822 | | - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, |
|---|
| 1823 | | - NULL, &dev->video_mode.slock, |
|---|
| 1824 | | - fh->type, V4L2_FIELD_INTERLACED, |
|---|
| 1825 | | - sizeof(struct cx231xx_buffer), |
|---|
| 1826 | | - fh, &dev->lock); |
|---|
| 1827 | | - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
|---|
| 1536 | + if (vdev->vfl_type == VFL_TYPE_VBI) { |
|---|
| 1828 | 1537 | /* Set the required alternate setting VBI interface works in |
|---|
| 1829 | 1538 | Bulk mode only */ |
|---|
| 1830 | 1539 | cx231xx_set_alt_setting(dev, INDEX_VANC, 0); |
|---|
| 1831 | | - |
|---|
| 1832 | | - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, |
|---|
| 1833 | | - NULL, &dev->vbi_mode.slock, |
|---|
| 1834 | | - fh->type, V4L2_FIELD_SEQ_TB, |
|---|
| 1835 | | - sizeof(struct cx231xx_buffer), |
|---|
| 1836 | | - fh, &dev->lock); |
|---|
| 1837 | 1540 | } |
|---|
| 1838 | 1541 | mutex_unlock(&dev->lock); |
|---|
| 1839 | | - v4l2_fh_add(&fh->fh); |
|---|
| 1840 | | - |
|---|
| 1841 | 1542 | return 0; |
|---|
| 1842 | 1543 | } |
|---|
| 1843 | 1544 | |
|---|
| 1844 | 1545 | /* |
|---|
| 1845 | 1546 | * cx231xx_realease_resources() |
|---|
| 1846 | 1547 | * unregisters the v4l2,i2c and usb devices |
|---|
| 1847 | | - * called when the device gets disconected or at module unload |
|---|
| 1548 | + * called when the device gets disconnected or at module unload |
|---|
| 1848 | 1549 | */ |
|---|
| 1849 | 1550 | void cx231xx_release_analog_resources(struct cx231xx *dev) |
|---|
| 1850 | 1551 | { |
|---|
| .. | .. |
|---|
| 1878 | 1579 | */ |
|---|
| 1879 | 1580 | static int cx231xx_close(struct file *filp) |
|---|
| 1880 | 1581 | { |
|---|
| 1881 | | - struct cx231xx_fh *fh = filp->private_data; |
|---|
| 1882 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1582 | + struct cx231xx *dev = video_drvdata(filp); |
|---|
| 1583 | + struct video_device *vdev = video_devdata(filp); |
|---|
| 1883 | 1584 | |
|---|
| 1884 | | - cx231xx_videodbg("users=%d\n", dev->users); |
|---|
| 1585 | + _vb2_fop_release(filp, NULL); |
|---|
| 1885 | 1586 | |
|---|
| 1886 | | - cx231xx_videodbg("users=%d\n", dev->users); |
|---|
| 1887 | | - if (res_check(fh)) |
|---|
| 1888 | | - res_free(fh); |
|---|
| 1889 | | - |
|---|
| 1890 | | - /* |
|---|
| 1891 | | - * To workaround error number=-71 on EP0 for VideoGrabber, |
|---|
| 1892 | | - * need exclude following. |
|---|
| 1893 | | - * FIXME: It is probably safe to remove most of these, as we're |
|---|
| 1894 | | - * now avoiding the alternate setting for INDEX_VANC |
|---|
| 1895 | | - */ |
|---|
| 1896 | | - if (!dev->board.no_alt_vanc) |
|---|
| 1897 | | - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
|---|
| 1898 | | - videobuf_stop(&fh->vb_vidq); |
|---|
| 1899 | | - videobuf_mmap_free(&fh->vb_vidq); |
|---|
| 1900 | | - |
|---|
| 1901 | | - /* the device is already disconnect, |
|---|
| 1902 | | - free the remaining resources */ |
|---|
| 1903 | | - if (dev->state & DEV_DISCONNECTED) { |
|---|
| 1904 | | - if (atomic_read(&dev->devlist_count) > 0) { |
|---|
| 1905 | | - cx231xx_release_resources(dev); |
|---|
| 1906 | | - fh->dev = NULL; |
|---|
| 1907 | | - return 0; |
|---|
| 1908 | | - } |
|---|
| 1909 | | - return 0; |
|---|
| 1910 | | - } |
|---|
| 1911 | | - |
|---|
| 1912 | | - /* do this before setting alternate! */ |
|---|
| 1913 | | - cx231xx_uninit_vbi_isoc(dev); |
|---|
| 1914 | | - |
|---|
| 1915 | | - /* set alternate 0 */ |
|---|
| 1916 | | - if (!dev->vbi_or_sliced_cc_mode) |
|---|
| 1917 | | - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); |
|---|
| 1918 | | - else |
|---|
| 1919 | | - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); |
|---|
| 1920 | | - |
|---|
| 1921 | | - v4l2_fh_del(&fh->fh); |
|---|
| 1922 | | - v4l2_fh_exit(&fh->fh); |
|---|
| 1923 | | - kfree(fh); |
|---|
| 1924 | | - dev->users--; |
|---|
| 1925 | | - wake_up_interruptible(&dev->open); |
|---|
| 1926 | | - return 0; |
|---|
| 1927 | | - } |
|---|
| 1928 | | - |
|---|
| 1929 | | - v4l2_fh_del(&fh->fh); |
|---|
| 1930 | | - dev->users--; |
|---|
| 1931 | | - if (!dev->users) { |
|---|
| 1932 | | - videobuf_stop(&fh->vb_vidq); |
|---|
| 1933 | | - videobuf_mmap_free(&fh->vb_vidq); |
|---|
| 1934 | | - |
|---|
| 1935 | | - /* the device is already disconnect, |
|---|
| 1936 | | - free the remaining resources */ |
|---|
| 1937 | | - if (dev->state & DEV_DISCONNECTED) { |
|---|
| 1938 | | - cx231xx_release_resources(dev); |
|---|
| 1939 | | - fh->dev = NULL; |
|---|
| 1940 | | - return 0; |
|---|
| 1941 | | - } |
|---|
| 1942 | | - |
|---|
| 1587 | + if (--dev->users == 0) { |
|---|
| 1943 | 1588 | /* Save some power by putting tuner to sleep */ |
|---|
| 1944 | 1589 | call_all(dev, tuner, standby); |
|---|
| 1945 | 1590 | |
|---|
| .. | .. |
|---|
| 1949 | 1594 | else |
|---|
| 1950 | 1595 | cx231xx_uninit_bulk(dev); |
|---|
| 1951 | 1596 | cx231xx_set_mode(dev, CX231XX_SUSPEND); |
|---|
| 1597 | + } |
|---|
| 1952 | 1598 | |
|---|
| 1599 | + /* |
|---|
| 1600 | + * To workaround error number=-71 on EP0 for VideoGrabber, |
|---|
| 1601 | + * need exclude following. |
|---|
| 1602 | + * FIXME: It is probably safe to remove most of these, as we're |
|---|
| 1603 | + * now avoiding the alternate setting for INDEX_VANC |
|---|
| 1604 | + */ |
|---|
| 1605 | + if (!dev->board.no_alt_vanc && vdev->vfl_type == VFL_TYPE_VBI) { |
|---|
| 1606 | + /* do this before setting alternate! */ |
|---|
| 1607 | + cx231xx_uninit_vbi_isoc(dev); |
|---|
| 1608 | + |
|---|
| 1609 | + /* set alternate 0 */ |
|---|
| 1610 | + if (!dev->vbi_or_sliced_cc_mode) |
|---|
| 1611 | + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); |
|---|
| 1612 | + else |
|---|
| 1613 | + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); |
|---|
| 1614 | + |
|---|
| 1615 | + wake_up_interruptible_nr(&dev->open, 1); |
|---|
| 1616 | + return 0; |
|---|
| 1617 | + } |
|---|
| 1618 | + |
|---|
| 1619 | + if (dev->users == 0) { |
|---|
| 1953 | 1620 | /* set alternate 0 */ |
|---|
| 1954 | 1621 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); |
|---|
| 1955 | 1622 | } |
|---|
| 1956 | | - v4l2_fh_exit(&fh->fh); |
|---|
| 1957 | | - kfree(fh); |
|---|
| 1623 | + |
|---|
| 1958 | 1624 | wake_up_interruptible(&dev->open); |
|---|
| 1959 | 1625 | return 0; |
|---|
| 1960 | 1626 | } |
|---|
| 1961 | 1627 | |
|---|
| 1962 | 1628 | static int cx231xx_v4l2_close(struct file *filp) |
|---|
| 1963 | 1629 | { |
|---|
| 1964 | | - struct cx231xx_fh *fh = filp->private_data; |
|---|
| 1965 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1630 | + struct cx231xx *dev = video_drvdata(filp); |
|---|
| 1966 | 1631 | int rc; |
|---|
| 1967 | 1632 | |
|---|
| 1968 | 1633 | mutex_lock(&dev->lock); |
|---|
| .. | .. |
|---|
| 1971 | 1636 | return rc; |
|---|
| 1972 | 1637 | } |
|---|
| 1973 | 1638 | |
|---|
| 1974 | | -/* |
|---|
| 1975 | | - * cx231xx_v4l2_read() |
|---|
| 1976 | | - * will allocate buffers when called for the first time |
|---|
| 1977 | | - */ |
|---|
| 1978 | | -static ssize_t |
|---|
| 1979 | | -cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, |
|---|
| 1980 | | - loff_t *pos) |
|---|
| 1981 | | -{ |
|---|
| 1982 | | - struct cx231xx_fh *fh = filp->private_data; |
|---|
| 1983 | | - struct cx231xx *dev = fh->dev; |
|---|
| 1984 | | - int rc; |
|---|
| 1985 | | - |
|---|
| 1986 | | - rc = check_dev(dev); |
|---|
| 1987 | | - if (rc < 0) |
|---|
| 1988 | | - return rc; |
|---|
| 1989 | | - |
|---|
| 1990 | | - if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || |
|---|
| 1991 | | - (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) { |
|---|
| 1992 | | - rc = res_get(fh); |
|---|
| 1993 | | - |
|---|
| 1994 | | - if (unlikely(rc < 0)) |
|---|
| 1995 | | - return rc; |
|---|
| 1996 | | - |
|---|
| 1997 | | - if (mutex_lock_interruptible(&dev->lock)) |
|---|
| 1998 | | - return -ERESTARTSYS; |
|---|
| 1999 | | - rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, |
|---|
| 2000 | | - filp->f_flags & O_NONBLOCK); |
|---|
| 2001 | | - mutex_unlock(&dev->lock); |
|---|
| 2002 | | - return rc; |
|---|
| 2003 | | - } |
|---|
| 2004 | | - return 0; |
|---|
| 2005 | | -} |
|---|
| 2006 | | - |
|---|
| 2007 | | -/* |
|---|
| 2008 | | - * cx231xx_v4l2_poll() |
|---|
| 2009 | | - * will allocate buffers when called for the first time |
|---|
| 2010 | | - */ |
|---|
| 2011 | | -static __poll_t cx231xx_v4l2_poll(struct file *filp, poll_table *wait) |
|---|
| 2012 | | -{ |
|---|
| 2013 | | - __poll_t req_events = poll_requested_events(wait); |
|---|
| 2014 | | - struct cx231xx_fh *fh = filp->private_data; |
|---|
| 2015 | | - struct cx231xx *dev = fh->dev; |
|---|
| 2016 | | - __poll_t res = 0; |
|---|
| 2017 | | - int rc; |
|---|
| 2018 | | - |
|---|
| 2019 | | - rc = check_dev(dev); |
|---|
| 2020 | | - if (rc < 0) |
|---|
| 2021 | | - return EPOLLERR; |
|---|
| 2022 | | - |
|---|
| 2023 | | - rc = res_get(fh); |
|---|
| 2024 | | - |
|---|
| 2025 | | - if (unlikely(rc < 0)) |
|---|
| 2026 | | - return EPOLLERR; |
|---|
| 2027 | | - |
|---|
| 2028 | | - if (v4l2_event_pending(&fh->fh)) |
|---|
| 2029 | | - res |= EPOLLPRI; |
|---|
| 2030 | | - else |
|---|
| 2031 | | - poll_wait(filp, &fh->fh.wait, wait); |
|---|
| 2032 | | - |
|---|
| 2033 | | - if (!(req_events & (EPOLLIN | EPOLLRDNORM))) |
|---|
| 2034 | | - return res; |
|---|
| 2035 | | - |
|---|
| 2036 | | - if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || |
|---|
| 2037 | | - (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) { |
|---|
| 2038 | | - mutex_lock(&dev->lock); |
|---|
| 2039 | | - res |= videobuf_poll_stream(filp, &fh->vb_vidq, wait); |
|---|
| 2040 | | - mutex_unlock(&dev->lock); |
|---|
| 2041 | | - return res; |
|---|
| 2042 | | - } |
|---|
| 2043 | | - return res | EPOLLERR; |
|---|
| 2044 | | -} |
|---|
| 2045 | | - |
|---|
| 2046 | | -/* |
|---|
| 2047 | | - * cx231xx_v4l2_mmap() |
|---|
| 2048 | | - */ |
|---|
| 2049 | | -static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) |
|---|
| 2050 | | -{ |
|---|
| 2051 | | - struct cx231xx_fh *fh = filp->private_data; |
|---|
| 2052 | | - struct cx231xx *dev = fh->dev; |
|---|
| 2053 | | - int rc; |
|---|
| 2054 | | - |
|---|
| 2055 | | - rc = check_dev(dev); |
|---|
| 2056 | | - if (rc < 0) |
|---|
| 2057 | | - return rc; |
|---|
| 2058 | | - |
|---|
| 2059 | | - rc = res_get(fh); |
|---|
| 2060 | | - |
|---|
| 2061 | | - if (unlikely(rc < 0)) |
|---|
| 2062 | | - return rc; |
|---|
| 2063 | | - |
|---|
| 2064 | | - if (mutex_lock_interruptible(&dev->lock)) |
|---|
| 2065 | | - return -ERESTARTSYS; |
|---|
| 2066 | | - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); |
|---|
| 2067 | | - mutex_unlock(&dev->lock); |
|---|
| 2068 | | - |
|---|
| 2069 | | - cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", |
|---|
| 2070 | | - (unsigned long)vma->vm_start, |
|---|
| 2071 | | - (unsigned long)vma->vm_end - |
|---|
| 2072 | | - (unsigned long)vma->vm_start, rc); |
|---|
| 2073 | | - |
|---|
| 2074 | | - return rc; |
|---|
| 2075 | | -} |
|---|
| 2076 | | - |
|---|
| 2077 | 1639 | static const struct v4l2_file_operations cx231xx_v4l_fops = { |
|---|
| 2078 | 1640 | .owner = THIS_MODULE, |
|---|
| 2079 | 1641 | .open = cx231xx_v4l2_open, |
|---|
| 2080 | 1642 | .release = cx231xx_v4l2_close, |
|---|
| 2081 | | - .read = cx231xx_v4l2_read, |
|---|
| 2082 | | - .poll = cx231xx_v4l2_poll, |
|---|
| 2083 | | - .mmap = cx231xx_v4l2_mmap, |
|---|
| 1643 | + .read = vb2_fop_read, |
|---|
| 1644 | + .poll = vb2_fop_poll, |
|---|
| 1645 | + .mmap = vb2_fop_mmap, |
|---|
| 2084 | 1646 | .unlocked_ioctl = video_ioctl2, |
|---|
| 2085 | 1647 | }; |
|---|
| 2086 | 1648 | |
|---|
| .. | .. |
|---|
| 2093 | 1655 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, |
|---|
| 2094 | 1656 | .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, |
|---|
| 2095 | 1657 | .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, |
|---|
| 2096 | | - .vidioc_cropcap = vidioc_cropcap, |
|---|
| 2097 | | - .vidioc_reqbufs = vidioc_reqbufs, |
|---|
| 2098 | | - .vidioc_querybuf = vidioc_querybuf, |
|---|
| 2099 | | - .vidioc_qbuf = vidioc_qbuf, |
|---|
| 2100 | | - .vidioc_dqbuf = vidioc_dqbuf, |
|---|
| 1658 | + .vidioc_g_pixelaspect = vidioc_g_pixelaspect, |
|---|
| 1659 | + .vidioc_g_selection = vidioc_g_selection, |
|---|
| 1660 | + .vidioc_reqbufs = vb2_ioctl_reqbufs, |
|---|
| 1661 | + .vidioc_querybuf = vb2_ioctl_querybuf, |
|---|
| 1662 | + .vidioc_qbuf = vb2_ioctl_qbuf, |
|---|
| 1663 | + .vidioc_dqbuf = vb2_ioctl_dqbuf, |
|---|
| 2101 | 1664 | .vidioc_s_std = vidioc_s_std, |
|---|
| 2102 | 1665 | .vidioc_g_std = vidioc_g_std, |
|---|
| 2103 | 1666 | .vidioc_enum_input = cx231xx_enum_input, |
|---|
| 2104 | 1667 | .vidioc_g_input = cx231xx_g_input, |
|---|
| 2105 | 1668 | .vidioc_s_input = cx231xx_s_input, |
|---|
| 2106 | | - .vidioc_streamon = vidioc_streamon, |
|---|
| 2107 | | - .vidioc_streamoff = vidioc_streamoff, |
|---|
| 1669 | + .vidioc_streamon = vb2_ioctl_streamon, |
|---|
| 1670 | + .vidioc_streamoff = vb2_ioctl_streamoff, |
|---|
| 2108 | 1671 | .vidioc_g_tuner = cx231xx_g_tuner, |
|---|
| 2109 | 1672 | .vidioc_s_tuner = cx231xx_s_tuner, |
|---|
| 2110 | 1673 | .vidioc_g_frequency = cx231xx_g_frequency, |
|---|
| .. | .. |
|---|
| 2172 | 1735 | |
|---|
| 2173 | 1736 | video_set_drvdata(vfd, dev); |
|---|
| 2174 | 1737 | if (dev->tuner_type == TUNER_ABSENT) { |
|---|
| 2175 | | - v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); |
|---|
| 2176 | | - v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY); |
|---|
| 2177 | | - v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); |
|---|
| 2178 | | - v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); |
|---|
| 1738 | + switch (dev->model) { |
|---|
| 1739 | + case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: |
|---|
| 1740 | + case CX231XX_BOARD_HAUPPAUGE_935C: |
|---|
| 1741 | + case CX231XX_BOARD_HAUPPAUGE_955Q: |
|---|
| 1742 | + case CX231XX_BOARD_HAUPPAUGE_975: |
|---|
| 1743 | + case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: |
|---|
| 1744 | + break; |
|---|
| 1745 | + default: |
|---|
| 1746 | + v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); |
|---|
| 1747 | + v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY); |
|---|
| 1748 | + v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); |
|---|
| 1749 | + v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); |
|---|
| 1750 | + break; |
|---|
| 1751 | + } |
|---|
| 2179 | 1752 | } |
|---|
| 2180 | 1753 | } |
|---|
| 2181 | 1754 | |
|---|
| 2182 | 1755 | int cx231xx_register_analog_devices(struct cx231xx *dev) |
|---|
| 2183 | 1756 | { |
|---|
| 1757 | + struct vb2_queue *q; |
|---|
| 2184 | 1758 | int ret; |
|---|
| 2185 | 1759 | |
|---|
| 2186 | 1760 | dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION); |
|---|
| .. | .. |
|---|
| 2204 | 1778 | |
|---|
| 2205 | 1779 | if (dev->sd_cx25840) { |
|---|
| 2206 | 1780 | v4l2_ctrl_add_handler(&dev->ctrl_handler, |
|---|
| 2207 | | - dev->sd_cx25840->ctrl_handler, NULL); |
|---|
| 1781 | + dev->sd_cx25840->ctrl_handler, NULL, true); |
|---|
| 2208 | 1782 | v4l2_ctrl_add_handler(&dev->radio_ctrl_handler, |
|---|
| 2209 | 1783 | dev->sd_cx25840->ctrl_handler, |
|---|
| 2210 | | - v4l2_ctrl_radio_filter); |
|---|
| 1784 | + v4l2_ctrl_radio_filter, true); |
|---|
| 2211 | 1785 | } |
|---|
| 2212 | 1786 | |
|---|
| 2213 | 1787 | if (dev->ctrl_handler.error) |
|---|
| .. | .. |
|---|
| 2227 | 1801 | dev_err(dev->dev, "failed to initialize video media entity!\n"); |
|---|
| 2228 | 1802 | #endif |
|---|
| 2229 | 1803 | dev->vdev.ctrl_handler = &dev->ctrl_handler; |
|---|
| 1804 | + |
|---|
| 1805 | + q = &dev->vidq; |
|---|
| 1806 | + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|---|
| 1807 | + q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; |
|---|
| 1808 | + q->drv_priv = dev; |
|---|
| 1809 | + q->buf_struct_size = sizeof(struct cx231xx_buffer); |
|---|
| 1810 | + q->ops = &cx231xx_video_qops; |
|---|
| 1811 | + q->mem_ops = &vb2_vmalloc_memops; |
|---|
| 1812 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
|---|
| 1813 | + q->min_buffers_needed = 1; |
|---|
| 1814 | + q->lock = &dev->lock; |
|---|
| 1815 | + ret = vb2_queue_init(q); |
|---|
| 1816 | + if (ret) |
|---|
| 1817 | + return ret; |
|---|
| 1818 | + dev->vdev.queue = q; |
|---|
| 1819 | + dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | |
|---|
| 1820 | + V4L2_CAP_VIDEO_CAPTURE; |
|---|
| 1821 | + |
|---|
| 1822 | + switch (dev->model) { /* i2c device tuners */ |
|---|
| 1823 | + case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: |
|---|
| 1824 | + case CX231XX_BOARD_HAUPPAUGE_935C: |
|---|
| 1825 | + case CX231XX_BOARD_HAUPPAUGE_955Q: |
|---|
| 1826 | + case CX231XX_BOARD_HAUPPAUGE_975: |
|---|
| 1827 | + case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: |
|---|
| 1828 | + dev->vdev.device_caps |= V4L2_CAP_TUNER; |
|---|
| 1829 | + break; |
|---|
| 1830 | + default: |
|---|
| 1831 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1832 | + dev->vdev.device_caps |= V4L2_CAP_TUNER; |
|---|
| 1833 | + break; |
|---|
| 1834 | + } |
|---|
| 1835 | + |
|---|
| 2230 | 1836 | /* register v4l2 video video_device */ |
|---|
| 2231 | | - ret = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, |
|---|
| 1837 | + ret = video_register_device(&dev->vdev, VFL_TYPE_VIDEO, |
|---|
| 2232 | 1838 | video_nr[dev->devno]); |
|---|
| 2233 | 1839 | if (ret) { |
|---|
| 2234 | 1840 | dev_err(dev->dev, |
|---|
| .. | .. |
|---|
| 2242 | 1848 | |
|---|
| 2243 | 1849 | /* Initialize VBI template */ |
|---|
| 2244 | 1850 | cx231xx_vbi_template = cx231xx_video_template; |
|---|
| 2245 | | - strcpy(cx231xx_vbi_template.name, "cx231xx-vbi"); |
|---|
| 1851 | + strscpy(cx231xx_vbi_template.name, "cx231xx-vbi", |
|---|
| 1852 | + sizeof(cx231xx_vbi_template.name)); |
|---|
| 2246 | 1853 | |
|---|
| 2247 | 1854 | /* Allocate and fill vbi video_device struct */ |
|---|
| 2248 | 1855 | cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi"); |
|---|
| .. | .. |
|---|
| 2254 | 1861 | dev_err(dev->dev, "failed to initialize vbi media entity!\n"); |
|---|
| 2255 | 1862 | #endif |
|---|
| 2256 | 1863 | dev->vbi_dev.ctrl_handler = &dev->ctrl_handler; |
|---|
| 1864 | + |
|---|
| 1865 | + q = &dev->vbiq; |
|---|
| 1866 | + q->type = V4L2_BUF_TYPE_VBI_CAPTURE; |
|---|
| 1867 | + q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; |
|---|
| 1868 | + q->drv_priv = dev; |
|---|
| 1869 | + q->buf_struct_size = sizeof(struct cx231xx_buffer); |
|---|
| 1870 | + q->ops = &cx231xx_vbi_qops; |
|---|
| 1871 | + q->mem_ops = &vb2_vmalloc_memops; |
|---|
| 1872 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
|---|
| 1873 | + q->min_buffers_needed = 1; |
|---|
| 1874 | + q->lock = &dev->lock; |
|---|
| 1875 | + ret = vb2_queue_init(q); |
|---|
| 1876 | + if (ret) |
|---|
| 1877 | + return ret; |
|---|
| 1878 | + dev->vbi_dev.queue = q; |
|---|
| 1879 | + dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | |
|---|
| 1880 | + V4L2_CAP_VBI_CAPTURE; |
|---|
| 1881 | + switch (dev->model) { /* i2c device tuners */ |
|---|
| 1882 | + case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: |
|---|
| 1883 | + case CX231XX_BOARD_HAUPPAUGE_935C: |
|---|
| 1884 | + case CX231XX_BOARD_HAUPPAUGE_955Q: |
|---|
| 1885 | + case CX231XX_BOARD_HAUPPAUGE_975: |
|---|
| 1886 | + case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: |
|---|
| 1887 | + dev->vbi_dev.device_caps |= V4L2_CAP_TUNER; |
|---|
| 1888 | + break; |
|---|
| 1889 | + default: |
|---|
| 1890 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1891 | + dev->vbi_dev.device_caps |= V4L2_CAP_TUNER; |
|---|
| 1892 | + } |
|---|
| 1893 | + |
|---|
| 2257 | 1894 | /* register v4l2 vbi video_device */ |
|---|
| 2258 | 1895 | ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI, |
|---|
| 2259 | 1896 | vbi_nr[dev->devno]); |
|---|
| .. | .. |
|---|
| 2269 | 1906 | cx231xx_vdev_init(dev, &dev->radio_dev, |
|---|
| 2270 | 1907 | &cx231xx_radio_template, "radio"); |
|---|
| 2271 | 1908 | dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler; |
|---|
| 1909 | + dev->radio_dev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; |
|---|
| 2272 | 1910 | ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO, |
|---|
| 2273 | 1911 | radio_nr[dev->devno]); |
|---|
| 2274 | 1912 | if (ret < 0) { |
|---|