/* uvc_xu_ctrls.h
 * UVC Extension Unit controls for Sensoray Model 2263
 * Copyright (c) Sensoray 2013
 */

#ifndef __UVC_XU_CTRLS_H__
#define __UVC_XU_CTRLS_H__


#ifndef UVC_NTSC
#define UVC_NTSC 1
#endif
#ifndef UVC_PAL
#define UVC_PAL 2
#endif

/* These are the unit ids in the UVC descriptors */
#define UVC_ID_SELECTOR_UNIT		6
#define UVC_ID_PROCESSING_UNIT		7
#define UVC_ID_EXTENSION_UNIT		8
#define UVC_ID_H264_EXTENSION_UNIT	9

#define GUID_EXTENSION_UNIT {	\
	0x43, 0x7b, 0xa9, 0x19, 0x7d, 0x72, 0x21, 0x63,	\
	0x82, 0x57, 0x37, 0x84, 0x19, 0x26, 0x76, 0x48 \
}

#define GUID_H264_EXTENSION_UNIT { \
	0x41, 0x76, 0x9e, 0xa2, 0x04, 0xde, 0xe3, 0x47, \
	0x8b, 0x2b, 0xf4, 0x34, 0x1a, 0xff, 0x00, 0x3b, \
}

#define GUID_H264_VIDEO_STREAMING { \
	0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, \
	0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71, \
}



// see uvc.h: struct uvc_request_data 
// NOTE: Windows XP will only work with at most 10 bytes
#define MAX_UVC_REQUEST_DATA_XP 10
#define MAX_UVC_REQUEST_DATA    60
// absolute maximum is 60, based on struct uvc_request_data(linux/drivers/usb/gadget/uvc.h)

// extension unit control selector ids (these are 1-based indexing)

// CROP added in buld 3473
#define SRAY_XU_CROP_VERSION 3473
#define UVC_XU_CAPTURE_CROP	1
#define UVC_XU_PREVIEW_CROP	2
#define UVC_XU_PRIVACY_MASK     3
/* struct rect {
 *   x: u16;
 *   y: u16;
 *   width: u16;
 *   height: u16;
 * }
 * Cropping is inactive when width or height are zero.
 * Coordinates are relative the values provided by UVC_XU_VIDDEC_INFO
 */

#define UVC_XU_FIRMWARE_VERSION	4
#define UVC_XU_BOARD_INFO	5


/* struct clock {
 *   year: u8;   // minus 1900, similar to struct tm
 *   month: u8;  // 1-12
 *   day: u8;    // 1-31
 *   hour: u8;   // 0-23
 *   minute: u8; // 0-59
 *   second: u8; // 0-59
 * }
 */
#define UVC_XU_CLOCK		6
#define SRAY_XU_CLOCK_VERSION 3579

// Added in build 3761 - capture and preview frame counters
#define SRAY_XU_FRAMECOUNT_VERSION 3761
#define UVC_XU_CAPTURE_FC    7
#define UVC_XU_PREVIEW_FC    8

// Read the number of overlay bytes received by the device, to check for errors
// Will be zero if overlay was completely received
#define SRAY_XU_OVERLAY_CHECK_VERSION 3612
#define UVC_XU_OVERLAY_CHECK    9

#define UVC_XU_VIDDEC_INFO	10
#define SRAY_XU_AHD_STD_VERSION 3382
#define SRAY_XU_SET_AHD_STD_VERSION 4101
/* 
 * 
 */
#define UVC_XU_OVERLAY_HEADER	11
#define UVC_XU_OVERLAY_DATA	12
// these will replace BITRATE, GOPSIZE, RATEMODE, H264_LEVEL, H264_PROFILE, JPEG_QUALITY, CAPTURE_MODE
/* struct capture_params {
 * bitrate: u16; // 100-20000
 * gopsize: u8;  // 0-255
 * ratemode: u2; // 0=cbr 1=vbr 2=fixedQP constant quality
 * level: u4:    // H.264 level enum{1.0, 1.b, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, 5.0}
 * profile: u2;  // H.264 profile 0=baseline(66) 1=main(77) 2=extended(88) 3=high(100)
 * interlaced: u4; // 0=progressive/interpolate 1=interlaced/auto  2=top 3=bottom 4=interlaced 5=seq_tb 6=seq_bt 7=alternate 8=int_tb 9=int_bt
 * streammode: u4;// 0=TS/H.264+AAC, 1=TS/H.264, 2=ES/H.264, 3=MJPEG
 * frameskip: u5; // frame rate divider minus one (0..31)
 * intraFrameQP: u6; // 0..51
 * interPFrameQP: u6; // 0..51
 * aspectratio: u2; // 0=none 1=4:3 2=16:9
 * jpegquality: u7: // jpeg quality 10-99
 * flip: u2; // bit 0=hflip 1=vflip
 * slicemode: u3; // 0=off 1=on(5 slices per frame)
 * rotate: u1; // 0=off 1=on (use with flip to change direction) SD resolution only!
 * state: u1; // 0=off 1=on  (added in fw 3980)
 * 
 *      7       6       5       4       3       2       1       0
 * 0 [  bitrate[7..0]                                                   ]
 * 1 [  bitrate[15..8]                                                  ]
 * 2 [  gopsize[7..0]                                                   ]
 * 3 [  state][                                                         ]
 * 4 [  ratemode       ][ profile[1..0] ][ level[3..0]                  ]
 * 5 [  interlaced                      ][ streammode                   ]
 * 6 [  slicemode               ][ frameskip                            ]
 * 7 [  flip            ][ intraframeqp[5..0]                           ]
 * 8 [  aspectratio     ][ interpframeqp[5..0]                          ]
 * 9 [  rotate  ][ jpeg quality[6..0]                                   ]
 * } */

