Files
insta360-link-controller/docs/PROTOCOL.md
T

36 KiB
Raw Blame History

Insta360 Link / Link 2 / Link 2C USB & UVC Protocol Specification

This document provides the complete, byte-accurate hardware control protocol specification for the Insta360 Link, Insta360 Link 2, Insta360 Link 2C, and Insta360 Link 2 Pro (PUC3) webcam family.

All protocol structures, USB descriptors, UVC Extension Unit GUIDs, control selectors, sub-opcodes, payload layouts, and state machines documented here were reverse-engineered directly from the official macOS binary:

  • Binary Path: /Applications/Insta360 Link Controller.app/Contents/MacOS/Webcam-desktop
  • Application Version: 2.0.2 (arm64 Mach-O executable)
  • SHA-256 Digest: 41db6e352223f06fa2fd70989a4d2faf622fd9c14b16a84da2aff39c0dcff22e

1. USB Device Identification & Firmware Images

All Insta360 Link family cameras enumerate under Arashi Vision's USB Vendor ID (0x2e1a). Device discovery is implemented in MacUVCCameraControlImp::GetUVCCameraList (0x100191478) and UVCCameraDeviceWatcherImp::StartWatch (0x10019e29c).

  • USB Vendor ID (idVendor): 0x2e1a (11802 decimal — Arashi Vision Inc. / Insta360)

1.1 Product IDs (idProduct) and Firmware Targets

Verified at 0x100191480 (0x4c01..=0x4c06), 0x100191664 (0x00c2), Webcam::CameraInsta::GetCameraModel() (0x10005f92c), UVCCameraExtendControllerImp::FirmwareUpgrade jump table (0x10286f37d), and firmware path table (0x1001a0a0c):

PID (idProduct) Camera Model Internal Code Physical Gimbal SetVideoMode Payload Virtual MSC Firmware Target Path
0x4c01 Insta360 Link (1st Gen) link1 Yes (3-axis) 8 bytes a:\Insta360WebCamFW.bin
0x4c02 Insta360 Link 2 Pro (PUC3 Gimbal A) link2_gimbal Yes (2-axis) 8 bytes a:\Insta360PUC3FW_GIMBAL.bin
0x4c03 Insta360 Link 2C (Fixed-Lens 4K) link2_main No 36 bytes a:\Insta360LINK2CFW_HOST.bin
0x4c04 Insta360 Link 2 (2-Axis Gimbal 4K) link2_gimbal Yes (2-axis) 8 bytes a:\Insta360LINK2FW_GIMBAL.bin
0x4c05 Insta360 Link 2C Pro (PUC3 Host) link2_main No 36 bytes a:\Insta360PUC3FW_HOST.bin
0x4c06 Insta360 Link 2 Pro (PUC3 Gimbal B) link2_gimbal Yes (2-axis) 8 bytes a:\Insta360PUC3FW_GIMBAL.bin
0x00c2 Insta360 Link Simple-Class / DFU link1 — 36 bytes a:\Insta360WebCamFW.bin

SetVideoMode Payload Length Note (0x1001970f4): In MacUVCCameraExtendController::SetVideoMode, when a 36-byte (0x24) VideoModeAuxiliaryData structure is supplied and pid is in 0x4c01..=0x4c06, the binary tests bit (pid - 0x4c01) against the bitmask 0x2b (0b101011, matching PIDs 0x4c01, 0x4c02, 0x4c04, 0x4c06). If the bit is set, the transfer length is truncated to 8 bytes (w4 = 8). For gimbal-less models (0x4c03 Link 2C and 0x4c05 PUC3 Host), the full 36-byte (0x24) buffer is transmitted.


2. Per-Model Hardware Capability Matrix

Derived from Webcam::CameraDeviceSupporter::UpdateUIStatus (0x10004a8b8), the controller determines per-device feature support directly from the USB Product ID:

Capability Flag Condition in Binary (0x10004a8b8) 0x4c01 Link 0x4c02 PUC3 Gimbal A 0x4c03 Link 2C 0x4c04 Link 2 0x4c05 PUC3 Host 0x4c06 PUC3 Gimbal B
has_physical_gimbal pid != 0x4c03 && pid != 0x4c05 Yes Yes No Yes No Yes
support_ptz_drag pid != 0x4c03 && pid != 0x4c05 Yes Yes No Yes No Yes
support_auto_framing pid != 0x4c01 No Yes Yes Yes Yes Yes
support_highlighting pid != 0x4c01 No Yes Yes Yes Yes Yes
support_mirror_vertically pid != 0x4c01 No Yes Yes Yes Yes Yes
support_track_speed pid != 0x4c03 && pid != 0x4c05 Yes Yes No Yes No Yes
support_image_template pid != 0x4c01 No Yes Yes Yes Yes Yes
support_privacy_mode pid != 0x4c01 No Yes Yes Yes Yes Yes
support_area_track (pid & 0xfffd) == 0x4c04 No No No Yes No Yes
support_roll_adjustment pid == 0x4c01 Yes No No No No No
support_ai_denoise pid != 0x4c01 No Yes Yes Yes Yes Yes
support_sound_wall pid == 0x4c05 || pid == 0x4c06 No No No No Yes Yes
support_speak_tracking (pid & 0xfffd) == 0x4c04 No No No Yes No Yes
support_auto_track pid != 0x4c03 && pid != 0x4c05 Yes Yes No Yes No Yes
support_smart_adjustment pid != 0x4c03 && pid != 0x4c05 Yes Yes No Yes No Yes
support_audio_capture_mode pid != 0x4c01 No Yes Yes Yes Yes Yes
support_horizontal_correction pid == 0x4c04 No No No Yes No No

