[RESEND PATCH v6] media: uvcvideo: UVC minimum relative pan/tilt/zoom speed fix.

Gergo Koteles
2025-12-01T16:12:05Z

From: John Bauer <johnebgood@securitylive.com>

In Video4Linux, a negative value in V4L2_CID_ZOOM_CONTINUOUS,
V4L2_CID_PAN_SPEED and V4L2_CID_TILT_SPEED indicates a movement in the
"opposite" direction to the standard direction.

Currently, we were using -UVC_GET_MIN as the negative value, which
resulted in the camera moving in the slowest possible speed.

Quirk the driver to return -UVC_GET_MAX for the affected controls.

Note that the get/set function from the mapping cannot be used for
this, because we need to use the information from GET_MAX for GET_MIN
and hacking uvc_ctrl_populate_cache seems like a worse alternative.

Tested on OBSBOT Tiny 2.

lsusb -v:

Bus 008 Device 002: ID 3564:fef8 Remo Tech Co., Ltd. OBSBOT Tiny 2
Negotiated speed: SuperSpeed (5Gbps)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 3.10
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2 [unknown]
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 9
idVendor 0x3564 Remo Tech Co., Ltd.
idProduct 0xfef8 OBSBOT Tiny 2
bcdDevice 4.09
iManufacturer 1 Remo Tech Co., Ltd.
iProduct 2 OBSBOT Tiny 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x04fc
bNumInterfaces 4
bConfigurationValue 1
iConfiguration 4 OBSBOT Multifunction
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 14 Video
bFunctionSubClass 3 Video Interface Collection
bFunctionProtocol 0
iFunction 5 OBSBOT Tiny 2 StreamCamera
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 1 Video Control
bInterfaceProtocol 0
iInterface 5 OBSBOT Tiny 2 StreamCamera
VideoControl Interface Descriptor:
bLength 13
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdUVC 1.00
wTotalLength 0x0050
dwClockFrequency 48.000000MHz
bInCollection 1
baInterfaceNr( 0) 1
VideoControl Interface Descriptor:
bLength 18
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1
wTerminalType 0x0201 Camera Sensor
bAssocTerminal 0
iTerminal 0
wObjectiveFocalLengthMin 0
wObjectiveFocalLengthMax 0
wOcularFocalLength 0
bControlSize 3
bmControls 0x00023e3e
Auto-Exposure Mode
Auto-Exposure Priority
Exposure Time (Absolute)
Exposure Time (Relative)
Focus (Absolute)
Zoom (Absolute)
Zoom (Relative)
PanTilt (Absolute)
PanTilt (Relative)
Roll (Absolute)
Focus, Auto
VideoControl Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 5 (PROCESSING_UNIT)
Warning: Descriptor too short
bUnitID 3
bSourceID 1
wMaxMultiplier 400
bControlSize 2
bmControls 0x0000f7df
Brightness
Contrast
Hue
Saturation
Sharpness
White Balance Temperature
White Balance Component
Backlight Compensation
Gain
Power Line Frequency
White Balance Temperature, Auto
White Balance Component, Auto
Digital Multiplier
Digital Multiplier Limit
iProcessing 0
bmVideoStandards 0x1d
None
PAL - 625/50
SECAM - 625/50
NTSC - 625/50
VideoControl Interface Descriptor:
bLength 29
bDescriptorType 36
bDescriptorSubtype 6 (EXTENSION_UNIT)
bUnitID 2
guidExtensionCode {9a1e7291-6843-4683-6d92-39bc7906ee49}
bNumControls 19
bNrInPins 1
baSourceID( 0) 3
bControlSize 4
bmControls( 0) 0xff
bmControls( 1) 0xff
bmControls( 2) 0x04
bmControls( 3) 0x00
iExtension 0
VideoControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 7
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 2
iTerminal 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 8
bMaxBurst 0
VideoControl Endpoint Descriptor:
bLength 5
bDescriptorType 37
bDescriptorSubtype 3 (EP_INTERRUPT)
wMaxTransferSize 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 0
iInterface 6 Video Streaming
VideoStreaming Interface Descriptor:
bLength 16
bDescriptorType 36
bDescriptorSubtype 1 (INPUT_HEADER)
bNumFormats 3
wTotalLength 0x03f8
bEndpointAddress 0x81 EP 1 IN
bmInfo 0
bTerminalLink 7
bStillCaptureMethod 0
bTriggerSupport 0
bTriggerUsage 0
bControlSize 1
bmaControls( 0) 4
bmaControls( 1) 0
bmaControls( 2) 4
VideoStreaming Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 6 (FORMAT_MJPEG)
bFormatIndex 1
bNumFrameDescriptors 6
bFlags 0
Fixed-size samples: No
bDefaultFrameIndex 1
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 1 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
VideoStreaming Interface Descriptor:
bLength 62
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1080
dwMinBitRate 995328000
dwMaxBitRate 1990656000
dwMaxVideoFrameBufferSize 4147200
dwDefaultFrameInterval 333333
bFrameIntervalType 9
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 166833
dwFrameInterval( 2) 200000
dwFrameInterval( 3) 333333
dwFrameInterval( 4) 333666
dwFrameInterval( 5) 400000
dwFrameInterval( 6) 416666
dwFrameInterval( 7) 500000
dwFrameInterval( 8) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 2
bmCapabilities 0x00
Still image unsupported
wWidth 3840
wHeight 2160
dwMinBitRate 1327104000
dwMaxBitRate 1327104000
dwMaxVideoFrameBufferSize 16588800
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 333333
dwFrameInterval( 1) 333666
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 62
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 3
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 720
dwMinBitRate 221184000
dwMaxBitRate 884736000
dwMaxVideoFrameBufferSize 1843200
dwDefaultFrameInterval 333333
bFrameIntervalType 9
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 166833
dwFrameInterval( 2) 200000
dwFrameInterval( 3) 333333
dwFrameInterval( 4) 333666
dwFrameInterval( 5) 400000
dwFrameInterval( 6) 416666
dwFrameInterval( 7) 500000
dwFrameInterval( 8) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 4
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 960
dwMinBitRate 294912000
dwMaxBitRate 1179648000
dwMaxVideoFrameBufferSize 2457600
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 5
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1440
dwMinBitRate 663552000
dwMaxBitRate 1327104000
dwMaxVideoFrameBufferSize 5529600
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 46
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 6
bmCapabilities 0x00
Still image unsupported
wWidth 4000
wHeight 3000
dwMinBitRate 1920000000
dwMaxBitRate 1920000000
dwMaxVideoFrameBufferSize 24000000
dwDefaultFrameInterval 333333
bFrameIntervalType 5
dwFrameInterval( 0) 333333
dwFrameInterval( 1) 400000
dwFrameInterval( 2) 416666
dwFrameInterval( 3) 500000
dwFrameInterval( 4) 666666
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
VideoStreaming Interface Descriptor:
bLength 27
bDescriptorType 36
bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED)
bFormatIndex 2
bNumFrameDescriptors 7
guidFormat {32595559-0000-0010-8000-00aa00389b71}
bBitsPerPixel 16
bDefaultFrameIndex 5
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 2 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 640
wHeight 360
dwMinBitRate 55296000
dwMaxBitRate 221184000
dwMaxVideoFrameBufferSize 460800
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 2
bmCapabilities 0x00
Still image unsupported
wWidth 640
wHeight 480
dwMinBitRate 73728000
dwMaxBitRate 294912000
dwMaxVideoFrameBufferSize 614400
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 3
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 720
dwMinBitRate 221184000
dwMaxBitRate 884736000
dwMaxVideoFrameBufferSize 1843200
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 4
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 960
dwMinBitRate 294912000
dwMaxBitRate 1179648000
dwMaxVideoFrameBufferSize 2457600
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 46
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 5
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1080
dwMinBitRate 497664000
dwMaxBitRate 995328000
dwMaxVideoFrameBufferSize 4147200
dwDefaultFrameInterval 333333
bFrameIntervalType 5
dwFrameInterval( 0) 333333
dwFrameInterval( 1) 400000
dwFrameInterval( 2) 416666
dwFrameInterval( 3) 500000
dwFrameInterval( 4) 666666
VideoStreaming Interface Descriptor:
bLength 46
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 6
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1440
dwMinBitRate 663552000
dwMaxBitRate 1327104000
dwMaxVideoFrameBufferSize 5529600
dwDefaultFrameInterval 333333
bFrameIntervalType 5
dwFrameInterval( 0) 333333
dwFrameInterval( 1) 400000
dwFrameInterval( 2) 416666
dwFrameInterval( 3) 500000
dwFrameInterval( 4) 666666
VideoStreaming Interface Descriptor:
bLength 30
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 7
bmCapabilities 0x00
Still image unsupported
wWidth 3840
wHeight 2160
dwMinBitRate 1990656000
dwMaxBitRate 1990656000
dwMaxVideoFrameBufferSize 16588800
dwDefaultFrameInterval 666666
bFrameIntervalType 1
dwFrameInterval( 0) 666666
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
VideoStreaming Interface Descriptor:
bLength 28
bDescriptorType 36
bDescriptorSubtype 16 (FORMAT_FRAME_BASED)
bFormatIndex 3
bNumFrameDescriptors 5
guidFormat {34363248-0000-0010-8000-00aa00389b71}
bBitsPerPixel 16
bDefaultFrameIndex 1
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 2 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
bVariableSize 1
VideoStreaming Interface Descriptor:
bLength 62
bDescriptorType 36
bDescriptorSubtype 17 (FRAME_FRAME_BASED)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1080
dwMinBitRate 497664000
dwMaxBitRate 1990656000
dwDefaultFrameInterval 333333
bFrameIntervalType 9
dwBytesPerLine 0
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 166833
dwFrameInterval( 2) 200000
dwFrameInterval( 3) 333333
dwFrameInterval( 4) 333666
dwFrameInterval( 5) 400000
dwFrameInterval( 6) 416666
dwFrameInterval( 7) 500000
dwFrameInterval( 8) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 17 (FRAME_FRAME_BASED)
bFrameIndex 2
bmCapabilities 0x00
Still image unsupported
wWidth 3840
wHeight 2160
dwMinBitRate 1327104000
dwMaxBitRate 1327104000
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwBytesPerLine 0
dwFrameInterval( 0) 333333
dwFrameInterval( 1) 333666
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 62
bDescriptorType 36
bDescriptorSubtype 17 (FRAME_FRAME_BASED)
bFrameIndex 4
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 720
dwMinBitRate 221184000
dwMaxBitRate 884736000
dwDefaultFrameInterval 333333
bFrameIntervalType 9
dwBytesPerLine 0
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 166833
dwFrameInterval( 2) 200000
dwFrameInterval( 3) 333333
dwFrameInterval( 4) 333666
dwFrameInterval( 5) 400000
dwFrameInterval( 6) 416666
dwFrameInterval( 7) 500000
dwFrameInterval( 8) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 17 (FRAME_FRAME_BASED)
bFrameIndex 5
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 960
dwMinBitRate 294912000
dwMaxBitRate 1179648000
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwBytesPerLine 0
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 50
bDescriptorType 36
bDescriptorSubtype 17 (FRAME_FRAME_BASED)
bFrameIndex 6
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1440
dwMinBitRate 663552000
dwMaxBitRate 1327104000
dwDefaultFrameInterval 333333
bFrameIntervalType 6
dwBytesPerLine 0
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 416666
dwFrameInterval( 4) 500000
dwFrameInterval( 5) 666666
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0400 1x 1024 bytes
bInterval 0
bMaxBurst 13
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 2
bInterfaceCount 2
bFunctionClass 1 Audio
bFunctionSubClass 0 [unknown]
bFunctionProtocol 0
iFunction 8 OBSBOT Tiny2 Audio
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 8 OBSBOT Tiny2 Audio
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 0x0027
bInCollection 1
baInterfaceNr(0) 3
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 3
wTerminalType 0x0201 Microphone
bAssocTerminal 0
bNrChannels 2
wChannelConfig 0x0003
Left Front (L)
Right Front (R)
iChannelNames 13 Capture Channels
iTerminal 12 OBSBOT Tiny2 Microphone
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 4
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 5
iTerminal 14 Capture Output terminal
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 5
bSourceID 3
bControlSize 2
bmaControls(0) 0x0003
Mute Control
Volume Control
iFeature 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 17 OBSBOT Tiny2 Microphone
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 18 Capture Active
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 4
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 1 Discrete
tSamFreq[ 0] 48000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x00c0 1x 192 bytes
bInterval 4
bRefresh 0
bSynchAddress 0
bMaxBurst 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 0 Undefined
wLockDelay 0x0000
Binary Object Store Descriptor:
bLength 5
bDescriptorType 15
wTotalLength 0x0016
bNumDeviceCaps 2
USB 2.0 Extension Device Capability:
bLength 7
bDescriptorType 16
bDevCapabilityType 2
bmAttributes 0x00000006
BESL Link Power Management (LPM) Supported
SuperSpeed USB Device Capability:
bLength 10
bDescriptorType 16
bDevCapabilityType 3
bmAttributes 0x00
wSpeedsSupported 0x000f
Device can operate at Low Speed (1Mbps)
Device can operate at Full Speed (12Mbps)
Device can operate at High Speed (480Mbps)
Device can operate at SuperSpeed (5Gbps)
bFunctionalitySupport 1
Lowest fully-functional device speed is Full Speed (12Mbps)
bU1DevExitLat 1 micro seconds
bU2DevExitLat 500 micro seconds
Device Status: 0x0001
Self Powered