// added in build 2772
#define UVC_XU_CAPTURE_PARAMS	13
#define UVC_XU_PREVIEW_PARAMS	14
#define UVC_XU_VIDEO_LOCK	15

#define UVC_XU_AUDIO_INPUT	16

/* struct deint_params {
 *   enabled: u8;        // 0=disabled 1=enabled
 *   channel: u8;        // 0=Recording 1=Preview
 *   threshold_low: u8;  // NOTE: threshold_low < threshold_high and
 *   threshold_high: u8; // NOTE: threshold_high - threshold_low must be power of 2
 *   exclude_start: u16; // don't deinterlace these lines in the captured video
 *   exclude_count: u16; // use count=0 to exclude none
 * }
 */
// Note: Deinterlacer will only operate when selected stream resolution
//       is 720x576 or less, and capture_params.interlaced==0
// added in build 3793
#define UVC_XU_DEINT_PARAMS	17
#define SRAY_XU_DEINT_PARAMS_VERSION 3793


// TODO: pack audio controls into one
/* struct audio_params {
 * bitrate: u9; // 96-256 in steps of 32 (units of kbps)
 * volume: u16; // left and right u8 (analog only)
 * samplerate: u16; // 32k, 44100 and 48k
 * channels: u2; // 1 or 2
 * monomode: u2; // 0=mix L&R 1=left only 2=right only
 * encoding: u2: 0=none 1=AAC 2=MP3 3=PCM 
 * audio input u2: 2=digital 1=analog

 *      7       6       5       4       3       2       1       0
 * 0 [  bitrate[7..0]                                                   ]
 * 1 [  bitrate[15..8]                                                  ]
 * 2 [  volume left                                                     ]
 * 3 [  volume right                                                    ]
 * 4 [  samplerate[7..0]                                                ]
 * 5 [  samplerate[15..8]                                               ]
 * 6 [                              monomode        ][  channels        ]
 * 7 [  encoding                                                        ]
 * 8 [  audio input                                                     ]
 */
// added in build 2772
#define UVC_XU_AUDIO_PARAMS     19

// TODO recycle these
#define UVC_XU_AUDIO_BITRATE	20
#define UVC_XU_AUDIO_VOLUME	21
#define UVC_XU_AUDIO_SAMPLERATE	22
#define UVC_XU_AUDIO_CHANNELS	23
#define UVC_XU_AUDIO_ENCODING	24

/* commands:
 * 1=firmware upload
 * 2=stop stream A  (removed UVC_XU_CAPTURE_STATE)
 * 3=stop stream B  (removed UVC_XU_PREVIEW_STATE)
 * 4=reboot
 * 5=pause capture stream
 * 6=resume capture stream
 * 7=pause preview stream
 * 8=resume preview stream
 * 9=disable message "No video lock" when input disconnected
 * 10=enable message "No video lock" when input disconnected
 * 11=stop servicing watchdog timer, board will reset automatically
 * 12=jpeg snapshot on recording stream, will be transferred in-band
 * 13=enable colorkiller circuit (switch to monochrome when color carrier is weak)
 * 14=disable colorkiller circuit
 * 15=enable serial debug port
 * 16=USB PHY Reset (HW errata fix)
 * 17=restart capture stream (after stream timeout)
 * 18=restart preview stream (after stream timeout)
 * 19=enable periodic USB PHY Reset (HW errata fix) at idle 10 mins intervals
 */
#define UVC_XU_COMMAND_FW_UPLOAD 1
#define UVC_XU_COMMAND_STOP_STREAM_A 2
#define UVC_XU_COMMAND_STOP_STREAM_B 3
#define UVC_XU_COMMAND_REBOOT 4
#define UVC_XU_COMMAND_CAPTURE_PAUSE 5
#define UVC_XU_COMMAND_CAPTURE_RESUME 6
#define UVC_XU_COMMAND_PREVIEW_PAUSE 7
#define UVC_XU_COMMAND_PREVIEW_RESUME 8
#define UVC_XU_COMMAND_DISABLE_NO_LOCK_MSG 9
#define UVC_XU_COMMAND_ENABLE_NO_LOCK_MSG 10
#define UVC_XU_COMMAND_TEST_WATCHDOG_RESET 11
#define UVC_XU_COMMAND_SNAPSHOT 12
#define UVC_XU_COMMAND_COLORKILLER_ENABLE 13
#define UVC_XU_COMMAND_COLORKILLER_DISABLE 14
#define UVC_XU_COMMAND_ENABLE_DEBUG_PORT 15
#define UVC_XU_COMMAND_USB_PHY_RESET 16
#define UVC_XU_COMMAND_CAPTURE_RESTART 17
#define UVC_XU_COMMAND_PREVIEW_RESTART 18
#define UVC_XU_COMMAND_PERIODIC_USB_PHY_RESET 19
#define UVC_XU_COMMAND_LAST 19

#define SRAY_XU_SNAPSHOT_VERSION 3605
#define SRAY_XU_USB_PHY_RESET_VERSION 3980
#define SRAY_XU_PERIODIC_USB_PHY_RESET_VERSION 4115

#define UVC_XU_COMMAND	25