3. UVC Descriptor Discovery & Extension Unit GUIDs

In FindControllerInterfaceForServiceObject (0x100190fe0), the host walks the USB Configuration Descriptor (bDescriptorType = 0x04 Interface Descriptor) looking for the UVC VideoControl interface:

  • bInterfaceClass = 0x0e (CC_VIDEO)
  • bInterfaceSubclass = 0x01 (SC_VIDEOCONTROL)

Within the VideoControl interface, class-specific interface descriptors (bDescriptorType = 0x24, CS_INTERFACE) are parsed by bDescriptorSubtype:

  1. VC_INPUT_TERMINAL (0x02):
    • Checks wTerminalType == 0x0201 (ITT_CAMERA at byte offset 4..6) and records bTerminalID (desc[3]).
  2. VC_PROCESSING_UNIT (0x05):
    • Records bUnitID (desc[3]).
  3. VC_EXTENSION_UNIT (0x06):
    • Compares the 16-byte guidExtensionCode (desc[4..20]) against two proprietary Insta360 Extension Unit GUIDs.

3.1 Proprietary Extension Unit GUIDs

Extension Unit Canonical UUID String (0x102a9d098 / 0x102a9d0b8) Mixed-Endian 16-Byte USB guidExtensionCode (desc[4..20]) Default bUnitID
Extension Unit 1 (XU1) FAF1672D-B71B-4793-8C91-7B1C9B7F95F8 2d 67 f1 fa 1b b7 93 47 8c 91 7b 1c 9b 7f 95 f8 9 (0x09)
Extension Unit 2 (XU2) E307E649-4618-A3FF-82FC-2D8B5F216773 49 e6 07 e3 18 46 ff a3 82 fc 2d 8b 5f 21 67 73 10 (0x0a)

Mixed-Endian UUID Conversion (0x100191140 & 0x100191168): Per the USB Video Class specification, the first three fields of guidExtensionCode (Data1: u32, Data2: u16, Data3: u16) are encoded in little-endian byte order, while Data4: [u8; 8] is encoded in big-endian (network) byte order:

  • FAF1672D-B71B-4793-8C91-7B1C9B7F95F8 → 2D 67 F1 FA | 1B B7 | 93 47 | 8C 91 | 7B 1C 9B 7F 95 F8
  • E307E649-4618-A3FF-82FC-2D8B5F216773 → 49 E6 07 E3 | 18 46 | FF A3 | 82 FC | 2D 8B 5F 21 67 73

3.2 Default UVC Unit IDs

When UVC descriptors are not overridden, Insta360 Link family cameras use the following standard unit IDs:

Unit / Interface Constant Default ID
UVC VideoControl Interface DEFAULT_CONTROL_INTERFACE 0 (0x00)
Camera Input Terminal (CT) DEFAULT_INPUT_TERMINAL_ID 1 (0x01)
Processing Unit (PU) DEFAULT_PROCESSING_UNIT_ID 2 (0x02)
Insta360 Extension Unit 1 (XU1) DEFAULT_EXTENSION_UNIT_ID 9 (0x09)
Insta360 Extension Unit 2 (XU2) DEFAULT_EXTENSION_UNIT2_ID 10 (0x0a)

4. UVC Control Request Framing

All standard and extension unit commands are transmitted as USB Control Transfers to Endpoint 0 targeting the UVC VideoControl interface (MacUVCCameraControl::SetData at 0x100192880 and MacUVCCameraControl::GetData at 0x10019282c).

4.1 USB Setup Packet Layout

Field Size Value / Formula Description
bmRequestType u8 0x21 (SET_CUR) or 0xa1 (GET_*) Class-specific (0x20), Interface recipient (0x01), Host-to-Device (0x00) or Device-to-Host (0x80)
bRequest u8 0x01 or 0x81..0x87 UVC Request Code (see table below)
wValue u16 (LE) (selector as u16) << 8 Control Selector (CS) in high byte, 0x00 in low byte
wIndex u16 (LE) ((unit_id as u16) << 8) | (interface_num as u16) Entity/Unit/Terminal ID in high byte, VideoControl bInterfaceNumber in low byte
wLength u16 (LE) data.len() as u16 Payload length in bytes

4.2 UVC Request Codes (bRequest)

Request Name bmRequestType bRequest Direction Usage
SET_CUR 0x21 0x01 OUT (Host → Camera) Write control value or execute command
GET_CUR 0xa1 0x81 IN (Camera → Host) Read current control value or status
GET_MIN 0xa1 0x82 IN (Camera → Host) Read minimum supported value
GET_MAX 0xa1 0x83 IN (Camera → Host) Read maximum supported value
GET_RES 0xa1 0x84 IN (Camera → Host) Read step resolution
GET_LEN 0xa1 0x85 IN (Camera → Host) Read payload length (u16 LE, 2 bytes) for variable-length XU selectors
GET_INFO 0xa1 0x86 IN (Camera → Host) Read control capability flags (1 byte)
GET_DEF 0xa1 0x87 IN (Camera → Host) Read factory default value

