Quellcode durchsuchen

change driver_h264_usbimx291 and change driver_h264_dec.

yuchuli vor 3 Jahren
Ursprung
Commit
07f27820aa

+ 73 - 0
src/driver/driver_h264_usbimx291/.gitignore

@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+

+ 8 - 0
src/driver/driver_h264_usbimx291/debug.h

@@ -0,0 +1,8 @@
+extern int Dbg_Param;
+#define TestAp_Printf(flag, msg...) ((Dbg_Param & flag)?printf(msg):flag)
+
+#define TESTAP_DBG_USAGE	(1 << 0)
+#define TESTAP_DBG_ERR		(1 << 1)
+#define TESTAP_DBG_FLOW		(1 << 2)
+#define TESTAP_DBG_FRAME	(1 << 3)
+#define TESTAP_DBG_BW	    (1 << 4)

+ 34 - 0
src/driver/driver_h264_usbimx291/driver_h264_usbimx291.pro

@@ -0,0 +1,34 @@
+QT -= gui
+
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which as been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += main.cpp \
+    sonix_xu_ctrls.c \
+    sonix_io.c \
+    nalu.c \
+    imx291frame.cpp
+
+
+
+HEADERS += \
+    sonix_xu_ctrls.h \
+    debug.h \
+    sonix_io.h \
+    nalu.h \
+    imx291frame.h
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}

+ 72 - 0
src/driver/driver_h264_usbimx291/main.cpp