/* Display Params
 * display mode: u8; 0=idle 1=HD passthru 6=SD passthru
 * display std: u8; 0=auto  others=use CEA/EIA-861F
 * display output: u8 0=composite 1=component 2=digital
 * 
 *      7       6       5       4       3       2       1       0
 * 0 [ display mode                                                     ]
 * 1 [ display std                                                      ]
 * 2 [ display output                                                   ]
 * 3 [                                                                  ]
 * 4 [                                                                  ]
 * 5 [                                                                  ]
 * 6 [                                                                  ]
 * 7 [                                                                  ]
 * 8 [                                                                  ]
 */
#define UVC_XU_DISPLAY_PARAMS	26

// Read temperature sensor on model 2271,2273
// u16: value, divide by 16 to get degrees C
#define UVC_XU_TEMP_SENSOR	27
#define SRAY_XU_TEMP_SENSOR_VERSION 3910


#define UVC_XU_LOG_DATA		28
#define UVC_XU_GPIO             29
#define SRAY_XU_GPIO_VERSION 3919
#define UVC_XU_DEBUG_REG_ADDR	30
#define UVC_XU_DEBUG_REG_VALUE	31
/* Windows only looks at first 31 controls per extension unit */
#define UVC_XU_VIDEO_INPUT	32  // backup control for buggy UVC module
#define SRAY_XU_VIDEO_INPUT_VERSION 3210

#define UVC_XU_RESERVED_33	33
#define UVC_XU_RESERVED_34	34
#define UVC_XU_VIDDEC_REG_ADDR	35
#define UVC_XU_VIDDEC_REG_VALUE	36
#define UVC_XU_FRAMESIZE_RINGBUFFER 37
#define UVC_XU_OVERLAY_DATA60	38

/* additional controls go here */
#define UVC_XU_CONTROL_LAST	38

#define SRAY_XU_SWAP_CAPTURE_PREVIEW_VERSION 2524
#define SRAY_XU_NEW_PARAM_VERSION 2772
#define SRAY_XU_OLD_VERSION 2680
// removed in build 2681
#define UVC_XU_SERIAL_NUMBER	5
#define UVC_XU_VIDDEC_FRAMERATE	10
#define UVC_XU_VIDDEC_WIDTH	11
#define UVC_XU_VIDDEC_HEIGHT	12
#define UVC_XU_VIDDEC_INTERLACED 13
#define UVC_XU_FIRMWARE_TIMESTAMP 14
#define UVC_XU_FIRMWARE_UPLOAD  25
#define UVC_XU_JPEG_QUALITY	26
// removed in build 3370
#define UVC_XU_BITRATE		1
#define UVC_XU_GOPSIZE		2
#define UVC_XU_RATEMODE		3
#define UVC_XU_H264_LEVEL	6
#define UVC_XU_H264_PROFILE	7
#define UVC_XU_CAPTURE_INTERLACED 8
#define UVC_XU_PREVIEW_INTERLACED 9
#define UVC_XU_CAPTURE_STATE	17
#define UVC_XU_PREVIEW_STATE	18
#define UVC_XU_CPU_LOAD		31
// removed in build 3588
#define UVC_XU_CAPTURE_MODE	27
// removed in build 3919
#define UVC_XU_FEATURE_FLAGS	29

#define DEFN_BM_CONTROL(n, i0, i1, i2, i3, i4, i5, i6, i7) ( \
	(i0?(1UL << (i0-8*n-1)):0) | \
	(i1?(1UL << (i1-8*n-1)):0) | \
	(i2?(1UL << (i2-8*n-1)):0) | \
	(i3?(1UL << (i3-8*n-1)):0) | \
	(i4?(1UL << (i4-8*n-1)):0) | \
	(i5?(1UL << (i5-8*n-1)):0) | \
	(i6?(1UL << (i6-8*n-1)):0) | \
	(i7?(1UL << (i7-8*n-1)):0))

#define BM_CONTROLS_0 DEFN_BM_CONTROL(0, UVC_XU_CAPTURE_CROP, UVC_XU_PREVIEW_CROP, UVC_XU_PRIVACY_MASK, UVC_XU_FIRMWARE_VERSION, \
	UVC_XU_BOARD_INFO, UVC_XU_CLOCK, UVC_XU_CAPTURE_FC, UVC_XU_PREVIEW_FC)
#define BM_CONTROLS_1 DEFN_BM_CONTROL(1, UVC_XU_OVERLAY_CHECK, UVC_XU_VIDDEC_INFO,  \
	UVC_XU_OVERLAY_HEADER, UVC_XU_OVERLAY_DATA, UVC_XU_CAPTURE_PARAMS, UVC_XU_PREVIEW_PARAMS, UVC_XU_VIDEO_LOCK, UVC_XU_AUDIO_INPUT)
#define BM_CONTROLS_2 DEFN_BM_CONTROL(2, UVC_XU_DEINT_PARAMS, 0, UVC_XU_AUDIO_PARAMS, UVC_XU_AUDIO_BITRATE, \
	UVC_XU_AUDIO_VOLUME, UVC_XU_AUDIO_SAMPLERATE, UVC_XU_AUDIO_CHANNELS, UVC_XU_AUDIO_ENCODING)
#define BM_CONTROLS_3 DEFN_BM_CONTROL(3, UVC_XU_COMMAND, UVC_XU_DISPLAY_PARAMS, UVC_XU_TEMP_SENSOR, \
	UVC_XU_LOG_DATA, UVC_XU_FEATURE_FLAGS, UVC_XU_DEBUG_REG_ADDR, UVC_XU_DEBUG_REG_VALUE, UVC_XU_VIDEO_INPUT)