5. Standard UVC Camera Terminal (CT_*) & Processing Unit (PU_*) Controls

Implemented in MacUVCCameraController (0x100193694–0x100195800).

5.1 Camera Terminal Controls (unit_id = input_terminal_id, default 1)

Selector UVC Control Name Size Type (LE) Description & Typical Values
0x02 CT_AE_MODE_CONTROL 1B u8 Auto-Exposure mode bitmap: 1 = Manual, 2 = Auto, 4 = Shutter Priority, 8 = Aperture Priority
0x04 CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 4B u32 Shutter speed / exposure duration in 100 µs units (e.g. 10..1000, default 200)
0x06 CT_FOCUS_ABSOLUTE_CONTROL 2B u16 Manual focus distance (0..100, step 1, default 50)
0x08 CT_FOCUS_AUTO_CONTROL 1B u8 Auto-focus enable: 0 = Manual Focus, 1 = Auto Focus
0x0b CT_ZOOM_ABSOLUTE_CONTROL 2B u16 Digital zoom multiplier (100 = 1.0x .. 400 = 4.0x, step 1, default 100)
0x0d CT_PANTILT_ABSOLUTE_CONTROL 8B (i32, i32) [0..4] Pan angle in arcseconds (-468000..+468000), [4..8] Tilt angle in arcseconds (-324000..+324000); 1° = 3600 arcsec
0x0e CT_PANTILT_RELATIVE_CONTROL 4B [i8, u8, i8, u8] [0] pan_dir (-1, 0, +1), [1] pan_speed, [2] tilt_dir (-1, 0, +1), [3] tilt_speed
0x0f CT_ROLL_ABSOLUTE_CONTROL 2B i16 Gimbal roll angle in tenths of a degree (Link 1 0x4c01 only, e.g. -1800..+1800)

5.2 Processing Unit Controls (unit_id = processing_unit_id, default 2)

Selector UVC Control Name Size Type (LE) Description & Typical Values
0x02 PU_BRIGHTNESS_CONTROL 2B i16 Image brightness (0..100, step 1, default 50)
0x03 PU_CONTRAST_CONTROL 2B u16 Image contrast (0..100, step 1, default 50)
0x05 PU_POWER_LINE_FREQUENCY_CONTROL 1B u8 Anti-flicker frequency: 0 = Disabled, 1 = 50 Hz, 2 = 60 Hz, 3 = Auto
0x07 PU_SATURATION_CONTROL 2B u16 Color saturation (0..100, step 1, default 50)
0x08 PU_SHARPNESS_CONTROL 2B u16 Image sharpness (0..100, step 1, default 50)
0x0a PU_WHITE_BALANCE_TEMPERATURE_CONTROL 2B u16 Color temperature in Kelvin (2000..10000, step 50, default 5000)
0x0c PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 1B u8 Auto White Balance (AWB): 0 = Manual, 1 = Auto

6. Proprietary Extension Unit 1 (XU1) Selectors (0x01 – 0x0f)

  • GUID: FAF1672D-B71B-4793-8C91-7B1C9B7F95F8
  • Default Unit ID: 9 (0x09)
  • Binary Implementation: MacUVCCameraExtendController (0x100195a18–0x10019bd00)

Summary Table of XU1 Selectors

Selector Constant Name Size Requests Primary Function
0x01 SYSTEM_AND_PRESET_CMD 4B / 5B SET_CUR Preset recall/add/delete, Gimbal reset, Factory default, Composition bias, Forbidden area mode
0x02 VIDEO_MODE 8B / 36B SET_CUR, GET_CUR Video mode (Normal, AutoTracking, WhiteBoard, OverheadShot, DeskView, AutoFraming, SmartWhiteBoard) & ROI/pitch/zoom
0x03 TRACKING_AND_GESTURE 6B / 16B SET_CUR, GET_CUR Hand gesture enables, AI tracking speed, Composition style, Smart Whiteboard force
0x04 AUDIO_CONTROL 2B SET_CUR, GET_CUR Audio AI noise reduction (0..1) & Audio capture mode (1..5)
0x05 TRACK_OBJECT_SELECT 10B SET_CUR Select target person/object bounding box (UVCRect) for AI tracking
0x06 TRACK_OBJECT_LIST_V1 N * 10B GET_LEN, GET_CUR Detected trackable objects bounding box array (Insta360 Link 1 0x4c01)
0x07 EXPOSURE_CURVE_AND_ISO 259B SET_CUR, GET_CUR Auto/Manual exposure mode (u8), Manual ISO (u16), and 128-point tone curve ([u16; 128])
0x08 EXPOSURE_COMPENSATION 4B SET_CUR, GET_CUR Exposure compensation EV (f32 IEEE-754 little-endian)
0x09 WHITE_BALANCE_EXT 129B SET_CUR, GET_CUR Extended white balance mode (u8) and 32-channel gain array ([u32; 32])
0x0a EXTEND_FUNC_BITMASK 8B SET_CUR, GET_CUR 15-bit Extended Function bitmask (u32 mask, u32 values)
0x0b PANTILT_RELATIVE_EXT 4B SET_CUR, GET_CUR Proprietary gimbal relative pan/tilt ([pan_speed, pan_dir, tilt_speed, tilt_dir])
0x0c DEVICE_STATUS 4B GET_CUR Runtime device status bitflags (u32)
0x0d PTZ_VERSION_AND_ABS 30B GET_CUR Gimbal firmware version string ([0..20]) and current pan/tilt/zoom ([20..27])
0x0e PRESET_POSITION_FLAGS 8B GET_CUR Populated gimbal preset slot bitmask, active slot, and max slots
0x0f USB_MODE_SWITCH 4B SET_CUR Switch to Read-Only Mass Storage Class ([2, 0, 0, 0]) or camera file download ([1, 0, 0, 0])

