| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * uvc_video.c -- USB Video Class driver - Video handling |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2005-2010 |
|---|
| 5 | 6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | 7 | */ |
|---|
| 13 | 8 | |
|---|
| 14 | 9 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 659 | 654 | * to avoid losing precision in the division. Similarly, the host timestamp is |
|---|
| 660 | 655 | * computed with |
|---|
| 661 | 656 | * |
|---|
| 662 | | - * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) |
|---|
| 657 | + * TS = ((TS2 - TS1) * SOF + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) |
|---|
| 663 | 658 | * |
|---|
| 664 | 659 | * SOF values are coded on 11 bits by USB. We extend their precision with 16 |
|---|
| 665 | 660 | * decimal bits, leading to a 11.16 coding. |
|---|
| .. | .. |
|---|
| 802 | 797 | unsigned int header_size; |
|---|
| 803 | 798 | bool has_pts = false; |
|---|
| 804 | 799 | bool has_scr = false; |
|---|
| 805 | | - u16 uninitialized_var(scr_sof); |
|---|
| 806 | | - u32 uninitialized_var(scr_stc); |
|---|
| 807 | | - u32 uninitialized_var(pts); |
|---|
| 800 | + u16 scr_sof; |
|---|
| 801 | + u32 scr_stc; |
|---|
| 802 | + u32 pts; |
|---|
| 808 | 803 | |
|---|
| 809 | 804 | if (stream->stats.stream.nb_frames == 0 && |
|---|
| 810 | 805 | stream->stats.frame.nb_packets == 0) |
|---|
| .. | .. |
|---|
| 1546 | 1541 | default: |
|---|
| 1547 | 1542 | uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " |
|---|
| 1548 | 1543 | "completion handler.\n", urb->status); |
|---|
| 1549 | | - /* fall through */ |
|---|
| 1544 | + fallthrough; |
|---|
| 1550 | 1545 | case -ENOENT: /* usb_poison_urb() called. */ |
|---|
| 1551 | 1546 | if (stream->frozen) |
|---|
| 1552 | 1547 | return; |
|---|
| 1553 | | - /* fall through */ |
|---|
| 1548 | + fallthrough; |
|---|
| 1554 | 1549 | case -ECONNRESET: /* usb_unlink_urb() called. */ |
|---|
| 1555 | 1550 | case -ESHUTDOWN: /* The endpoint is being disabled. */ |
|---|
| 1556 | 1551 | uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); |
|---|
| .. | .. |
|---|
| 1596 | 1591 | */ |
|---|
| 1597 | 1592 | static void uvc_free_urb_buffers(struct uvc_streaming *stream) |
|---|
| 1598 | 1593 | { |
|---|
| 1599 | | - unsigned int i; |
|---|
| 1594 | + struct uvc_urb *uvc_urb; |
|---|
| 1600 | 1595 | |
|---|
| 1601 | | - for (i = 0; i < UVC_URBS; ++i) { |
|---|
| 1602 | | - struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; |
|---|
| 1596 | + for_each_uvc_urb(uvc_urb, stream) { |
|---|
| 1597 | + if (!uvc_urb->buffer) |
|---|
| 1598 | + continue; |
|---|
| 1603 | 1599 | |
|---|
| 1604 | | - if (uvc_urb->buffer) { |
|---|
| 1605 | 1600 | #ifndef CONFIG_DMA_NONCOHERENT |
|---|
| 1606 | | - usb_free_coherent(stream->dev->udev, stream->urb_size, |
|---|
| 1607 | | - uvc_urb->buffer, uvc_urb->dma); |
|---|
| 1601 | + usb_free_coherent(stream->dev->udev, stream->urb_size, |
|---|
| 1602 | + uvc_urb->buffer, uvc_urb->dma); |
|---|
| 1608 | 1603 | #else |
|---|
| 1609 | | - kfree(uvc_urb->buffer); |
|---|
| 1604 | + kfree(uvc_urb->buffer); |
|---|
| 1610 | 1605 | #endif |
|---|
| 1611 | | - uvc_urb->buffer = NULL; |
|---|
| 1612 | | - } |
|---|
| 1606 | + uvc_urb->buffer = NULL; |
|---|
| 1613 | 1607 | } |
|---|
| 1614 | 1608 | |
|---|
| 1615 | 1609 | stream->urb_size = 0; |
|---|
| .. | .. |
|---|
| 1681 | 1675 | /* |
|---|
| 1682 | 1676 | * Uninitialize isochronous/bulk URBs and free transfer buffers. |
|---|
| 1683 | 1677 | */ |
|---|
| 1684 | | -static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) |
|---|
| 1678 | +static void uvc_video_stop_transfer(struct uvc_streaming *stream, |
|---|
| 1679 | + int free_buffers) |
|---|
| 1685 | 1680 | { |
|---|
| 1686 | 1681 | struct uvc_urb *uvc_urb; |
|---|
| 1687 | 1682 | |
|---|
| .. | .. |
|---|
| 1740 | 1735 | struct usb_host_endpoint *ep, gfp_t gfp_flags) |
|---|
| 1741 | 1736 | { |
|---|
| 1742 | 1737 | struct urb *urb; |
|---|
| 1743 | | - unsigned int npackets, i, j; |
|---|
| 1738 | + struct uvc_urb *uvc_urb; |
|---|
| 1739 | + unsigned int npackets, i; |
|---|
| 1744 | 1740 | u16 psize; |
|---|
| 1745 | 1741 | u32 size; |
|---|
| 1746 | 1742 | |
|---|
| .. | .. |
|---|
| 1753 | 1749 | |
|---|
| 1754 | 1750 | size = npackets * psize; |
|---|
| 1755 | 1751 | |
|---|
| 1756 | | - for (i = 0; i < UVC_URBS; ++i) { |
|---|
| 1757 | | - struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; |
|---|
| 1758 | | - |
|---|
| 1752 | + for_each_uvc_urb(uvc_urb, stream) { |
|---|
| 1759 | 1753 | urb = usb_alloc_urb(npackets, gfp_flags); |
|---|
| 1760 | 1754 | if (urb == NULL) { |
|---|
| 1761 | | - uvc_uninit_video(stream, 1); |
|---|
| 1755 | + uvc_video_stop_transfer(stream, 1); |
|---|
| 1762 | 1756 | return -ENOMEM; |
|---|
| 1763 | 1757 | } |
|---|
| 1764 | 1758 | |
|---|
| .. | .. |
|---|
| 1778 | 1772 | urb->number_of_packets = npackets; |
|---|
| 1779 | 1773 | urb->transfer_buffer_length = size; |
|---|
| 1780 | 1774 | |
|---|
| 1781 | | - for (j = 0; j < npackets; ++j) { |
|---|
| 1782 | | - urb->iso_frame_desc[j].offset = j * psize; |
|---|
| 1783 | | - urb->iso_frame_desc[j].length = psize; |
|---|
| 1775 | + for (i = 0; i < npackets; ++i) { |
|---|
| 1776 | + urb->iso_frame_desc[i].offset = i * psize; |
|---|
| 1777 | + urb->iso_frame_desc[i].length = psize; |
|---|
| 1784 | 1778 | } |
|---|
| 1785 | 1779 | |
|---|
| 1786 | 1780 | uvc_urb->urb = urb; |
|---|
| .. | .. |
|---|
| 1797 | 1791 | struct usb_host_endpoint *ep, gfp_t gfp_flags) |
|---|
| 1798 | 1792 | { |
|---|
| 1799 | 1793 | struct urb *urb; |
|---|
| 1800 | | - unsigned int npackets, pipe, i; |
|---|
| 1794 | + struct uvc_urb *uvc_urb; |
|---|
| 1795 | + unsigned int npackets, pipe; |
|---|
| 1801 | 1796 | u16 psize; |
|---|
| 1802 | 1797 | u32 size; |
|---|
| 1803 | 1798 | |
|---|
| .. | .. |
|---|
| 1821 | 1816 | if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) |
|---|
| 1822 | 1817 | size = 0; |
|---|
| 1823 | 1818 | |
|---|
| 1824 | | - for (i = 0; i < UVC_URBS; ++i) { |
|---|
| 1825 | | - struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; |
|---|
| 1826 | | - |
|---|
| 1819 | + for_each_uvc_urb(uvc_urb, stream) { |
|---|
| 1827 | 1820 | urb = usb_alloc_urb(0, gfp_flags); |
|---|
| 1828 | 1821 | if (urb == NULL) { |
|---|
| 1829 | | - uvc_uninit_video(stream, 1); |
|---|
| 1822 | + uvc_video_stop_transfer(stream, 1); |
|---|
| 1830 | 1823 | return -ENOMEM; |
|---|
| 1831 | 1824 | } |
|---|
| 1832 | 1825 | |
|---|
| .. | .. |
|---|
| 1846 | 1839 | /* |
|---|
| 1847 | 1840 | * Initialize isochronous/bulk URBs and allocate transfer buffers. |
|---|
| 1848 | 1841 | */ |
|---|
| 1849 | | -static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) |
|---|
| 1842 | +static int uvc_video_start_transfer(struct uvc_streaming *stream, |
|---|
| 1843 | + gfp_t gfp_flags) |
|---|
| 1850 | 1844 | { |
|---|
| 1851 | 1845 | struct usb_interface *intf = stream->intf; |
|---|
| 1852 | 1846 | struct usb_host_endpoint *ep; |
|---|
| 1847 | + struct uvc_urb *uvc_urb; |
|---|
| 1853 | 1848 | unsigned int i; |
|---|
| 1854 | 1849 | int ret; |
|---|
| 1855 | 1850 | |
|---|
| .. | .. |
|---|
| 1865 | 1860 | struct usb_host_endpoint *best_ep = NULL; |
|---|
| 1866 | 1861 | unsigned int best_psize = UINT_MAX; |
|---|
| 1867 | 1862 | unsigned int bandwidth; |
|---|
| 1868 | | - unsigned int uninitialized_var(altsetting); |
|---|
| 1863 | + unsigned int altsetting; |
|---|
| 1869 | 1864 | int intfnum = stream->intfnum; |
|---|
| 1870 | 1865 | |
|---|
| 1871 | 1866 | /* Isochronous endpoint, select the alternate setting. */ |
|---|
| .. | .. |
|---|
| 1931 | 1926 | return ret; |
|---|
| 1932 | 1927 | |
|---|
| 1933 | 1928 | /* Submit the URBs. */ |
|---|
| 1934 | | - for (i = 0; i < UVC_URBS; ++i) { |
|---|
| 1935 | | - struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; |
|---|
| 1936 | | - |
|---|
| 1929 | + for_each_uvc_urb(uvc_urb, stream) { |
|---|
| 1937 | 1930 | ret = usb_submit_urb(uvc_urb->urb, gfp_flags); |
|---|
| 1938 | 1931 | if (ret < 0) { |
|---|
| 1939 | | - uvc_printk(KERN_ERR, "Failed to submit URB %u " |
|---|
| 1940 | | - "(%d).\n", i, ret); |
|---|
| 1941 | | - uvc_uninit_video(stream, 1); |
|---|
| 1932 | + uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n", |
|---|
| 1933 | + uvc_urb_index(uvc_urb), ret); |
|---|
| 1934 | + uvc_video_stop_transfer(stream, 1); |
|---|
| 1942 | 1935 | return ret; |
|---|
| 1943 | 1936 | } |
|---|
| 1944 | 1937 | } |
|---|
| .. | .. |
|---|
| 1969 | 1962 | return 0; |
|---|
| 1970 | 1963 | |
|---|
| 1971 | 1964 | stream->frozen = 1; |
|---|
| 1972 | | - uvc_uninit_video(stream, 0); |
|---|
| 1965 | + uvc_video_stop_transfer(stream, 0); |
|---|
| 1973 | 1966 | usb_set_interface(stream->dev->udev, stream->intfnum, 0); |
|---|
| 1974 | 1967 | return 0; |
|---|
| 1975 | 1968 | } |
|---|
| .. | .. |
|---|
| 2005 | 1998 | if (ret < 0) |
|---|
| 2006 | 1999 | return ret; |
|---|
| 2007 | 2000 | |
|---|
| 2008 | | - return uvc_init_video(stream, GFP_NOIO); |
|---|
| 2001 | + return uvc_video_start_transfer(stream, GFP_NOIO); |
|---|
| 2009 | 2002 | } |
|---|
| 2010 | 2003 | |
|---|
| 2011 | 2004 | /* ------------------------------------------------------------------------ |
|---|
| .. | .. |
|---|
| 2046 | 2039 | usb_set_interface(stream->dev->udev, stream->intfnum, 0); |
|---|
| 2047 | 2040 | |
|---|
| 2048 | 2041 | /* Set the streaming probe control with default streaming parameters |
|---|
| 2049 | | - * retrieved from the device. Webcams that don't suport GET_DEF |
|---|
| 2042 | + * retrieved from the device. Webcams that don't support GET_DEF |
|---|
| 2050 | 2043 | * requests on the probe control will just keep their current streaming |
|---|
| 2051 | 2044 | * parameters. |
|---|
| 2052 | 2045 | */ |
|---|
| .. | .. |
|---|
| 2120 | 2113 | return 0; |
|---|
| 2121 | 2114 | } |
|---|
| 2122 | 2115 | |
|---|
| 2123 | | -/* |
|---|
| 2124 | | - * Enable or disable the video stream. |
|---|
| 2125 | | - */ |
|---|
| 2126 | | -int uvc_video_enable(struct uvc_streaming *stream, int enable) |
|---|
| 2116 | +int uvc_video_start_streaming(struct uvc_streaming *stream) |
|---|
| 2127 | 2117 | { |
|---|
| 2128 | 2118 | int ret; |
|---|
| 2129 | | - |
|---|
| 2130 | | - if (!enable) { |
|---|
| 2131 | | - uvc_uninit_video(stream, 1); |
|---|
| 2132 | | - if (stream->intf->num_altsetting > 1) { |
|---|
| 2133 | | - usb_set_interface(stream->dev->udev, |
|---|
| 2134 | | - stream->intfnum, 0); |
|---|
| 2135 | | - } else { |
|---|
| 2136 | | - /* UVC doesn't specify how to inform a bulk-based device |
|---|
| 2137 | | - * when the video stream is stopped. Windows sends a |
|---|
| 2138 | | - * CLEAR_FEATURE(HALT) request to the video streaming |
|---|
| 2139 | | - * bulk endpoint, mimic the same behaviour. |
|---|
| 2140 | | - */ |
|---|
| 2141 | | - unsigned int epnum = stream->header.bEndpointAddress |
|---|
| 2142 | | - & USB_ENDPOINT_NUMBER_MASK; |
|---|
| 2143 | | - unsigned int dir = stream->header.bEndpointAddress |
|---|
| 2144 | | - & USB_ENDPOINT_DIR_MASK; |
|---|
| 2145 | | - unsigned int pipe; |
|---|
| 2146 | | - |
|---|
| 2147 | | - pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir; |
|---|
| 2148 | | - usb_clear_halt(stream->dev->udev, pipe); |
|---|
| 2149 | | - } |
|---|
| 2150 | | - |
|---|
| 2151 | | - uvc_video_clock_cleanup(stream); |
|---|
| 2152 | | - return 0; |
|---|
| 2153 | | - } |
|---|
| 2154 | 2119 | |
|---|
| 2155 | 2120 | ret = uvc_video_clock_init(stream); |
|---|
| 2156 | 2121 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 2161 | 2126 | if (ret < 0) |
|---|
| 2162 | 2127 | goto error_commit; |
|---|
| 2163 | 2128 | |
|---|
| 2164 | | - ret = uvc_init_video(stream, GFP_KERNEL); |
|---|
| 2129 | + ret = uvc_video_start_transfer(stream, GFP_KERNEL); |
|---|
| 2165 | 2130 | if (ret < 0) |
|---|
| 2166 | 2131 | goto error_video; |
|---|
| 2167 | 2132 | |
|---|
| .. | .. |
|---|
| 2174 | 2139 | |
|---|
| 2175 | 2140 | return ret; |
|---|
| 2176 | 2141 | } |
|---|
| 2142 | + |
|---|
| 2143 | +void uvc_video_stop_streaming(struct uvc_streaming *stream) |
|---|
| 2144 | +{ |
|---|
| 2145 | + uvc_video_stop_transfer(stream, 1); |
|---|
| 2146 | + |
|---|
| 2147 | + if (stream->intf->num_altsetting > 1) { |
|---|
| 2148 | + usb_set_interface(stream->dev->udev, stream->intfnum, 0); |
|---|
| 2149 | + } else { |
|---|
| 2150 | + /* UVC doesn't specify how to inform a bulk-based device |
|---|
| 2151 | + * when the video stream is stopped. Windows sends a |
|---|
| 2152 | + * CLEAR_FEATURE(HALT) request to the video streaming |
|---|
| 2153 | + * bulk endpoint, mimic the same behaviour. |
|---|
| 2154 | + */ |
|---|
| 2155 | + unsigned int epnum = stream->header.bEndpointAddress |
|---|
| 2156 | + & USB_ENDPOINT_NUMBER_MASK; |
|---|
| 2157 | + unsigned int dir = stream->header.bEndpointAddress |
|---|
| 2158 | + & USB_ENDPOINT_DIR_MASK; |
|---|
| 2159 | + unsigned int pipe; |
|---|
| 2160 | + |
|---|
| 2161 | + pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir; |
|---|
| 2162 | + usb_clear_halt(stream->dev->udev, pipe); |
|---|
| 2163 | + } |
|---|
| 2164 | + |
|---|
| 2165 | + uvc_video_clock_cleanup(stream); |
|---|
| 2166 | +} |
|---|