#define BM_CONTROLS_4 DEFN_BM_CONTROL(4, 0, 0, UVC_XU_VIDDEC_REG_ADDR, \
	UVC_XU_VIDDEC_REG_VALUE, UVC_XU_FRAMESIZE_RINGBUFFER, UVC_XU_OVERLAY_DATA60, 0, 0)
	
	
	


/* The middleware needs to know the length/default/min/max values as well */

struct uvc_control_attr {
	__u8 id;
	__u8 length;
	__u8 info;
	__s8 name[29];
	__s32 def;
	__s32 min;
	__s32 max;
	__s32 res;
};

enum {
	RO = 1, /* read-only */
	RW = 3, /* read-write */
};


static const struct uvc_control_attr sray_pu_controls[] = {
	{UVC_PU_BRIGHTNESS_CONTROL, 2, RW, "Brightness", 127, 0, 255, 1},
	{UVC_PU_CONTRAST_CONTROL,   2, RW, "Contrast", 127, 0, 255, 1},
	/* FIXME: Hue control should be -18000 to 18000 (degrees * 100) by UVC spec */
	{UVC_PU_HUE_CONTROL,        2, RW, "Hue", 0, -128, 127, 1},
	{UVC_PU_SATURATION_CONTROL, 2, RW, "Saturation", 127, 0, 255, 1},

	{UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, 1, RW, "Video Standard", UVC_NTSC, UVC_NTSC, UVC_PAL, 1},
	{UVC_PU_ANALOG_LOCK_STATUS_CONTROL,    1, RO, "Lock Status", 0, 0, 1, 1},
	/* can't access this on Linux, so use UVC_XU_VIDDEC_INFO instead */
};

static const struct uvc_control_attr sray_su_controls[] = {
	{UVC_SU_INPUT_SELECT_CONTROL, 1, RW, "Input Select", 1, 1, 2, 1},
};

// index in array should match control selector id
static const struct uvc_control_attr sray_xu_controls[] = {
[UVC_XU_CAPTURE_CROP] = {UVC_XU_CAPTURE_CROP, 8, RW, "Capture Crop", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_PREVIEW_CROP] = {UVC_XU_PREVIEW_CROP, 8, RW, "Preview Crop", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_PRIVACY_MASK] = {UVC_XU_PRIVACY_MASK, 8, RW, "Privacy Mask", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_FIRMWARE_VERSION] = {UVC_XU_FIRMWARE_VERSION, 2, RO, "Firmware Version", 0, 0, 9999, 1},
[UVC_XU_BOARD_INFO] = {UVC_XU_BOARD_INFO, 10, RO, "Board Information", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_CLOCK] = {UVC_XU_CLOCK, 6, RW, "Clock", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_CAPTURE_FC] = {UVC_XU_CAPTURE_FC, 4, RW, "Capture Frame Counter", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_PREVIEW_FC] = {UVC_XU_PREVIEW_FC, 4, RW, "Preview Frame Counter", 0, -0x80000000, 0x7fffffff, 1},

[UVC_XU_OVERLAY_CHECK] = {UVC_XU_OVERLAY_CHECK, 4, RO, "Overlay Check", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDDEC_INFO] = {UVC_XU_VIDDEC_INFO, 10, RW, "Video Decoder Information", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_OVERLAY_HEADER] = {UVC_XU_OVERLAY_HEADER, 10, RW, "Overlay Header", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_OVERLAY_DATA] = {UVC_XU_OVERLAY_DATA, 10, RW, "Overlay Data", 0, -0x80000000, 0x7fffffff, 1},

[UVC_XU_CAPTURE_PARAMS] = {UVC_XU_CAPTURE_PARAMS, 10, RW, "Capture Params", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_PREVIEW_PARAMS] = {UVC_XU_PREVIEW_PARAMS, 10, RW, "Preview Params", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDEO_LOCK] = {UVC_XU_VIDEO_LOCK, 1, RO, "Video Lock", 0, 0, 1, 1},

[UVC_XU_AUDIO_INPUT] = {UVC_XU_AUDIO_INPUT, 1, RW, "Audio Input", 0, 0, 2, 1},
[UVC_XU_DEINT_PARAMS] = {UVC_XU_DEINT_PARAMS, 8, RW, "Deinterlace Params", 0, -0x80000000, 0x7fffffff, 1},

[UVC_XU_AUDIO_PARAMS] = {UVC_XU_AUDIO_PARAMS, 10, RW, "Audio Params", 0, -0x80000000, 0x7fffffff, 1},

[UVC_XU_AUDIO_BITRATE] = {UVC_XU_AUDIO_BITRATE, 2, RW, "Audio Bitrate", 192, 32, 512, 16},
[UVC_XU_AUDIO_VOLUME] = {UVC_XU_AUDIO_VOLUME, 2, RW, "Audio Volume", 0, 0, 127, 1},
[UVC_XU_AUDIO_SAMPLERATE] = {UVC_XU_AUDIO_SAMPLERATE, 2, RW, "Audio Samplerate", 48000, 8000, 48000, 1},
[UVC_XU_AUDIO_CHANNELS] = {UVC_XU_AUDIO_CHANNELS, 2, RW, "Audio Channels", 2, 1, 2, 1},
[UVC_XU_AUDIO_ENCODING] = {UVC_XU_AUDIO_ENCODING, 1, RW, "Audio Encoding", 0, 0, 2, 1},
[UVC_XU_COMMAND] = {UVC_XU_COMMAND, 1, RW, "Firmware Command", 0, 0, UVC_XU_COMMAND_LAST, 1},
[UVC_XU_DISPLAY_PARAMS] = {UVC_XU_DISPLAY_PARAMS, 10, RW, "Display Params", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_TEMP_SENSOR] = {UVC_XU_TEMP_SENSOR, 2, RO, "Temperature Sensor", 0, 0, 0xffff, 1},

[UVC_XU_LOG_DATA] = {UVC_XU_LOG_DATA, MAX_UVC_REQUEST_DATA_XP, RW, "Log Data", 0, 0, 255, 1},
[UVC_XU_GPIO] = {UVC_XU_GPIO, 1, RW, "GPIO", 0, 0, 1, 1},
[UVC_XU_DEBUG_REG_ADDR] = {UVC_XU_DEBUG_REG_ADDR, 4, RW, "Debug Register Address", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_DEBUG_REG_VALUE] = {UVC_XU_DEBUG_REG_VALUE, 4, RW, "Debug Register Value", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDEO_INPUT] = {UVC_XU_VIDEO_INPUT, 1, RW, "Video Input", 0, 0, 2, 1},
[UVC_XU_VIDDEC_REG_ADDR] = {UVC_XU_VIDDEC_REG_ADDR, 4, RW, "Video Register Address", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDDEC_REG_VALUE] = {UVC_XU_VIDDEC_REG_VALUE, 4, RW, "Video Register Value", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_FRAMESIZE_RINGBUFFER] = {UVC_XU_FRAMESIZE_RINGBUFFER, 4, RW, "Framesize Ringbuffer", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_OVERLAY_DATA60] = {UVC_XU_OVERLAY_DATA60, 60, RW, "Overlay Data", 0, -0x80000000, 0x7fffffff, 1},
};