@@ -0,0 +1,72 @@
+#include <QCoreApplication>
+
+#include "modulecomm.h"
+#include "xmlparam.h"
+
+#include "imx291frame.h"
+
+imx291frame * gpframe;
+std::thread * gpthread;
+
+void * gpa;
+
+bool gbrun = true;
+
+#include <QDateTime>
+
+void ThreadGetData()
+{
+    while(gbrun)
+    {
+        iv::h264framendata xframe;
+        if(gpframe->GetFrame(xframe) == 1)
+        {
+            qint64 recvtime = std::chrono::system_clock::now().time_since_epoch().count();
+            recvtime = recvtime/1000;
+            double frecvtime = recvtime;
+            frecvtime = frecvtime/1000000.0;
+//            qDebug(" recvtime : %13.6f  datatime:%13.6f",frecvtime,xframe.mfrecvtime);
+            iv::modulecomm::ModuleSendMsg(gpa,xframe.mpstr_ptr.get(),xframe.mdatalen);
+
+//            char * str = (char * )xframe.mpstr_ptr.get();
+//            if(xframe.mdatalen > 5)
+//            {
+//                qDebug("   Head: %02x %02x %02x %02x %02x",str[0],str[1],str[2],str[3],str[4]);
+//                if(str[4] != 0x67)
+//                {
+//                    int a;
+//                     a= 1;
+//                }
+//            }
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication a(argc, argv);
+
+    std::string strxmlpath;
+    if(argc == 1)
+    {
+        strxmlpath = "./driver_h264_usbimx291.xml";
+    }
+    else
+    {
+        strxmlpath = argv[1];
+    }
+
+    iv::xmlparam::Xmlparam xp(strxmlpath);
+    std::string strdevname =  xp.GetParam("devname","/dev/video5");
+    int nwidth = xp.GetParam("width",1920);
+    int nheigth = xp.GetParam("height",1080);
+    int nbitrate = xp.GetParam("bitrate",4000000);
+    int ngop = xp.GetParam("gop",10);
+    std::string strframename = xp.GetParam("outmsgname","h264frame");
+
+    gpa = iv::modulecomm::RegisterSend(strframename.data(),3000000,1);
+    gpframe = new imx291frame(strdevname.data(),nwidth,nheigth,nbitrate,ngop);
+    gpthread = new std::thread(&ThreadGetData);
+
+    return a.exec();
+}

+ 224 - 0
src/driver/driver_h264_usbimx291/nalu.c

@@ -0,0 +1,224 @@
+//----------------------------------------------//
+//	H264 NALU c source code						//
+//----------------------------------------------//
+#include "nalu.h"
+
+unsigned char* FindNextH264StartCode(unsigned char *pBuf, unsigned char *pBuf_end)
+{
+    unsigned char zero_cnt;
+    zero_cnt = 0;
+
+    while(1)
+    {
+        if(pBuf == pBuf_end)
+        {
+            break;
+        }
+        if(*pBuf == 0)
+        {
+            zero_cnt++;
+        }
+        else if((zero_cnt >= 3) && (*pBuf == 1))
+        {
+            zero_cnt = 0;
+            pBuf++;
+            break;
+        }
+        else
+        {
+            zero_cnt = 0;
+        }
+        pBuf++;
+    }
+    return pBuf;
+}
+
+unsigned int Ue(unsigned char *pBuff, unsigned int nLen, unsigned int *nStartBit)
+{
+	unsigned int i=0;
+    unsigned int nZeroNum = 0;
+	unsigned long dwRet = 0;
+	
+    while((*nStartBit) < (nLen * 8))
+    {
+        if(pBuff[(*nStartBit) / 8] & (0x80 >> ((*nStartBit) % 8)))
+            break;
+
+        nZeroNum++;
+        (*nStartBit)++;
+    }
+    (*nStartBit) ++;
+
+    for(i=0; i<nZeroNum; i++)
+    {
+        dwRet <<= 1;
+        if((pBuff[(*nStartBit) / 8]) & (0x80 >> ((*nStartBit) % 8)))
+        {
+            dwRet += 1;
+        }
+        (*nStartBit)++;
+    }
+    return (1 << nZeroNum) - 1 + dwRet;
+}
+
+int Se(unsigned char *pBuff, unsigned int nLen, unsigned int *nStartBit)
+{
+#if 0
+    int UeVal=Ue(pBuff,nLen,*nStartBit);
+	double k=UeVal;
+	int nValue=ceil(k/2);
+    
+    if(UeVal % 2==0)
+        nValue=-nValue;
+
+    return nValue;
+#else
+    int UeVal=Ue(pBuff,nLen,nStartBit);
+	int nValue = UeVal / 2;
+	if( nValue > 0) nValue += UeVal & 0x01;
+	if(UeVal % 2==0)
+		nValue=-nValue;
+
+	return nValue;
+#endif
+}
+
+unsigned long u(unsigned int BitCount,unsigned char * buf,unsigned int *nStartBit)
+{
+    unsigned long dwRet = 0;
+	unsigned int i = 0;
+	
+	for(i=0; i<BitCount; i++)
+    {
+        dwRet <<= 1;
+        if(buf[(*nStartBit) / 8] & (0x80 >> ((*nStartBit) % 8)))
+        {
+            dwRet += 1;
+        }
+        (*nStartBit)++;
+    }
+
+    return dwRet;
+}
+
+bool h264_decode_seq_parameter_set(unsigned char * buf, unsigned int nLen, int *Width, int *Height)
+{
+    unsigned int StartBit=0;
+    int forbidden_zero_bit, nal_ref_idc, nal_unit_type;
+	
+	forbidden_zero_bit=u(1,buf,&StartBit);
+    nal_ref_idc=u(2,buf,&StartBit);
+    nal_unit_type=u(5,buf,&StartBit);
+	
+    if(nal_unit_type==7)
+    {
+		int profile_idc, constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag, reserved_zero_4bits, level_idc;
+		int seq_parameter_set_id, log2_max_frame_num_minus4, pic_order_cnt_type;
+		int num_ref_frames, gaps_in_frame_num_value_allowed_flag, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1, frame_mbs_only_flag;
+        int direct_8x8_inference_flag, frame_cropping_flag;   
+        int frame_crop_left_offset, frame_crop_right_offset, frame_crop_top_offset, frame_crop_bottom_offset;
+        
+		profile_idc=u(8,buf,&StartBit);
+        constraint_set0_flag=u(1,buf,&StartBit);//(buf[1] & 0x80)>>7;
+        constraint_set1_flag=u(1,buf,&StartBit);//(buf[1] & 0x40)>>6;
+        constraint_set2_flag=u(1,buf,&StartBit);//(buf[1] & 0x20)>>5;
+        constraint_set3_flag=u(1,buf,&StartBit);//(buf[1] & 0x10)>>4;
+        reserved_zero_4bits=u(4,buf,&StartBit);
+        level_idc=u(8,buf,&StartBit);
+		
+        seq_parameter_set_id=Ue(buf,nLen,&StartBit);
+
+        if((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 144))
+        {
+			int chroma_format_idc, residual_colour_transform_flag, bit_depth_luma_minus8, bit_depth_chroma_minus8, qpprime_y_zero_transform_bypass_flag;
+			int seq_scaling_matrix_present_flag;
+            
+			chroma_format_idc=Ue(buf,nLen,&StartBit);
+			residual_colour_transform_flag = 0;
+			
+            if(chroma_format_idc == 3)
+                residual_colour_transform_flag=u(1,buf,&StartBit);
+
+            bit_depth_luma_minus8=Ue(buf,nLen,&StartBit);
+            bit_depth_chroma_minus8=Ue(buf,nLen,&StartBit);
+            qpprime_y_zero_transform_bypass_flag=u(1,buf,&StartBit);
+            seq_scaling_matrix_present_flag=u(1,buf,&StartBit);
+
+            if(seq_scaling_matrix_present_flag)
+            {
+				int seq_scaling_list_present_flag[8];
+				int i=0;
+                for( i = 0; i < 8; i++ )
+                {
+                    seq_scaling_list_present_flag[i]=u(1,buf,&StartBit);
+                }
+            }
+        }
+        
+		log2_max_frame_num_minus4=Ue(buf,nLen,&StartBit);
+        pic_order_cnt_type=Ue(buf,nLen,&StartBit);
+		
+        if(pic_order_cnt_type == 0)
+        {
+            int log2_max_pic_order_cnt_lsb_minus4=Ue(buf,nLen,&StartBit);
+        }
+        else if(pic_order_cnt_type == 1)
+        {
+            int delta_pic_order_always_zero_flag=u(1,buf,&StartBit);
+            int offset_for_non_ref_pic=Se(buf,nLen,&StartBit);
+            int offset_for_top_to_bottom_field=Se(buf,nLen,&StartBit);
+            int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf,nLen,&StartBit);
+#if 0
+            int *offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle];
+            for(int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
+                offset_for_ref_frame[i]=Se(buf,nLen,&StartBit);
+
+            delete [] offset_for_ref_frame;
+#else
+			int offset_for_ref_frame = 0;
+			int i = 0;
+            for(i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
+                offset_for_ref_frame =Se(buf,nLen,&StartBit);
+#endif
+
+        }
+
+        num_ref_frames=Ue(buf,nLen,&StartBit);
+        gaps_in_frame_num_value_allowed_flag=u(1,buf,&StartBit);
+        pic_width_in_mbs_minus1=Ue(buf,nLen,&StartBit);
+        pic_height_in_map_units_minus1=Ue(buf,nLen,&StartBit);
+        
+        frame_mbs_only_flag=u(1,buf,&StartBit);
+        if(!frame_mbs_only_flag)
+        {
+            int mb_adaptive_frame_field_flag;
+            mb_adaptive_frame_field_flag =u(1,buf,&StartBit);
+        }
+        direct_8x8_inference_flag=u(1,buf,&StartBit);
+        frame_cropping_flag=u(1,buf,&StartBit);
+        if(frame_cropping_flag == 1)
+        {
+            frame_crop_left_offset=Ue(buf,nLen,&StartBit);
+            frame_crop_right_offset=Ue(buf,nLen,&StartBit);
+            frame_crop_top_offset=Ue(buf,nLen,&StartBit);
+            frame_crop_bottom_offset=Ue(buf,nLen,&StartBit);
+        }
+        else
+        {
+            frame_crop_left_offset=0;
+            frame_crop_right_offset=0;
+            frame_crop_top_offset=0;
+            frame_crop_bottom_offset=0;
+        }
+
+        *Width=((pic_width_in_mbs_minus1+1)*16)-(frame_crop_left_offset*2)-(frame_crop_right_offset*2);
+        *Height=((pic_height_in_map_units_minus1+1)*16)-(frame_crop_top_offset*2)-(frame_crop_bottom_offset*2);
+
+		
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}

+ 27 - 0
src/driver/driver_h264_usbimx291/nalu.h

@@ -0,0 +1,27 @@
+#ifndef _NALU_H_
+#define _NALU_H_
+
+#include <stdbool.h>
+
+//unsigned char* FindNextH264StartCode(unsigned char *pBuf, unsigned int Buf_len);
+unsigned char* FindNextH264StartCode(unsigned char *pBuf, unsigned char *pBuf_end);
+
+bool h264_decode_seq_parameter_set(unsigned char *buf, unsigned int nLen, int *Width, int *Height);
+
+#if 0
+//! NAL unit structure
+typedef struct nalu_sps
+{
+    unsigned char profile_idc;
+    unsigned constraint_set0_flag:1;
+    unsigned constraint_set1_flag:1;
+    unsigned constraint_set2_flag:1;
+    unsigned constraint_set3_flag:1;
+    unsigned reserved_zero_4bits:4;
+    unsigned char level_idc;
+    unsigned seq_parameter_set_id:1;
+    unsigned log2_max_frame_num_minus4:5;
+} NALU_SPS;
+#endif
+
+#endif

+ 776 - 0
src/driver/driver_h264_usbimx291/sonix_io.c

@@ -0,0 +1,776 @@
+
+
+#include "sonix_xu_ctrls.h"
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <sys/time.h>		//for timestamp incomplete error in kernel 2.6.21
+#include <linux/videodev2.h>
+#include <linux/version.h>
+#include <sys/utsname.h>
+#include <pthread.h>
+
+//#include "v4l2uvc.h"
+#include "sonix_xu_ctrls.h"
+#include "nalu.h"
+#include "debug.h"
+//#include "cap_desc_parser.h"
+//#include "cap_desc.h"
+
+#define V4L_BUFFERS_DEFAULT	6//16
+#define V4L_BUFFERS_MAX		16//32
+
+#define H264_SIZE_HD				((1280<<16)|720)
+#define H264_SIZE_VGA				((640<<16)|480)
+#define H264_SIZE_QVGA				((320<<16)|240)
+#define H264_SIZE_QQVGA				((160<<16)|112)
+#define H264_SIZE_360P				((640<<16)|360)
+#define H264_SIZE_180P				((320<<16)|180)
+
+#define MULTI_STREAM_HD_QVGA		0x01
+#define MULTI_STREAM_HD_180P		0x02
+#define MULTI_STREAM_HD_360P		0x04
+#define MULTI_STREAM_HD_VGA			0x08
+#define MULTI_STREAM_HD_QVGA_VGA	0x10
+#define MULTI_STREAM_QVGA_VGA	    0x20
+#define MULTI_STREAM_HD_180P_360P	0x40
+#define MULTI_STREAM_360P_180P	    0x80
+
+
+struct H264Format *gH264fmt = NULL;
+int Dbg_Param = 0x1f;
+
+int video_get_framerate(int dev, int *framerate)
+{
+    struct v4l2_streamparm parm;
+    int ret;
+
+    memset(&parm, 0, sizeof parm);
+    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    ret = ioctl(dev, VIDIOC_G_PARM, &parm);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to get frame rate: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "Current frame rate: %u/%u\n",
+        parm.parm.capture.timeperframe.numerator,
+        parm.parm.capture.timeperframe.denominator);
+    *framerate = parm.parm.capture.timeperframe.denominator;
+
+    return 0;
+}
+
+static int video_open(const char *devname)
+{
+    struct v4l2_capability cap;
+    int dev, ret;
+
+    dev = open(devname, O_RDWR);
+    if (dev < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Error opening device %s: %d.\n", devname, errno);
+        return dev;
+    }
+
+    memset(&cap, 0, sizeof cap);
+    ret = ioctl(dev, VIDIOC_QUERYCAP, &cap);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Error opening device %s: unable to query device.\n",
+            devname);
+        close(dev);
+        return ret;
+    }
+
+#if 0
+    if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Error opening device %s: video capture not supported.\n",
+            devname);
+        close(dev);
+        return -EINVAL;
+    }
+#endif
+
+    printf( "Device %s opened: %s.\n", devname, cap.card);
+    return dev;
+}
+
+static int get_vendor_verson(int dev, unsigned char szFlashVendorVer[12])
+{
+    return XU_SF_Read(dev, 0x154, szFlashVendorVer, 12);
+}
+
+static int video_set_format(int dev, unsigned int w, unsigned int h, unsigned int format)
+{
+    struct v4l2_format fmt;
+    int ret;
+
+    memset(&fmt, 0, sizeof fmt);
+    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    fmt.fmt.pix.width = w;
+    fmt.fmt.pix.height = h;
+    fmt.fmt.pix.pixelformat = format;
+    fmt.fmt.pix.field = V4L2_FIELD_ANY;
+
+    ret = ioctl(dev, VIDIOC_S_FMT, &fmt);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to set format: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "Video format set: width: %u height: %u buffer size: %u\n",
+        fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.sizeimage);
+    return 0;
+}
+
+
+static int video_set_still_format(int dev, unsigned int w, unsigned int h, unsigned int format)
+{
+    struct v4l2_format fmt;
+    int ret;
+
+    memset(&fmt, 0, sizeof fmt);
+    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    fmt.fmt.pix.width = w;
+    fmt.fmt.pix.height = h;
+    fmt.fmt.pix.pixelformat = format;
+    fmt.fmt.pix.field = V4L2_FIELD_ANY;
+
+    if(GetKernelVersion()> KERNEL_VERSION (3, 0, 36))
+        ret = ioctl(dev, UVCIOC_STILL_S_FMT_KNL3, &fmt);
+    else
+        ret = ioctl(dev, UVCIOC_STILL_S_FMT_KNL2, &fmt);
+
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to set still format: %d.\n", errno);
+        if(errno == EINVAL)
+        TestAp_Printf(TESTAP_DBG_ERR, "still function doesn't support?\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "still format set: width: %u height: %u buffer size: %u\n",
+        fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.sizeimage);
+    return 0;
+}
+
+
+
+static int video_set_framerate(int dev, int framerate, unsigned int *MaxPayloadTransferSize)
+{
+    struct v4l2_streamparm parm;
+    int ret;
+
+    memset(&parm, 0, sizeof parm);
+    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    ret = ioctl(dev, VIDIOC_G_PARM, &parm);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to get frame rate: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "Current frame rate: %u/%u\n",
+        parm.parm.capture.timeperframe.numerator,
+        parm.parm.capture.timeperframe.denominator);
+
+    parm.parm.capture.timeperframe.numerator = 1;
+    parm.parm.capture.timeperframe.denominator = framerate;
+
+    ret = ioctl(dev, VIDIOC_S_PARM, &parm);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to set frame rate: %d.\n", errno);
+        return ret;
+    }
+
+    //yiling: get MaxPayloadTransferSize from sonix driver
+    if(MaxPayloadTransferSize)
+        *MaxPayloadTransferSize = parm.parm.capture.reserved[0];
+
+    ret = ioctl(dev, VIDIOC_G_PARM, &parm);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to get frame rate: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "Frame rate set: %u/%u\n",
+        parm.parm.capture.timeperframe.numerator,
+        parm.parm.capture.timeperframe.denominator);
+    return 0;
+}
+
+static int video_req_still_buf(int dev)
+{
+    struct v4l2_requestbuffers rb;
+    int ret;
+
+    memset(&rb, 0, sizeof rb);
+    rb.count = 1;
+    rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    rb.memory = V4L2_MEMORY_MMAP;
+
+    if(GetKernelVersion()> KERNEL_VERSION (3, 0, 36))
+        ret = ioctl(dev, UVCIOC_STILL_REQBUF_KNL3, &rb);
+    else
+        ret = ioctl(dev, UVCIOC_STILL_REQBUF_KNL2, &rb);
+
+
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to allocate still buffers: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "still buffers allocated.\n");
+    return rb.count;
+}
+
+static int video_enable(int dev, int enable)
+{
+    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    int ret;
+
+    ret = ioctl(dev, enable ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to %s capture: %d.\n",
+            enable ? "start" : "stop", errno);
+        return ret;
+    }
+
+    return 0;
+}
+
+int get_still_image(int dev, unsigned int w, unsigned int h, unsigned int format)
+{
+    char filename[30];
+    struct v4l2_buffer buf;
+    FILE *file = NULL;
+    int ret = 0, repeat_setting = 0;
+    void *mem;
+    static int counter = 0;
+    static int still_dev = 0, still_width = 0, still_height = 0, still_format = 0;
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "%s ============>\n",__FUNCTION__);
+    if(still_dev == dev && still_width == w && still_height == h && still_format == format)
+        repeat_setting = 1;
+
+
+    //set file name
+    if(format == V4L2_PIX_FMT_MJPEG)
+        sprintf(filename, "still_img-%02u.jpg", counter);
+    else if(format == V4L2_PIX_FMT_YUYV)
+        sprintf(filename, "still_img-%02u.yuyv", counter);
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "repeat_setting = %d, fname = %s\n",repeat_setting, filename);
+
+    if(!repeat_setting)
+    {
+        //set format
+        video_set_still_format(dev, w, h, format);
+
+        //request still buffer
+        ret = video_req_still_buf(dev);
+        if (ret < 0) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to request still buffer(%d).\n", errno);
+            return ret;
+        }
+    }
+    //mmap
+    memset(&buf, 0, sizeof buf);
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_MMAP;
+    if(GetKernelVersion()> KERNEL_VERSION (3, 0, 36))
+        ret = ioctl(dev, UVCIOC_STILL_QUERYBUF_KNL3, &buf);
+    else
+        ret = ioctl(dev, UVCIOC_STILL_QUERYBUF_KNL2, &buf);
+
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to query still buffer(%d).\n", errno);
+        return ret;
+    }
+    TestAp_Printf(TESTAP_DBG_FLOW, "length: %u offset: %10u     --  ", buf.length, buf.m.offset);
+
+
+    mem = mmap(0, buf.length, PROT_READ, MAP_SHARED, dev, buf.m.offset);
+
+    if (mem == MAP_FAILED) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to map still buffer(%d)\n", errno);
+        return -1;
+    }
+    TestAp_Printf(TESTAP_DBG_FLOW, "still Buffer mapped at address %p.\n", mem);
+
+    //get data
+    if(GetKernelVersion()> KERNEL_VERSION (3, 0, 36))
+        ret = ioctl(dev, UVCIOC_STILL_GET_FRAME_KNL3, &buf);
+    else
+        ret = ioctl(dev, UVCIOC_STILL_GET_FRAME_KNL2, &buf);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to get still image(%d).\n", errno);
+        return ret;
+    }
+    TestAp_Printf(TESTAP_DBG_FLOW, "buf.bytesused = %d\n", buf.bytesused);
+
+    file = fopen(filename, "wb");
+    if (file != NULL)
+        fwrite(mem, buf.bytesused, 1, file);
+
+    fclose(file);
+    munmap(mem, buf.length);
+
+    counter ++;
+    TestAp_Printf(TESTAP_DBG_FLOW, "%s <============\n",__FUNCTION__);
+    still_dev = dev;
+    still_width = w;
+    still_height = h;
+    still_format = format;
+    return 0;
+
+}
+
+
+static int GetFreeRam(int* freeram)
+{
+    FILE *meminfo = fopen("/proc/meminfo", "r");
+    char line[256];
+    if(meminfo == NULL)
+    {
+        TestAp_Printf(TESTAP_DBG_ERR, "/proc/meminfo can't open\n");
+        return 0;
+    }
+    while(fgets(line, sizeof(line), meminfo))
+    {
+        if(sscanf(line, "MemFree: %d kB", freeram) == 1)
+        {
+            *freeram <<= 10;
+            fclose(meminfo);
+            return 1;
+        }
+    }
+
+    fclose(meminfo);
+    return 0;
+}
+
+static int video_reqbufs(int dev, int nbufs)
+{
+    struct v4l2_requestbuffers rb;
+    int ret;
+
+    memset(&rb, 0, sizeof rb);
+    rb.count = nbufs;
+    rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    rb.memory = V4L2_MEMORY_MMAP;
+
+    ret = ioctl(dev, VIDIOC_REQBUFS, &rb);
+    if (ret < 0) {
+        TestAp_Printf(TESTAP_DBG_ERR, "Unable to allocate buffers: %d.\n", errno);
+        return ret;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "%u buffers allocated.\n", rb.count);
+    return rb.count;
+}
+
+int test(const char * strdevname)
+{
+    char filename[] = "quickcam-0000.jpg";
+    char rec_filename[30] = "RecordH264.h264";			/*"H264.ts"*/
+    char rec_filename1[30] = "RecordH264HD.h264";		/*"H264.ts"*/
+    char rec_filename2[30] = "RecordH264QVGA.h264";	/*"H264.ts"*/
+    char rec_filename3[30] = "RecordH264QQVGA.h264";	/*"H264.ts"*/
+    char rec_filename4[30] = "RecordH264VGA.h264";		/*"H264.ts"*/
+    int dev, ret;
+    int fake_dev; // chris
+    int freeram;
+
+    /* Options parsings */
+    char do_save = 0, do_enum_inputs = 0, do_capture = 0, do_get_still_image = 0;
+    char do_list_controls = 0, do_set_input = 0;
+    char *endptr;
+    int c;
+    int framerate = 30;
+    int bit_num = 0, tmp = 0;
+
+    /* Video buffers */
+    void *mem0[V4L_BUFFERS_MAX];
+    void *mem1[V4L_BUFFERS_MAX];
+    unsigned int pixelformat = V4L2_PIX_FMT_MJPEG;
+    unsigned int width = 1280;
+    unsigned int height = 720;
+    unsigned int nbufs = V4L_BUFFERS_DEFAULT;
+    unsigned int input = 0;
+    unsigned int skip = 0;
+
+    /* Capture loop */
+    struct timeval start, end, ts;
+    unsigned int delay = 0, nframes = (unsigned int)-1;
+    FILE *file = NULL;
+    FILE *rec_fp1 = NULL;
+    FILE *rec_fp2 = NULL;
+    FILE *rec_fp3 = NULL;
+    FILE *rec_fp4 = NULL;
+    double fps;
+
+    struct v4l2_buffer buf0;
+    struct v4l2_buffer buf1;
+    unsigned int i;
+
+    char do_record 			= 0;
+    /* Houston 2010/11/23 XU Ctrls */
+    char do_add_xu_ctrl 	= 0;
+    char do_xu_get_chip 	= 0;
+    char do_xu_get_fmt   	= 0;
+    char do_xu_set_fmt   	= 0;
+    char do_xu_get_qp  		= 0;
+    char do_xu_set_qp  		= 0;
+    char do_xu_get_br  		= 0;
+    char do_xu_set_br  		= 0;
+    char do_enum_MaxPayloadTransSize = 0;
+    int m_QP_Val = 0;
+    double m_BitRate = 0.0;
+    struct Cur_H264Format cur_H264fmt;
+    char do_xu_get 			= 0;
+    char do_xu_set 			= 0;
+    unsigned char GetXU_ID = 0;
+    unsigned char SetXU_ID = 0;
+    unsigned char GetCS = 0;
+    unsigned char SetCS = 0;
+    unsigned char GetCmdDataNum = 0;
+    unsigned char SetCmdDataNum = 0;
+    __u8 GetData[11] = {0};
+    __u8 SetData[11] = {0};
+
+    char do_vendor_version_get = 0;
+    char do_bri_set = 0;
+    char do_bri_get = 0;
+    int m_bri_val = 0;
+    char do_shrp_set = 0;
+    char do_shrp_get = 0;
+    int m_shrp_val = 0;
+    char do_asic_r = 0;
+    char do_asic_w = 0;
+    unsigned int rAsicAddr = 0x0;
+    unsigned char rAsicData = 0x0;
+    unsigned int wAsicAddr = 0x0;
+    unsigned char wAsicData = 0x0;
+
+ // chris +
+    /* multi-stream */
+    unsigned char multi_stream_format = 0;
+    unsigned char multi_stream_enable = 0;
+    unsigned int multi_stream_width = 0;//1280;
+    unsigned int multi_stream_height = 0;//720;
+    unsigned int multi_stream_resolution = 0;//(multi_stream_width << 16) | (multi_stream_height);
+    unsigned int MS_bitrate = 0;
+    unsigned int MS_qp = 0;
+    unsigned int MS_H264_mode = 0;
+    unsigned int MS_sub_fr = 0;
+    unsigned int MS_sub_gop = 0;
+    unsigned int streamID_set = 0;
+    unsigned int streamID_get = 0;
+    char do_multi_stream_set_bitrate = 0;
+    char do_multi_stream_get_bitrate = 0;
+    char do_multi_stream_set_qp = 0;
+    char do_multi_stream_get_qp = 0;
+    char do_multi_stream_set_H264Mode = 0;
+    char do_multi_stream_get_H264Mode = 0;
+    char do_multi_stream_set_sub_fr = 0;
+    char do_multi_stream_get_sub_fr = 0;
+    char do_multi_stream_set_sub_gop = 0;
+    char do_multi_stream_get_sub_gop = 0;
+ // chris -
+ //cjc +
+    char do_multi_stream_set_type = 0;
+    struct Multistream_Info TestInfo;
+    char do_multi_stream_get_status = 0;
+    char do_multi_stream_get_info = 0;
+    char do_multi_stream_set_enable = 0;
+    char do_multi_stream_get_enable = 0;
+    char do_osd_timer_ctrl_set = 0;
+    char do_osd_rtc_set = 0;
+    char do_osd_rtc_get = 0;
+    char do_osd_size_set = 0;
+    char do_osd_size_get = 0;
+    char do_osd_color_set = 0;
+    char do_osd_color_get = 0;
+    char do_osd_show_set = 0;
+    char do_osd_show_get = 0;
+    char do_osd_autoscale_set = 0;
+    char do_osd_autoscale_get = 0;
+    char do_osd_ms_size_set = 0;
+    char do_osd_ms_size_get = 0;
+    char do_osd_position_set = 0;
+    char do_osd_position_get = 0;
+    char do_osd_ms_position_set = 0;
+    char do_osd_ms_position_get = 0;
+    char do_md_mode_set = 0;
+    char do_md_mode_get = 0;
+    char do_md_threshold_set = 0;
+    char do_md_threshold_get = 0;
+    char do_md_mask_set = 0;
+    char do_md_mask_get = 0;
+    char do_md_result_set = 0;
+    char do_md_result_get = 0;
+    char do_mjpg_bitrate_set = 0;
+    char do_mjpg_bitrate_get = 0;
+    char do_h264_iframe_set = 0;
+    char do_h264_sei_set = 0;
+    char do_h264_sei_get = 0;
+    char do_h264_gop_set = 0;
+    char do_h264_gop_get = 0;
+    char do_h264_mode_get = 0;
+    char do_h264_mode_set = 0;
+    char do_img_mirror_set = 0;
+    char do_img_mirror_get = 0;
+    char do_img_flip_set = 0;
+    char do_img_flip_get = 0;
+    char do_img_color_set = 0;
+    char do_img_color_get = 0;
+    char do_osd_string_set = 0;
+    char do_osd_string_get = 0;
+    char do_osd_carcam_set = 0;
+    char do_osd_carcam_get = 0;
+    char do_osd_speed_set = 0;
+    char do_osd_speed_get = 0;
+    char do_osd_coordinate_set = 0;
+    char do_osd_coordinate_get = 0;
+    char do_gpio_ctrl_set = 0;
+    char do_gpio_ctrl_get = 0;
+    char do_frame_drop_en_set = 0;
+    char do_frame_drop_en_get = 0;
+    char do_frame_drop_ctrl_set = 0;
+    char do_frame_drop_ctrl_get = 0;
+    unsigned char osd_timer_count = 0;
+    unsigned int osd_rtc_year = 0;
+    unsigned char osd_rtc_month = 0;
+    unsigned char osd_rtc_day = 0;
+    unsigned char osd_rtc_hour = 0;
+    unsigned char osd_rtc_minute = 0;
+    unsigned char osd_rtc_second = 0;
+    unsigned char osd_size_line = 0;
+    unsigned char osd_size_block = 0;
+    unsigned char osd_color_font = 0;
+    unsigned char osd_color_border = 0;
+    unsigned char osd_show_line = 0;
+    unsigned char osd_show_block = 0;
+    unsigned char osd_autoscale_line = 0;
+    unsigned char osd_autoscale_block = 0;
+    unsigned char osd_ms_size_stream0 = 0;
+    unsigned char osd_ms_size_stream1 = 0;
+    unsigned char osd_ms_size_stream2 = 0;
+    unsigned char osd_type = 0;
+    unsigned int osd_start_row = 0;
+    unsigned int osd_start_col = 0;
+    unsigned char osd_ms_position_streamid = 0;
+    unsigned char osd_ms_start_row = 0;
+    unsigned char osd_ms_start_col = 0;
+    unsigned char osd_ms_s0_start_row = 0;
+    unsigned char osd_ms_s0_start_col = 0;
+    unsigned char osd_ms_s1_start_row = 0;
+    unsigned char osd_ms_s1_start_col = 0;
+    unsigned char osd_ms_s2_start_row = 0;
+    unsigned char osd_ms_s2_start_col = 0;
+    unsigned int osd_line_start_row = 0;
+    unsigned int osd_line_start_col = 0;
+    unsigned int osd_block_start_row = 0;
+    unsigned int osd_block_start_col = 0;
+    unsigned char md_mode = 0;
+    unsigned int md_threshold = 0;
+    unsigned char md_mask[24] = {0};
+    unsigned char md_result[24] = {0};
+    unsigned int mjpg_bitrate = 0;
+    unsigned char h264_sei_en = 0;
+    unsigned int h264_gop = 0;
+    unsigned int h264_mode = 0;
+    unsigned char img_mirror = 0;
+    unsigned char img_flip = 0;
+    unsigned char img_color = 0;
+    unsigned char h264_iframe_reset = 0;
+    unsigned char osd_2nd_string_group = 0;
+    unsigned char osd_speed_en = 0;
+    unsigned char osd_coordinate_en = 0;
+    unsigned char osd_coordinate_ctrl = 0;
+    unsigned int osd_speed = 0;
+    unsigned char osd_coordinate_direction = 0;
+    unsigned char osd_direction_value[6] = {0};
+    unsigned char osd_direction_value1 = 0;
+    unsigned long osd_direction_value2 = 0;
+    unsigned char osd_direction_value3 = 0;
+    unsigned long osd_direction_value4 = 0;
+    unsigned char gpio_ctrl_en = 0;
+    unsigned char gpio_ctrl_output_value = 0;
+    unsigned char gpio_ctrl_input_value = 0;
+    unsigned char stream1_frame_drop_en = 0;
+    unsigned char stream2_frame_drop_en = 0;
+    unsigned char stream1_frame_drop_ctrl = 0;
+    unsigned char stream2_frame_drop_ctrl = 0;
+    char osd_string[12] = {"0"};
+    pthread_t thread_capture_id;
+    do_xu_get_chip = 1;
+
+    do_capture = 1;
+    do_xu_get_br = 1;
+    do_xu_set_br = 1;
+    do_vendor_version_get = 1;
+
+    dev = video_open(strdevname);
+    if (dev < 0)
+    {
+        printf("fail open device.\n");
+        return -1;
+    }
+
+    if(do_vendor_version_get)
+    {
+        char vendor_version[12];
+        get_vendor_verson(dev, vendor_version);
+        TestAp_Printf(TESTAP_DBG_FLOW, "Vendor Version : %s\n",vendor_version);
+
+    }
+
+    // cjc +
+    ret = XU_Ctrl_ReadChipID(dev);
+    if(ret<0)
+        TestAp_Printf(TESTAP_DBG_ERR, "SONiX_UVC_TestAP @main : XU_Ctrl_ReadChipID Failed\n");
+    // cjc -
+
+    if(do_xu_get_br)
+    {
+        XU_H264_Get_BitRate(dev, &m_BitRate);
+        if(m_BitRate < 0 )
+            TestAp_Printf(TESTAP_DBG_ERR, "SONiX_UVC_TestAP @main : XU_H264_Get_BitRate Failed\n");
+        TestAp_Printf(TESTAP_DBG_FLOW, "Current bit rate: %.2f Kbps\n",m_BitRate);
+    }
+
+    m_BitRate = 10000000;
+    if(do_xu_set_br)
+    {
+        if(XU_H264_Set_BitRate(dev, m_BitRate) < 0 )
+            TestAp_Printf(TESTAP_DBG_ERR, "SONiX_UVC_TestAP @main : XU_H264_Set_BitRate Failed\n");
+    }
+
+
+
+    width = 1920;
+    height = 1080;
+    framerate = 30;
+    if (video_set_format(dev, width, height, pixelformat) < 0) {
+// cjc +
+        if(pixelformat == V4L2_PIX_FMT_H264) {
+            TestAp_Printf(TESTAP_DBG_ERR, " === Set Format Failed : skip for H264 ===  \n");
+        }
+        else {
+// cjc -
+            close(dev);
+            return 1;
+        }
+    }
+
+    /* Set the frame rate. */
+    if (video_set_framerate(dev, framerate, NULL) < 0) {
+        close(dev);
+        return -2;
+    }
+
+
+    if(GetFreeRam(&freeram) && freeram<1843200*nbufs+4194304)
+    {
+        TestAp_Printf(TESTAP_DBG_ERR, "free memory isn't enough(%d)\n",freeram);
+        return 1;
+    }
+
+    /* Allocate buffers. */
+    if ((int)(nbufs = video_reqbufs(dev, nbufs)) < 0) {
+        close(dev);
+    }
+
+    /* Map the buffers. */
+    for (i = 0; i < nbufs; ++i) {
+        memset(&buf0, 0, sizeof buf0);
+        buf0.index = i;
+        buf0.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buf0.memory = V4L2_MEMORY_MMAP;
+        ret = ioctl(dev, VIDIOC_QUERYBUF, &buf0);
+        if (ret < 0) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to query buffer %u (%d).\n", i, errno);
+            close(dev);
+            return 1;
+        }
+        TestAp_Printf(TESTAP_DBG_FLOW, "length: %u offset: %10u     --  ", buf0.length, buf0.m.offset);
+
+        mem0[i] = mmap(0, buf0.length, PROT_READ, MAP_SHARED, dev, buf0.m.offset);
+        if (mem0[i] == MAP_FAILED) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to map buffer %u (%d)\n", i, errno);
+            close(dev);
+            return 1;
+        }
+        TestAp_Printf(TESTAP_DBG_FLOW, "Buffer %u mapped at address %p.\n", i, mem0[i]);
+    }
+
+    /* Queue the buffers. */
+    for (i = 0; i < nbufs; ++i) {
+        memset(&buf0, 0, sizeof buf0);
+        buf0.index = i;
+        buf0.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buf0.memory = V4L2_MEMORY_MMAP;
+        ret = ioctl(dev, VIDIOC_QBUF, &buf0);
+        if (ret < 0) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to queue buffer0(%d).\n", errno);
+            close(dev);
+            return 1;
+        }
+    }
+
+    /* Start streaming. */
+    video_enable(dev, 1);
+
+    for (i = 0; i < nframes; ++i) {
+
+
+
+        /* Dequeue a buffer. */
+        memset(&buf0, 0, sizeof buf0);
+        buf0.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buf0.memory = V4L2_MEMORY_MMAP;
+        ret = ioctl(dev, VIDIOC_DQBUF, &buf0);
+        if (ret < 0) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to dequeue buffer0 (%d).\n", errno);
+            close(dev);
+            if(multi_stream_enable)
+                close(fake_dev);
+            return 1;
+        }
+
+        gettimeofday(&ts, NULL);
+
+
+        TestAp_Printf(TESTAP_DBG_FRAME, "Frame[%4u] %u bytes %ld.%06ld %ld.%06ld\n ", i, buf0.bytesused, buf0.timestamp.tv_sec, buf0.timestamp.tv_usec, ts.tv_sec, ts.tv_usec);
+
+
+        if (i == 0)
+            start = ts;
+
+
+        ret = ioctl(dev, VIDIOC_QBUF, &buf0);
+        if (ret < 0) {
+            TestAp_Printf(TESTAP_DBG_ERR, "Unable to requeue buffer0 (%d).\n", errno);
+            close(dev);
+            if(multi_stream_enable)
+                close(fake_dev);
+            return 1;
+        }
+
+        fflush(stdout);
+    }
+
+
+    return 0;
+
+}
+