Detailed XU1 Selector Payloads

XU1 0x01 — SYSTEM_AND_PRESET_CMD (4 or 5 Bytes, SET_CUR)

Multiplexed command register dispatched by sub-opcode in byte[0]:

Sub-Opcode (byte[0]) Method in Binary Address Length Wire Payload (Hex / Layout) Description
0x00 SetCurPresetPosition(u8 index) 0x100199918 4B [0x00, index, 0x00, 0x00] Recall gimbal preset slot index (0..=5)
0x01 AddPresetPosition(u8 index) 0x1001999b4 4B [0x01, index, 0x00, 0x00] Save current gimbal PTZ to slot index (0..=5)
0x02 DeletePresetPosition(u8 index) 0x100199a54 4B [0x02, index, 0x00, 0x00] Delete gimbal preset slot index (0..=5)
0x03 ResetGimbal() 0x100196fb0 4B [0x03, 0x00, 0x00, 0x00] Center/home gimbal pan, tilt, roll, and zoom
0x04 LoadFactoryDefault() 0x10019701c 4B [0x04, 0x00, 0x00, 0x00] Reset image/camera parameters to factory defaults
0x06 SetCompositionBias(i16 x, i16 y) 0x10019933c 5B [0x06, x_lo, x_hi, y_lo, y_hi] Set AI tracking composition offset (x = 0x7fff, y = 0x7fff resets bias)
0x07 EnterTrackForbiddenAreaSetting() 0x10019bf74 4B [0x07, 0x01, 0x00, 0x00] Enter interactive tracking forbidden-area calibration mode
0x08 ExitTrackForbiddenAreaSetting() 0x10019bfb4 4B [0x08, 0x01, 0x00, 0x00] Exit tracking forbidden-area calibration mode

XU1 0x02 — VIDEO_MODE (8 or 36 Bytes)

Verified in SetVideoMode (0x100197088) and GetVideoMode (0x1001978b8).

VideoMode Enum Values (byte[0], verified in CameraInsta at 0x1000601d4–0x100060234):

Value Variant UI Display Name Description
0 Normal Normal Standard webcam mode
1 AutoTracking AI Tracking Single-person gimbal/digital AI tracking
4 WhiteBoard Whiteboard Corner-marker whiteboard keystone enhancement
5 OverheadShot Overhead Gimbal pitched straight down (-90°) for top-down view
6 DeskView DeskView Tilted trapezoid perspective correction for desktop view
7 AutoFraming Auto Framing Multi-person group framing (Link 2 / Link 2C / PUC3)
8 (or 10) SmartWhiteBoard Smart Whiteboard Markerless AI whiteboard detection & perspective correction

Wire Layout (36-Byte VideoModeAuxiliaryData):

Byte Offset Type Field Description
0 u8 mode VideoMode enum value (0, 1, 4, 5, 6, 7, 8)
1 u8 flags Auxiliary mode flags (0 by default)
2..6 i32 LE rect[0] (x) ROI X or corner coordinate
6..10 i32 LE rect[1] (y) ROI Y or corner coordinate
10..14 i32 LE rect[2] (w) ROI Width or corner coordinate
14..18 i32 LE rect[3] (h) ROI Height or corner coordinate
18..20 i16 LE pitch DeskView / Host pitch angle (-900..0 or -61926 sentinel)
20..22 u16 LE zoom Mode zoom percentage (default 100)
22..36 [u8; 14] extra Mode-specific auxiliary bytes

Note: On Link (0x4c01), Link 2 (0x4c04), and PUC3 Gimbal (0x4c02, 0x4c06), SET_CUR sends only the first 8 bytes ([0..8]). On Link 2C (0x4c03) and PUC3 Host (0x4c05), SET_CUR sends all 36 bytes. GET_CUR always reads 36 bytes.


XU1 0x03 — TRACKING_AND_GESTURE (6 or 16 Bytes)