static const struct uvc_control_attr sray_xu_controls_old[] = {
[UVC_XU_BITRATE] = {UVC_XU_BITRATE, 2, RW, "Bitrate", 2500, 100, 20000, 1},
[UVC_XU_GOPSIZE] = {UVC_XU_GOPSIZE, 1, RW, "GOP Size", 30, 1, 255, 1},
[UVC_XU_RATEMODE] = {UVC_XU_RATEMODE, 1, RW, "Rate Mode", 0, 0, 1, 1},
[UVC_XU_FIRMWARE_VERSION] = {UVC_XU_FIRMWARE_VERSION, 2, RO, "Firmware Version", 0, 0, 9999, 1},
[UVC_XU_SERIAL_NUMBER] = {UVC_XU_SERIAL_NUMBER, 4, RW, "Serial Number", 0, 0, 999999, 1},
[UVC_XU_H264_LEVEL] = {UVC_XU_H264_LEVEL, 1, RW, "H264 Level", 100, 0, 100, 1},
[UVC_XU_H264_PROFILE] = {UVC_XU_H264_PROFILE, 1, RW, "H264 Profile", 40, 0, 50, 1},
[UVC_XU_CAPTURE_INTERLACED] = {UVC_XU_CAPTURE_INTERLACED, 1, RW, "Capture Interlace", 1, 0, 1, 1},
[UVC_XU_PREVIEW_INTERLACED] = {UVC_XU_PREVIEW_INTERLACED, 1, RW, "Preview Interlace", 0, 0, 1, 1},

[UVC_XU_VIDDEC_FRAMERATE] = {UVC_XU_VIDDEC_FRAMERATE, 2, RW, "Video Frame Rate", 30000, 0, 60000, 1},
[UVC_XU_VIDDEC_WIDTH] = {UVC_XU_VIDDEC_WIDTH, 2, RW, "Video Width", 0, 0, 1920, 1},
[UVC_XU_VIDDEC_HEIGHT] = {UVC_XU_VIDDEC_HEIGHT, 2, RW, "Video Height", 0, 0, 1200, 1},
[UVC_XU_VIDDEC_INTERLACED] = {UVC_XU_VIDDEC_INTERLACED, 1, RW, "Video Interlaced", 1, 0, 1, 1},
[UVC_XU_FIRMWARE_TIMESTAMP] = {UVC_XU_FIRMWARE_TIMESTAMP, 4, RO, "Firmware Timestamp", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDEO_LOCK] = {UVC_XU_VIDEO_LOCK, 1, RO, "Video Lock", 0, 0, 1, 1},

[UVC_XU_AUDIO_INPUT] = {UVC_XU_AUDIO_INPUT, 1, RW, "Audio Input", 0, 0, 2, 1},
[UVC_XU_CAPTURE_STATE] = {UVC_XU_CAPTURE_STATE, 1, RW, "Capture State", 0, 0, 1, 1},
[UVC_XU_PREVIEW_STATE] = {UVC_XU_PREVIEW_STATE, 1, RW, "Preview State", 0, 0, 1, 1},

[UVC_XU_AUDIO_BITRATE] = {UVC_XU_AUDIO_BITRATE, 2, RW, "Audio Bitrate", 192, 32, 512, 16},
[UVC_XU_AUDIO_VOLUME] = {UVC_XU_AUDIO_VOLUME, 2, RW, "Audio Volume", 0, 0, 127, 1},
[UVC_XU_AUDIO_SAMPLERATE] = {UVC_XU_AUDIO_SAMPLERATE, 2, RW, "Audio Samplerate", 48000, 8000, 48000, 1},
[UVC_XU_AUDIO_CHANNELS] = {UVC_XU_AUDIO_CHANNELS, 2, RW, "Audio Channels", 2, 1, 2, 1},
[UVC_XU_AUDIO_ENCODING] = {UVC_XU_AUDIO_ENCODING, 1, RW, "Audio Encoding", 0, 0, 2, 1},
[UVC_XU_FIRMWARE_UPLOAD] = {UVC_XU_FIRMWARE_UPLOAD, 1, RW, "Firmware Upload", 0, 0, 1, 1},
[UVC_XU_JPEG_QUALITY] = {UVC_XU_JPEG_QUALITY, 1, RW, "JPEG Quality", 90, 0, 100, 1},
[UVC_XU_CAPTURE_MODE] = {UVC_XU_CAPTURE_MODE, 1, RW, "Capture Mode", 0, 0, 5, 1},
[UVC_XU_LOG_DATA] = {UVC_XU_LOG_DATA, MAX_UVC_REQUEST_DATA_XP, RW, "Log Data", 0, 0, 255, 1},

[UVC_XU_FEATURE_FLAGS] = {UVC_XU_FEATURE_FLAGS, 4, RO, "Feature Flags", 0, 0, 1, 1},
[UVC_XU_CPU_LOAD] = {UVC_XU_CPU_LOAD, 1, RO, "CPU Load", 0, 0, 100, 1},
//[UVC_XU_TRACE_DATA] = {UVC_XU_TRACE_DATA, 60, RO, "Trace Data", 0, 0, 1, 1},
[UVC_XU_VIDDEC_REG_ADDR] = {UVC_XU_VIDDEC_REG_ADDR, 4, RW, "Video Register Address", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_VIDDEC_REG_VALUE] = {UVC_XU_VIDDEC_REG_VALUE, 4, RW, "Video Register Value", 0, -0x80000000, 0x7fffffff, 1},
[UVC_XU_FRAMESIZE_RINGBUFFER] = {UVC_XU_FRAMESIZE_RINGBUFFER, 4, RO, "Framesize Ringbuffer", 0, -0x80000000, 0x7fffffff, 1},
};