+ 7 - 0
src/driver/driver_h264_usbimx291/sonix_io.h

@@ -0,0 +1,7 @@
+#ifndef SONIX_IO_H
+#define SONIX_IO_H
+
+
+int test(const char * strdevname);
+
+#endif // SONIX_IO_H

+ 5382 - 0
src/driver/driver_h264_usbimx291/sonix_xu_ctrls.c

@@ -0,0 +1,5382 @@
+#define N_(x) x
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include "sonix_xu_ctrls.h"
+#include "debug.h"
+
+extern struct H264Format *gH264fmt;
+
+unsigned char m_CurrentFPS = 24;
+unsigned char m_CurrentFPS_292 = 30;
+unsigned int  chip_id = CHIP_NONE;
+
+#define Default_fwLen 13
+const unsigned char Default_fwData[Default_fwLen] = {0x05, 0x00, 0x02, 0xD0, 0x01,		// W=1280, H=720, NumOfFrmRate=1
+										   0xFF, 0xFF, 0xFF, 0xFF,			// Frame size
+										   0x07, 0xA1, 0xFF, 0xFF,			// 20
+											};
+
+#define LENGTH_OF_SONIX_XU_SYS_CTR		(7)
+#define LENGTH_OF_SONIX_XU_USR_CTR		(9)
+#define SONIX_SN9C291_SERIES_CHIPID 	0x90
+#define SONIX_SN9C292_SERIES_CHIPID		0x92
+#define SONIX_SN9C292_DDR_64M			0x00
+#define SONIX_SN9C292_DDR_16M			0x03
+
+
+extern int video_get_framerate(int dev, int *framerate);
+
+static struct uvc_xu_control_info sonix_xu_sys_ctrls[] = 
+{
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_ASIC_RW,
+		.index    = 0,
+		.size     = 4,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | 
+		            UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_FLASH_CTRL,
+		.index    = 1,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | 
+		            UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_FRAME_INFO,
+		.index    = 2,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | 
+		            UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_H264_CTRL,
+		.index    = 3,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_MJPG_CTRL,
+		.index    = 4,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_OSD_CTRL,
+		.index    = 5,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | 
+		            UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_MOTION_DETECTION,
+		.index    = 6,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+	},
+	{
+		.entity   = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector = XU_SONIX_SYS_IMG_SETTING,
+		.index    = 7,
+		.size     = 11,
+		.flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+	},
+};
+
+static struct uvc_xu_control_info sonix_xu_usr_ctrls[] =
+{
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_FRAME_INFO,
+      .index    = 0,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
+                  UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_H264_CTRL,
+      .index    = 1,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_MJPG_CTRL,
+      .index    = 2,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_OSD_CTRL,
+      .index    = 3,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
+                  UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_MOTION_DETECTION,
+      .index    = 4,
+      .size     = 24,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_IMG_SETTING,
+      .index    = 5,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_MULTI_STREAM_CTRL,
+      .index    = 6,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },	
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_GPIO_CTRL,
+      .index    = 7,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },	
+    {
+      .entity   = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector = XU_SONIX_USR_DYNAMIC_FPS_CTRL,
+      .index    = 8,
+      .size     = 11,
+      .flags    = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+    },	
+};
+
+//  SONiX XU system Ctrls Mapping
+static struct uvc_xu_control_mapping_2_6 sonix_xu_sys_mappings[] = 
+{
+	{
+		.id        = V4L2_CID_ASIC_RW_SONIX,
+		.name      = "SONiX: Asic Read",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_ASIC_RW,
+		.size      = 4,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_SIGNED
+	},
+	{
+		.id        = V4L2_CID_FLASH_CTRL,
+		.name      = "SONiX: Flash Control",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_FLASH_CTRL,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_SIGNED
+	},
+	{
+		.id        = V4L2_CID_FRAME_INFO_SONIX,
+		.name      = "SONiX: H264 Format",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_FRAME_INFO,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_RAW
+	},
+	{
+		.id        = V4L2_CID_H264_CTRL_SONIX,
+		.name      = "SONiX: H264 Control",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_H264_CTRL,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+	},
+	{
+		.id        = V4L2_CID_MJPG_CTRL_SONIX,
+		.name      = "SONiX: MJPG Control",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_MJPG_CTRL,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+	},
+	{
+		.id        = V4L2_CID_OSD_CTRL_SONIX,
+		.name      = "SONiX: OSD Control",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_OSD_CTRL,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_RAW
+	},
+	{
+		.id        = V4L2_CID_MOTION_DETECTION_SONIX,
+		.name      = "SONiX: Motion Detection",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_MOTION_DETECTION,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+	},
+	{
+		.id        = V4L2_CID_IMG_SETTING_SONIX,
+		.name      = "SONiX: Image Setting",
+		.entity    = UVC_GUID_SONIX_SYS_HW_CTRL,
+		.selector  = XU_SONIX_SYS_IMG_SETTING,
+		.size      = 11,
+		.offset    = 0,
+		.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+		.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+	},
+};
+
+// SONiX XU user Ctrls Mapping
+static struct uvc_xu_control_mapping_2_6 sonix_xu_usr_mappings[] =
+{
+    {
+      .id        = V4L2_CID_FRAME_INFO_SONIX,
+      .name      = "SONiX: H264 Format",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_FRAME_INFO,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_RAW
+    },
+    {
+      .id        = V4L2_CID_H264_CTRL_SONIX,
+      .name      = "SONiX: H264 Control",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_H264_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },
+    {
+      .id        = V4L2_CID_MJPG_CTRL_SONIX,
+      .name      = "SONiX: MJPG Control",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_MJPG_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },
+    {
+      .id        = V4L2_CID_OSD_CTRL_SONIX,
+      .name      = "SONiX: OSD Control",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_OSD_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_RAW
+    },
+    {
+      .id        = V4L2_CID_MOTION_DETECTION_SONIX,
+      .name      = "SONiX: Motion Detection",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_MOTION_DETECTION,
+      .size      = 24,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },
+    {
+      .id        = V4L2_CID_IMG_SETTING_SONIX,
+      .name      = "SONiX: Image Setting",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_IMG_SETTING,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },
+    {
+      .id        = V4L2_CID_MULTI_STREAM_CTRL_SONIX,
+      .name      = "SONiX: Multi Stram Control ",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_MULTI_STREAM_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },	
+    {
+      .id        = V4L2_CID_GPIO_CTRL_SONIX,
+      .name      = "SONiX: GPIO Control ",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_GPIO_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },	
+    {
+      .id        = V4L2_CID_DYNAMIC_FPS_CTRL_SONIX,
+      .name      = "SONiX: Dynamic fps Control ",
+      .entity    = UVC_GUID_SONIX_USR_HW_CTRL,
+      .selector  = XU_SONIX_USR_DYNAMIC_FPS_CTRL,
+      .size      = 11,
+      .offset    = 0,
+      .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
+      .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
+    },	
+};
+
+
+int GetKernelVersion(void)
+{
+	struct utsname KernelInfo;
+	int kernelRelease = 0, version[3];
+	char *endptr;
+	uname(&KernelInfo);
+	version[0]= strtol(KernelInfo.release, &endptr, 10);
+	version[1]= strtol(endptr+1, &endptr, 10);
+	version[2]= strtol(endptr+1, &endptr, 10);
+	kernelRelease = (version[0]<<16) |  (version[1]<<8) | version[2];
+	TestAp_Printf(TESTAP_DBG_FLOW, "kernelRelease:0x%x \n",kernelRelease);
+	return kernelRelease;	
+}
+
+
+int XU_Set_Cur(int fd, __u8 xu_unit, __u8 xu_selector, __u16 xu_size, __u8 *xu_data)
+{
+	int err=0;
+	if( GetKernelVersion()>KERNEL_VERSION (3, 0, 36) )
+	{
+		struct uvc_xu_control_query_3 xctrlq;
+		xctrlq.unit = xu_unit;
+		xctrlq.selector = xu_selector;
+		xctrlq.query = UVC_SET_CUR;
+		xctrlq.size = xu_size;
+		xctrlq.data = xu_data;
+		err=ioctl(fd, UVCIOC_CTRL_QUERY, &xctrlq);
+	}
+	else
+	{
+		struct uvc_xu_control xctrl;	
+		xctrl.unit = xu_unit;
+		xctrl.selector = xu_selector;
+		xctrl.size = xu_size;
+		xctrl.data = xu_data;
+		err=ioctl(fd, UVCIOC_CTRL_SET, &xctrl);
+	}
+	
+	return err;
+}
+
+int XU_Get_Cur(int fd, __u8 xu_unit, __u8 xu_selector, __u16 xu_size, __u8 *xu_data)
+{
+	int err=0;
+	if( GetKernelVersion()>KERNEL_VERSION (3, 0, 36) )
+	{
+		struct uvc_xu_control_query_3 xctrlq;
+		xctrlq.unit = xu_unit;
+		xctrlq.selector = xu_selector;
+		xctrlq.query = UVC_GET_CUR;
+		xctrlq.size = xu_size;
+		xctrlq.data = xu_data;
+		err=ioctl(fd, UVCIOC_CTRL_QUERY, &xctrlq);
+	}
+	else
+	{
+		struct uvc_xu_control xctrl;	
+		xctrl.unit = xu_unit;
+		xctrl.selector = xu_selector;
+		xctrl.size = xu_size;
+		xctrl.data = xu_data;
+		err=ioctl(fd, UVCIOC_CTRL_GET, &xctrl);
+	}
+	return err;
+}
+
+
+// Houston 2011/08/08 XU ctrls ----------------------------------------------------------
+
+int XU_Ctrl_Add(int fd, struct uvc_xu_control_info *info, struct uvc_xu_control_mapping_2_6 *map) 
+{
+	int i=0;
+	int err=0;
+	
+	/* try to add controls listed */
+	if(GetKernelVersion() <= KERNEL_VERSION (3, 0, 36))
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "Adding XU Ctrls - %s\n", map->name);
+		if ((err=ioctl(fd, UVCIOC_CTRL_ADD, info)) < 0 ) 
+		{
+			if (errno == EEXIST ) 
+			{	
+				TestAp_Printf(TESTAP_DBG_ERR, "UVCIOC_CTRL_ADD - Ignored, uvc driver had already defined\n");
+				return (-EEXIST);
+			}
+			else if (errno == EACCES)
+			{
+				TestAp_Printf(TESTAP_DBG_ERR, "Need admin previledges for adding extension unit(XU) controls\n");
+				TestAp_Printf(TESTAP_DBG_ERR, "please run 'SONiX_UVC_TestAP --add_ctrls' as root (or with sudo)\n");
+				return  (-1);
+			}
+			else perror("Control exists");
+		}
+	}	
+	/* after adding the controls, add the mapping now */
+	TestAp_Printf(TESTAP_DBG_FLOW, "Mapping XU Ctrls - %s\n", map->name);
+	
+	if(GetKernelVersion() < KERNEL_VERSION (3, 0, 1))
+		err=ioctl(fd, UVCIOC_CTRL_MAP_2_6, map);
+	else if(GetKernelVersion() <= KERNEL_VERSION (3, 0, 36))
+	{
+		struct uvc_xu_control_mapping_3 map_3;
+		memset(&map_3, 0, sizeof(struct uvc_xu_control_mapping_3));
+		memcpy(&map_3, map, sizeof(struct uvc_xu_control_mapping_2_6));
+		err=ioctl(fd, UVCIOC_CTRL_MAP_3_0, &map_3);
+	}
+	else	//(GetKernelVersion() > KERNEL_VERSION (3, 0, 36))
+	{
+		struct uvc_xu_control_mapping_3 map_3;
+		memset(&map_3, 0, sizeof(struct uvc_xu_control_mapping_3));
+		memcpy(&map_3, map, sizeof(struct uvc_xu_control_mapping_2_6));
+		
+		err=ioctl(fd, UVCIOC_CTRL_MAP_3_X, &map_3);
+	}		
+	
+	if (err < 0) 
+	{
+		if ((errno!=EEXIST) && (errno != EACCES))
+		{
+			TestAp_Printf(TESTAP_DBG_ERR, "UVCIOC_CTRL_MAP - Error(err= %d)\n", errno);
+			return (-2);
+		}
+		else if (errno == EACCES)
+		{
+			TestAp_Printf(TESTAP_DBG_ERR, "Need admin previledges for adding extension unit(XU) controls\n");
+			TestAp_Printf(TESTAP_DBG_ERR, "please run 'SONiX_UVC_TestAP --add_ctrls' as root (or with sudo)\n");
+			return  (-1);
+		}
+		else perror("Mapping exists");
+	}
+	
+	return 0;
+}
+
+int XU_Init_Ctrl(int fd) 
+{
+	int i=0;
+	int err=0;
+	int length;
+	struct uvc_xu_control_info *xu_infos;
+	struct uvc_xu_control_mapping_2_6 *xu_mappings;
+	
+	// Add xu READ ASIC first
+	err = XU_Ctrl_Add(fd, &sonix_xu_sys_ctrls[i], &sonix_xu_sys_mappings[i]);
+	if (err == EEXIST){}
+	else if (err < 0) {return err;}
+
+	// Read chip ID
+	err = XU_Ctrl_ReadChipID(fd);
+	if (err < 0) return err;
+
+
+	// Add xu flash control
+	i++;
+	err = XU_Ctrl_Add(fd, &sonix_xu_sys_ctrls[i], &sonix_xu_sys_mappings[i]);
+	if (err == EEXIST){}
+	else if (err < 0) {return err;}
+
+
+	// Decide which xu set had been add
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_infos = sonix_xu_sys_ctrls;
+		xu_mappings = sonix_xu_sys_mappings;
+		i = 2;
+		length = LENGTH_OF_SONIX_XU_SYS_CTR;
+		TestAp_Printf(TESTAP_DBG_FLOW, "SN9C291\n");
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_infos = sonix_xu_usr_ctrls;
+		xu_mappings = sonix_xu_usr_mappings;
+		i = 0;
+		length = LENGTH_OF_SONIX_XU_USR_CTR;
+		TestAp_Printf(TESTAP_DBG_FLOW, "SN9C292\n");
+	}
+	else
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, "Unknown chip id 0x%x\n", chip_id);
+		return -1;
+	}
+	
+	// Add other xu accroding chip ID
+	for ( ; i<length; i++ ) 
+	{
+		err = XU_Ctrl_Add(fd, &xu_infos[i], &xu_mappings[i]);
+		//if (err < 0) break;
+	} 
+	return 0;
+}
+
+int XU_Ctrl_ReadChipID(int fd)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Ctrl_ReadChipID ==>\n");
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[4];
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 3; 
+	__u8 xu_selector= XU_SONIX_SYS_ASIC_RW;
+	__u16 xu_size= 4;
+	__u8 *xu_data= ctrldata;
+
+
+	xu_data[0] = 0x1f;
+	xu_data[1] = 0x10;
+	xu_data[2] = 0x0;
+	xu_data[3] = 0xFF;		/* Dummy Write */
+	
+	/* Dummy Write */
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, "  ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		return err;
+	}
+
+	/* Asic Read */
+	xu_data[3] = 0x00;
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, "   ioctl(UVCIOC_CTRL_GET) FAILED (%i)  \n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR, "    Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_Ctrl_ReadChipID Success == \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      ASIC READ data[0] : %x\n", xu_data[0]);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      ASIC READ data[1] : %x\n", xu_data[1]);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      ASIC READ data[2] : %x (Chip ID)\n", xu_data[2]);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      ASIC READ data[3] : %x\n", xu_data[3]);
+	
+	if(xu_data[2] == SONIX_SN9C291_SERIES_CHIPID)
+	{
+		chip_id = CHIP_SNC291A;
+	}	
+	if(xu_data[2] == SONIX_SN9C292_SERIES_CHIPID)
+	{
+		xu_data[0] = 0x07;		//DRAM SIZE
+		xu_data[1] = 0x16;
+		xu_data[2] = 0x0;
+		xu_data[3] = 0xFF;		/* Dummy Write */
+
+		/* Dummy Write */
+		if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+		{
+			TestAp_Printf(TESTAP_DBG_ERR, "  ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+			return err;
+		}
+
+		/* Asic Read */
+		xu_data[3] = 0x00;
+		if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+		{
+			TestAp_Printf(TESTAP_DBG_ERR, "   ioctl(UVCIOC_CTRL_GET) FAILED (%i)  \n",err);
+			if(err==EINVAL)
+				TestAp_Printf(TESTAP_DBG_ERR, "    Invalid arguments\n");
+			return err;
+		}
+		
+		if(xu_data[2] == SONIX_SN9C292_DDR_64M)
+			chip_id = CHIP_SNC292A;
+		else if(xu_data[2] == SONIX_SN9C292_DDR_16M)
+			chip_id = CHIP_SNC291B;			
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "ChipID = %d\n",chip_id);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Ctrl_ReadChipID <==\n");
+	return ret;
+}
+
+int H264_GetFormat(int fd)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "H264_GetFormat ==>\n");
+	int i,j;
+	int iH264FormatCount = 0;
+	int success = 1;
+	
+	unsigned char *fwData = NULL;
+	unsigned short fwLen = 0;
+
+	// Init H264 XU Ctrl Format
+	if( XU_H264_InitFormat(fd) < 0 )
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, " H264 XU Ctrl Format failed , use default Format\n");
+		fwLen = Default_fwLen;
+		fwData = (unsigned char *)calloc(fwLen,sizeof(unsigned char));
+		memcpy(fwData, Default_fwData, fwLen);
+		goto Skip_XU_GetFormat;
+	}
+
+	// Probe : Get format through XU ctrl
+	success = XU_H264_GetFormatLength(fd, &fwLen);
+	if( success < 0 || fwLen <= 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, " XU Get Format Length failed !\n");
+	}
+	TestAp_Printf(TESTAP_DBG_FLOW, "fwLen = 0x%x\n", fwLen);
+	
+	// alloc memory
+	fwData = (unsigned char *)calloc(fwLen,sizeof(unsigned char));
+
+	if( XU_H264_GetFormatData(fd, fwData,fwLen) < 0 )
+	{
+		TestAp_Printf(TESTAP_DBG_ERR, " XU Get Format Data failed !\n");
+	}
+
+Skip_XU_GetFormat :
+
+	// Get H.264 format count
+	iH264FormatCount = H264_CountFormat(fwData, fwLen);
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "H264_GetFormat ==> FormatCount : %d \n", iH264FormatCount);
+
+	if(iH264FormatCount>0)
+		gH264fmt = (struct H264Format *)malloc(sizeof(struct H264Format)*iH264FormatCount);
+	else
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"Get Resolution Data Failed\n");
+	}
+
+	// Parse & Save Size/Framerate into structure
+	success = H264_ParseFormat(fwData, fwLen, gH264fmt);
+
+	if(success)
+	{
+		for(i=0; i<iH264FormatCount; i++)
+		{
+			TestAp_Printf(TESTAP_DBG_FLOW, "Format index: %d --- (%d x %d) ---\n", i+1, gH264fmt[i].wWidth, gH264fmt[i].wHeight);
+			for(j=0; j<gH264fmt[i].fpsCnt; j++)
+			{
+				if(chip_id == CHIP_SNC291A)
+				{
+					TestAp_Printf(TESTAP_DBG_FLOW, "(%d) %2d fps\n", j+1, H264_GetFPS(gH264fmt[i].FrPay[j]));
+				}
+				else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+				{
+					TestAp_Printf(TESTAP_DBG_FLOW, "(%d) %2d fps\n", j+1, H264_GetFPS(gH264fmt[i].FrPay[j*2]));
+				}
+			}
+		}
+	}
+
+	if(fwData)
+	{
+		free(fwData);
+		fwData = NULL;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "H264_GetFormat <== \n");
+	return success;
+}
+
+int H264_CountFormat(unsigned char *Data, int len)
+{
+	int fmtCnt = 0;
+	int fpsCnt = 0;
+	int cur_len = 0;
+	int cur_fmtid = 0;
+	int cur_fpsNum = 0;
+	
+	if( Data == NULL || len == 0)
+		return 0;
+
+	// count Format numbers
+	while(cur_len < len)
+	{
+		cur_fpsNum = Data[cur_len+4];
+		
+		TestAp_Printf(TESTAP_DBG_FLOW, "H264_CountFormat ==> cur_len = %d, cur_fpsNum= %d\n", cur_len , cur_fpsNum);
+
+		if(chip_id == CHIP_SNC291A)
+		{
+			cur_len += 9 + cur_fpsNum * 4;
+		}
+		else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+		{
+			cur_len += 9 + cur_fpsNum * 6;
+		}
+
+		fmtCnt++;
+	}
+	
+	if(cur_len != len)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "H264_CountFormat ==> cur_len = %d, fwLen= %d\n", cur_len , len);
+		return 0;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "  ========  fmtCnt=%d   ======== \n",fmtCnt);
+	return fmtCnt;
+}
+int H264_ParseFormat(unsigned char *Data, int len, struct H264Format *fmt)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "H264_ParseFormat ==>\n");
+	int fpsCnt = 0;
+	int cur_len = 0;
+	int cur_fmtid = 0;
+	int cur_fpsNum = 0;
+	int i;
+
+	while(cur_len < len)
+	{
+		// Copy Size
+		fmt[cur_fmtid].wWidth  = ((unsigned short)Data[cur_len]<<8)   + (unsigned short)Data[cur_len+1];
+		fmt[cur_fmtid].wHeight = ((unsigned short)Data[cur_len+2]<<8) + (unsigned short)Data[cur_len+3];
+		fmt[cur_fmtid].fpsCnt  = Data[cur_len+4];
+		fmt[cur_fmtid].FrameSize =	((unsigned int)Data[cur_len+5] << 24) | 
+						((unsigned int)Data[cur_len+6] << 16) | 
+						((unsigned int)Data[cur_len+7] << 8 ) | 
+						((unsigned int)Data[cur_len+8]);
+
+		TestAp_Printf(TESTAP_DBG_FLOW, "Data[5~8]: 0x%02x%02x%02x%02x \n", Data[cur_len+5],Data[cur_len+6],Data[cur_len+7],Data[cur_len+8]);
+		TestAp_Printf(TESTAP_DBG_FLOW, "fmt[%d].FrameSize: 0x%08x \n", cur_fmtid, fmt[cur_fmtid].FrameSize);
+
+		// Alloc memory for Frame rate 
+		cur_fpsNum = Data[cur_len+4];
+		
+		if(chip_id == CHIP_SNC291A)
+		{
+			fmt[cur_fmtid].FrPay = (unsigned int *)malloc(sizeof(unsigned int)*cur_fpsNum);
+		}
+		else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+		{
+			fmt[cur_fmtid].FrPay = (unsigned int *)malloc(sizeof(unsigned int)*cur_fpsNum*2);
+		}
+		
+		for(i=0; i<cur_fpsNum; i++)
+		{
+			if(chip_id == CHIP_SNC291A)
+			{
+				fmt[cur_fmtid].FrPay[i] =	(unsigned int)Data[cur_len+9+i*4]   << 24 | 
+								(unsigned int)Data[cur_len+9+i*4+1] << 16 |
+								(unsigned int)Data[cur_len+9+i*4+2] << 8  |
+								(unsigned int)Data[cur_len+9+i*4+3] ;
+			
+			//TestAp_Printf(TESTAP_DBG_FLOW, "fmt[cur_fmtid].FrPay[%d]: 0x%08x \n", i, fmt[cur_fmtid].FrPay[i]);
+			}
+			else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+			{
+				fmt[cur_fmtid].FrPay[i*2] =	(unsigned int)Data[cur_len+9+i*6]   << 8 | (unsigned int)Data[cur_len+9+i*6+1];
+				fmt[cur_fmtid].FrPay[i*2+1] =	(unsigned int)Data[cur_len+9+i*6+2]   << 24 | 
+								(unsigned int)Data[cur_len+9+i*6+3] << 16 |
+								(unsigned int)Data[cur_len+9+i*6+4] << 8  |
+								(unsigned int)Data[cur_len+9+i*6+5] ;
+
+				TestAp_Printf(TESTAP_DBG_FLOW, "fmt[cur_fmtid].FrPay[%d]: 0x%04x  0x%08x \n", i, fmt[cur_fmtid].FrPay[i*2], fmt[cur_fmtid].FrPay[i*2+1]);
+			}
+		}
+		
+		// Do next format
+		if(chip_id == CHIP_SNC291A)
+		{
+			cur_len += 9 + cur_fpsNum * 4;
+		}
+		else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+		{
+			cur_len += 9 + cur_fpsNum * 6;
+		}
+		cur_fmtid++;
+	}
+	if(cur_len != len)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"H264_ParseFormat <==  fail \n");
+		return 0;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "H264_ParseFormat <==\n");
+	return 1;
+}
+
+int H264_GetFPS(unsigned int FrPay)
+{
+	int fps = 0;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		//TestAp_Printf(TESTAP_DBG_FLOW, "H264_GetFPS==> FrPay = 0x%04x\n", (FrPay & 0xFFFF0000)>>16);
+
+		unsigned short frH = (FrPay & 0xFF000000)>>16;
+		unsigned short frL = (FrPay & 0x00FF0000)>>16;
+		unsigned short fr = (frH|frL);
+	
+		//TestAp_Printf(TESTAP_DBG_FLOW, "FrPay: 0x%x -> fr = 0x%x\n",FrPay,fr);
+	
+		fps = ((unsigned int)10000000/fr)>>8;
+
+		//TestAp_Printf(TESTAP_DBG_FLOW, "fps : %d\n", fps);
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		//TestAp_Printf(TESTAP_DBG_FLOW, "H264_GetFPS==> Fr = 0x%04x\n", (unsigned short)FrPay);
+
+		fps = ((unsigned int)10000000/(unsigned short)FrPay)>>8;
+
+		//TestAp_Printf(TESTAP_DBG_FLOW, "fps : %d\n", fps);
+	}
+
+	return fps;
+}
+
+
+int XU_H264_InitFormat(int fd)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_InitFormat ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_FRAME_INFO;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_FRAME_INFO;
+	}
+		
+	// Switch command : FMT_NUM_INFO
+	// data[0] = 0x01;
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x01;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   Set Switch command : FMT_NUM_INFO FAILED (%i)\n",err);
+		return err;
+	}
+	
+	//xu_data[0] = 0;
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{	
+		TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		return err;
+	}
+	
+	for(i=0; i<xu_size; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, " Get Data[%d] = 0x%x\n",i, xu_data[i]);
+	TestAp_Printf(TESTAP_DBG_FLOW, " ubH264Idx_S1 = %d\n", xu_data[5]);
+
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_InitFormat <== Success\n");
+	return ret;
+}
+
+int XU_H264_GetFormatLength(int fd, unsigned short *fwLen)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_GetFormatLength ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_FRAME_INFO;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_FRAME_INFO;
+	}	
+		
+	// Switch command : FMT_Data Length_INFO
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x02;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) >= 0) 
+	{
+		//for(i=0; i<11; i++)	xu_data[i] = 0;		// clean data
+		memset(xu_data, 0, xu_size);
+
+		if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) >= 0)
+		{
+			for (i=0 ; i<11 ; i+=2)
+				TestAp_Printf(TESTAP_DBG_FLOW, " Get Data[%d] = 0x%x\n", i, (xu_data[i]<<8)+xu_data[i+1]);
+
+			// Get H.264 format length
+			*fwLen = ((unsigned short)xu_data[6]<<8) + xu_data[7];
+			TestAp_Printf(TESTAP_DBG_FLOW, " H.264 format Length = 0x%x\n", *fwLen);
+		}
+		else
+		{
+			TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+			return err;
+		}
+	}
+	else
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   Set Switch command : FMT_Data Length_INFO FAILED (%i)\n",err);
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_GetFormatLength <== Success\n");
+	return ret;
+}
+
+int XU_H264_GetFormatData(int fd, unsigned char *fwData, unsigned short fwLen)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_GetFormatData ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	int loop = 0;
+	int LoopCnt  = (fwLen%11) ? (fwLen/11)+1 : (fwLen/11) ;
+	int Copyleft = fwLen;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_FRAME_INFO;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_FRAME_INFO;
+	}
+	
+	// Switch command
+	xu_data[0] = 0x9A;		
+	xu_data[1] = 0x03;		// FRM_DATA_INFO
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   Set Switch command : FRM_DATA_INFO FAILED (%i)\n",err);
+		return err;
+	}
+
+	// Get H.264 Format Data
+	xu_data[0] = 0x02;		// Stream: 1
+	xu_data[1] = 0x01;		// Format: 1 (H.264)
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) >= 0) 
+	{
+		// Read all H.264 format data
+		for(loop = 0 ; loop < LoopCnt ; loop ++)
+		{
+			for(i=0; i<11; i++)	xu_data[i] = 0;		// clean data
+			
+			TestAp_Printf(TESTAP_DBG_FLOW, "--> Loop : %d <--\n",  loop);
+			
+			if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) >= 0)
+			{
+				for (i=0 ; i<11 ; i++)
+					TestAp_Printf(TESTAP_DBG_FLOW, " Data[%d] = 0x%x\n", i, xu_data[i]);
+
+				// Copy Data
+				if(Copyleft >= 11)
+				{
+					memcpy( &fwData[loop*11] , xu_data, 11);
+					Copyleft -= 11;
+				}
+				else
+				{
+					memcpy( &fwData[loop*11] , xu_data, Copyleft);
+					Copyleft = 0;
+				}
+			}
+			else
+			{
+				TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+				return err;
+			}
+		}
+	}
+	else
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   Set Switch command : FRM_DATA_INFO FAILED (%i)\n",err);
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_GetFormatData <== Success\n");
+	return ret;
+}
+
+int XU_H264_SetFormat(int fd, struct Cur_H264Format fmt)
+{
+	// Need to get H264 format first
+	if(gH264fmt==NULL)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "SONiX_UVC_TestAP @XU_H264_SetFormat : Do XU_H264_GetFormat before setting H264 format\n");
+		return -EINVAL;
+	}
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_SetFormat ==> %d-%d => (%d x %d):%d fps\n", 
+				fmt.FmtId+1, fmt.FrameRateId+1, 
+				gH264fmt[fmt.FmtId].wWidth, 
+				gH264fmt[fmt.FmtId].wHeight, 
+				H264_GetFPS(gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId]));
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_SetFormat ==> %d-%d => (%d x %d):%d fps\n", 
+				fmt.FmtId+1, fmt.FrameRateId+1, 
+				gH264fmt[fmt.FmtId].wWidth, 
+				gH264fmt[fmt.FmtId].wHeight, 
+				H264_GetFPS(gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2]));
+	}
+
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_FRAME_INFO;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_FRAME_INFO;
+	}
+		
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x21;				// Commit_INFO
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_FMT ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set H.264 format setting data
+	xu_data[0] = 0x02;				// Stream : 1
+	xu_data[1] = 0x01;				// Format index : 1 (H.264) 
+	xu_data[2] = fmt.FmtId + 1;		// Frame index (Resolution index), firmware index starts from 1
+//	xu_data[3] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0xFF000000 ) >> 24;	// Frame interval
+//	xu_data[4] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x00FF0000 ) >> 16;
+	xu_data[5] = ( gH264fmt[fmt.FmtId].FrameSize & 0x00FF0000) >> 16;
+	xu_data[6] = ( gH264fmt[fmt.FmtId].FrameSize & 0x0000FF00) >> 8;
+	xu_data[7] = ( gH264fmt[fmt.FmtId].FrameSize & 0x000000FF);
+//	xu_data[8] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x0000FF00 ) >> 8;
+//	xu_data[9] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x000000FF ) ;
+
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_data[3] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0xFF000000 ) >> 24;	// Frame interval
+		xu_data[4] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x00FF0000 ) >> 16;
+		xu_data[8] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x0000FF00 ) >> 8;
+		xu_data[9] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId] & 0x000000FF ) ;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_data[3] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2] & 0x0000FF00 ) >> 8;	// Frame interval
+		xu_data[4] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2] & 0x000000FF ) ;
+		xu_data[8] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2+1] & 0xFF000000 ) >> 24;
+		xu_data[9] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2+1] & 0x00FF0000 ) >> 16;
+		xu_data[10] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2+1] & 0x0000FF00 ) >> 8;
+	}	
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_FMT ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		memset(xu_data, 0, xu_size);
+		xu_data[0] = ( gH264fmt[fmt.FmtId].FrPay[fmt.FrameRateId*2+1] & 0x000000FF ) ;
+
+		if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+		{
+			TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_FMT____2 ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+			if(err==EINVAL)
+				TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+			return err;
+		}
+	}	
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_SetFormat <== Success \n");
+	return ret;
+
+}
+
+
+int XU_H264_Get_Mode(int fd, int *Mode)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_Mode ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;				// H264_ctrl_type
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x06;				// H264_mode
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Get mode
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_Mode ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_H264_Get_Mode Success == \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", 0, xu_data[0]);
+
+	*Mode = xu_data[0];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_Mode (%s)<==\n", *Mode==1?"CBR mode":(*Mode==2?"VBR mode":"error"));
+	return ret;
+}
+
+int XU_H264_Set_Mode(int fd, int Mode)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_Mode (0x%x) ==>\n", Mode);
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;				// H264_ctrl_type
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x06;				// H264_mode
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+
+	// Set CBR/VBR Mode
+	memset(xu_data, 0, xu_size);
+	xu_data[0] = Mode;
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_Mode ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_Mode <== Success \n");
+	return ret;
+
+}
+
+
+
+int XU_H264_Get_QP_Limit(int fd, int *QP_Min, int *QP_Max)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_QP_Limit ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;				// H264_limit
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;				// H264_limit
+	}
+
+
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_QP_Limit ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	memset(xu_data, 0, xu_size);
+	// Get QP value
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_QP_Limit ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_H264_Get_QP_Limit Success == \n");
+	for(i=0; i<2; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*QP_Min = xu_data[0];
+	*QP_Max = xu_data[1];
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_QP_Limit (0x%x, 0x%x)<==\n", *QP_Min, *QP_Max);
+	return ret;
+
+}
+
+int XU_H264_Get_QP(int fd, int *QP_Val)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_QP ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	*QP_Val = -1;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		int qp_min, qp_max;
+		XU_H264_Get_QP_Limit(fd, &qp_min, &qp_max);	
+	}
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x05;				// H264_VBR_QP
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x07;				// H264_QP
+	}
+	
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_QP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_FLOW, "Invalid arguments\n");
+		return err;
+	}
+	
+	// Get QP value
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_QP ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_H264_Get_QP Success == \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", 0, xu_data[0]);
+
+	*QP_Val = xu_data[0];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_QP (0x%x)<==\n", *QP_Val);
+	return ret;
+
+}
+
+int XU_H264_Set_QP(int fd, int QP_Val)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_QP (0x%x) ==>\n", QP_Val);
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x05;				// H264_VBR_QP
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x07;				// H264_QP	
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_QP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+
+	// Set QP value
+	memset(xu_data, 0, xu_size);
+	xu_data[0] = QP_Val;
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_QP ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_QP <== Success \n");
+	return ret;
+
+}
+
+int XU_H264_Get_BitRate(int fd, double *BitRate)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_BitRate ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+	*BitRate = -1.0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;				// H264_BitRate
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;				// H264_BitRate
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Get Bit rate ctrl number
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_BitRate ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_H264_Get_BitRate Success == \n");
+	
+	if(chip_id == CHIP_SNC291A)
+	{
+		for(i=0; i<2; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+		BitRate_CtrlNum = ( xu_data[0]<<8 )| (xu_data[1]) ;
+
+		// Bit Rate = BitRate_Ctrl_Num*512*fps*8 /1000(Kbps)
+		*BitRate = (double)(BitRate_CtrlNum*512.0*m_CurrentFPS*8)/1024.0;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		for(i=0; i<3; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+		BitRate_CtrlNum =  ( xu_data[0]<<16 )| ( xu_data[1]<<8 )| (xu_data[2]) ;
+
+		*BitRate = BitRate_CtrlNum;
+	}	
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_BitRate (%.2f)<==\n", *BitRate);
+	return ret;
+}
+
+int XU_H264_Set_BitRate(int fd, double BitRate)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_BitRate (%.2f) ==>\n",BitRate);
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;				// H264_BitRate
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;				// H264_BitRate
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Bit Rate Ctrl Number
+	if(chip_id == CHIP_SNC291A)
+	{
+		// Bit Rate = BitRate_Ctrl_Num*512*fps*8/1000 (Kbps)
+		BitRate_CtrlNum = (int)((BitRate*1024)/(512*m_CurrentFPS*8));
+		xu_data[0] = (BitRate_CtrlNum & 0xFF00)>>8;	// BitRate ctrl Num
+		xu_data[1] = (BitRate_CtrlNum & 0x00FF);
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		// Bit Rate = BitRate_Ctrl_Num*512*fps*8/1000 (Kbps)
+		xu_data[0] = ((int)BitRate & 0x00FF0000)>>16;
+		xu_data[1] = ((int)BitRate & 0x0000FF00)>>8;
+		xu_data[2] = ((int)BitRate & 0x000000FF);
+	}	
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_BitRate ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_BitRate <== Success \n");
+	return ret;
+}
+
+int XU_H264_Set_IFRAME(int fd)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_IFRAME ==>\n");
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_H264_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x06;				// H264_IFRAME
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_H264_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x04;				// H264_IFRAME
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_IFRAME ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Set IFrame reset
+	xu_data[0] = 1;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_IFRAME ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}	
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_IFRAME <== Success \n");
+	return ret;
+}
+
+int XU_H264_Get_SEI(int fd, unsigned char *SEI)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_SEI ==>\n");
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_H264_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, " ==SN9C290 no support get SEI==\n");	
+		return 0;
+	}
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x05;				// H264_SEI
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_SEI ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Get SEI
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_SEI ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*SEI = xu_data[0];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "      SEI : 0x%x\n",*SEI);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_SEI <== Success \n");
+
+	return 0;
+}
+
+int XU_H264_Set_SEI(int fd, unsigned char SEI)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_SEI ==>\n");
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_H264_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, " ==SN9C290 no support Set SEI==\n");	
+		return 0;
+	}
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x05;				// H264_SEI
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_SEI ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set SEI
+	xu_data[0] = SEI;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_SEI ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_SEI <== Success \n");
+	return 0;
+}
+
+int XU_H264_Get_GOP(int fd, unsigned int *GOP)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_GOP ==>\n");
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_H264_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// H264_GOP
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_GOP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Get GOP
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Get_GOP ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*GOP = (xu_data[1] << 8) | xu_data[0];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "      GOP : %d\n",*GOP);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Get_GOP <== Success \n");
+
+	return 0;
+}
+
+int XU_H264_Set_GOP(int fd, unsigned int GOP)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_GOP ==>\n");
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_H264_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// H264_GOP
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_GOP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set GOP
+	xu_data[0] = (GOP & 0xFF);
+	xu_data[1] = (GOP >> 8) & 0xFF;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_H264_Set_GOP ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_H264_Set_GOP <== Success \n");
+	return 0;
+}
+
+int XU_Get(int fd, struct uvc_xu_control *xctrl)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU Get ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+
+	// XU Set
+	if ((err=XU_Set_Cur(fd, xctrl->unit, xctrl->selector, xctrl->size, xctrl->data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU Get ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// XU Get
+	if ((err=XU_Get_Cur(fd, xctrl->unit, xctrl->selector, xctrl->size, xctrl->data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU Get ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU Get Success == \n");
+	for(i=0; i<xctrl->size; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xctrl->data[i]);
+	return ret;
+}
+
+int XU_Set(int fd, struct uvc_xu_control xctrl)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU Set ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+
+	// XU Set
+	for(i=0; i<xctrl.size; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Set data[%d] : 0x%x\n", i, xctrl.data[i]);
+	
+	if ((err=XU_Set_Cur(fd, xctrl.unit, xctrl.selector, xctrl.size, xctrl.data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU Set ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU Set Success == \n");
+	return ret;
+}
+
+int XU_Asic_Read(int fd, unsigned int Addr, unsigned char *AsicData)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Asic_Read ==>\n");
+	int ret = 0;
+	__u8 ctrldata[4];
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 3; 
+	__u8 xu_selector= XU_SONIX_SYS_ASIC_RW;
+	__u16 xu_size= 4;
+	__u8 *xu_data= ctrldata;
+
+	xu_data[0] = (Addr & 0xFF);
+	xu_data[1] = ((Addr >> 8) & 0xFF);
+	xu_data[2] = 0x0;
+	xu_data[3] = 0xFF;		/* Dummy Write */
+	
+	/* Dummy Write */
+	if ((ret=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_SET) FAILED (%i) \n",ret);
+		if(ret==EINVAL)			TestAp_Printf(TESTAP_DBG_ERR,"    Invalid arguments\n");		
+		return ret;
+	}
+	
+	/* Asic Read */
+	xu_data[3] = 0x00;
+	if ((ret=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",ret);
+		if(ret==EINVAL)			TestAp_Printf(TESTAP_DBG_ERR,"    Invalid arguments\n");
+		return ret;
+	}
+	*AsicData = xu_data[2];
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_Asic_Read Success ==\n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Address:0x%x = 0x%x \n", Addr, *AsicData);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Asic_Read <== Success\n");
+	return ret;
+}
+
+int XU_Asic_Write(int fd, unsigned int Addr, unsigned char AsicData)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Asic_Write ==>\n");
+	int ret = 0;
+	__u8 ctrldata[4];
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 3; 
+	__u8 xu_selector= XU_SONIX_SYS_ASIC_RW;
+	__u16 xu_size= 4;
+	__u8 *xu_data= ctrldata;
+
+	xu_data[0] = (Addr & 0xFF);			/* Addr Low */
+	xu_data[1] = ((Addr >> 8) & 0xFF);	/* Addr High */
+	xu_data[2] = AsicData;
+	xu_data[3] = 0x0;					/* Normal Write */
+	
+	/* Normal Write */
+	if ((ret=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"   ioctl(UVCIOC_CTRL_SET) FAILED (%i) \n",ret);
+		if(ret==EINVAL)			TestAp_Printf(TESTAP_DBG_ERR,"    Invalid arguments\n");		
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Asic_Write <== %s\n",(ret<0?"Failed":"Success"));
+	return ret;
+}
+
+int XU_Multi_Get_status(int fd, struct Multistream_Info *status)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_status ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x01;				// Multi-Stream Status
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_status ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get status
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_status ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	status->strm_type = xu_data[0];
+	status->format = ( xu_data[1]<<8 )| (xu_data[2]) ;
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_Multi_Get_status Success == \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get strm_type %d\n", status->strm_type);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get cur_format %d\n", status->format);
+
+	return 0;
+}
+
+int XU_Multi_Get_Info(int fd, struct Multistream_Info *Info)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_Info ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;				// Multi-Stream Stream Info
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_Info ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get Info
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_Info ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	Info->strm_type = xu_data[0];
+	Info->format = ( xu_data[1]<<8 )| (xu_data[2]) ;
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_Multi_Get_Info Success == \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get Support Stream %d\n", Info->strm_type);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get Support Resolution 0x%x\n", Info->format);
+
+	return 0;
+}
+
+int XU_Multi_Set_Type(int fd, unsigned int format)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_Type (%d) ==>\n",format);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_Type ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	if(chip_id == CHIP_SNC291B && (format==4 ||format==8 ||format==16))
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return -1;
+	}
+	
+
+	// Set format
+	xu_data[0] = format;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_Type ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_Type <== Success \n");
+	return 0;
+
+}
+
+int XU_Multi_Set_Enable(int fd, unsigned char enable)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_Enable ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// Enable Multi-Stream Flag
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_Enable ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set enable / disable multistream
+	xu_data[0] = enable;
+	xu_data[1] = 0;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_Enable ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "Set H264_Multi_Enable = %d \n",(xu_data[0] &0x01));
+	TestAp_Printf(TESTAP_DBG_FLOW, "Set MJPG_Multi_Enable = %d \n",((xu_data[0] >> 1) &0x01));
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_Enable <== Success \n");
+	return 0;
+}
+
+int XU_Multi_Get_Enable(int fd, unsigned char *enable)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_Enable ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// Enable Multi-Stream Flag
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_Enable ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get Enable
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_Enable ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	*enable = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get H264 Multi Stream Enable = %d\n", xu_data[0] & 0x01);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get MJPG Multi Stream Enable =  %d\n", (xu_data[0] >> 1) & 0x01);	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_Enable <== Success\n");
+	return 0;
+}
+
+#if 0
+int XU_Multi_Set_BitRate(int fd, unsigned int BitRate1, unsigned int BitRate2, unsigned int BitRate3)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_BitRate  BiteRate1=%d  BiteRate2=%d  BiteRate3=%d   ==>\n",BitRate1, BitRate2, BitRate3);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x04;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set BitRate1~3  (unit:bps)
+	xu_data[0] = (BitRate1 >> 16)&0xFF;
+	xu_data[1] = (BitRate1 >> 8)&0xFF;
+	xu_data[2] = BitRate1&0xFF;
+	xu_data[3] = (BitRate2 >> 16)&0xFF;
+	xu_data[4] = (BitRate2 >> 8)&0xFF;
+	xu_data[5] = BitRate2&0xFF;
+	xu_data[6] = (BitRate3 >> 16)&0xFF;
+	xu_data[7] = (BitRate3 >> 8)&0xFF;
+	xu_data[8] = BitRate3&0xFF;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_BitRate ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_BitRate <== Success \n");
+	return 0;
+}
+
+int XU_Multi_Get_BitRate(int fd)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_BitRate  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	int BitRate1 = 0;
+	int BitRate2 = 0;
+	int BitRate3 = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x04;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get BitRate1~3  (unit:bps)
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_BitRate ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_BitRate <== Success \n");
+	
+	for(i=0; i<9; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	BitRate1 =  ( xu_data[0]<<16 )| ( xu_data[1]<<8 )| (xu_data[2]) ;
+	BitRate2 =  ( xu_data[3]<<16 )| ( xu_data[4]<<8 )| (xu_data[5]) ;
+	BitRate3 =  ( xu_data[6]<<16 )| ( xu_data[7]<<8 )| (xu_data[8]) ;
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "  HD BitRate (%d)\n", BitRate1);
+	TestAp_Printf(TESTAP_DBG_FLOW, "  QVGA BitRate (%d)\n", BitRate2);
+	TestAp_Printf(TESTAP_DBG_FLOW, "  QQVGA BitRate (%d)\n", BitRate3);
+
+	return 0;
+}
+#endif
+
+int XU_Multi_Set_BitRate(int fd, unsigned int StreamID, unsigned int BitRate)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_BitRate  StreamID=%d  BiteRate=%d  ==>\n",StreamID ,BitRate);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x04;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set BitRate  (unit:bps)
+	xu_data[0] = StreamID;
+	xu_data[1] = (BitRate >> 16)&0xFF;
+	xu_data[2] = (BitRate >> 8)&0xFF;
+	xu_data[3] = BitRate&0xFF;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_BitRate ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_BitRate <== Success \n");
+	return 0;
+}
+
+int XU_Multi_Get_BitRate(int fd, unsigned int StreamID, unsigned int *BitRate)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_BitRate  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x05;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Stream ID
+	xu_data[0] = StreamID;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_BitRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get BitRate (unit:bps)
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_BitRate ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_BitRate <== Success \n");
+	
+	for(i=0; i<4; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*BitRate = ( xu_data[1]<<16 ) | ( xu_data[2]<<8 ) | xu_data[3];
+	TestAp_Printf(TESTAP_DBG_FLOW, "  Stream= %d   BitRate= %d\n", xu_data[0], *BitRate);
+
+	return 0;
+}
+
+int XU_Multi_Set_QP(int fd, unsigned int StreamID, unsigned int QP_Val)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_QP  StreamID=%d  QP_Val=%d  ==>\n",StreamID ,QP_Val);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x05;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_QP ==> Switch cmd(5) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Stream ID
+	xu_data[0] = StreamID;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_QP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x06;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_QP ==> Switch cmd(6) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set QP
+	xu_data[0] = StreamID;
+	xu_data[1] = QP_Val;
+
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_QP ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_QP <== Success \n");
+	return 0;
+}
+
+int XU_Multi_Get_QP(int fd, unsigned int StreamID, unsigned int *QP_val)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_QP  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x05;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_QP ==> Switch cmd(5) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Stream ID
+	xu_data[0] = StreamID;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_QP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x06;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_QP ==> Switch cmd(6) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get QP
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_QP ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_QP <== Success \n");
+	
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*QP_val = xu_data[1];
+	TestAp_Printf(TESTAP_DBG_FLOW, "  Stream= %d   QP_val = %d\n", xu_data[0], *QP_val);
+
+	return 0;
+}
+
+int XU_Multi_Set_H264Mode(int fd, unsigned int StreamID, unsigned int Mode)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_H264Mode  StreamID=%d  Mode=%d  ==>\n",StreamID ,Mode);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x07;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_H264Mode ==> Switch cmd(7) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Stream ID
+	xu_data[0] = StreamID;
+    xu_data[1] = Mode;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_H264Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_H264Mode <== Success \n");
+	return 0;
+}
+
+int XU_Multi_Get_H264Mode(int fd, unsigned int StreamID, unsigned int *Mode)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_H264Mode  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x05;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_H264Mode ==> Switch cmd(5) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Stream ID
+	xu_data[0] = StreamID;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_H264Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x07;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_H264Mode ==> Switch cmd(7) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get H264 Mode
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_H264Mode ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_H264Mode <== Success \n");
+	
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*Mode = xu_data[1];
+	TestAp_Printf(TESTAP_DBG_FLOW, "  Stream= %d   Mode = %d\n", xu_data[0], *Mode);
+
+	return 0;
+}
+
+int XU_Multi_Set_SubStream_FrameRate(int fd, unsigned int sub_fps)
+{   
+    TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_SubStream_FrameRate sub_fps=%d  ==>\n",sub_fps);
+
+    int err = 0, main_fps = 0;
+    __u8 ctrldata[11]={0};
+    int BitRate_CtrlNum = 0;
+
+    //uvc_xu_control parmeters
+    __u8 xu_unit= XU_SONIX_USR_ID; 
+    __u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+    __u16 xu_size= 11;
+    __u8 *xu_data= ctrldata;
+
+    video_get_framerate(fd, &main_fps);
+    if(sub_fps>main_fps)
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"set sub_fps as %d, because sub_fps must less than or equal to main_fps\n", main_fps);
+        sub_fps = main_fps;
+    }
+
+    // Switch command
+    xu_data[0] = 0x9A;
+    xu_data[1] = 0x08;
+
+    if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_SubStream_FrameRate ==> Switch cmd(8) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+        if(err==EINVAL)
+            TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+        return err;
+    }
+
+    // Set Stream ID
+    xu_data[0] = sub_fps;
+
+    if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_SubStream_FrameRate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+        if(err==EINVAL)
+            TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+        return err;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_SubStream_FrameRate <== Success \n");
+    return 0;
+}
+
+int XU_Multi_Get_SubStream_FrameRate(int fd, unsigned int *sub_fps)
+
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_SubStream_FrameRate  ==>\n");
+
+	int i = 0;
+	int err = 0, main_fps;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+    
+    video_get_framerate(fd, &main_fps);
+    
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x08;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_H264Mode ==> Switch cmd(8) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get substream fr
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_SubStream_FrameRate ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_SubStream_FrameRate <== Success \n");
+	
+
+	*sub_fps = (xu_data[0]<main_fps?xu_data[0]:main_fps);
+	TestAp_Printf(TESTAP_DBG_FLOW, "sub_fps = min(%d, %d)\n",  xu_data[0],main_fps);
+
+	return 0;
+}
+
+int XU_Multi_Set_SubStream_GOP(int fd, unsigned int sub_gop)
+{   
+    TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_SubStream_GOP sub_gop=%d  ==>\n",sub_gop);
+
+    int err = 0, main_gop = 0;
+    __u8 ctrldata[11]={0};
+    int BitRate_CtrlNum = 0;
+
+    //uvc_xu_control parmeters
+    __u8 xu_unit= XU_SONIX_USR_ID; 
+    __u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+    __u16 xu_size= 11;
+    __u8 *xu_data= ctrldata;
+
+    XU_H264_Get_GOP(fd, &main_gop);
+    if(sub_gop>main_gop)
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"set sub_gop as %d, because sub_gop must less than or equal to main_gop\n", main_gop);
+        sub_gop= main_gop;
+    }
+
+    // Switch command
+    xu_data[0] = 0x9A;
+    xu_data[1] = 0x09;
+
+    if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_SubStream_GOP ==> Switch cmd(9) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+        if(err==EINVAL)
+            TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+        return err;
+    }
+
+    // Set sub_gop
+    xu_data[0] = sub_gop&0xff;
+    xu_data[1] = (sub_gop&0xff00)>>8;
+    if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    {
+        TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Set_SubStream_GOP ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+        if(err==EINVAL)
+            TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+        return err;
+    }
+
+    TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Set_SubStream_GOP <== Success \n");
+    return 0;
+}
+
+int XU_Multi_Get_SubStream_GOP(int fd, unsigned int *sub_gop)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_SubStream_GOP  ==>\n");
+
+	int i = 0;
+	int err = 0, main_gop, get_gop;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MULTI_STREAM_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+    
+    XU_H264_Get_GOP(fd, &main_gop);
+    
+	// Switch command
+	xu_data[0] = 0x9A;
+	xu_data[1] = 0x09;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_SubStream_GOP ==> Switch cmd(9) : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get substream gop
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Multi_Get_SubStream_GOP ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Multi_Get_SubStream_GOP <== Success \n");
+	get_gop = (xu_data[1]<<8) | xu_data[0]; 
+	*sub_gop= (get_gop<main_gop?get_gop:main_gop);
+	TestAp_Printf(TESTAP_DBG_FLOW, "sub_fps = min(%d, %d)\n",  get_gop,main_gop);
+
+	return 0;
+}
+
+
+int XU_OSD_Timer_Ctrl(int fd, unsigned char enable)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Timer_Ctrl  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x00;				// OSD Timer control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Timer_Ctrl ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set enable / disable timer count
+	xu_data[0] = enable;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Timer_Ctrl ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Timer_Ctrl <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Set_RTC(int fd, unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_RTC  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x01;				// OSD RTC control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_RTC ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set RTC
+	xu_data[0] = second;
+	xu_data[1] = minute;
+	xu_data[2] = hour;
+	xu_data[3] = day;
+	xu_data[4] = month;
+	xu_data[5] = (year & 0xFF00) >> 8;
+	xu_data[6] = (year & 0x00FF);
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_RTC ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	for(i=0; i<7; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Set data[%d] : 0x%x\n", i, xu_data[i]);
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_RTC <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_RTC(int fd, unsigned int *year, unsigned char *month, unsigned char *day, unsigned char *hour, unsigned char *minute, unsigned char *second)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_RTC  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x01;				// OSD RTC control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_RTC ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_RTC ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<7; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_RTC <== Success \n");
+	
+	*year = (xu_data[5]<<8) | xu_data[6];
+	*month = xu_data[4];
+	*day = xu_data[3];
+	*hour = xu_data[2];
+	*minute = xu_data[1];
+	*second = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, " year 	= %d \n",*year);
+	TestAp_Printf(TESTAP_DBG_FLOW, " month	= %d \n",*month);
+	TestAp_Printf(TESTAP_DBG_FLOW, " day 	= %d \n",*day);
+	TestAp_Printf(TESTAP_DBG_FLOW, " hour 	= %d \n",*hour);
+	TestAp_Printf(TESTAP_DBG_FLOW, " minute	= %d \n",*minute);
+	TestAp_Printf(TESTAP_DBG_FLOW, " second	= %d \n",*second);
+	
+	return 0;
+}
+
+int XU_OSD_Set_Size(int fd, unsigned char LineSize, unsigned char BlockSize)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Size  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;				// OSD Size control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Size ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	if(LineSize > 4)
+		LineSize = 4;
+
+	if(BlockSize > 4)
+		BlockSize = 4;
+		
+	// Set data
+	xu_data[0] = LineSize;
+	xu_data[1] = BlockSize;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Size ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Size <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_Size(int fd, unsigned char *LineSize, unsigned char *BlockSize)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Size  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;				// OSD Size control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Size ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Size ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*LineSize = xu_data[0];
+	*BlockSize = xu_data[1];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Size (Line) = %d\n",*LineSize);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Size (Block) = %d\n",*BlockSize);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Size <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Color(int fd, unsigned char FontColor, unsigned char BorderColor)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Color  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// OSD Color control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Color ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	if(FontColor > 4)
+		FontColor = 4;
+
+	if(BorderColor > 4)
+		BorderColor = 4;
+		
+	// Set data
+	xu_data[0] = FontColor;
+	xu_data[1] = BorderColor;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Color ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Color <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_Color(int fd, unsigned char *FontColor, unsigned char *BorderColor)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Color  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// OSD Color control
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Color ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Color ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*FontColor = xu_data[0];
+	*BorderColor = xu_data[1];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Font Color = %d\n",*FontColor );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Border Color = %d\n",*BorderColor);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Color <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Enable(int fd, unsigned char Enable_Line, unsigned char Enable_Block)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Enable  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x04;				// OSD enable
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Enable ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+		
+	// Set data
+	xu_data[0] = Enable_Line;
+	xu_data[1] = Enable_Block;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Enable ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Enable <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_Enable(int fd, unsigned char *Enable_Line, unsigned char *Enable_Block)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Enable  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x04;				// OSD Enable
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Enable ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Enable ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*Enable_Line = xu_data[0];
+	*Enable_Block = xu_data[1];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Enable Line = %d\n",*Enable_Line);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Enable Block = %d\n",*Enable_Block);
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Enable <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_AutoScale(int fd, unsigned char Enable_Line, unsigned char Enable_Block)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_AutoScale  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x05;				// OSD Auto Scale enable
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_AutoScale ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+		
+	// Set data
+	xu_data[0] = Enable_Line;
+	xu_data[1] = Enable_Block;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_AutoScale ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_AutoScale <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_AutoScale(int fd, unsigned char *Enable_Line, unsigned char *Enable_Block)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_AutoScale  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x05;				// OSD Auto Scale enable
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_AutoScale ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_AutoScale ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<2; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*Enable_Line = xu_data[0];
+	*Enable_Block = xu_data[1];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Enable Line  Auto Scale = %d\n",*Enable_Line);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Enable Block Auto Scale = %d\n",*Enable_Block);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_AutoScale <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Multi_Size(int fd, unsigned char Stream0, unsigned char Stream1, unsigned char Stream2)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Multi_Size  %d   %d   %d  ==>\n",Stream0 ,Stream1 , Stream2);
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x06;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Multi_Size ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Set data
+	xu_data[0] = Stream0;
+	xu_data[1] = Stream1;
+	xu_data[2] = Stream2;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Multi_Size ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Multi_Size <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_Multi_Size(int fd, unsigned char *Stream0, unsigned char *Stream1, unsigned char *Stream2)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Multi_Size  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x06;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Multi_Size ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Multi_Size ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<3; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*Stream0 = xu_data[0];
+	*Stream1 = xu_data[1];
+	*Stream2 = xu_data[2];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Multi Stream 0 Size = %d\n",*Stream0);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Multi Stream 1 Size = %d\n",*Stream1);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Multi Stream 2 Size = %d\n",*Stream2);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Multi_Size <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Start_Position(int fd, unsigned char OSD_Type, unsigned int RowStart, unsigned int ColStart)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Start_Position  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x08;				// OSD Start Position
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Start_Position ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	if(OSD_Type > 3)
+		OSD_Type = 0;
+		
+	// Set data
+	xu_data[0] = OSD_Type;
+	xu_data[1] = (RowStart & 0xFF00) >> 8;	//unit 16 lines
+	xu_data[2] = RowStart & 0x00FF;
+	xu_data[3] = (ColStart & 0xFF00) >> 8;	//unit 16 pixels
+	xu_data[4] = ColStart & 0x00FF;	
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Start_Position ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Start_Position <== Success \n");
+
+	return 0;
+}
+
+int XU_OSD_Get_Start_Position(int fd, unsigned int *LineRowStart, unsigned int *LineColStart, unsigned int *BlockRowStart, unsigned int *BlockColStart)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Start_Position  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x08;				// OSD Start Position
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Start_Position ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Start_Position ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<8; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*LineRowStart = (xu_data[0] << 8) | xu_data[1];
+	*LineColStart = (xu_data[2] << 8) | xu_data[3];
+	*BlockRowStart = (xu_data[4] << 8) | xu_data[5];
+	*BlockColStart = (xu_data[6] << 8) | xu_data[7];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Line Start Row =%d * 16lines\n",*LineRowStart);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Line Start Col =%d * 16pixels\n",*LineColStart);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Block Start Row =%d * 16lines\n",*BlockRowStart);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Block Start Col =%d * 16pixels\n",*BlockColStart);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Start_Position <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_MS_Start_Position(int fd, unsigned char StreamID, unsigned char RowStart, unsigned char ColStart)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_MS_Start_Position  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x09;				// OSD MS Start Position
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_MS_Start_Position ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Set data
+	xu_data[0] = StreamID;
+	xu_data[1] = RowStart & 0x00FF;
+	xu_data[2] = ColStart & 0x00FF;	
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_MS_Start_Position ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_MS_Start_Position  %d %d %d<== Success \n", StreamID, RowStart, ColStart);
+
+	return 0;
+}
+
+int XU_OSD_Get_MS_Start_Position(int fd, unsigned char *S0_Row, unsigned char *S0_Col, unsigned char *S1_Row, unsigned char *S1_Col, unsigned char *S2_Row, unsigned char *S2_Col)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_MS_Start_Position  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x09;				// OSD MS Start Position
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_MS_Start_Position ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_MS_Start_Position ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<6; i++)
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+	*S0_Row = xu_data[0];
+	*S0_Col = xu_data[1];
+	*S1_Row = xu_data[2];
+	*S1_Col = xu_data[3];
+	*S2_Row = xu_data[4];
+	*S2_Col = xu_data[5];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream0 Start Row = %d * 16lines\n",*S0_Row);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream0 Start Col = %d * 16pixels\n",*S0_Col);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream1 Start Row = %d * 16lines\n",*S1_Row);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream1 Start Col = %d * 16pixels\n",*S1_Col);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream2 Start Row = %d * 16lines\n",*S2_Row);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Stream2 Start Col = %d * 16pixels\n",*S2_Col);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_MS_Start_Position <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_String(int fd, unsigned char group, char *String)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_String  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x07;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_String ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = 1;
+	xu_data[1] = group;
+
+	for(i=0; i<8; i++)
+		xu_data[i+2] = String[i];
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_String ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_String <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Get_String(int fd, unsigned char group, char *String)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_String  ==>\n");
+
+	int i = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x07;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_String ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set read mode
+	xu_data[0] = 0;
+	xu_data[1] = group;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_String ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_String ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	group = xu_data[1];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[0] : 0x%x\n", xu_data[0]);
+	TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[1] : 0x%x\n", group);
+	
+	for(i=0; i<8; i++)
+	{
+		String[i] = xu_data[i+2];
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i+2, String[i]);
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD String = %s \n",String);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_String <== Success \n");
+
+	return 0;
+}
+
+int XU_MD_Set_Mode(int fd, unsigned char Enable)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Mode  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x01;				// Motion detection mode
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Enable;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Mode ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Mode <== Success \n");
+
+	return 0;
+}
+
+int XU_MD_Get_Mode(int fd, unsigned char *Enable)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Mode  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x01;				// Motion detection mode
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Mode ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Mode ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	*Enable = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "Motion Detect mode = %d\n",*Enable);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Mode <== Success \n");
+	
+	return 0;
+}
+
+int XU_MD_Set_Threshold(int fd, unsigned int MD_Threshold)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Threshold  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;				// Motion detection threshold
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Threshold ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = (MD_Threshold & 0xFF00) >> 8;
+	xu_data[1] = MD_Threshold & 0x00FF;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Threshold ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Threshold <== Success \n");
+
+	return 0;
+}
+
+int XU_MD_Get_Threshold(int fd, unsigned int *MD_Threshold)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Threshold  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x02;				// Motion detection threshold
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Threshold ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Threshold ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	*MD_Threshold = (xu_data[0] << 8) | xu_data[1];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "Motion Detect threshold = %d\n",*MD_Threshold);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Threshold <== Success \n");
+	
+	return 0;
+}
+
+int XU_MD_Set_Mask(int fd, unsigned char *Mask)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Mask  ==>\n");
+
+	int err = 0;
+	unsigned char i;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// Motion detection mask
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Mask ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	for(i=0; i < 24; i++)
+	{
+		xu_data[i] = Mask[i];
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_Mask ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_Mask <== Success \n");
+
+	return 0;
+}
+
+int XU_MD_Get_Mask(int fd, unsigned char *Mask)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Mask  ==>\n");
+
+	int err = 0;
+	int i,j,k,l;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x03;				// Motion detection mask
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Mask ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)  \n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_Mask ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i) \n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<24; i++)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+		Mask[i] = xu_data[i];
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "               ======   Motion Detect Mask   ======                \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 \n");
+	
+	for(k=0; k<12; k++)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "%2d   ",k+1);
+		for(j=0; j<2; j++)
+		{
+			for(i=0; i<8; i++)
+				TestAp_Printf(TESTAP_DBG_FLOW, "%d   ",(Mask[k*2+j]>>i)&0x01);
+		}
+		TestAp_Printf(TESTAP_DBG_FLOW, "\n");
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_Mask <== Success \n");
+	
+	return 0;
+}
+
+int XU_MD_Set_RESULT(int fd, unsigned char *Result)
+{	
+	//TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_RESULT  ==>\n");
+
+	int err = 0;
+	unsigned char i;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x04;				// Motion detection Result
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_RESULT ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	for(i=0; i < 24; i++)
+	{
+		xu_data[i] = Result[i];
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Set_RESULT ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	//TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Set_RESULT <== Success \n");
+
+	return 0;
+}
+
+int XU_MD_Get_RESULT(int fd, unsigned char *Result)
+{	
+	//TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_RESULT  ==>\n");
+
+	int err = 0;
+	int i,j,k,l;
+	__u8 ctrldata[24]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_MOTION_DETECTION;
+	__u16 xu_size= 24;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x04;				// Motion detection Result
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_RESULT ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)  \n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MD_Get_RESULT ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i) \n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	for(i=0; i<24; i++)
+	{
+		//TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+		Result[i] = xu_data[i];
+	}
+
+	system("clear");
+	TestAp_Printf(TESTAP_DBG_FLOW, "               ------   Motion Detect Result   ------                \n");
+	TestAp_Printf(TESTAP_DBG_FLOW, "     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 \n");
+	
+	for(k=0; k<12; k++)
+	{
+		TestAp_Printf(TESTAP_DBG_FLOW, "%2d   ",k+1);
+		for(j=0; j<2; j++)
+		{
+			for(i=0; i<8; i++)
+				TestAp_Printf(TESTAP_DBG_FLOW, "%d   ",(Result[k*2+j]>>i)&0x01);
+		}
+		TestAp_Printf(TESTAP_DBG_FLOW, "\n");
+	}
+
+	//TestAp_Printf(TESTAP_DBG_FLOW, "XU_MD_Get_RESULT <== Success \n");
+	
+	return 0;
+}
+
+int XU_MJPG_Get_Bitrate(int fd, unsigned int *MJPG_Bitrate)
+{
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MJPG_Get_Bitrate ==>\n");
+	int i = 0;
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+	*MJPG_Bitrate = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_MJPG_CTRL;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_MJPG_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MJPG_Get_Bitrate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	// Get Bit rate ctrl number
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MJPG_Get_Bitrate ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "   == XU_MJPG_Get_Bitrate Success == \n");
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		for(i=0; i<2; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+		BitRate_CtrlNum = ( xu_data[0]<<8 )| (xu_data[1]) ;
+
+		// Bit Rate = BitRate_Ctrl_Num*256*fps*8 /1024(Kbps)
+		*MJPG_Bitrate = (BitRate_CtrlNum*256.0*m_CurrentFPS*8)/1024.0;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		for(i=0; i<4; i++)
+			TestAp_Printf(TESTAP_DBG_FLOW, "      Get data[%d] : 0x%x\n", i, xu_data[i]);
+
+		*MJPG_Bitrate = (xu_data[0] << 24) | (xu_data[1] << 16) | (xu_data[2] << 8) | (xu_data[3]) ;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MJPG_Get_Bitrate (%x)<==\n", *MJPG_Bitrate);
+	return ret;
+}
+
+int XU_MJPG_Set_Bitrate(int fd, unsigned int MJPG_Bitrate)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MJPG_Set_Bitrate (%x) ==>\n",MJPG_Bitrate);
+	int ret = 0;
+	int err = 0;
+	__u8 ctrldata[11]={0};
+	int BitRate_CtrlNum = 0;
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_MJPG_CTRL;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_MJPG_CTRL;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MJPG_Set_Bitrate ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set Bit Rate Ctrl Number
+	if(chip_id == CHIP_SNC291A)
+	{
+		// Bit Rate = BitRate_Ctrl_Num*256*fps*8/1024 (Kbps)
+		BitRate_CtrlNum = ((MJPG_Bitrate*1024)/(256*m_CurrentFPS*8));
+
+		xu_data[0] = (BitRate_CtrlNum & 0xFF00) >> 8;
+		xu_data[1] = (BitRate_CtrlNum & 0x00FF);
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_data[0] = (MJPG_Bitrate & 0xFF000000) >> 24;
+		xu_data[1] = (MJPG_Bitrate & 0x00FF0000) >> 16;
+		xu_data[2] = (MJPG_Bitrate & 0x0000FF00) >> 8;
+		xu_data[3] = (MJPG_Bitrate & 0x000000FF);
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_MJPG_Set_Bitrate ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_MJPG_Set_Bitrate <== Success \n");
+	return ret;
+}
+
+int XU_IMG_Set_Mirror(int fd, unsigned char Mirror)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Mirror  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Mirror ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Mirror;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Mirror ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Mirror  0x%x <== Success \n",Mirror);
+
+	return 0;
+}
+
+int XU_IMG_Get_Mirror(int fd, unsigned char *Mirror)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Mirror  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x01;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Mirror ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Mirror ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Mirror = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "Mirror = %d\n",*Mirror);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Mirror <== Success \n");
+	
+	return 0;
+}
+
+int XU_IMG_Set_Flip(int fd, unsigned char Flip)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Flip  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Flip ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Flip;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Flip ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Flip  0x%x <== Success \n",Flip);
+
+	return 0;
+}
+
+int XU_IMG_Get_Flip(int fd, unsigned char *Flip)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Flip  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x02;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Flip ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Flip ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Flip = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "Flip = %d\n",*Flip);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Flip <== Success \n");
+	
+	return 0;
+}
+
+int XU_IMG_Set_Color(int fd, unsigned char Color)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Color  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Color ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Color;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Set_Color ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Set_Color  0x%x <== Success \n",Color);
+
+	return 0;
+}
+
+int XU_IMG_Get_Color(int fd, unsigned char *Color)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Color  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= 0; 
+	__u8 xu_selector= 0;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	if(chip_id == CHIP_SNC291A)
+	{
+		xu_unit = XU_SONIX_SYS_ID;
+		xu_selector = XU_SONIX_SYS_IMG_SETTING;
+		
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;
+	}
+	else if((chip_id == CHIP_SNC291B)||(chip_id == CHIP_SNC292A))
+	{
+		xu_unit = XU_SONIX_USR_ID;
+		xu_selector = XU_SONIX_USR_IMG_SETTING;
+
+		// Switch command
+		xu_data[0] = 0x9A;				// Tag
+		xu_data[1] = 0x03;
+	}
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Color ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_IMG_Get_Color ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Color = xu_data[0];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "Image Color = %d\n",*Color);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_IMG_Get_Color <== Success \n");
+	
+	return 0;
+}
+
+//--------------------------------------------------------------------------------------
+int XU_OSD_Set_CarcamCtrl(int fd, unsigned char SpeedEn, unsigned char CoordinateEn, unsigned char CoordinateCtrl)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_CarcamCtrl  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0A;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_CarcamCtrl ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = SpeedEn;
+	xu_data[1] = CoordinateEn;
+	xu_data[2] = CoordinateCtrl;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_CarcamCtrl ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_CarcamCtrl  0x%x  0x%x  0x%x <== Success \n", xu_data[0], xu_data[1], xu_data[2]);
+
+	return 0;
+}
+
+int XU_OSD_Get_CarcamCtrl(int fd, unsigned char *SpeedEn, unsigned char *CoordinateEn, unsigned char *CoordinateCtrl)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_CarcamCtrl  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0A;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_CarcamCtrl ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_CarcamCtrl ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*SpeedEn = xu_data[0];
+	*CoordinateEn = xu_data[1];
+	*CoordinateCtrl = xu_data[2];
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD speed en = %d\n",*SpeedEn);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD coordinate en = %d\n",*CoordinateEn);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD coordinate ctrl = %d\n",*CoordinateCtrl);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_CarcamCtrl <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Speed(int fd, unsigned int Speed)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Speed  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0B;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Speed ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = (Speed >> 8) & 0xFF;
+	xu_data[1] = Speed & 0xFF;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Speed ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Speed  0x%x  0x%x  <== Success \n", xu_data[0], xu_data[1]);
+
+	return 0;
+}
+
+int XU_OSD_Get_Speed(int fd, unsigned int *Speed)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Speed  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0B;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Speed ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Speed ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Speed = (xu_data[0]<<8) | (xu_data[1]);
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD speed = %d \n",*Speed);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Speed <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Set_Coordinate1(int fd, unsigned char Direction, unsigned char *Vaule)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Coordinate1  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0C;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Coordinate1 ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Direction;
+	xu_data[1] = Vaule[0];
+	xu_data[2] = Vaule[1];
+	xu_data[3] = Vaule[2];
+	xu_data[4] = 0;
+	xu_data[5] = Vaule[3];
+	xu_data[6] = Vaule[4];
+	xu_data[7] = Vaule[5];
+	xu_data[8] = 0;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Coordinate1 ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Coordinate  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x 0x%x <== Success \n", xu_data[0], xu_data[1],
+	xu_data[2], xu_data[3], xu_data[4], xu_data[5], xu_data[6], xu_data[7], xu_data[8]);
+
+	return 0;
+}
+
+int XU_OSD_Set_Coordinate2(int fd, unsigned char Direction, unsigned char Vaule1, unsigned long Vaule2, unsigned char Vaule3, unsigned long Vaule4)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Coordinate2  ==>\n");
+
+	int err = 0;
+	char i;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0C;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Coordinate2 ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Direction;
+	xu_data[1] = Vaule1;
+	xu_data[2] = (Vaule2 >> 16) & 0xFF;
+	xu_data[3] = (Vaule2 >> 8) & 0xFF;
+	xu_data[4] = Vaule2 & 0xFF;
+	
+	xu_data[5] = Vaule3;
+	xu_data[6] = (Vaule4 >> 16) & 0xFF;
+	xu_data[7] = (Vaule4 >> 8) & 0xFF;
+	xu_data[8] = Vaule4 & 0xFF;	
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Set_Coordinate2 ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Set_Coordinate2  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x <== Success \n", xu_data[0], xu_data[1],
+	xu_data[2], xu_data[3], xu_data[4], xu_data[5], xu_data[6], xu_data[7], xu_data[8]);
+
+	return 0;
+}
+
+int XU_OSD_Get_Coordinate1(int fd, unsigned char *Direction, unsigned char *Vaule)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate1  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0C;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Coordinate1 ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Coordinate1 ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Direction = xu_data[0];
+	Vaule[0] = xu_data[1];
+	Vaule[1] = xu_data[2];
+	Vaule[2] = xu_data[3];
+	Vaule[3] = xu_data[5];
+	Vaule[4] = xu_data[6];
+	Vaule[5] = xu_data[7];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate direction = %d\n",*Direction);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate degree1 = %d\n",Vaule[0] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate minute1 = %d\n",Vaule[1] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate second1 = %d\n",Vaule[2] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate degree2 = %d\n",Vaule[3] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate minute2 = %d\n",Vaule[4] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate second2 = %d\n",Vaule[5] );
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate1 <== Success \n");
+	
+	return 0;
+}
+
+int XU_OSD_Get_Coordinate2(int fd, unsigned char *Direction, unsigned char *Vaule1, unsigned long *Vaule2, unsigned char *Vaule3, unsigned long *Vaule4)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate2  ==>\n");
+
+	int err = 0;
+	char i;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_OSD_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;				// Tag
+	xu_data[1] = 0x0C;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Coordinate2 ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_OSD_Get_Coordinate2 ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Direction = xu_data[0];
+	*Vaule1 = xu_data[1];
+	*Vaule2 =(xu_data[2]<<16) | (xu_data[3]<<8) | (xu_data[4]);
+	*Vaule3 = xu_data[5];
+	*Vaule4 =(xu_data[6]<<16) | (xu_data[7]<<8) | (xu_data[8]);
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate direction = %d\n",*Direction);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate degree1 = %d.%05ld\n",*Vaule1, *Vaule2);
+	TestAp_Printf(TESTAP_DBG_FLOW, "OSD Coordinate degree2 = %d.%05ld\n",*Vaule3, *Vaule4);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate2 <== Success \n");
+	
+	return 0;
+}
+
+
+int XU_GPIO_Ctrl_Set(int fd, unsigned char GPIO_En, unsigned char GPIO_Value)
+{
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_GPIO_Ctrl_Set  ==>\n");
+
+	int err = 0;
+	char i;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_GPIO_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x01;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_GPIO_Ctrl_Set ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = GPIO_En;
+	xu_data[1] = GPIO_Value;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_GPIO_Ctrl_Set ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_GPIO_Ctrl_Set  0x%x  0x%x <== Success \n", xu_data[0], xu_data[1]);
+
+	return 0;
+
+}
+
+
+
+int XU_GPIO_Ctrl_Get(int fd, unsigned char *GPIO_En, unsigned char *GPIO_OutputValue, unsigned char *GPIO_InputValue)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_GPIO_Ctrl_Get  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_GPIO_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x01;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_GPIO_Ctrl_Get ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_GPIO_Ctrl_Get ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*GPIO_En = xu_data[0];
+	*GPIO_OutputValue = xu_data[1];
+    *GPIO_InputValue = xu_data[2];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "GPIO enable = 0x%x\n",*GPIO_En);
+	TestAp_Printf(TESTAP_DBG_FLOW, "GPIO Output value = 0x%x, Input value = 0x%x\n",*GPIO_OutputValue,*GPIO_InputValue);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_GPIO_Ctrl_Get <== Success \n");
+	
+	return 0;
+}
+
+
+
+int XU_Frame_Drop_En_Set(int fd, unsigned char Stream1_En, unsigned char Stream2_En)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_En_Set  ==>\n");
+
+	int err = 0;
+	char i;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_DYNAMIC_FPS_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x01;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_En_Set ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Stream1_En;
+	xu_data[1] = Stream2_En;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_En_Set ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_En_Set  0x%x  0x%x <== Success \n", xu_data[0], xu_data[1]);
+
+	return 0;
+}
+
+int XU_Frame_Drop_En_Get(int fd, unsigned char *Stream1_En, unsigned char *Stream2_En)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_En_Get  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_DYNAMIC_FPS_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x01;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_En_Get ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_En_Get ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Stream1_En = xu_data[0];
+	*Stream2_En = xu_data[1];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "Stream1 frame drop enable = %d\n",*Stream1_En);
+	TestAp_Printf(TESTAP_DBG_FLOW, "Stream2 frame drop enable = %d\n",*Stream2_En);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate1 <== Success \n");
+	
+	return 0;
+}
+
+int XU_Frame_Drop_Ctrl_Set(int fd, unsigned char Stream1_fps, unsigned char Stream2_fps)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_Ctrl_Set  ==>\n");
+
+	int err = 0;
+	char i;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_DYNAMIC_FPS_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x02;
+	
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_Ctrl_Set ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Set data
+	xu_data[0] = Stream1_fps;
+	xu_data[1] = Stream2_fps;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_Ctrl_Set ==> ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_Ctrl_Set  0x%x  0x%x <== Success \n", xu_data[0], xu_data[1]);
+
+	return 0;
+}
+
+int XU_Frame_Drop_Ctrl_Get(int fd, unsigned char *Stream1_fps, unsigned char *Stream2_fps)
+{	
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_Frame_Drop_Ctrl_Get  ==>\n");
+
+	int err = 0;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_USR_ID; 
+	__u8 xu_selector= XU_SONIX_USR_DYNAMIC_FPS_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+	// Switch command
+	xu_data[0] = 0x9A;						// Tag
+	xu_data[1] = 0x02;
+
+	if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_Ctrl_Get ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+
+	// Get data
+	memset(xu_data, 0, xu_size);
+	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0)
+	{
+		TestAp_Printf(TESTAP_DBG_ERR,"XU_Frame_Drop_Ctrl_Get ==> ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+		if(err==EINVAL)
+			TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+		return err;
+	}
+	
+	*Stream1_fps = xu_data[0];
+	*Stream2_fps = xu_data[1];
+	
+	TestAp_Printf(TESTAP_DBG_FLOW, "Stream1 frame  = %d\n",*Stream1_fps);
+	TestAp_Printf(TESTAP_DBG_FLOW, "Stream2 frame  = %d\n",*Stream2_fps);
+	TestAp_Printf(TESTAP_DBG_FLOW, "XU_OSD_Get_Coordinate1 <== Success \n");
+	
+	return 0;
+}
+
+
+int XU_SF_Read(int fd, unsigned int Addr, unsigned char* pData,unsigned int Length)
+{
+    #define DEF_SF_RW_LENGTH 8
+    #define min(a,b) a<b?a:b
+	//TestAp_Printf(TESTAP_DBG_FLOW, "XU_SF_Read  ==>\n");
+
+	int err = 0, i;
+	unsigned int ValidLength = 0, loop = 0, remain = 0;
+    unsigned char* pCopy = pData;
+	__u8 ctrldata[11]={0};
+
+	//uvc_xu_control parmeters
+	__u8 xu_unit= XU_SONIX_SYS_ID; 
+	__u8 xu_selector= XU_SONIX_SYS_FLASH_CTRL;
+	__u16 xu_size= 11;
+	__u8 *xu_data= ctrldata;
+
+
+    if(Addr < 0x10000)
+        ValidLength = min(0x10000 - Addr, Length);
+    else
+        ValidLength = min(0x20000 - Addr, Length);
+    loop = ValidLength/DEF_SF_RW_LENGTH;
+    remain = ValidLength%DEF_SF_RW_LENGTH;
+    //TestAp_Printf(TESTAP_DBG_ERR,"valid = %d, loop = %d, remain = %d\n", ValidLength,loop,remain);
+		
+    //get sf data
+    for(i = 0; i< loop; i++)
+    {
+
+        xu_data[0] = (Addr+i*DEF_SF_RW_LENGTH)&0xff;                     
+        xu_data[1] = ((Addr+i*DEF_SF_RW_LENGTH)>>8)&0xff;
+        if(Addr+i*DEF_SF_RW_LENGTH < 0x10000)
+            xu_data[2] = 0x80 | DEF_SF_RW_LENGTH;
+        else
+            xu_data[2] = 0x90 | DEF_SF_RW_LENGTH;
+
+        //set sf start addr
+        if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+        {
+            TestAp_Printf(TESTAP_DBG_ERR,"XU_SF_Read ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+            if(err==EINVAL)
+                TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+            return err;
+        }
+        memset(xu_data, 0, xu_size*sizeof(__u8));
+      	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    	{
+    		TestAp_Printf(TESTAP_DBG_ERR,"XU_SF_Read ==> Switch cmd : ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+    		if(err==EINVAL)
+    			TestAp_Printf(TESTAP_DBG_ERR,"Read SF error\n");
+    		return err;
+    	}  
+        memcpy(pCopy,xu_data+3,DEF_SF_RW_LENGTH);
+        pCopy += DEF_SF_RW_LENGTH;
+    }
+
+    if(remain)
+    {
+        xu_data[0] = (Addr+loop*DEF_SF_RW_LENGTH)&0xff;                     
+        xu_data[1] = ((Addr+loop*DEF_SF_RW_LENGTH)>>8)&0xff;
+        if(Addr < 0x10000)
+            xu_data[2] = 0x80 | remain;
+        else
+            xu_data[2] = 0x90 | remain;
+        //set addr and length of remain 
+        if ((err=XU_Set_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+        {
+            TestAp_Printf(TESTAP_DBG_ERR,"XU_SF_Read ==> Switch cmd : ioctl(UVCIOC_CTRL_SET) FAILED (%i)\n",err);
+            if(err==EINVAL)
+                TestAp_Printf(TESTAP_DBG_ERR,"Invalid arguments\n");
+            return err;
+        }
+
+        //get data of remain 
+    
+        memset(xu_data, 0, xu_size*sizeof(__u8));
+      	if ((err=XU_Get_Cur(fd, xu_unit, xu_selector, xu_size, xu_data)) < 0) 
+    	{
+    		TestAp_Printf(TESTAP_DBG_ERR,"XU_SF_Read ==> Switch cmd : ioctl(UVCIOC_CTRL_GET) FAILED (%i)\n",err);
+    		if(err==EINVAL)
+    			TestAp_Printf(TESTAP_DBG_ERR,"Read SF error\n");
+    		return err;
+    	} 
+        
+        memcpy(pCopy,xu_data+3,remain);
+
+    }
+    //TestAp_Printf(TESTAP_DBG_FLOW, "XU_SF_Read <== Success \n");
+    return 0;
+
+}
+
+

+ 401 - 0
src/driver/driver_h264_usbimx291/sonix_xu_ctrls.h

@@ -0,0 +1,401 @@
+#ifndef SONIX_XU_CTRLS_H
+#define SONIX_XU_CTRLS_H
+
+#include <linux/videodev2.h>
+#include <linux/version.h>
+
+//#if LINUX_VERSION_CODE > KERNEL_VERSION (3, 0, 36)
+//#include <linux/uvcvideo.h>
+//#endif
+
+#define CARCAM_PROJECT				0
+
+/*
+ * Dynamic controls
+ */
+//copy from uvcvideo.h
+#define UVC_CTRL_DATA_TYPE_RAW		0
+#define UVC_CTRL_DATA_TYPE_SIGNED	1
+#define UVC_CTRL_DATA_TYPE_UNSIGNED	2
+#define UVC_CTRL_DATA_TYPE_BOOLEAN	3
+#define UVC_CTRL_DATA_TYPE_ENUM		4
+#define UVC_CTRL_DATA_TYPE_BITMASK	5
+
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#define V4L2_CID_BASE_EXTCTR_SONIX				0x0A0c4501
+#define V4L2_CID_BASE_SONIX						V4L2_CID_BASE_EXTCTR_SONIX
+#define V4L2_CID_ASIC_RW_SONIX					V4L2_CID_BASE_SONIX+1
+#define V4L2_CID_FLASH_CTRL					    V4L2_CID_BASE_SONIX+2
+#define V4L2_CID_FRAME_INFO_SONIX				V4L2_CID_BASE_SONIX+3
+#define V4L2_CID_H264_CTRL_SONIX				V4L2_CID_BASE_SONIX+4
+#define V4L2_CID_MJPG_CTRL_SONIX				V4L2_CID_BASE_SONIX+5
+#define V4L2_CID_OSD_CTRL_SONIX					V4L2_CID_BASE_SONIX+6
+#define V4L2_CID_MOTION_DETECTION_SONIX			V4L2_CID_BASE_SONIX+7
+#define V4L2_CID_IMG_SETTING_SONIX				V4L2_CID_BASE_SONIX+8
+#define V4L2_CID_MULTI_STREAM_CTRL_SONIX		V4L2_CID_BASE_SONIX+9
+#define V4L2_CID_GPIO_CTRL_SONIX				V4L2_CID_BASE_SONIX+10
+#define V4L2_CID_DYNAMIC_FPS_CTRL_SONIX			V4L2_CID_BASE_SONIX+11
+#define V4L2_CID_LAST_EXTCTR_SONIX				V4L2_CID_DYNAMIC_FPS_CTRL_SONIX
+
+/* ---------------------------------------------------------------------------- */
+
+#define UVC_GUID_SONIX_SYS_HW_CTRL				{0x70, 0x33, 0xf0, 0x28, 0x11, 0x63, 0x2e, 0x4a, 0xba, 0x2c, 0x68, 0x90, 0xeb, 0x33, 0x40, 0x16}	//291A
+#define UVC_GUID_SONIX_USR_HW_CTRL				{0x94, 0x73, 0xDF, 0xDD, 0x3E, 0x97, 0x27, 0x47, 0xBE, 0xD9, 0x04, 0xED, 0x64, 0x26, 0xDC, 0x67}	//292
+//#define UVC_GUID_SONIX_USR_HW_CTRL				{0x3F, 0xAE, 0x12, 0x28, 0xD7, 0xBC, 0x11, 0x4E, 0xA3, 0x57, 0x6F, 0x1E, 0xDE, 0xF7, 0xD6, 0x1D}	//292
+
+#define XU_SONIX_SYS_ID							0x03
+#define XU_SONIX_USR_ID							0x04
+
+// ----------------------------- XU Control Selector ------------------------------------
+#define XU_SONIX_SYS_ASIC_RW	      			0x01
+#define XU_SONIX_SYS_FLASH_CTRL					0x03
+#define XU_SONIX_SYS_FRAME_INFO					0x06
+#define XU_SONIX_SYS_H264_CTRL					0x07
+#define XU_SONIX_SYS_MJPG_CTRL					0x08
+#define XU_SONIX_SYS_OSD_CTRL					0x09
+#define XU_SONIX_SYS_MOTION_DETECTION			0x0A
+#define XU_SONIX_SYS_IMG_SETTING				0x0B
+
+#define XU_SONIX_USR_FRAME_INFO					0x01
+#define XU_SONIX_USR_H264_CTRL					0x02
+#define XU_SONIX_USR_MJPG_CTRL					0x03
+#define XU_SONIX_USR_OSD_CTRL					0x04
+#define XU_SONIX_USR_MOTION_DETECTION			0x05
+#define XU_SONIX_USR_IMG_SETTING				0x06
+#define XU_SONIX_USR_MULTI_STREAM_CTRL			0x07
+#define XU_SONIX_USR_GPIO_CTRL					0x08
+#define XU_SONIX_USR_DYNAMIC_FPS_CTRL			0x09
+
+// ----------------------------- XU Control Selector ------------------------------------
+//copy from uvcvideo.h
+#define UVC_CONTROL_SET_CUR	(1 << 0)
+#define UVC_CONTROL_GET_CUR	(1 << 1)
+#define UVC_CONTROL_GET_MIN	(1 << 2)
+#define UVC_CONTROL_GET_MAX	(1 << 3)
+#define UVC_CONTROL_GET_RES	(1 << 4)
+#define UVC_CONTROL_GET_DEF	(1 << 5)
+/* Control should be saved at suspend and restored at resume. */
+#define UVC_CONTROL_RESTORE	(1 << 6)
+/* Control can be updated by the camera. */
+#define UVC_CONTROL_AUTO_UPDATE	(1 << 7)
+
+#define UVC_CONTROL_GET_RANGE   (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
+                                 UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
+                                 UVC_CONTROL_GET_DEF)
+
+struct uvc_xu_control_info {
+	__u8 entity[16];
+	__u8 index;
+	__u8 selector;
+	__u16 size;
+	__u32 flags;
+};
+
+
+struct uvc_xu_control_mapping_2_6{
+	__u32 id;
+	__u8 name[32];
+	__u8 entity[16];
+	__u8 selector;
+
+	__u8 size;
+	__u8 offset;
+ 
+	enum v4l2_ctrl_type v4l2_type;
+	__u32 data_type;
+   
+};
+
+struct uvc_xu_control_mapping_3 {
+	__u32 id;
+	__u8 name[32];
+	__u8 entity[16];
+	__u8 selector;
+
+	__u8 size;
+	__u8 offset;
+	__u32 v4l2_type;
+	__u32 data_type;
+
+	struct uvc_menu_info *menu_info;
+	__u32 menu_count;
+
+	__u32 reserved[4];
+ 
+};
+
+/*
+#if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 0, 36)
+struct uvc_xu_control_mapping {
+	__u32 id;
+	__u8 name[32];
+	__u8 entity[16];
+	__u8 selector;
+
+	__u8 size;
+	__u8 offset;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,1)
+	__u32 v4l2_type;
+	__u32 data_type;
+
+	struct uvc_menu_info __user *menu_info;
+	__u32 menu_count;
+
+	__u32 reserved[4];
+#else    
+	enum v4l2_ctrl_type v4l2_type;
+	__u32 data_type;
+#endif    
+};
+#endif
+*/
+
+struct uvc_xu_control_query_3 {	
+	__u8 unit;	
+	__u8 selector;	
+	__u8 query;		/* Video Class-Specific Request Code, */				
+					/* defined in linux/usb/video.h A.8.  */	
+	__u16 size;	
+	__u8  *data;
+};
+
+
+struct uvc_xu_control {
+	__u8 unit;
+	__u8 selector;
+	__u16 size;
+	__u8 *data;
+};
+
+struct H264Format
+{
+	unsigned short  wWidth;
+	unsigned short  wHeight;
+	int   		fpsCnt;
+	unsigned int	FrameSize;
+	unsigned int	*FrPay;		// FrameInterval[0|1]Payloadsize[2|3]
+};
+
+struct Cur_H264Format
+{	
+	int FmtId;
+	unsigned short wWidth;
+	unsigned short wHeight;
+	int FrameRateId;
+	unsigned char framerate;
+	unsigned int FrameSize;
+};
+
+struct Multistream_Info
+{
+	unsigned char strm_type;
+	unsigned int format; 
+};
+
+typedef enum{
+	CHIP_NONE = -1,
+	CHIP_SNC291A = 0,
+	CHIP_SNC291B,
+	CHIP_SNC292A
+}CHIP_SNC29X;
+
+//#if LINUX_VERSION_CODE > KERNEL_VERSION (3, 0, 36)
+#define UVC_SET_CUR					0x01
+#define UVC_GET_CUR					0x81
+#define UVCIOC_CTRL_MAP_3_X		_IOWR('u', 0x20, struct uvc_xu_control_mapping_3)
+#define UVCIOC_CTRL_QUERY		_IOWR('u', 0x21, struct uvc_xu_control_query_3)
+
+//#if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 0, 36)
+#define UVCIOC_CTRL_ADD			_IOW('U', 1, struct uvc_xu_control_info)
+#define UVCIOC_CTRL_MAP_2_6		_IOWR('U', 2, struct uvc_xu_control_mapping_2_6)
+#define UVCIOC_CTRL_MAP_3_0		_IOWR('U', 2, struct uvc_xu_control_mapping_3)
+#define UVCIOC_CTRL_GET			_IOWR('U', 3, struct uvc_xu_control)
+#define UVCIOC_CTRL_SET			_IOW('U', 4, struct uvc_xu_control)
+
+
+/*
+#if LINUX_VERSION_CODE > KERNEL_VERSION (3, 0, 36)
+#define UVC_SET_CUR					0x01
+#define UVC_GET_CUR					0x81
+#define UVCIOC_CTRL_MAP		_IOWR('u', 0x20, struct uvc_xu_control_mapping)
+#define UVCIOC_CTRL_QUERY	_IOWR('u', 0x21, struct uvc_xu_control_query)
+#else
+#define UVCIOC_CTRL_ADD		_IOW('U', 1, struct uvc_xu_control_info)
+#define UVCIOC_CTRL_MAP		_IOWR('U', 2, struct uvc_xu_control_mapping)
+#define UVCIOC_CTRL_GET		_IOWR('U', 3, struct uvc_xu_control)
+#define UVCIOC_CTRL_SET		_IOW('U', 4, struct uvc_xu_control)
+#endif
+*/
+
+//ioctl for still image
+//#if LINUX_VERSION_CODE > KERNEL_VERSION (3, 0, 36)
+#define UVCIOC_STILL_S_FMT_KNL3		_IOWR('u', 0x30, struct v4l2_format)
+#define UVCIOC_STILL_REQBUF_KNL3	_IOWR('u', 0x31, struct v4l2_requestbuffers)
+#define UVCIOC_STILL_QUERYBUF_KNL3	_IOWR('u', 0x32, struct v4l2_buffer)
+#define UVCIOC_STILL_GET_FRAME_KNL3	_IOWR('u', 0x33, struct v4l2_buffer)
+
+//#if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 0, 36)
+#define UVCIOC_STILL_S_FMT_KNL2		_IOWR('U', 10, struct v4l2_format)
+#define UVCIOC_STILL_REQBUF_KNL2	_IOWR('U', 11, struct v4l2_requestbuffers)
+#define UVCIOC_STILL_QUERYBUF_KNL2	_IOWR('U', 12, struct v4l2_buffer)
+#define UVCIOC_STILL_GET_FRAME_KNL2	_IOWR('U', 13, struct v4l2_buffer)
+
+
+/*
+//ioctl for still image
+#if LINUX_VERSION_CODE > KERNEL_VERSION (3, 0, 36)
+#define UVCIOC_STILL_S_FMT		_IOWR('u', 0x30, struct v4l2_format)
+#define UVCIOC_STILL_REQBUF		_IOWR('u', 0x31, struct v4l2_requestbuffers)
+#define UVCIOC_STILL_QUERYBUF	_IOWR('u', 0x32, struct v4l2_buffer)
+#define UVCIOC_STILL_GET_FRAME	_IOWR('u', 0x33, struct v4l2_buffer)
+#else
+#define UVCIOC_STILL_S_FMT		_IOWR('U', 10, struct v4l2_format)
+#define UVCIOC_STILL_REQBUF		_IOWR('U', 11, struct v4l2_requestbuffers)
+#define UVCIOC_STILL_QUERYBUF	_IOWR('U', 12, struct v4l2_buffer)
+#define UVCIOC_STILL_GET_FRAME	_IOWR('U', 13, struct v4l2_buffer)
+#endif
+*/
+
+
+extern unsigned int  chip_id;
+
+int XU_Init_Ctrl(int fd);
+int XU_Ctrl_ReadChipID(int fd);
+
+int H264_GetFormat(int fd);
+int H264_CountFormat(unsigned char *Data, int len);
+int H264_ParseFormat(unsigned char *Data, int len, struct H264Format *fmt);
+int H264_GetFPS(unsigned int FrPay);
+
+// H.264 XU +++++
+
+int XU_Set(int fd, struct uvc_xu_control xctrl);
+int XU_Get(int fd, struct uvc_xu_control *xctrl);
+
+int XU_Set_Cur(int fd, __u8 xu_unit, __u8 xu_selector, __u16 xu_size, __u8 *xu_data);
+int XU_Get_Cur(int fd, __u8 xu_unit, __u8 xu_selector, __u16 xu_size, __u8 *xu_data);
+
+int XU_H264_InitFormat(int fd);
+int XU_H264_GetFormatLength(int fd, unsigned short *fwLen);
+int XU_H264_GetFormatData(int fd, unsigned char *fwData, unsigned short fwLen);
+int XU_H264_SetFormat(int fd, struct Cur_H264Format fmt);
+
+int XU_H264_Get_QP_Limit(int fd, int *QP_Min, int *QP_Max);
+int XU_H264_Get_Mode(int fd, int *Mode);
+int XU_H264_Set_Mode(int fd, int Mode);
+
+int XU_H264_Get_QP(int fd, int *QP_Val);
+int XU_H264_Set_QP(int fd, int QP_Val);
+
+int XU_H264_Get_BitRate(int fd, double *BitRate);
+int XU_H264_Set_BitRate(int fd, double BitRate);
+
+int XU_H264_Set_IFRAME(int fd);
+
+int XU_H264_Get_SEI(int fd, unsigned char *SEI);
+int XU_H264_Set_SEI(int fd, unsigned char SEI);
+
+int XU_H264_Get_GOP(int fd, unsigned int *GOP);
+int XU_H264_Set_GOP(int fd, unsigned int GOP);
+
+int XU_Asic_Read(int fd, unsigned int Addr, unsigned char *AsicData);
+int XU_Asic_Write(int fd, unsigned int Addr, unsigned char AsicData);
+
+#if(CARCAM_PROJECT == 0)
+int XU_Multi_Get_status(int fd, struct Multistream_Info *status);
+int XU_Multi_Get_Info(int fd, struct Multistream_Info *Info);
+int XU_Multi_Set_Type(int fd, unsigned int format);
+
+int XU_Multi_Set_Enable(int fd, unsigned char enable);
+int XU_Multi_Get_Enable(int fd, unsigned char *enable);
+
+int XU_Multi_Set_BitRate(int fd, unsigned int StreamID, unsigned int BitRate);
+int XU_Multi_Get_BitRate(int fd, unsigned int StreamID, unsigned int *BitRate);
+int XU_Multi_Set_QP(int fd, unsigned int StreamID, unsigned int QP_Val);
+int XU_Multi_Get_QP(int fd, unsigned int StreamID, unsigned int *QP_val);
+int XU_Multi_Set_H264Mode(int fd, unsigned int StreamID, unsigned int Mode);
+int XU_Multi_Get_H264Mode(int fd, unsigned int StreamID, unsigned int *Mode);
+int XU_Multi_Set_SubStream_FrameRate(int fd, unsigned int sub_fps);
+int XU_Multi_Get_SubStream_FrameRate(int fd, unsigned int *sub_fps);
+int XU_Multi_Set_SubStream_GOP(int fd, unsigned int sub_gop);
+int XU_Multi_Get_SubStream_GOP(int fd, unsigned int *sub_gop);
+#endif
+
+int XU_OSD_Timer_Ctrl(int fd, unsigned char enable);
+int XU_OSD_Set_RTC(int fd, unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second);
+int XU_OSD_Get_RTC(int fd, unsigned int *year, unsigned char *month, unsigned char *day, unsigned char *hour, unsigned char *minute, unsigned char *second);
+
+int XU_OSD_Set_Size(int fd, unsigned char LineSize, unsigned char BlockSize);
+int XU_OSD_Get_Size(int fd, unsigned char *LineSize, unsigned char *BlockSize);
+
+int XU_OSD_Set_Color(int fd, unsigned char FontColor, unsigned char BorderColor);
+int XU_OSD_Get_Color(int fd, unsigned char *FontColor, unsigned char *BorderColor);
+
+int XU_OSD_Set_Enable(int fd, unsigned char Enable_Line, unsigned char Enable_Block);
+int XU_OSD_Get_Enable(int fd, unsigned char *Enable_Line, unsigned char *Enable_Block);
+
+int XU_OSD_Set_AutoScale(int fd, unsigned char Enable_Line, unsigned char Enable_Block);
+int XU_OSD_Get_AutoScale(int fd, unsigned char *Enable_Line, unsigned char *Enable_Block);
+
+int XU_OSD_Set_Start_Position(int fd, unsigned char OSD_Type, unsigned int RowStart, unsigned int ColStart);
+int XU_OSD_Get_Start_Position(int fd, unsigned int *LineRowStart, unsigned int *LineColStart, unsigned int *BlockRowStart, unsigned int *BlockColStart);
+
+#if(CARCAM_PROJECT == 0)
+int XU_OSD_Set_Multi_Size(int fd, unsigned char Stream0, unsigned char Stream1, unsigned char Stream2);
+int XU_OSD_Get_Multi_Size(int fd, unsigned char *Stream0, unsigned char *Stream1, unsigned char *Stream2);
+
+int XU_OSD_Set_MS_Start_Position(int fd, unsigned char StreamID, unsigned char RowStart, unsigned char ColStart);
+int XU_OSD_Get_MS_Start_Position(int fd, unsigned char *S0_Row, unsigned char *S0_Col, unsigned char *S1_Row, unsigned char *S1_Col, unsigned char *S2_Row, unsigned char *S2_Col);
+
+int XU_OSD_Set_String(int fd, unsigned char group, char *String);
+int XU_OSD_Get_String(int fd, unsigned char group, char *String);
+#endif
+
+int XU_MD_Set_Mode(int fd, unsigned char Enable);
+int XU_MD_Get_Mode(int fd, unsigned char *Enable);
+
+int XU_MD_Set_Threshold(int fd, unsigned int MD_Threshold);
+int XU_MD_Get_Threshold(int fd, unsigned int *MD_Threshold);
+
+int XU_MD_Set_Mask(int fd, unsigned char *Mask);
+int XU_MD_Get_Mask(int fd, unsigned char *Mask);
+
+int XU_MD_Set_RESULT(int fd, unsigned char *Result);
+int XU_MD_Get_RESULT(int fd, unsigned char *Result);
+
+int XU_MJPG_Set_Bitrate(int fd, unsigned int MJPG_Bitrate);
+int XU_MJPG_Get_Bitrate(int fd, unsigned int *MJPG_Bitrate);
+
+int XU_IMG_Set_Mirror(int fd, unsigned char Mirror);
+int XU_IMG_Get_Mirror(int fd, unsigned char *Mirror);
+
+int XU_IMG_Set_Flip(int fd, unsigned char Flip);
+int XU_IMG_Get_Flip(int fd, unsigned char *Flip);
+
+int XU_IMG_Set_Color(int fd, unsigned char Color);
+int XU_IMG_Get_Color(int fd, unsigned char *Color);
+// H.264 XU -----
+
+int XU_GPIO_Ctrl_Set(int fd, unsigned char GPIO_En, unsigned char GPIO_Value);
+int XU_GPIO_Ctrl_Get(int fd, unsigned char *GPIO_En, unsigned char *GPIO_OutputValue, unsigned char *GPIO_InputValue);
+
+int XU_Frame_Drop_En_Set(int fd, unsigned char Stream1_En, unsigned char Stream2_En);
+int XU_Frame_Drop_En_Get(int fd, unsigned char *Stream1_En, unsigned char *Stream2_En);
+int XU_Frame_Drop_Ctrl_Set(int fd, unsigned char Stream1_fps, unsigned char Stream2_fps);
+int XU_Frame_Drop_Ctrl_Get(int fd, unsigned char *Stream1_fps, unsigned char *Stream2_fps);
+int XU_SF_Read(int fd, unsigned int Addr, unsigned char* pData,unsigned int Length);
+
+
+#if(CARCAM_PROJECT == 1)
+int XU_OSD_Set_CarcamCtrl(int fd, unsigned char SpeedEn, unsigned char CoordinateEn, unsigned char CoordinateCtrl);
+int XU_OSD_Get_CarcamCtrl(int fd, unsigned char *SpeedEn, unsigned char *CoordinateEn, unsigned char *CoordinateCtrl);
+int XU_OSD_Set_Speed(int fd, unsigned int Speed);
+int XU_OSD_Get_Speed(int fd, unsigned int *Speed);
+int XU_OSD_Set_Coordinate1(int fd, unsigned char Direction, unsigned char *Vaule);
+int XU_OSD_Set_Coordinate2(int fd, unsigned char Direction, unsigned char Vaule1, unsigned long Vaule2, unsigned char Vaule3, unsigned long Vaule4);
+int XU_OSD_Get_Coordinate1(int fd, unsigned char *Direction, unsigned char *Vaule);
+int XU_OSD_Get_Coordinate2(int fd, unsigned char *Direction, unsigned char *Vaule1, unsigned long *Vaule2, unsigned char *Vaule3, unsigned long *Vaule4);
+#endif
+
+#endif