Multiplexed control for hand gestures, tracking speed, composition style, and Smart Whiteboard:

  1. SET_CUR (16 Bytes) — Dispatched by byte[0]:

    • byte[0] == 0x00 (EnableAllGesture at 0x100197b54): [0x00, enable_u8, 0x00, ...] (also toggles ExtendFunction::AllGestures bit 4 in XU1 0x0a).
    • byte[0] == 0x01 (EnableGestureWork at 0x100197bc8): Reads 6 bytes [all, ok, palm, l, v, rock] from GET_CUR, sets buf[0] = 0x01 and buf[gesture_idx + 1] = enable_u8, padded with zeros to 16 bytes.
    • byte[0] == 0x03 (ForceSetSmatrWhiteBoard at 0x1001980d0): [0x03, mode_u8, 0x00, ...].
    • byte[0] == 0x05 (SetTrackSpeed at 0x1001975bc): [0x05, speed_u8, 0x00, ...].
    • byte[0] == 0x06 (SetCompositionStyle at 0x100197498): [0x06, style_u8, 0x00, ...].
  2. GET_CUR (6 or 16 Bytes):

    • byte[0]: Master gesture enable (0 or 1)
    • byte[1]: Gesture::Ok (0) enable (0 or 1)
    • byte[2]: Gesture::Palm (1) enable (0 or 1)
    • byte[3]: Gesture::LShape (2) enable (0 or 1)
    • byte[4]: Gesture::VShape (3) enable (0 or 1)
    • byte[5]: Gesture::Rock (4) enable (0 or 1)
    • byte[6]: TrackSpeed (GetTrackSpeed at 0x100197630: 0 = Slow, 1 = Normal, 2 = Fast)
    • byte[7]: CompositionStyle (GetCompositionStyle at 0x10019750c: 0 = Head, 1 = HalfBody, 2 = WholeBody, 3 = Custom)

Gesture Indices (0x100197bc8 & setUseGesture* at 0x100067f58–0x100068888):

Index Enum Variant Hand Gesture Default Action
0 Gesture::Ok 👌 OK Sign Toggle AI Tracking / Auto Framing (byte[1])
1 Gesture::Palm ✋ Open Palm Toggle AI Tracking / Auto Framing (byte[2])
2 Gesture::LShape 👆 L-Shape Dynamic Zoom In/Out (byte[3])
3 Gesture::VShape ✌️ V-Shape (Peace) Toggle Whiteboard Mode (byte[4])
4 Gesture::Rock 🤘 Rock Sign Custom / Reserved (byte[5])

XU1 0x04 — AUDIO_CONTROL (2 Bytes)

Verified in EnableAudioNoiseReduction (0x100197798), GetAudioNoiseStatus (0x100197808), SetAudioCaptureMode (0x10019bf54), and GetAudioCaptureMode (0x10019bf64).

  • Payload: [value_u8, 0x00] (2 bytes)
  • For Link 1 noise reduction: value_u8 is 0 (Disabled) or 1 (Enabled).
  • For Link 2 / Link 2C / PUC3 AudioCaptureMode (0x1000702a8):
Value Variant UI Display Name Description
1 VoiceFocus Voice Focus Directional beamforming microphone mode
2 VoiceSuppression Noise Suppression Wide-angle background noise cancellation
3 MusicBalance Music Balance Balanced voice and ambient music fidelity
4 Original Original Sound Unprocessed raw microphone audio
5 SoundWall Sound Wall Virtual audio fence (PUC3 0x4c05 / 0x4c06 only)

XU1 0x05 & 0x06 — TRACK_OBJECT_SELECT & TRACK_OBJECT_LIST_V1 (10 Bytes per UVCRect)

Verified in SetTrackObj (0x100198a38) and GetTrackObjLists (0x100198adc). Each UVCRect entry is 10 bytes (5 × i16 little-endian):

Byte Offset Type Field Description
0..2 i16 LE x Normalized bounding box X coordinate
2..4 i16 LE y Normalized bounding box Y coordinate
4..6 i16 LE width Normalized bounding box width
6..8 i16 LE height Normalized bounding box height
8..10 i16 LE track_id Object tracking identifier

XU1 0x07 — EXPOSURE_CURVE_AND_ISO (259 Bytes)

Verified in GetExpouseCurve (0x10019aaa0), SetExpouseCurve (0x10019ab74), EnableAutoExposure (0x10019ac90), GetAutoExposureStatus (0x10019ad98), SetISOValue (0x10019ae24), and GetISOValue (0x10019af50).

Byte Offset Type Field Description
0 u8 mode Exposure mode: 0 = Manual Exposure, 1 = Auto Exposure
1..3 u16 LE iso Manual ISO sensitivity (e.g. 100..=3200)
3..259 [u16; 128] LE points 128-point tone/exposure lookup curve (256 bytes)

XU1 0x08 — EXPOSURE_COMPENSATION (4 Bytes)

Verified in SetExposureCompensation (0x100198f34) and GetExposureCompensation (0x100198fc0).

  • Payload: 4-byte IEEE-754 single-precision float (f32 little-endian) representing EV compensation (e.g., -3.0 to +3.0).

XU1 0x09 — WHITE_BALANCE_EXT (129 Bytes)

Verified in SetWhiteBalanceParam (0x10019afe0) and GetWhiteBalanceParam (0x10019b264).

  • byte[0]: u8 White balance mode
  • byte[1..129]: [u32; 32] Little-endian channel calibration gains (128 bytes).

XU1 0x0a — EXTEND_FUNC_BITMASK (8 Bytes)

Verified in EnableExtendFuncWork (0x100199afc), GetExtendFuncStatus (0x100199dd0), EnableVerticalScreen (0x10019b7d0), EnableLowResolution (0x10019b854), and the CameraInsta::Init jump table at 0x102864a20.

Wire Layout (8 Bytes):