struct board_info {
	unsigned int serial;
	unsigned int timestamp;
	unsigned features : 4;
	unsigned model : 12;
};
#define FEATURE_FLAG_SDI   4
#define FEATURE_FLAG_AHD   8


struct viddec_info {
	unsigned int framerate;
	unsigned short width;
	unsigned short height;
	unsigned char interlaced;
	unsigned char lock; // with AHD standard in mask 0x06: CVBS=0 AHD=2 TVI=4 CVI=6
};

#define VIDDEC_INFO_AHD_CVBS 0x00
#define VIDDEC_INFO_AHD_AHD  0x02
#define VIDDEC_INFO_AHD_TVI  0x04
#define VIDDEC_INFO_AHD_CVI  0x06
#define VIDDEC_INFO_AHD_MASK 0x06

struct deint_params {
	unsigned char enable;
	unsigned char channel;
	unsigned char threshold_low;
	unsigned char threshold_high;
	unsigned short exclude_start;
	unsigned short exclude_count;
};


#define OVERLAY_DATA_SIZE 10
struct overlay_header {
	unsigned int length; // length of data (little-endian), may be zero to update x, y, and alpha only, or 1,2 to show and 3 to hide
	unsigned char id; // bits[0..3]: channel, 0-15; bits[4..5]: 0=Record 1=Preview 2=Display
	unsigned char alpha; // alpha transparency 0=transparent .. 8=opaque
	short int x, y; // display coordinates (little-endian)
};

//TODO #define OVERLAY_FORMAT_LINE 0x656e696c

#define OVERLAY_FORMAT_TEXT 0x54584554
//  data: "TEXT", u16 mode, u8 text data
#define OVERLAY_TEXT_DISABLED   0
#define OVERLAY_TEXT_FONT_8x14  1
#define OVERLAY_TEXT_FONT_16x16 2
#define OVERLAY_TEXT_BG_SOLID (0 << 2)
#define OVERLAY_TEXT_BG_TRANSPARENT (1 << 2)
#define OVERLAY_TEXT_BG_SHADED (2 << 2)
#define OVERLAY_TEXT_BG_DARKSHADED (3 << 2)
#define OVERLAY_TEXT_DATE_MM_DD_YYYY (0 << 4)
#define OVERLAY_TEXT_DATE_DD_MM_YYYY (1 << 4)
#define OVERLAY_TEXT_DATE_MM_DD_YY (2 << 4)
#define OVERLAY_TEXT_DATE_DD_MM_YY (3 << 4)
#define OVERLAY_TEXT_DATE_MMM_DD_YYYY (4 << 4)
#define OVERLAY_TEXT_DATE_DD_MMM_YYYY (5 << 4)
#define OVERLAY_TEXT_DATE_MMM_DD_YY (6 << 4)
#define OVERLAY_TEXT_DATE_DD_MMM_YY (7 << 4)
#define OVERLAY_TEXT_DATE_MMM_DDc_YYYY (8 << 4)
#define OVERLAY_TEXT_DATE_DDMMMYYYY (9 << 4)
#define OVERLAY_TEXT_DATE_MMM_DDc_YY (10 << 4)
#define OVERLAY_TEXT_DATE_DDMMMYY (11 << 4)
#define OVERLAY_TEXT_DATE_YYYYMMDD (12 << 4)
#define OVERLAY_TEXT_DATE_YYYYMMMDD (13 << 4)
#define OVERLAY_TEXT_DATE_YYMMDD (14 << 4)
#define OVERLAY_TEXT_DATE_YYMMMDD (15 << 4)
#define OVERLAY_TEXT_DATE_YYYY_MM_DD (16 << 4)
#define OVERLAY_TEXT_DATE_YYYY_MMM_DD (17 << 4)
#define OVERLAY_TEXT_DATE_YY_MM_DD (18 << 4)
#define OVERLAY_TEXT_DATE_YY_MMM_DD (19 << 4)