Signed-off-by: John Bauer <johnebgood@securitylive.com>
Signed-off-by: Gergo Koteles <soyer@irl.hu>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
---
drivers/media/usb/uvc/uvc_ctrl.c | 62 ++++++++++++++++++++++++++------
1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 2905505c240c..123689b3f8ef 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -483,6 +483,7 @@ static int uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, u8 query,
return 0;

case UVC_GET_MIN:
+ /* Not used, we use -UVC_GET_MAX */
case UVC_GET_MAX:
case UVC_GET_RES:
case UVC_GET_DEF:
@@ -526,8 +527,7 @@ static int uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping,
*out = (sign == 0) ? 0 : (sign > 0 ? value : -value);
return 0;
case UVC_GET_MIN:
- *out = -value;
- return 0;
+ /* Not used, we use -UVC_GET_MAX */
case UVC_GET_MAX:
case UVC_GET_RES:
case UVC_GET_DEF:
@@ -1517,6 +1517,17 @@ static u32 uvc_get_ctrl_bitmap(struct uvc_control *ctrl,
return ~0;
}

+static bool uvc_ctrl_is_relative_ptz(__u32 ctrl_id)
+{
+ switch (ctrl_id) {
+ case V4L2_CID_ZOOM_CONTINUOUS:
+ case V4L2_CID_PAN_SPEED:
+ case V4L2_CID_TILT_SPEED:
+ return true;
+ }
+ return false;
+}
+
/*
* Maximum retry count to avoid spurious errors with controls. Increasing this
* value does no seem to produce better results in the tested hardware.
@@ -1576,18 +1587,32 @@ static int __uvc_queryctrl_boundaries(struct uvc_video_chain *chain,
break;
}

- if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)
- v4l2_ctrl->minimum = uvc_mapping_get_s32(mapping, UVC_GET_MIN,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
- else
- v4l2_ctrl->minimum = 0;
-
if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
v4l2_ctrl->maximum = uvc_mapping_get_s32(mapping, UVC_GET_MAX,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
else
v4l2_ctrl->maximum = 0;

+ if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) {
+ /*
+ * For relative PTZ controls, UVC_GET_MIN for
+ * b(Pan|Tilt|Zoom)Speed returns the minimum speed of the
+ * movement in direction specified in the sign field.
+ * See in USB Device Class Definition for Video Devices:
+ * 4.2.2.1.13 Zoom (Relative) Control
+ * 4.2.2.1.15 PanTilt (Relative) Control
+ *
+ * For minimum value, use maximum speed but in negative direction.
+ */
+ if (uvc_ctrl_is_relative_ptz(v4l2_ctrl->id))
+ v4l2_ctrl->minimum = -v4l2_ctrl->maximum;
+ else
+ v4l2_ctrl->minimum = uvc_mapping_get_s32(mapping,
+ UVC_GET_MIN, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
+ } else {
+ v4l2_ctrl->minimum = 0;
+ }
+
if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
v4l2_ctrl->step = uvc_mapping_get_s32(mapping, UVC_GET_RES,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
@@ -2449,6 +2474,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, u32 which,

static int uvc_ctrl_clamp(struct uvc_video_chain *chain,
struct uvc_control *ctrl,
+ u32 v4l2_id,
struct uvc_control_mapping *mapping,
s32 *value_in_out)
{
@@ -2466,10 +2492,24 @@ static int uvc_ctrl_clamp(struct uvc_video_chain *chain,
return ret;
}

- min = uvc_mapping_get_s32(mapping, UVC_GET_MIN,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
max = uvc_mapping_get_s32(mapping, UVC_GET_MAX,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+ /*
+ * For relative PTZ controls, UVC_GET_MIN for
+ * b(Pan|Tilt|Zoom)Speed returns the minimum speed of the
+ * movement in direction specified in the sign field.
+ * See in USB Device Class Definition for Video Devices:
+ * 4.2.2.1.13 Zoom (Relative) Control
+ * 4.2.2.1.15 PanTilt (Relative) Control
+ *
+ * For minimum value, use maximum speed but in negative direction.
+ */
+ if (uvc_ctrl_is_relative_ptz(v4l2_id))
+ min = -max;
+ else
+ min = uvc_mapping_get_s32(mapping, UVC_GET_MIN,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
+
step = uvc_mapping_get_s32(mapping, UVC_GET_RES,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
if (step == 0)
@@ -2583,7 +2623,7 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl)
if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
return -EACCES;

- ret = uvc_ctrl_clamp(chain, ctrl, mapping, &xctrl->value);
+ ret = uvc_ctrl_clamp(chain, ctrl, xctrl->id, mapping, &xctrl->value);
if (ret)
return ret;
/*
--
2.52.0