Byte Offset Type Field Description
0..4 u32 LE mask Bitmask of feature bit(s) being modified (1u32 << bit_index on SET_CUR)
4..8 u32 LE values Full 32-bit state bitmask of all enabled extended functions

Complete ExtendFunction Bit Definitions (0..14, verified at 0x102864a20):

Bit Index Bitmask (1 << bit) Enum Variant Internal Field in CameraInsta Description
0 0x0000_0001 AiZoom ai_zoom_checked_ Automatic AI Zoom during tracking
1 0x0000_0002 Reserved1 — Reserved
2 0x0000_0004 Hdr enable_hdr_ Hardware HDR mode
3 0x0000_0008 HorizontalMirror mirror_checked_ Horizontal image flip / mirror
4 0x0000_0010 AllGestures enable_all_gestures_ Master hand-gesture recognition flag
5 0x0000_0020 VerticalMode enable_vertical_mode_ 9:16 Vertical output resolution
6 0x0000_0040 StartupParams enable_startup_params_ Persist startup parameters in camera NVRAM
7 0x0000_0080 SingleTapTracking enable_single_tap_tracking_ Single-click target selection tracking
8 0x0000_0100 AutoTracking enable_auto_tracking_ Automatic human tracking enable
9 0x0000_0200 SmartAdjustment smart_adjustment_checked_ Smart exposure/frame adjustment
10 0x0000_0400 ForcedVertical forced_vertical_ Uncropped 9:16 portrait mode (physical 90° rotation)
11 0x0000_0800 UltimatePrivacyMode enable_privacy_mode_ 10-second inactivity sleep / gimbal tilt-down privacy
12 0x0000_1000 VerticalMirror enable_vertically_mirror_ Vertical image flip (upside-down mount)
13 0x0000_2000 LowResolution enable_low_resolution_ Low-resolution compatibility mode
14 0x0000_4000 TrackForbiddenArea enable_track_forbidden_area_ Enforce tracking forbidden zones

XU1 0x0b — PANTILT_RELATIVE_EXT (4 Bytes)

Verified in SetPanTiltRelative (0x1001990f4) and GetPanTiltRelative.

  • Payload: [pan_speed: u8, pan_dir: i8, tilt_speed: u8, tilt_dir: i8]
  • Note that the byte order (speed then dir) is reversed compared to standard UVC CT_PANTILT_RELATIVE_CONTROL (0x0e, which uses dir then speed).
  • dir: 0 = Stop, 1 = Positive (Right / Up), -1 (0xff) = Negative (Left / Down).

XU1 0x0c — DEVICE_STATUS (4 Bytes, GET_CUR)

Verified in GetDeviceStatus (0x10019b8dc). Returns a 32-bit little-endian status bitmask (DeviceStatus):

  • Bit 0 (0x01): TRACKING_ACTIVE
  • Bit 1 (0x02): WHITEBOARD_ACTIVE
  • Bit 2 (0x04): GESTURE_DETECTED
  • Bit 3 (0x08): PRIVACY_SLEEP
  • Bit 4 (0x10): OVERHEAD_MODE
  • Bit 5 (0x20): DESKVIEW_MODE
  • Bit 6 (0x40): UPGRADING

XU1 0x0d — PTZ_VERSION_AND_ABS (30 Bytes, GET_CUR)

Verified in GetPTZVersionInfo (0x1001993bc) and GetPanTiltAbsoluteValue (0x1001996cc).

  • byte[0..20]: Null-terminated ASCII gimbal firmware version string (e.g. "v1.3.1.0_build0").
  • byte[20..22]: i16 LE current Pan angle (in 0.1° units, 1° = 10 units = 3600 arcsec).
  • byte[22..24]: i16 LE current Tilt angle (in 0.1° units).
  • byte[24..26]: u16 LE current Zoom ratio (100..400).
  • byte[26]: u8 Gimbal status byte.
  • byte[27..30]: Reserved.

XU1 0x0e — PRESET_POSITION_FLAGS (8 Bytes, GET_CUR)

Verified in GetCurPresetPositionFlag (0x1001997c0).

  • byte[0]: slot_mask (u8 bitmask of saved presets, bits 0..5).
  • byte[1]: current_slot (u8 index of active preset).
  • byte[2]: max_slots (u8, typically 6).
  • byte[3..8]: Reserved.

XU1 0x0f — USB_MODE_SWITCH (4 Bytes, SET_CUR)

Verified in SwitchMscReadOnlyClass (0x10019b998) and DownloadFileFromCamera (0x10019b928):

  • [0x01, 0x00, 0x00, 0x00]: Trigger diagnostic log / file download mode.
  • [0x02, 0x00, 0x00, 0x00]: Switch camera USB personality to Read-Only Mass Storage Class (MSC) / Simple-Class mode for firmware upgrade.

7. Proprietary Extension Unit 2 (XU2) Selectors (0x01 – 0x0f)

  • GUID: E307E649-4618-A3FF-82FC-2D8B5F216773
  • Default Unit ID: 10 (0x0a)
  • Binary Implementation: MacUVCCameraExtendController (0x100195a18–0x10019c478)

Summary Table of XU2 Selectors