#define OVERLAY_TEXT_SECONDS_NONE (0 << 10)
#define OVERLAY_TEXT_SECONDS_TENTHS (1 << 10)
#define OVERLAY_TEXT_SECONDS_HUNDREDTHS (2 << 10)
#define OVERLAY_TEXT_SECONDS_THOUSANDTHS (3 << 10)
#define OVERLAY_TEXT_HOURS_MINUTES (4 << 10)
#define OVERLAY_TEXT_HOURS_MINUTES_AM_PM (5 << 10)
#define OVERLAY_TEXT_HOURS_MINUTES_A_P (6 << 10)

#define OVERLAY_FORMAT_RLE  0x20454c52
//  data: "RLE ", u16 w, u16 h, u8 RLE data


// preview frame sizes in X Macro
#define PREVIEW_FRAMES(X)	\
	X(1, 768, 576)	\
	X(2, 720, 576)	\
	X(3, 720, 480)	\
	X(4, 720, 408)	\
	X(5, 640, 480)	\
	X(6, 640, 360)	\
	X(7, 512, 384)	\
	X(8, 512, 288)	\
	X(9, 384, 288)	\
	X(10, 320, 240)	\
	X(11, 320, 180)	\
	X(12, 160, 120)
#define PREVIEW_FRAMES_NUM 12
	
#define CAPTURE_FRAMES(X,Y)	\
	Y(1, 1920, 1200)	\
	Y(2, 1920, 1080)	\
	Y(3, 1680, 1050)	\
	Y(4, 1600, 1200)	\
	Y(5, 1600, 900)	\
	Y(6, 1440, 900)	\
	Y(7, 1400, 1050)	\
	Y(8, 1366, 768)	\
	Y(9, 1360, 768)	\
	X(10, 1280, 1024)	\
	X(11, 1280, 960)	\
	X(12, 1280, 800)	\
	X(13, 1280, 768)	\
	X(14, 1280, 720)	\
	X(15, 1280, 600)	\
	X(16, 1152, 864)	\
	X(17, 1152, 648)	\
	X(18, 1024, 768)	\
	X(19, 960, 540)	\
	X(20, 800, 600)	\
	X(21, 752, 576)	\
	X(22, 720, 576)	\
	X(23, 720, 480)	\
	X(24, 720, 408)	\
	X(25, 640, 480)	\
	X(26, 640, 360)
#define CAPTURE_FRAMES_NUM 26




#ifdef ENABLE_H264_XU

// structs for H264 1.0 extension unit
enum {
	UVCX_VIDEO_UNDEFINED,		// 0x00 Reserved
	UVCX_VIDEO_CONFIG_PROBE,	// 0x01 Negotiate encoding parameters without altering current streaming state
	UVCX_VIDEO_CONFIG_COMMIT,	// 0x02 Sets the current configuration of the encoder
	UVCX_RATE_CONTROL_MODE,		// 0x03 Configuration of the encoder in bitrate/quality mode.
	UVCX_TEMPORAL_SCALE_MODE,	// 0x04 Number of layers
	UVCX_SPATIAL_SCALE_MODE,	// 0x05 Setting the spatial mode
	UVCX_SNR_SCALE_MODE,		// 0x06 Setting the quality mode
	UVCX_LTR_BUFFER_SIZE_CONTROL,	// 0x07 LTR Buffer usage
	UVCX_LTR_PICTURE_CONTROL,	// 0x08 LTR Control
	UVCX_PICTURE_TYPE_CONTROL,	// 0x09 I , IDR frame requests
	UVCX_VERSION,			// 0x0A Spec. version supported from the device
	UVCX_ENCODER_RESET,		// 0x0B Encoder Reset
	UVCX_FRAMERATE_CONFIG,		// 0x0C Dynamic frame rate configuration
	UVCX_VIDEO_ADVANCE_CONFIG,	// 0x0D Configuration for level_idc
	UVCX_BITRATE_LAYERS,		// 0x0E Bitrate per layer
	UVCX_QP_STEPS_LAYERS,		// 0x0F Minimum/Maximum QP Configuration per layers
};
	
struct uvcx_video_config {
	__u32 dwFrameInterval;
	__u32 dwBitRate;
	__u16 bmHints;
	__u16 wConfigurationIndex;
	__u16 wWidth;
	__u16 wHeight;
	__u16 wSliceUnits;
	__u16 wSliceMode;
	__u16 wProfile;
	__u16 wIFramePeriod;
	__u16 wEstimatedVideoDelay;
	__u16 wEstimatedMaxConfigDelay;
	__u8  bUsageType;
	__u8  bRateControlMode;
	__u8  bTemporalScaleMode;
	__u8  bSpatialScaleMode;
	__u8  bSNRScaleMode;
	__u8  bStreamMuxOption;
	__u8  bStreamFormat;
	__u8  bEntropyCABAC;
	__u8  bTimestamp;
	__u8  bNumOfReorderFrames;
	__u8  bPreviewFlipped;
	__u8  bView;
	__u8  bReserved1;
	__u8  bReserved2;
	__u8  bStreamID;
	__u8  bSpatialLayerRatio;
	__u16 wLeakyBucketSize;
} __attribute__((__packed__));

