diff options
author | Laurent Pinchart <laurent.pinchart@skynet.be> | 2008-11-08 17:14:50 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 14:53:31 -0500 |
commit | 44f0079ec74330b457d990072c13cbe28b0f1abf (patch) | |
tree | a5af6ae41c4ff9dabc882d08cfda79a791d56430 /drivers/media/video/uvc | |
parent | 7e21fda17e7f6156e2ad66ca4f76abcbe1063eb2 (diff) |
V4L/DVB (9570): uvcvideo: Handle failed video GET_{MIN|MAX|DEF} requests more gracefully
Failed requests will now generate a one-time warning message instead of the
usual "Failed to query..." error, which should be more user-friendly. The
driver will also recover automatically from failed GET_MIN/GET_MAX requests
when the device is half-broken without requiring the MINMAX quirk (fully
broken devices still need the quirk).
Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 126 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_v4l2.c | 4 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 63 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 14 |
4 files changed, 66 insertions, 141 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 11398ee66320..1e3b4fe5ae93 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1726,24 +1726,6 @@ static int uvc_reset_resume(struct usb_interface *intf) | |||
1726 | * though they are compliant. | 1726 | * though they are compliant. |
1727 | */ | 1727 | */ |
1728 | static struct usb_device_id uvc_ids[] = { | 1728 | static struct usb_device_id uvc_ids[] = { |
1729 | /* ALi M5606 (Clevo M540SR) */ | ||
1730 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1731 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1732 | .idVendor = 0x0402, | ||
1733 | .idProduct = 0x5606, | ||
1734 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1735 | .bInterfaceSubClass = 1, | ||
1736 | .bInterfaceProtocol = 0, | ||
1737 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1738 | /* Creative Live! Optia */ | ||
1739 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1740 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1741 | .idVendor = 0x041e, | ||
1742 | .idProduct = 0x4057, | ||
1743 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1744 | .bInterfaceSubClass = 1, | ||
1745 | .bInterfaceProtocol = 0, | ||
1746 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1747 | /* Microsoft Lifecam NX-6000 */ | 1729 | /* Microsoft Lifecam NX-6000 */ |
1748 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1730 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1749 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1731 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1829,15 +1811,6 @@ static struct usb_device_id uvc_ids[] = { | |||
1829 | .bInterfaceSubClass = 1, | 1811 | .bInterfaceSubClass = 1, |
1830 | .bInterfaceProtocol = 0, | 1812 | .bInterfaceProtocol = 0, |
1831 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 1813 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
1832 | /* Silicon Motion SM371 */ | ||
1833 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1834 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1835 | .idVendor = 0x090c, | ||
1836 | .idProduct = 0xb371, | ||
1837 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1838 | .bInterfaceSubClass = 1, | ||
1839 | .bInterfaceProtocol = 0, | ||
1840 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1841 | /* MT6227 */ | 1814 | /* MT6227 */ |
1842 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1815 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1843 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1816 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1922,105 +1895,6 @@ static struct usb_device_id uvc_ids[] = { | |||
1922 | .bInterfaceProtocol = 0, | 1895 | .bInterfaceProtocol = 0, |
1923 | .driver_info = UVC_QUIRK_PROBE_MINMAX | 1896 | .driver_info = UVC_QUIRK_PROBE_MINMAX |
1924 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, | 1897 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, |
1925 | /* Acer OEM Webcam - Unknown vendor */ | ||
1926 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1927 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1928 | .idVendor = 0x5986, | ||
1929 | .idProduct = 0x0100, | ||
1930 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1931 | .bInterfaceSubClass = 1, | ||
1932 | .bInterfaceProtocol = 0, | ||
1933 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1934 | /* Packard Bell OEM Webcam - Bison Electronics */ | ||
1935 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1936 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1937 | .idVendor = 0x5986, | ||
1938 | .idProduct = 0x0101, | ||
1939 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1940 | .bInterfaceSubClass = 1, | ||
1941 | .bInterfaceProtocol = 0, | ||
1942 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1943 | /* Acer Crystal Eye webcam - Bison Electronics */ | ||
1944 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1945 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1946 | .idVendor = 0x5986, | ||
1947 | .idProduct = 0x0102, | ||
1948 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1949 | .bInterfaceSubClass = 1, | ||
1950 | .bInterfaceProtocol = 0, | ||
1951 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1952 | /* Compaq Presario B1200 - Bison Electronics */ | ||
1953 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1954 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1955 | .idVendor = 0x5986, | ||
1956 | .idProduct = 0x0104, | ||
1957 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1958 | .bInterfaceSubClass = 1, | ||
1959 | .bInterfaceProtocol = 0, | ||
1960 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1961 | /* Acer Travelmate 7720 - Bison Electronics */ | ||
1962 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1963 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1964 | .idVendor = 0x5986, | ||
1965 | .idProduct = 0x0105, | ||
1966 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1967 | .bInterfaceSubClass = 1, | ||
1968 | .bInterfaceProtocol = 0, | ||
1969 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1970 | /* Medion Akoya Mini E1210 - Bison Electronics */ | ||
1971 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1972 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1973 | .idVendor = 0x5986, | ||
1974 | .idProduct = 0x0141, | ||
1975 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1976 | .bInterfaceSubClass = 1, | ||
1977 | .bInterfaceProtocol = 0, | ||
1978 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1979 | /* Acer OrbiCam - Bison Electronics */ | ||
1980 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1981 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1982 | .idVendor = 0x5986, | ||
1983 | .idProduct = 0x0200, | ||
1984 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1985 | .bInterfaceSubClass = 1, | ||
1986 | .bInterfaceProtocol = 0, | ||
1987 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1988 | /* Fujitsu Amilo SI2636 - Bison Electronics */ | ||
1989 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1990 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1991 | .idVendor = 0x5986, | ||
1992 | .idProduct = 0x0202, | ||
1993 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1994 | .bInterfaceSubClass = 1, | ||
1995 | .bInterfaceProtocol = 0, | ||
1996 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1997 | /* Advent 4211 - Bison Electronics */ | ||
1998 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1999 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2000 | .idVendor = 0x5986, | ||
2001 | .idProduct = 0x0203, | ||
2002 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2003 | .bInterfaceSubClass = 1, | ||
2004 | .bInterfaceProtocol = 0, | ||
2005 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2006 | /* Bison Electronics */ | ||
2007 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2008 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2009 | .idVendor = 0x5986, | ||
2010 | .idProduct = 0x0300, | ||
2011 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2012 | .bInterfaceSubClass = 1, | ||
2013 | .bInterfaceProtocol = 0, | ||
2014 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2015 | /* Clevo M570TU - Bison Electronics */ | ||
2016 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2017 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2018 | .idVendor = 0x5986, | ||
2019 | .idProduct = 0x0303, | ||
2020 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2021 | .bInterfaceSubClass = 1, | ||
2022 | .bInterfaceProtocol = 0, | ||
2023 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2024 | /* Generic USB Video Class */ | 1898 | /* Generic USB Video Class */ |
2025 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, | 1899 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, |
2026 | {} | 1900 | {} |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 8361367806a9..624bf74de673 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -252,7 +252,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, | |||
252 | if (ret < 0) | 252 | if (ret < 0) |
253 | return ret; | 253 | return ret; |
254 | 254 | ||
255 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | 255 | if ((ret = uvc_commit_video(video, &probe)) < 0) |
256 | return ret; | 256 | return ret; |
257 | 257 | ||
258 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | 258 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); |
@@ -316,7 +316,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, | |||
316 | return ret; | 316 | return ret; |
317 | 317 | ||
318 | /* Commit the new settings. */ | 318 | /* Commit the new settings. */ |
319 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | 319 | if ((ret = uvc_commit_video(video, &probe)) < 0) |
320 | return ret; | 320 | return ret; |
321 | 321 | ||
322 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | 322 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index b7bb23820d80..4af94707ef69 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -36,15 +36,22 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | |||
36 | { | 36 | { |
37 | __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | 37 | __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
38 | unsigned int pipe; | 38 | unsigned int pipe; |
39 | int ret; | ||
40 | 39 | ||
41 | pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) | 40 | pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) |
42 | : usb_sndctrlpipe(dev->udev, 0); | 41 | : usb_sndctrlpipe(dev->udev, 0); |
43 | type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; | 42 | type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; |
44 | 43 | ||
45 | ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8, | 44 | return usb_control_msg(dev->udev, pipe, query, type, cs << 8, |
46 | unit << 8 | intfnum, data, size, timeout); | 45 | unit << 8 | intfnum, data, size, timeout); |
46 | } | ||
47 | |||
48 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
49 | __u8 intfnum, __u8 cs, void *data, __u16 size) | ||
50 | { | ||
51 | int ret; | ||
47 | 52 | ||
53 | ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, | ||
54 | UVC_CTRL_CONTROL_TIMEOUT); | ||
48 | if (ret != size) { | 55 | if (ret != size) { |
49 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " | 56 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " |
50 | "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, | 57 | "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, |
@@ -55,13 +62,6 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | |||
55 | return 0; | 62 | return 0; |
56 | } | 63 | } |
57 | 64 | ||
58 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
59 | __u8 intfnum, __u8 cs, void *data, __u16 size) | ||
60 | { | ||
61 | return __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, | ||
62 | UVC_CTRL_CONTROL_TIMEOUT); | ||
63 | } | ||
64 | |||
65 | static void uvc_fixup_buffer_size(struct uvc_video_device *video, | 65 | static void uvc_fixup_buffer_size(struct uvc_video_device *video, |
66 | struct uvc_streaming_control *ctrl) | 66 | struct uvc_streaming_control *ctrl) |
67 | { | 67 | { |
@@ -102,8 +102,36 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, | |||
102 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, | 102 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, |
103 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, | 103 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, |
104 | UVC_CTRL_STREAMING_TIMEOUT); | 104 | UVC_CTRL_STREAMING_TIMEOUT); |
105 | if (ret < 0) | 105 | |
106 | if ((query == GET_MIN || query == GET_MAX) && ret == 2) { | ||
107 | /* Some cameras, mostly based on Bison Electronics chipsets, | ||
108 | * answer a GET_MIN or GET_MAX request with the wCompQuality | ||
109 | * field only. | ||
110 | */ | ||
111 | uvc_warn_once(video->dev, UVC_WARN_MINMAX, "UVC non " | ||
112 | "compliance - GET_MIN/MAX(PROBE) incorrectly " | ||
113 | "supported. Enabling workaround.\n"); | ||
114 | memset(ctrl, 0, sizeof ctrl); | ||
115 | ctrl->wCompQuality = le16_to_cpup((__le16 *)data); | ||
116 | ret = 0; | ||
106 | goto out; | 117 | goto out; |
118 | } else if (query == GET_DEF && probe == 1) { | ||
119 | /* Many cameras don't support the GET_DEF request on their | ||
120 | * video probe control. Warn once and return, the caller will | ||
121 | * fall back to GET_CUR. | ||
122 | */ | ||
123 | uvc_warn_once(video->dev, UVC_WARN_PROBE_DEF, "UVC non " | ||
124 | "compliance - GET_DEF(PROBE) not supported. " | ||
125 | "Enabling workaround.\n"); | ||
126 | ret = -EIO; | ||
127 | goto out; | ||
128 | } else if (ret != size) { | ||
129 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : " | ||
130 | "%d (exp. %u).\n", query, probe ? "probe" : "commit", | ||
131 | ret, size); | ||
132 | ret = -EIO; | ||
133 | goto out; | ||
134 | } | ||
107 | 135 | ||
108 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); | 136 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); |
109 | ctrl->bFormatIndex = data[2]; | 137 | ctrl->bFormatIndex = data[2]; |
@@ -138,13 +166,14 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, | |||
138 | * Try to get the value from the format and frame descriptor. | 166 | * Try to get the value from the format and frame descriptor. |
139 | */ | 167 | */ |
140 | uvc_fixup_buffer_size(video, ctrl); | 168 | uvc_fixup_buffer_size(video, ctrl); |
169 | ret = 0; | ||
141 | 170 | ||
142 | out: | 171 | out: |
143 | kfree(data); | 172 | kfree(data); |
144 | return ret; | 173 | return ret; |
145 | } | 174 | } |
146 | 175 | ||
147 | int uvc_set_video_ctrl(struct uvc_video_device *video, | 176 | static int uvc_set_video_ctrl(struct uvc_video_device *video, |
148 | struct uvc_streaming_control *ctrl, int probe) | 177 | struct uvc_streaming_control *ctrl, int probe) |
149 | { | 178 | { |
150 | __u8 *data; | 179 | __u8 *data; |
@@ -186,6 +215,12 @@ int uvc_set_video_ctrl(struct uvc_video_device *video, | |||
186 | video->streaming->intfnum, | 215 | video->streaming->intfnum, |
187 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, | 216 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, |
188 | UVC_CTRL_STREAMING_TIMEOUT); | 217 | UVC_CTRL_STREAMING_TIMEOUT); |
218 | if (ret != size) { | ||
219 | uvc_printk(KERN_ERR, "Failed to set UVC %s control : " | ||
220 | "%d (exp. %u).\n", probe ? "probe" : "commit", | ||
221 | ret, size); | ||
222 | ret = -EIO; | ||
223 | } | ||
189 | 224 | ||
190 | kfree(data); | 225 | kfree(data); |
191 | return ret; | 226 | return ret; |
@@ -252,6 +287,12 @@ done: | |||
252 | return ret; | 287 | return ret; |
253 | } | 288 | } |
254 | 289 | ||
290 | int uvc_commit_video(struct uvc_video_device *video, | ||
291 | struct uvc_streaming_control *probe) | ||
292 | { | ||
293 | return uvc_set_video_ctrl(video, probe, 0); | ||
294 | } | ||
295 | |||
255 | /* ------------------------------------------------------------------------ | 296 | /* ------------------------------------------------------------------------ |
256 | * Video codecs | 297 | * Video codecs |
257 | */ | 298 | */ |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 9a6bc1aafb16..595b90ee6528 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -617,6 +617,7 @@ enum uvc_device_state { | |||
617 | struct uvc_device { | 617 | struct uvc_device { |
618 | struct usb_device *udev; | 618 | struct usb_device *udev; |
619 | struct usb_interface *intf; | 619 | struct usb_interface *intf; |
620 | unsigned long warnings; | ||
620 | __u32 quirks; | 621 | __u32 quirks; |
621 | int intfnum; | 622 | int intfnum; |
622 | char name[32]; | 623 | char name[32]; |
@@ -679,6 +680,9 @@ struct uvc_driver { | |||
679 | #define UVC_TRACE_SUSPEND (1 << 8) | 680 | #define UVC_TRACE_SUSPEND (1 << 8) |
680 | #define UVC_TRACE_STATUS (1 << 9) | 681 | #define UVC_TRACE_STATUS (1 << 9) |
681 | 682 | ||
683 | #define UVC_WARN_MINMAX 0 | ||
684 | #define UVC_WARN_PROBE_DEF 1 | ||
685 | |||
682 | extern unsigned int uvc_trace_param; | 686 | extern unsigned int uvc_trace_param; |
683 | 687 | ||
684 | #define uvc_trace(flag, msg...) \ | 688 | #define uvc_trace(flag, msg...) \ |
@@ -687,6 +691,12 @@ extern unsigned int uvc_trace_param; | |||
687 | printk(KERN_DEBUG "uvcvideo: " msg); \ | 691 | printk(KERN_DEBUG "uvcvideo: " msg); \ |
688 | } while (0) | 692 | } while (0) |
689 | 693 | ||
694 | #define uvc_warn_once(dev, warn, msg...) \ | ||
695 | do { \ | ||
696 | if (!test_and_set_bit(warn, &dev->warnings)) \ | ||
697 | printk(KERN_INFO "uvcvideo: " msg); \ | ||
698 | } while (0) | ||
699 | |||
690 | #define uvc_printk(level, msg...) \ | 700 | #define uvc_printk(level, msg...) \ |
691 | printk(level "uvcvideo: " msg) | 701 | printk(level "uvcvideo: " msg) |
692 | 702 | ||
@@ -740,10 +750,10 @@ extern int uvc_video_resume(struct uvc_video_device *video); | |||
740 | extern int uvc_video_enable(struct uvc_video_device *video, int enable); | 750 | extern int uvc_video_enable(struct uvc_video_device *video, int enable); |
741 | extern int uvc_probe_video(struct uvc_video_device *video, | 751 | extern int uvc_probe_video(struct uvc_video_device *video, |
742 | struct uvc_streaming_control *probe); | 752 | struct uvc_streaming_control *probe); |
753 | extern int uvc_commit_video(struct uvc_video_device *video, | ||
754 | struct uvc_streaming_control *ctrl); | ||
743 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | 755 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, |
744 | __u8 intfnum, __u8 cs, void *data, __u16 size); | 756 | __u8 intfnum, __u8 cs, void *data, __u16 size); |
745 | extern int uvc_set_video_ctrl(struct uvc_video_device *video, | ||
746 | struct uvc_streaming_control *ctrl, int probe); | ||
747 | 757 | ||
748 | /* Status */ | 758 | /* Status */ |
749 | extern int uvc_status_init(struct uvc_device *dev); | 759 | extern int uvc_status_init(struct uvc_device *dev); |