Selector Constant Name Size Requests Primary Function
0x01 GESTURE_BINDING_MAP 16B SET_CUR, GET_CUR Map hand gestures (0..4) to GestureFunction actions (0..4)
0x02 SYSTEM_TIME_AND_IQ 10B SET_CUR Sync host UTC timestamp, set IQ switches (D0/D1), or restore factory settings
0x03 DEVICE_INFO 150B GET_CUR Read device name ([0..50]), firmware version ([50..100]), and serial number ([100..150])
0x04 IMAGE_TEMPLATE_INFO 11B SET_CUR, GET_CUR Image preset template save/apply/delete & populated 64-bit slot bitmask
0x05 IMAGE_TEMPLATE_NAME 65B SET_CUR, GET_CUR Read/write 64-byte ASCII name for image template id (byte[0])
0x06 FILTER_MODE 1B SET_CUR, GET_CUR Hardware LUT color filter (0..=8)
0x07 (Reserved) — — Unused in v2.0.2
0x08 PRIVACY_AND_FILL_LIGHT 4B SET_CUR, GET_CUR Hardware privacy mode ([2, enable, 0, 0]) and fill light parameters
0x09 HOST_PTZ 8B SET_CUR Digital crop box on gimbal-less cameras (u16 x, y, width, height, normalized 0..5140)
0x0a TRACK_OBJECT_LIST_V2 N * 10B GET_LEN, GET_CUR Detected trackable objects bounding box array (GetNewTrackObjLists for Link 2 / 2C)
0x0b TRACK_FORBIDDEN_AREA 40B SET_CUR, GET_CUR Configure/enable gimbal tracking exclusion zones (ForbiddenAreaInfo_s)
0x0c DEFAULT_TRACK_MODE 1B SET_CUR, GET_CUR Default AI tracking mode (0 = Single Person, 1 = Group / Auto Framing)
0x0d HORIZONTAL_CORRECTION 1B SET_CUR, GET_CUR Gimbal horizon leveling (0 = Off, 1 = On; Link 2 0x4c04)
0x0e REAL_ZOOM_AND_UDISK 4B SET_CUR, GET_CUR Query real optical/digital zoom value (u16 LE) and UDisk open counter
0x0f REPORT_DATA Variable GET_LEN, GET_CUR Telemetry and diagnostic report buffer (GetReportData)

Detailed XU2 Selector Payloads

XU2 0x01 — GESTURE_BINDING_MAP (16 Bytes)

Verified in GetGestureBindingMap (0x100198384) and SetGestureBindingFunc (0x10019874c). Maps each Gesture (0..4) to a GestureFunction:

  • 0 = None
  • 1 = AutoTracking
  • 2 = Zoom
  • 3 = WhiteBoard
  • 4 = AutoFraming

XU2 0x02 — SYSTEM_TIME_AND_IQ (10 Bytes, SET_CUR)

Multiplexed system control dispatched by byte[0]:

Sub-Opcode (byte[0]) Method in Binary Address Wire Payload (10 Bytes) Description
0x01 SetTimestamp(u64 ms) 0x10019be40 [0x01, ts_le[0..8], 0x00] Synchronize camera RTC with 64-bit host timestamp (ms)
0x02 SetIQSwitch(int bit, bool en) 0x100199ce0 [0x02, mask_u32_le[0..4], 0..] Toggle ISP Image Quality switch bit (0 = D0, 1 = D1)
0x04 RestoreFactorySet(true) 0x10019c1ac [0x04, 0x01, 0x00, ...] Full factory reset and reboot camera
0x05 RestoreFactorySet(false) 0x10019c1ac [0x05, 0x01, 0x00, ...] Restore factory settings without rebooting

XU2 0x03 — DEVICE_INFO (150 Bytes, GET_CUR)

Verified in GetDeviceInfo (0x100196e74) and GetSerialNumber (0x100196d10). Contains three fixed 50-byte null-terminated ASCII strings:

  • byte[0..50]: device_name (e.g. "Insta360 Link 2")
  • byte[50..100]: firmware_version (e.g. "v2.5.8.8_build1")
  • byte[100..150]: serial_number (e.g. "INK2A240912345")

XU2 0x04 & 0x05 — IMAGE_TEMPLATE_INFO (11 Bytes) & IMAGE_TEMPLATE_NAME (65 Bytes)

Verified in GetImageTemplateInfo (0x10019ba4c), SetImageTemplate (0x10019bb08), DeleteTemplate (0x10019bbc8), GetImageTemplateName (0x10019bc74), and SetImageTemplateName (0x10019bd14).

XU2 0x04 (IMAGE_TEMPLATE_INFO, 11 Bytes):

Byte Offset Type Field Description
0 i8 current_id Active template slot ID (0..63, or -1 if none active)
1 u8 operation ImageOperation: 0 = None, 1 = SaveOrUpdate, 2 = Apply
2..10 u64 LE bitmask 64-bit mask of populated template slots (bit N = 1 if slot N exists)
10 u8 max_templates Maximum supported templates (typically 10)

XU2 0x05 (IMAGE_TEMPLATE_NAME, 65 Bytes):

  • byte[0]: i8 template_id (0..63)
  • byte[1..65]: 64-byte null-terminated UTF-8/ASCII template name.

XU2 0x06 — FILTER_MODE (1 Byte)

Verified in SetFilter (0x10019bdb0), GetFilter (0x10019bdf8), and UI mapping at 0x100096f94:

Value Variant Filter Name
0 FilterMode::None None (Original)
1 FilterMode::Style1 Style 1
2 FilterMode::Style2 Style 2
3 FilterMode::Fresh Fresh
4 FilterMode::Amber Amber
5 FilterMode::Film1 Film 1
6 FilterMode::Film2 Film 2
7 FilterMode::Cool Cool
8 FilterMode::Warm Warm

XU2 0x08 — PRIVACY_AND_FILL_LIGHT (4 Bytes)

Verified in SetPrivacyMode (0x10019c108) and GetPrivacyMode (0x10019c168):

  • SET_CUR (4 Bytes): [0x02, enable_u8, 0x00, 0x00] where enable_u8 is 1 (Privacy On) or 0 (Privacy Off).
  • GET_CUR (4 Bytes): byte[0] = status code (i8), byte[1] = 1 if privacy mode is enabled else 0.

XU2 0x09 — HOST_PTZ (8 Bytes, SET_CUR)

Verified in SetHostPTZ (0x10019bec0). Used on gimbal-less models (Link 2C 0x4c03 and PUC3 Host 0x4c05) for digital pan/tilt/zoom cropping within a 5140 × 5140 coordinate space:

  • byte[0..2]: u16 LE x (0..5140)
  • byte[2..4]: u16 LE y (0..5140)
  • byte[4..6]: u16 LE width (default 5140)
  • byte[6..8]: u16 LE height (default 5140)

XU2 0x0b — TRACK_FORBIDDEN_AREA (40 Bytes)

Verified in SetTrackForbiddenArea (0x10019bff4), GetTrackForbiddenArea (0x10019c038), and EnableTrackForbiddenArea. Stores up to 4 ForbiddenAreaInfo_s entries (10 bytes each: u8 enabled, u8 index, i16 pan_min, i16 pan_max, i16 tilt_min, i16 tilt_max).


XU2 0x0c — DEFAULT_TRACK_MODE (1 Byte)

Verified in SetDefaultTrackMode (0x10019c220) and GetDefaultTrackMode (0x10019c268).

  • byte[0]: 0 = Single-person tracking, 1 = Multi-person / Group tracking.

XU2 0x0d — HORIZONTAL_CORRECTION (1 Byte)

Verified in EnableHorizontalCorrection (0x10019c2b0) and GetEnableHorizontalCorrection (0x10019c2f8).

  • byte[0]: 0 = Disabled, 1 = Enabled (supported on Insta360 Link 2 0x4c04).

XU2 0x0e — REAL_ZOOM_AND_UDISK (4 Bytes)

Verified in GetRealZoomValue (0x10019c340), GetUDiskOpenCount, and SetUDiskOpenCount.

  • byte[0..2]: u16 LE real zoom factor (100..400).

8. Firmware Upgrade Protocol (UVCCameraExtendControllerImp::FirmwareUpgrade)

Verified in UVCCameraExtendControllerImp::FirmwareUpgrade (0x10019fc88) and MacSimpleClassControlImp (0x1001a0a0c).

Insta360 cameras support two firmware delivery paths depending on the active USB mode:

  1. Read-Only Mass Storage Class (MSC) Mode: Triggered via XU1 selector 0x0f ([0x02, 0x00, 0x00, 0x00]).
  2. USB Vendor Simple-Class Mode (PID 0x00c2 or vendor interface): Transfers the firmware image over raw USB Vendor Control + Bulk OUT transfers.

8.1 Step-by-Step USB Simple-Class Upgrade Sequence (0x10019fc88)

  1. Initiate Firmware Transfer (Vendor Control Transfer OUT):

    • bmRequestType = 0x41 (Host-to-Device, Vendor, Interface)
    • bRequest = 0x01
    • wValue = 0x0004
    • wIndex = 0x0000
    • wLength = 137 (0x0089 bytes)
    • 137-Byte Header Payload:
      • byte[0..8]: u64 LE total firmware file size in bytes
      • byte[8]: 0x5c ('\\' path separator sentinel)
      • byte[9..137]: 128-byte null-padded ASCII target path on camera flash (from 0x1001a0a0c, e.g. a:\Insta360WebCamFW.bin, a:\Insta360LINK2FW_GIMBAL.bin, a:\Insta360LINK2CFW_HOST.bin, a:\Insta360PUC3FW_GIMBAL.bin, or a:\Insta360PUC3FW_HOST.bin).
  2. Stream Firmware Image in 512 KB Bulk Chunks:

    • Endpoint: Bulk OUT Endpoint 0x01
    • Chunk Size: 0x80000 bytes (524,288 bytes = 512 KB) per bulk transfer until the entire firmware binary is transmitted.
  3. Verify Firmware Reception (Vendor Control Transfer IN):

    • bmRequestType = 0xc1 (Device-to-Host, Vendor, Interface)
    • bRequest = 0x81
    • wValue = 0x0004
    • wIndex = 0x0000
    • wLength = 1
    • Response: 1 byte (0x00 indicates checksum/transfer verification succeeded).
  4. Reboot into Normal UVC Mode (Vendor Control Transfer OUT):

    • bmRequestType = 0x41 (Host-to-Device, Vendor, Interface)
    • bRequest = 0x01
    • wValue = 0x0002
    • wIndex = 0x0000
    • wLength = 1
    • Payload: [0x01]