struct uvcx_rate_control_mode {
	__u16 wLayerID;
	__u8  bRateControlMode;
} __attribute__((__packed__));

struct uvcx_temporal_scale_mode {
	__u16 wLayerID;
	__u8  bTemporalScaleMode;
} __attribute__((__packed__));

struct uvcx_spatial_scale_mode {
	__u16 wLayerID;
	__u8  bSpatialScaleMode;
} __attribute__((__packed__));

struct uvcx_snr_scale_mode {
	__u16 wLayerID;
	__u8  bSNRScaleMode;
	__u8  bMGSSublayerMode;
} __attribute__((__packed__));

struct uvcx_ltr_buffer_size_control {
	__u16 wLayerID;
	__u8  bLTRBufferSize;
	__u8  bLTREncoderControl;
} __attribute__((__packed__));

struct uvcx_ltr_picture_control {
	__u16 wLayerID;
	__u8  bPutAtPositionInLTRBuffer;
	__u8  bEncodeUsingLTR;
} __attribute__((__packed__));

struct uvcx_picture_type_control {
	__u16 wLayerID;
	__u16 wPicType;
} __attribute__((__packed__));

struct uvcx_version {
	__u16 wVersion;
} __attribute__((__packed__));

struct uvcx_encoder_reset {
	__u16 wLayerID;
} __attribute__((__packed__));

struct uvcx_framerate_config {
	__u16 wLayerID;
	__u32 dwFrameInterval;
} __attribute__((__packed__));

struct uvcx_video_advance_config {
	__u16 wLayerID;
	__u32 dwMb_max;
	__u8  blevel_idc;
	__u8  bReserved;
} __attribute__((__packed__));

struct uvcx_bitrate_layers {
	__u16 wLayerID;
	__u32 dwPeakBitrate;
	__u32 dwAverageBitrate;
} __attribute__((__packed__));

struct uvcx_qp_steps_layers {
	__u16 wLayerID;
	__u8  bFrameType;
	__u8  bMinQp;
	__u8  bMaxQp;
} __attribute__((__packed__));

static const struct uvc_control_attr h264_xu_controls[] = {
[UVCX_VIDEO_CONFIG_PROBE] = {UVCX_VIDEO_CONFIG_PROBE, sizeof(struct uvcx_video_config), RW, "Video Config Probe", 0, 0, 0, 0},
[UVCX_VIDEO_CONFIG_COMMIT] = {UVCX_VIDEO_CONFIG_COMMIT, sizeof(struct uvcx_video_config), RW, "Video Config Commit", 0, 0, 0, 0},
[UVCX_RATE_CONTROL_MODE] = {UVCX_RATE_CONTROL_MODE, sizeof(struct uvcx_rate_control_mode), RW, "Rate Control Mode", 0, 0, 0, 0},
[UVCX_TEMPORAL_SCALE_MODE] = {UVCX_TEMPORAL_SCALE_MODE, sizeof(struct uvcx_temporal_scale_mode), RW, "Temporal Scale Mode", 0, 0, 0, 0},
[UVCX_SPATIAL_SCALE_MODE] = {UVCX_SPATIAL_SCALE_MODE, sizeof(struct uvcx_spatial_scale_mode), RW, "Spatial Scale Mode", 0, 0, 0, 0},
[UVCX_SNR_SCALE_MODE] = {UVCX_SNR_SCALE_MODE, sizeof(struct uvcx_snr_scale_mode), RW, "SNR Scale Mode", 0, 0, 0, 0},
[UVCX_LTR_BUFFER_SIZE_CONTROL] = {UVCX_LTR_BUFFER_SIZE_CONTROL, sizeof(struct uvcx_ltr_buffer_size_control), RW, "LTR Buffer Size Control", 0, 0, 0, 0},
[UVCX_LTR_PICTURE_CONTROL] = {UVCX_LTR_PICTURE_CONTROL, sizeof(struct uvcx_ltr_picture_control), RW, "LTR Picture Control", 0, 0, 0, 0},
[UVCX_PICTURE_TYPE_CONTROL] = {UVCX_PICTURE_TYPE_CONTROL, sizeof(struct uvcx_picture_type_control), RW, "Picture Type Control", 0, 0, 0, 0},
[UVCX_VERSION] = {UVCX_VERSION, sizeof(struct uvcx_version), RO, "Version", 0, 0, 0, 0},
[UVCX_ENCODER_RESET] = {UVCX_ENCODER_RESET, sizeof(struct uvcx_encoder_reset), RW, "Encoder Reset", 0, 0, 0, 0},
[UVCX_FRAMERATE_CONFIG] = {UVCX_FRAMERATE_CONFIG, sizeof(struct uvcx_framerate_config), RW, "Framerate Config", 0, 0, 0, 0},
[UVCX_VIDEO_ADVANCE_CONFIG] = {UVCX_VIDEO_ADVANCE_CONFIG, sizeof(struct uvcx_video_advance_config), RW, "Video Advance Config", 0, 0, 0, 0},
[UVCX_BITRATE_LAYERS] = {UVCX_BITRATE_LAYERS, sizeof(struct uvcx_bitrate_layers), RW, "Bitrate Layers", 0, 0, 0, 0},
[UVCX_QP_STEPS_LAYERS] = {UVCX_QP_STEPS_LAYERS, sizeof(struct uvcx_qp_steps_layers), RW, "QP Steps Layers", 0, 0, 0, 0},
};
#endif // ENABLE_H264_XU

#endif // __UVC_XU_CTRLS_H__

