/*@!Encoding:936*/
includes
{
  #include "VH1160.cin"
  #include "CanTP.cin"
  #include "AppToFbl.cin"
  #pragma library("..\Dll\CAPL_FlashFileParse.dll")
  #pragma library("..\Dll\CaplCRC.dll")
}

variables
{  
  dword PhyAddr, RespAddr, FuncAddr;
  
  /*********************Download**************************/
  int RevSize;
  byte RevData[0xFFFFFF];
  dword CrcVal;
  dword LEARNMASK = 0x27AB4C5E;
  
  
  /*******************************************************/
  const int gSeedSize = 4;
  const int gKeySize = 4;
  byte gSeed[4], gKey[gKeySize];
  byte u8AppKeyConst[4] = {0xA7,0x23,0x64,0xAA};
  byte CRC16BUF_APP[2];
  byte CRC16BUF_FBL[2];
  byte CRC16BUF_DRIVER[2];
  byte CRC16BUF_CAL[2];
  byte CRC16BUF_WRONG[2];
  byte CRC16BUF_TEMP[2];
  byte CurrentFlashedBlk = 0xFF;
  const byte FlashDrvBlk = 0x01;
  const byte FlashFBLBlk = 0x02;
  const byte FlashAppBlk = 0x03;
  const byte FlashCodBlk = 0x04;
  /*******************Flash Flags*************************/
  int gDownloadwithDriverFileOnly;
  int gDownloadwithDriverFileError;
  int gDownloadwithAppFileOnly;
  int gDownloadwithAppFileError;
  int gDownloadwithFblFileOnly;
  int gDownloadwithFblFileError;
  int gSkipCheckProgrammingPrecondition;
  int gSkipProgrammingSession;
  int gSkipExtendedSession;
  int gSkipDefaultSession;
  int gSkipSecurityAccess;
  int gSecurityAccessFail;
  int gSkipFingerPrint;
  int gSkipEraseMemory;
  int gSkipRequestDownload;
  int gSkipTransmitData;
  int gSkipCheckProgrammingDependencies;
  int gSkipCheckProgrammingIntegrity;
  int gSkipDlCalFile;
  int gCheckProgrammingIntegrity_CrcError;
  int gPoweroffDuringEraseMemory;
  int gPoweroffDuringFlashProgressPercent;
  int gSkipCheckMemoryRoutine;
  int gUpgradeFromFBL;
  int gSkipDTCSettingOff;
  int gSkipDisableNonDiagnosticsCommunication;
  int gAppliacationInvalidFlashTest;
  int gTransferLessThanMaxNumber;
  int gAppFileInValid;
  int gFblFileInValid;
  int gCalFileInValid;
  int gReadFingerPrintAfterFlash;
  int gComInterruptBeforeErase;
  int gComInterruptDuringTransfer;
  int gSkipDownloadFlashDriver;
  int gTransferPartialData;
  int gSkipPartialDataDuring36;
  int gCheckMemoryError;
  int gSkipBlockNumber2;
  int gBlockLengthTest;
  int gDriverAddressInvalid;
  int gDriverLengthInvalid;
  int gEraseAddressInvalid;
  int gFlashAddressInvalid;
  int gFlashLengthInvalid;
  int gEraseLengthInvalid;
  int gRepeatTransferData;
  int gLostTransferData;
  int gRightLight;
}

void InitFlags()
{
  if(PhyAddr == 0x774)
  {
    gRightLight = 1;
    u8AppKeyConst[0] = 0xC5;
    u8AppKeyConst[1] = 0x4D;
    u8AppKeyConst[2] = 0x87;
    u8AppKeyConst[3] = 0x73;
  }
  else
  {
    gRightLight = 0;
  }
  InitDiagConfig();
    
  gDownloadwithDriverFileOnly = 0;
  gDownloadwithDriverFileError = 0;
  gDownloadwithAppFileOnly = 0;
  gDownloadwithAppFileError = 0;
  gDownloadwithFblFileOnly = 0;
  gDownloadwithFblFileError = 0;
  gSkipCheckProgrammingPrecondition = 0;
  gSkipProgrammingSession = 0;
  gSkipExtendedSession = 0;
  gSkipDefaultSession = 0;
  gSkipSecurityAccess = 0;
  gSecurityAccessFail = 0;
  gSkipFingerPrint = 0;
  gSkipEraseMemory = 0;
  gSkipRequestDownload = 0;
  gSkipTransmitData = 0;
  gSkipCheckProgrammingDependencies = 0;
  gSkipCheckProgrammingIntegrity = 0;
  gCheckProgrammingIntegrity_CrcError = 0;
  gPoweroffDuringEraseMemory = 0;
  gPoweroffDuringFlashProgressPercent = 100;
  gSkipCheckMemoryRoutine = 0;
  gUpgradeFromFBL = 0;
  gSkipDTCSettingOff = 0;
  gSkipDisableNonDiagnosticsCommunication = 0;
  gAppliacationInvalidFlashTest = 0;
  gTransferLessThanMaxNumber = 0;
  gAppFileInValid = 1;
  gFblFileInValid = 1;
  gCalFileInValid = 1;
  gReadFingerPrintAfterFlash = 0;
  gComInterruptBeforeErase = 0;
  gComInterruptDuringTransfer = 0;
  gSkipDownloadFlashDriver = 0;
  gTransferPartialData = 0;
  gSkipPartialDataDuring36 = 0;
  gCheckMemoryError = 0;
  gSkipBlockNumber2 = 0;
  gBlockLengthTest = 0;
  gDriverAddressInvalid = 0;
  gDriverLengthInvalid = 0;
  gEraseAddressInvalid = 0;
  gFlashAddressInvalid = 0;
  gFlashLengthInvalid = 0;
  gEraseLengthInvalid = 0;
  gRepeatTransferData = 0;
  gLostTransferData = 0;
  gSkipDlCalFile = 0;
}

/// <Program>
int PreProgramming()
{
  int result;
  
  //如果当前处于APP
  if(gUpgradeFromFBL == 0)
  {
    //发送NM报文，唤醒APP
    CanSendNM();
    testWaitForTimeout(500);
    CanSendNM();
  }
  
  if(gSkipExtendedSession == 0){
    result = SessionControl(0x03, PhyAddr);
    if(result == 1)
    {
      testStepPass("", "成功进入扩展会话模式");
    }
    else
    {
      testStepFail("", "进入扩展会话模式失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过进入扩展会话模式");
  }
  
  result = SessionControl(0x83, FuncAddr);
  if(result == 1)
  {
     testStepPass("", "功能寻址进入扩展会话模式成功");
  }
  else
  {
     testStepFail("", "功能寻址进入扩展会话模式失败");
     return -1;
  }
  
  result = ReadService_22(0xF1,0x8A,PhyAddr);
  if(result == 1)
  {
    testStepPass("", "成功读取F18A");
  }
  else
  {
     testStepFail("", "读取F18A失败");
     return -1;
  }
  result = ReadService_22(0xF0,0x89,PhyAddr);
  if(result == 1)
  {
    testStepPass("", "成功读取F089");
  }
  else
  {
     testStepFail("", "读取F089失败");
     return -1;
  }
  result = ReadService_22(0xF1,0x89,PhyAddr);
  if(result == 1)
  {
    testStepPass("", "成功读取F189");
  }
  else
  {
     testStepFail("", "读取F189失败");
     return -1;
  }
  
  if(gSkipCheckProgrammingPrecondition == 0){
    result = checkProgrammingPreconditions();
    if(result == 1)
    {
      testStepPass("", "执行检查编程预条件成功");
    }
    else{
      testStepFail("", "执行检查编程预条件失败");
      return -1;
    }
  }
  else{
    testStepPass("", "跳过执行检查编程预条件");
  }
    
  if(gSkipDTCSettingOff == 0){
    result = DTCSetting(0x82);
    if(result == 1)
    {
      testStepPass("", "关闭DTC成功");
    }
    else{
      testStepFail("", "关闭DTC失败");
      return -1;
    }
  }
  else{
    testStepPass("", "跳过关闭DTC");
  }
    
  if(gSkipDisableNonDiagnosticsCommunication == 0){
    result = CommunicationControl(0x83,0x03);
    if(result == 1)
    {
      testStepPass("", "关闭非诊断通信成功");
    }
    else{
      testStepFail("", "关闭非诊断通信失败");
      return -1;
    }
  }
  else{
    testStepPass("", "跳过关闭非诊断通信");
  }
  
  return result;
}

/// <Program>
int ProgramPrepare()
{
  int result,i;
  InitDownLoadProgress();             /* init dl progress bar      */    
  result = InputFileValidJudge();     /* check input file validity */
  
  for(i = 0;i < 2; i++)
  {
    CRC16BUF_WRONG[i] = 0;
  }
  return result;
}

/// <Program>
int APPJumpToFBL()
{
  int result;
  byte flag;
    ///from FBL to APP
  if(gUpgradeFromFBL == 0)
  {
    //发送NM报文，唤醒APP
    CanSendNM();
    testWaitForTimeout(500);
    CanSendNM();
    ///APP进入扩展会话
    result = SessionControl(0x03, PhyAddr);
    if(result == 1)
    {
      testStepPass("", "APP进入扩展会话模式成功");
    }
    else
    {
      testStepFail("", "APP进入扩展会话模式失败");
      return -1;
    }
    
    if(gSkipCheckProgrammingPrecondition == 0){
      result = checkProgrammingPreconditions();
      if(result == 1)
      {
        testStepPass("", "执行检查编程预条件成功");
      }
      else{
        testStepFail("", "执行检查编程预条件失败");
        return -1;
      }
    }
    else{
      testStepPass("", "跳过执行检查编程预条件");
    }
    
    ///APP进入编程会话(进入编程会话后重启回到FBL)
    result = SessionControl(0x02, PhyAddr);
    if(result == 1)
    {
      testStepPass("", "APP进入编程会话模式成功");
    }
    else
    {
      testStepPass("", "APP进入编程会话，reset APP");
      //return -1;
    }
    
    ///延时2s等待进入FBL
    testWaitForTimeout(3000);
    return 1;
  }
  else
  {
    testStepPass("", "Upgrade start from FBL");
    return 1;
  }
  
}

/// <Program>
int Programming()
{
  int result;
  
  if(gSkipProgrammingSession == 0)
  {
    result = SessionControl(0x02, PhyAddr);
    if(result == 1)
    {
      testStepPass("", "进入编程会话模式成功");
    }
    else
    {
      testStepFail("", "进入编程会话超时");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过进入编程会话模式");
  }

  //Delay 500ms
  testWaitForTimeout(500);
  
  if(gSkipSecurityAccess == 0)
  {
    result = SecurityAccess(4);
    if(result == 1)
    {
      testStepPass("", "安全访问成功");
    }
    else
    {
      testStepFail("", "安全访问失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过执行安全访问");
  }
  
  result = ReadService_22(0xF1,0x70,PhyAddr);
  if(result == 1)
  {
    testStepPass("", "成功读取F170");
  }
  else
  {
     testStepFail("", "读取F170失败");
     return -1;
  }
  result = ReadService_22(0xF1,0x71,PhyAddr);
  if(result == 1)
  {
    testStepPass("", "成功读取F171");
  }
  else
  {
     testStepFail("", "读取F171失败");
     return -1;
  }
  
  if(gSkipFingerPrint == 0)
  {
    result = writeFingerPrint();
    if(result == 1)
    {
      testStepPass("", "写入指纹信息成功");
    }
    else
    {
      testStepFail("", "写入指纹信息失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过执行写入指纹信息");
  }
  
  if(gDownloadwithDriverFileOnly == 0)
  {
    result = DownloadDriverFile();
    if(result == 1)
    {
      testStepPass("", "下载Driver文件成功");
    }
    else
    {
      testStepFail("", "下载Driver文件失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过下载Driver文件");
  }
  
  /* dl app file */
  if(gAppFileInValid == 0)
  {
    if(gDownloadwithFblFileOnly == 0)
    {
      result = DownloadAppFile();
      if(result == 1)
      {
        testStepPass("", "下载App文件成功");
      }
      else
      {
        testStepFail("", "下载App文件失败");
        if((gCheckMemoryError == 0) && (gLostTransferData == 0))
        {
          return -1;
        }   
      }
    }
    else
    {
      testStepPass("", "跳过下载App文件");
    }
  }
  else
  {
    /* app file path is invalid,skip dl app */
    testStepPass("", "不下载App文件");
  }

  /* dl cal file */
  if(gCalFileInValid == 0)
  {
    if(gSkipDlCalFile == 0)
    {
      result = DownloadCalFile();
      if(result == 1)
      {
        testStepPass("", "下载Calibration文件成功");
      }
      else
      {
        testStepFail("", "下载Calibration文件失败");
        if((gCheckMemoryError == 0) && (gLostTransferData == 0))
        {
          return -1;
        } 
      }
    }
    else
    {
      testStepPass("", "跳过下载Calibration文件");
    }
  }
  else
  {
    /* cal file path is invalid,skip dl fbl */
    testStepPass("", "不下载Calibration文件");
  }
  
  /* dl fbl file */
  if(gFblFileInValid == 0)
  {
    if(gDownloadwithAppFileOnly == 0)
    {
      result = DownloadFblFile();
      if(result == 1)
      {
        testStepPass("", "下载Fbl文件成功");
      }
      else
      {
        testStepFail("", "下载Fbl文件失败");
        if((gCheckMemoryError == 0) && (gLostTransferData == 0))
        {
          return -1;
        } 
      }
    }
    else
    {
      testStepPass("", "跳过下载Fbl文件");
    }
  }
  else
  {
    /* fbl file path is invalid,skip dl fbl */
    testStepPass("", "不下载Fbl文件");
  }
  
  if(gSkipCheckProgrammingDependencies == 0)
  {
    result = checkProgrammingDependencies();
    if(result == 1)
    {
      testStepPass("", "检查编程依赖性满足条件");
    }
    else
    {
      testStepFail("", "检查编程依赖性不满足条件");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过检查编程依赖性");
  }
  
  result = Reset(0x03);
  if(result == 1)
  {
    testStepPass("", "重启ECU成功");
  }
  else
  {
    testStepFail("", "重启ECU失败");
    return -1;
  }
  
  //Delay 1s
  testWaitForTimeout(1000);
  
  return result;
}

/// <Program>
int PostProgramming()
{
  int result;
  
  //重启后跳往APP
  //发送NM报文，唤醒APP
  CanSendNM();
  testWaitForTimeout(500);
  CanSendNM();
  
  if(gSkipExtendedSession == 0){
    result = SessionControl(0x03, PhyAddr);
    if(result == 1)
    {
      testStepPass("", "成功进入扩展会话模式");
    }
    else
    {
      testStepFail("", "进入扩展会话模式失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过进入扩展会话模式");
  }    

  if(gSkipDisableNonDiagnosticsCommunication == 0){
    result = CommunicationControl(0x80,0x03);
    if(result == 1)
    {
      testStepPass("", "开启非诊断通信成功");
    }
    else{
      testStepFail("", "开启非诊断通信失败");
      return -1;
    }
  }
  else{
    testStepPass("", "跳过开启非诊断通信");
  }  
  
  if(gSkipDTCSettingOff == 0){
    result = DTCSetting(0x81);
    if(result == 1)
    {
      testStepPass("", "开启DTC成功");
    }
    else{
      testStepFail("", "开启DTC失败");
      return -1;
    }
  }
  else{
    testStepPass("", "跳过开启DTC");
  }
  
  if(gSkipDefaultSession == 0){
    result = SessionControl(0x81, FuncAddr);
    if(result == 1)
    {
      testStepPass("", "成功进入默认会话模式");
    }
    else
    {
      testStepFail("", "进入默认会话模式失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过进入默认会话模式");
  }
  
  return result;
}

/// <DiagService>
int CanReqSend(byte req[], dword len, dword Addr)
{
  int result;
  if(Addr == PhyAddr)
  {
    CanTP_Send(req, len, physical);
    result = ECU_Response(P2Client);
  }
  else
  {
    CanTP_Send(req, len, functional);
    result = 0x01;
  }
  
  return result;
}

/// <DiagService/CommunicationControl>
int CommunicationControl(byte ControlType, byte CommuType)
{
  int result;
  byte req[3];
  req[0] = 0x28;
  req[1] = ControlType;
  req[2] = CommuType;
  if((ControlType&0x80) != 0)
  {
    result = CanReqSend(req, elcount(req), FuncAddr);
  }
  else
  {
    result = CanReqSend(req, elcount(req), PhyAddr);
  }
  return result;
}

/// <DiagService/DTCSetting>
int DTCSetting(byte DTCSettingType)
{
  int result;
  byte req[2];
  req[0] = 0x85;
  req[1] = DTCSettingType;
  
  if((DTCSettingType&0x80) != 0)
  {
    result = CanReqSend(req, elCount(req),FuncAddr);
  }
  else
  {
    result = CanReqSend(req, elCount(req),PhyAddr);
  }
  return result;
}

/// <DiagService/SessionControl_10>
int SessionControl(byte Session, dword Addr)
{
  int result;
  byte req[2];
  req[0] = 0x10;
  req[1] = Session;
  result = CanReqSend(req, elcount(req), Addr);
  
  return result;
}

int ReadService_22(byte DidMSB, byte DidLSB,dword Addr)
{
  int result;
  byte req[3];
  req[0] = 0x22;
  req[1] = DidMSB;
  req[2] = DidLSB;
  result = CanReqSend(req, elcount(req), Addr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int checkProgrammingPreconditions()
{
  int result;
  byte ridCheckProgrammingPreconditions[2] = {0x02, 0x03};
  result = routineControl(0x01, ridCheckProgrammingPreconditions, PhyAddr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int checkProgrammingIntegrity(byte file_type)
{
  int result;
  byte ridCheckProgrammingIntegrity[2] = {0x02, 0x02};
  
  /* 0 -> check Flash Driver CRC16 */
  /* 1 -> check APP CRC16          */
  /* 2 -> check FBL CRC16          */
  switch(file_type)
  {
    case 0:
      result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_DRIVER, PhyAddr);
      break;
    case 1:
      if(gCheckMemoryError == 1)
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_WRONG, PhyAddr);
      }
      else
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_APP, PhyAddr);
      }
      break;
    case 2:
      if(gCheckMemoryError == 1)
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_WRONG, PhyAddr);
      }
      else
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_FBL, PhyAddr);
      }
      break;
    case 3:
      if(gCheckMemoryError == 1)
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_WRONG, PhyAddr);
      }
      else
      {
        result = routineControl(0x01, ridCheckProgrammingIntegrity, CRC16BUF_CAL, PhyAddr);
      }
      break;
    default :
      result = -1; /* invalid type*/
      break;
  }
  
  return result;
}

/// <DiagService/RoutineControl_31>
int checkProgrammingDependencies()
{
  int result;
  byte ridCheckProgrammingDependencies[2] = {0xFF, 0x01};
  result = routineControl(0x01, ridCheckProgrammingDependencies, PhyAddr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int EraseMemory(dword Address, dword Size)
{
  int result;
  byte ridEraseMemory[2] = {0xFF, 0x00};
  byte ridOption[8];
  
  ridOption[0] = (Address >> 24) & 0xFF;
  writeDbgLevel(5, "appStartAddress[%d] : 0x%X", 0, ridOption[0]);
  ridOption[1] = (Address >> 16) & 0xFF;
  writeDbgLevel(5, "appStartAddress[%d] : 0x%X", 1, ridOption[1]);
  ridOption[2] = (Address >> 8) & 0xFF;
  writeDbgLevel(5, "appStartAddress[%d] : 0x%X", 2, ridOption[2]);
  ridOption[3] = (Address) & 0xFF;
  writeDbgLevel(5, "appStartAddress[%d] : 0x%X", 3, ridOption[3]);
  ridOption[4] = (Size >> 24) & 0xFF;
  writeDbgLevel(5, "appSize[%d] : 0x%X", 0, ridOption[4]);
  ridOption[5] = (Size >> 16) & 0xFF;
  writeDbgLevel(5, "appSize[%d] : 0x%X", 1, ridOption[5]);
  ridOption[6] = (Size >> 8) & 0xFF;
  writeDbgLevel(5, "appSize[%d] : 0x%X", 2, ridOption[6]);
  ridOption[7] = (Size) & 0xFF;
  writeDbgLevel(5, "appSize[%d] : 0x%X", 3, ridOption[7]);
  
  result = routineControl(0x01, ridEraseMemory, ridOption, PhyAddr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int routineControl(byte routineControlType, byte rid[], dword Addr)
{
  int result;
  byte req[4];
  req[0] = 0x31;
  req[1] = routineControlType;
  req[2] = rid[0];
  req[3] = rid[1];
  result = CanReqSend(req, elCount(req), Addr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int checkMemoryRoutine()
{
  int result;
  byte routineControlType = 0x01;
  byte checkMemoryRoutine[2] = {0x02,0x02};

  result = routineControl(routineControlType, checkMemoryRoutine, CRC16BUF_APP,PhyAddr);
  
  return result;
}

/// <DiagService/RoutineControl_31>
int routineControl(byte routineControlType, byte rid[], byte ridOption[], dword Addr)
{
  int i, result;
  byte req[1024];
  req[0] = 0x31;
  req[1] = routineControlType;
  req[2] = rid[0];
  req[3] = rid[1];
  
  for(i = 0; i < elCount(ridOption); i++)
  {
    req[4+i] = ridOption[i];
  }
  
  result = CanReqSend(req, 4+elcount(ridOption), Addr);
  
  return result;
}

/// <DiagService/SecurityAccess_27>
int SecurityAccess(byte SecurityAccessLevel)
{
  int result;
  result = RequestSeed(SecurityAccessLevel);
  if(result == 1)
  {
    testStepPass("", "成功请求种子");
  }
  else
  {
    testStepFail("", "失败请求种子");
    return -1;
  }
  
  result = SendKey(SecurityAccessLevel);
  if(result == 1)
  {
    testStepPass("", "成功发送密钥");
  }
  else
  {
    testStepFail("", "发送密钥失败");
    return -1;
  }
  
  return result;
}

dword ReverseBit32(dword u32ReverseInput)
{
    u32ReverseInput = (((u32ReverseInput & 0xAAAAAAAA) >> 1) | ((u32ReverseInput & 0x55555555) << 1));
    u32ReverseInput = (((u32ReverseInput & 0xCCCCCCCC) >> 2) | ((u32ReverseInput & 0x33333333) << 2));
    u32ReverseInput = (((u32ReverseInput & 0xF0F0F0F0) >> 4) | ((u32ReverseInput & 0x0F0F0F0F) << 4));
    u32ReverseInput = (((u32ReverseInput & 0xFF00FF00) >> 8) | ((u32ReverseInput & 0x00FF00FF) << 8));

   return((u32ReverseInput >> 16) | (u32ReverseInput << 16));

}

void ASAP1A_CCP_ComputeKeyFromSeed(byte seed[])
{
   byte key1[4];
   byte key2[4];
   byte Seed2[4];
   dword u32Seed1 = 0x0;
   dword u32Seed2 = 0x0;
   dword u32Key1 = 0x0;
   dword u32Key2 = 0x0;
   dword u32Key = 0x0;
   qword u64KeyAdd = 0x0;
  /*Step2: Perform Bitwise Ex-OR operation of seed with a constant, AppKeyConst[4], to obtain Key1 [4].*/
   key1[0] = seed[0] ^ u8AppKeyConst[0];
   key1[1] = seed[1] ^ u8AppKeyConst[1];
   key1[2] = seed[2] ^ u8AppKeyConst[2];
   key1[3] = seed[3] ^ u8AppKeyConst[3];
  /*Step3: Rotate the seed [4] by 16 bits to obtain Seed2 [4] as the Diagram 1.*/
   u32Seed1 |= ((dword)seed[0]) << 24;
   u32Seed1 |= ((dword)seed[1]) << 16;
   u32Seed1 |= ((dword)seed[2]) << 8;
   u32Seed1 |= ((dword)seed[3]) << 0;
   u32Seed2 = ReverseBit32(u32Seed1);
   Seed2[0] = (byte)((u32Seed2>>24)&0xFF);
   Seed2[1] = (byte)((u32Seed2>>16)&0xFF);
   Seed2[2] = (byte)((u32Seed2>>8)&0xFF);
   Seed2[3] = (byte)((u32Seed2>>0)&0xFF);
  /*Step4: Perform Bitwise Ex-OR operation of seed2 with the same constant,AppKeyConst [4], to obtain Key2 [4]*/
   key2[0] = Seed2[0] ^ u8AppKeyConst[0];
   key2[1] = Seed2[1] ^ u8AppKeyConst[1];
   key2[2] = Seed2[2] ^ u8AppKeyConst[2];
   key2[3] = Seed2[3] ^ u8AppKeyConst[3];
  /*Step5: 5) Add Key1 and Key2 and discard the final carry bit if any to obtain the key (Key [4])*/
   u32Key1 |= ((dword)key1[0]) << 24;
   u32Key1 |= ((dword)key1[1]) << 16;
   u32Key1 |= ((dword)key1[2]) << 8;
   u32Key1 |= ((dword)key1[3]) << 0;

   u32Key2 |= ((dword)key2[0]) << 24;
   u32Key2 |= ((dword)key2[1]) << 16;
   u32Key2 |= ((dword)key2[2]) << 8;
   u32Key2 |= ((dword)key2[3]) << 0;
  
   u64KeyAdd = u32Key1 + u32Key2;
   u32Key = (dword)(u64KeyAdd & 0xFFFFFFFF);

   gKey[0] = (byte)((u32Key>>24)&0xFF);
   gKey[1] = (byte)((u32Key>>16)&0xFF);
   gKey[2] = (byte)((u32Key>>8)&0xFF);
   gKey[3] = (byte)((u32Key>>0)&0xFF);
}

void InitDownLoadProgress()
{
  /*清空下载进度 */
  sysSetVariableFloat("FBLFlash", "DriverDownloadProgress", 0);
  sysSetVariableFloat("FBLFlash", "AppDownloadProgress", 0);
  sysSetVariableFloat("FBLFlash", "FblDownloadProgress", 0);
  sysSetVariableFloat("FBLFlash", "CalDownloadProgress", 0);
}

/// <DiagService/SecurityAccess_27>
int RequestSeed(byte SecurityAccessLevel)
{
  int i, result;
  byte req[2];
  req[0] = 0x27;
  if(SecurityAccessLevel == 2)
  {
    req[1] = 3;
  }
  else if(SecurityAccessLevel == 4)
  {
    req[1] = 1;
  }
  else if(SecurityAccessLevel == 6)
  {
    req[1] = 0x61;
  }
  else
  {
    writeDbgLevel(5, "Request security level don't exit!");
    return -1;
  }  
  result = CanReqSend(req, elcount(req), PhyAddr);
  
  if(result == 1)
  {
    for(i = 0; i < gSeedSize; i++){
      gSeed[i] = RevData[i+2];
    }
  }
  
  return result;
}

/// <DiagService/SecurityAccess_27>
int SendKey(byte SecurityAccessLevel)
{
  int i, result;
  byte req[6];
  
  char gVariant[10] = "Variant";
  char gIpOption[10] = "IpOption";
  dword gKeyActualSizeout = 0;
  long Kresult;
  
  req[0] = 0x27;
  if(SecurityAccessLevel == 2)
  {
    req[1] = 4;    
  }
  else if(SecurityAccessLevel == 4)
  {
    req[1] = 2;
  }
  else if(SecurityAccessLevel == 6)
  {
    req[1] = 0x62;
  }
  else
  {
    writeDbgLevel(5, "Request security level don't exit!");
    return -1;
  }
  ASAP1A_CCP_ComputeKeyFromSeed(gSeed);
  
  if(gSecurityAccessFail == 0){
    for(i = 0; i < gKeySize; i++)
    {
      req[i+2] = gKey[i];
    }
  }
  else
  {
    for(i = 0; i < gKeySize; i++)
    {
      if((gKey[i] & 0x01) == 0x01)
      {
        req[i+2] = gKey[i] & 0xFE;
      }
      else
      {
        req[i+2] = gKey[i] | 0x01;
      }
    }
  }
  
  result = CanReqSend(req, elcount(req), PhyAddr);
  
  return result;
}

/// <DiagService/DownloadFile>
int InputFileValidJudge()
{
  int result;
  byte driver_code,app_code,fbl_code,cal_code;
  char FilePath_drivercode[1024],FilePath_appcode[1024],
       FilePath_fblcode[1024],FilePath_calcode[1024];
  
  result = 0;
  /* get codeflash status */
  sysGetVariableString(sysvar::FBLFlash::DriverFile, FilePath_drivercode, elCount(FilePath_drivercode));
  driver_code = strlen(FilePath_drivercode);
  sysGetVariableString(sysvar::FBLFlash::AppFile, FilePath_appcode, elCount(FilePath_appcode));
  app_code = strlen(FilePath_appcode);
  sysGetVariableString(sysvar::FBLFlash::FblFile, FilePath_fblcode, elCount(FilePath_fblcode));
  fbl_code = strlen(FilePath_fblcode);
  sysGetVariableString(sysvar::FBLFlash::CalFile, FilePath_calcode, elCount(FilePath_calcode));
  cal_code = strlen(FilePath_calcode);
  
  if((driver_code == 0) && (app_code == 0) && (fbl_code == 0))
  {
    testStepFail("刷写文件为空！");
    result = -1;
  }
  else
  {
    if(driver_code != 0)
    {
      if(app_code != 0)
      {
        gAppFileInValid = 0;
        result++;    
      }
      else
      {
        write("APP刷写文件为空！");
      }
      
      if(cal_code != 0)
      {
        gCalFileInValid = 0;
        result = result + 1;   
      }
      else
      {
        write("Calibration刷写文件为空！");
      }
      
      if(fbl_code != 0)
      {
        gFblFileInValid = 0;
        result = result + 1;    
      }
      else
      {
        write("FBL刷写文件为空！");
      }
      
      if(result == 0)
      {
         testStepFail("APP,Calibration和FBL文件不能同时为空！");
         result = -1;
      }
      else
      {
        result = 1;
      }
    }
    else
    {
      testStepFail("驱动刷写文件为空！");
      result = -1;
    }
  }
  
  /*-1 invalid,1 valid*/
  return result;
}

/// <DiagService/DownloadFile>
int DownloadDriverFile()
{
  char DriverDownloadProgressNameSpace[100] = "FBLFlash";
  char DriverDownloadProgressVar[100] = "DriverDownloadProgress";
  
  int i, result;
  char driverFilePath[1024];
  dword driverStartAddress, driverSize;
  long blockNum, allBytesNum;
 
  testStep("", "开始下载驱动文件");
  CurrentFlashedBlk = FlashDrvBlk;
  sysGetVariableString(sysvar::FBLFlash::DriverFile, driverFilePath, elcount(driverFilePath));
  writeDbgLevel(5, "Driver File: %s", driverFilePath);
  blockNum = CAPL_ParseFlashFile(driverFilePath);
  writeDbgLevel(5, "block Num: %s", blockNum);
  allBytesNum = CAPL_GetAllByteNumber();
  writeDbgLevel(5, "Byte Num: 0x%X", allBytesNum);
  
  for(i = 0; i < blockNum; i++)
  {
    driverStartAddress = CAPL_GetBlockStartAddress(i);
    writeDbgLevel(5, "block %d start Address: 0x%X", i, driverStartAddress);
    driverSize = CAPL_GetBlockByteNumber(i);
    writeDbgLevel(5, "block % byte Num: 0x%X", i, driverSize);

    /*driver 地址无效*/
    if(gDriverAddressInvalid == 1)
    {
      driverStartAddress = driverStartAddress + 1;
    }
    
    /*driver 大小无效*/
    if(gDriverLengthInvalid)
    {
      driverSize = driverSize + 1;
    }
    if(gSkipDownloadFlashDriver == 0){
      result = DownloadFile(driverFilePath, driverStartAddress, driverSize, allBytesNum, 
      DriverDownloadProgressNameSpace, DriverDownloadProgressVar);
      
      if(result != 1)
      {
        return -2;
      }
    }
  }
  
  if(gSkipCheckProgrammingIntegrity == 0)
  {
    result = checkProgrammingIntegrity(0);
  }
  
  return result;
}

byte asciiTobyte(byte data)
{
  byte val = 0;
  if( data >= '0' && data <= '9')
  {
    val = data - 0x30;
  }
  else if( data >= 'A' && data <= 'F')
  {
    val = data - 0x37;
  }
  else if(data >= 'a' && data <= 'f')
  {
    val = data - 0x57;
  }
  
  return val;
}

/// <DiagService/DownloadFile>
int DownloadFile(char FilePath[], dword StartAddress, dword Size, long AllBytes, char DownloadProgressNameSpacce[], 
  char DownloadProgressVar[])
{
  int i, dataIndex, result, bufferIndex;
  byte buffer[0xFFFFFF], errorBuffer[0xFFFFFF], rowbuffer[80], databuffer[32];
  dword fileHandle;
  long binindex, rownum = 0;
  long rowflag = 0;
  long rowLength = 0;
  long rowIndex;
  byte repeatTrans;
  byte block1_buffer[4096];
  long  block1_number;
  
  long downloadedByteNum, readoutByteNum, readBlockNum, maxNumberofBlockLength;
  int maxNumberOfBlockLengthFormat, transmitData;

  CrcVal = 0xFFFFFFFF;
  block1_number = 0;
  /*无效的请求地址*/
  if((gFlashAddressInvalid == 1) && (StartAddress != 0x08021000))
  {
    StartAddress = StartAddress + 1; 
  }
  
  /*无效的请求大小*/
  if((gFlashLengthInvalid == 1) && (StartAddress != 0x08021000))
  {
    Size = Size + 1; 
  }
    
  if((gSkipRequestDownload == 1) &&((StartAddress == 0x10050000) || (StartAddress == 0x10020000)))
  {
    testStepPass("", "跳过执行请求下载");
  }
  else
  { 
    result = RequestDownload(0x00, 0x44, StartAddress, Size);
    if(result == 1)
    {
      testStepPass("", "执行请求下载成功");
    }
    else
    {
      testStepFail("", "执行请求下载失败");
      return -1;
    }
  }
  
  if(gSkipTransmitData == 0)
  {
    //计算一次传输最大数量
    maxNumberOfBlockLengthFormat = (RevData[1] >> 4);
    maxNumberofBlockLength = 0;
    for(i = 0; i < maxNumberOfBlockLengthFormat; i++)
    {
      maxNumberofBlockLength = maxNumberofBlockLength << 8;
      maxNumberofBlockLength += (RevData[i+2]);
    }
    
    if((gSkipRequestDownload == 1) &&((StartAddress == 0x10050000) || (StartAddress == 0x10020000)))
    {
      maxNumberofBlockLength = 0x802;
    }
    
    /*使用小于2K的大小传输*/
    if(gTransferLessThanMaxNumber == 1)
    {
      maxNumberofBlockLength = 0x402;
    }
    else
    {
      /* do nothing */
    }

    if(gBlockLengthTest == 1)
    {
      maxNumberofBlockLength = 0x822;
    }
    writeDbgLevel(5, "maxNumberofBlockLength : %d", maxNumberofBlockLength);
    
    //计算在一次传输最大数量时，可传输的次数
    transmitData = Size/(maxNumberofBlockLength-2);
    if((Size % (maxNumberofBlockLength-2) ) > 0)
    {
      transmitData++;
    }
    writeDbgLevel(5, "transmitData : %d", transmitData);
    
    fileHandle = openFileRead(FilePath, 1);
    if(fileHandle == 0)
    {
      writeDbgLevel(5, "读取文件失败");
      return -2;
    }
    
    //只传输一次
    if((gAppliacationInvalidFlashTest == 1) && (StartAddress == 0x10050000))
    {
      transmitData = 1;
    }
    else
    {
      /* do nothing */      
    }
    //传输部分数据，然后37退出
    if((gTransferPartialData == 1) || (gLostTransferData == 1))
    {
      if((StartAddress == 0x10050000) || (StartAddress == 0x10020000))
      {
         transmitData = 10;
      }
    }
    
    downloadedByteNum = 0;
    repeatTrans = 0;
    for(dataIndex=0; dataIndex < transmitData; dataIndex++)
    {
      /*重复传送两次36 01*/
      if((gRepeatTransferData == 1) && (StartAddress != 0x08021000))
      {
        if((dataIndex == 1) & (repeatTrans == 0))
        {
          dataIndex = 0;
          repeatTrans = 1;
        }
      }
      
      /*跳过一段数据，然后继续36传输*/
      if((gSkipPartialDataDuring36 == 1) && dataIndex == 15)
      {
        dataIndex++;
      }
      
      /*传输block1,跳过block2,传输block3*/
      if((gSkipBlockNumber2 == 1) && (dataIndex == 1) && (StartAddress != 0x08021000))
      {
        write("StartAddress = %d",StartAddress);
        dataIndex++;
      }
      
      rownum = 0;
      rowflag = 0;
      rowLength = 0;
      readBlockNum = 0;
      rownum = ((maxNumberofBlockLength-2) / 32);
      //writeDbgLevel(5, "rownum : %d", rownum);
      rowflag = ((maxNumberofBlockLength-2) % 32);
      //writeDbgLevel(5, "rowflag : %d", rowflag);
      
      if(rowflag == 0)
      {
        /* 第二次传输block2*/
        if((repeatTrans == 1) && (dataIndex == 0))
        {
          /* do nothing */
        }
        else
        {
          bufferIndex = 0;
          while(rownum > 0)
          {
            
            rowIndex = 0;
            readoutByteNum = fileGetBinaryBlock(rowbuffer, 80, fileHandle);
            //writeDbgLevel(5, "readoutByteNum : %d", readoutByteNum);
            rowLength = (asciiTobyte(rowbuffer[2]) * 16 + asciiTobyte(rowbuffer[3]));
            //writeDbgLevel(5, "rowLength : %d", rowLength);
            
            for(binindex=0; binindex < (2 * (rowLength - 5)); binindex = binindex + 2)
            {
              databuffer[rowIndex] = ((asciiTobyte(rowbuffer[binindex + 12]) * 0x10) + asciiTobyte(rowbuffer[binindex + 13]));
              rowIndex ++;
            }
            
            //writeDbgLevel(5, "rowIndex : %d", rowIndex);
            //writeDbgLevel(5, "bufferIndex : %d", bufferIndex);
            memcpy_off(buffer, bufferIndex, databuffer, 0, rowIndex);
            bufferIndex = bufferIndex + rowIndex;
            rownum --;
          }
          readBlockNum = bufferIndex;
          writeDbgLevel(5, "readBlockNum : %d", readBlockNum);
        }

      }
      else
      {
        writeDbgLevel(5, "单次传输block大小错误，需被32整除");
        return -102;
      }
      
      /* 保存block1的数据 */
      if((repeatTrans == 0) && (gRepeatTransferData == 1) && (dataIndex == 0))
      {
        memcpy(block1_buffer,buffer,readBlockNum);
        block1_number = readBlockNum;
      }
      else if((repeatTrans == 1) && (dataIndex == 0))
      {
        readBlockNum = block1_number;
        memcpy(buffer,block1_buffer,readBlockNum);
      }
      
      //如果刷写内容出错
      if((gDownloadwithDriverFileError == 1) || (gDownloadwithAppFileError == 1) || (gDownloadwithFblFileError == 1))
      {
        memcmp(buffer, errorBuffer, readBlockNum);
        if((errorBuffer[0] & 0x01) == 0x01)
        {
          errorBuffer[0] = errorBuffer[0] & 0xFE;
        }
        else
        {
          errorBuffer[0] = errorBuffer[0] | 0x01;
        }
        if(TransferData(dataIndex+1, buffer, readBlockNum) != 1)
        {
          testStepFail("", "传输数据时发生错误");
          return -3;
        }
      }
      else
      {
        //36服务传输数据
        result = TransferData(dataIndex+1, buffer, readBlockNum);
        if(result != 1)
        {
          if(RevData[2] == 0x24)
          {
            testStepFail("", "因跳过执行请求下载导致数据发生错误");
            return -2;
          }
          else
          {
            testStepFail("", "传输数据时发生错误");
            return -3;
          }
        }
      }
      
      /* 在传输过程中通信中断 */
      if((gComInterruptDuringTransfer == 1) && (dataIndex == 15))
      {
        DUTPowerOff();
        testWaitForTimeout(3000);
        return -101;
      }
      
      CrcVal = CAPL_CRC32Append(CrcVal, buffer, readBlockNum);
      writeDbgLevel(5, "CrcVal : 0x%X", CrcVal);
      writeDbgLevel(5, "dataIndex : 0x%X", (dataIndex + 1));

      /* 第二次传输block2*/
      if((repeatTrans == 1) && (dataIndex == 0))
      {
        /* do nothing */
      }
      else
      {
        downloadedByteNum += readBlockNum;
        sysSetVariableFloat(DownloadProgressNameSpacce, DownloadProgressVar, downloadedByteNum*100.0/AllBytes);
      }

 
      if(downloadedByteNum*100.0/AllBytes > gPoweroffDuringFlashProgressPercent)
      {
        DUTPowerOff();
        testWaitForTimeout(3000);
        return -101;
      }
    }
    
  }
  
  
  result = RequestTransferExit();
  
  
  return result;
}

int DownloadTestFile(char FilePath[], dword StartAddress, dword Size, long AllBytes, char DownloadProgressNameSpacce[], 
  char DownloadProgressVar[])
{
  int i, dataIndex, result, bufferIndex;
  byte buffer[0xFFFFFF], errorBuffer[0xFFFFFF];
  dword fileHandle;
  long blockIndex = 0;
  
  long downloadedByteNum, readBlockNum, maxNumberofBlockLength;
  int maxNumberOfBlockLengthFormat, transmitData;
  
  CrcVal = 0xFFFFFFFF;
  if(gSkipRequestDownload == 0)
  {
    result = RequestDownload(0x00, 0x44, StartAddress, Size);
    if(result == 1)
    {
      testStepPass("", "执行请求下载成功");
    }
    else
    {
      testStepFail("", "执行请求下载失败");
      return -1;
    }
  }
  else
  {
    testStepPass("", "跳过执行请求下载");
  }
  
  if(gSkipTransmitData == 0)
  {
    //计算一次传输最大数量
    maxNumberOfBlockLengthFormat = (RevData[1] >> 4);
    maxNumberofBlockLength = 0;
    for(i = 0; i < maxNumberOfBlockLengthFormat; i++)
    {
      maxNumberofBlockLength = maxNumberofBlockLength << 8;
      maxNumberofBlockLength += (RevData[i+2]);
    }
    
    //计算在一次传输最大数量时，可传输的次数
    transmitData = Size/(maxNumberofBlockLength-2);
    if((Size % (maxNumberofBlockLength-2) ) > 0)
    {
      transmitData++;
    }
    
    readBlockNum = maxNumberofBlockLength-2;
    Read_s19File(FilePath, buffer);
    
    downloadedByteNum = 0;
    for(dataIndex=0; dataIndex < transmitData; dataIndex++)
    {
      byte blockBuffer[0xFFFF];
      
      memcpy_off(blockBuffer, 0, buffer, blockIndex, readBlockNum);
      blockIndex = blockIndex + readBlockNum;
        
      //如果刷写内容出错
      if((gDownloadwithDriverFileError == 1) || (gDownloadwithAppFileError == 1) || (gDownloadwithFblFileError == 1))
      {
        memcmp(blockBuffer, errorBuffer, readBlockNum);
        if((errorBuffer[0] & 0x01) == 0x01)
        {
          errorBuffer[0] = errorBuffer[0] & 0xFE;
        }
        else
        {
          errorBuffer[0] = errorBuffer[0] | 0x01;
        }
        if(TransferData(dataIndex+1, blockBuffer, readBlockNum) != 1)
        {
          testStepFail("", "传输数据时发生错误");
          return -3;
        }
      }
      else
      {
        //36服务传输数据
        result = TransferData(dataIndex+1, blockBuffer, readBlockNum);
        if(result != 1)
        {
          if(RevData[2] == 0x24)
          {
            testStepFail("", "因跳过执行请求下载导致数据发生错误");
            return -2;
          }
          else
          {
            testStepFail("", "传输数据时发生错误");
            return -3;
          }
        }
      }
      
      CrcVal = CAPL_CRC32Append(CrcVal, buffer, readBlockNum);
      writeDbgLevel(5, "CrcVal : 0x%X", CrcVal);
      
      downloadedByteNum += readBlockNum;
      sysSetVariableFloat(DownloadProgressNameSpacce, DownloadProgressVar, downloadedByteNum*100.0/AllBytes);
      
      if(downloadedByteNum*100.0/AllBytes > gPoweroffDuringFlashProgressPercent)
      {
        DUTPowerOff();
        testWaitForTimeout(3000);
        return -101;
      }
    }
  }
  
  result = RequestTransferExit();
  
  return result;
}

void Read_s19File(char Filename[], byte dataBuffer[])
{
  long file_handle;
  char str[80];
  long char_index=0;
  long mem_Address;
  int Line_Length;
  long buff_index = 0;
  long length;
  file_handle = openFileRead(Filename, 0);

  if(file_handle != 0)
  {
    buff_index = 0;
    
    while(fileGetString(str, elcount(str), file_handle) != 0)
    {
      if((str[0] == 'S') && (str[1] == '3'))
      {
        // memory address char 4 to 11
        mem_Address = charTobyte(str[4]) * 0x10000000 + charTobyte(str[5]) * 0x1000000
                    + charTobyte(str[6]) * 0x100000 + charTobyte(str[7]) * 0x10000
                    + charTobyte(str[8]) * 0x1000 + charTobyte(str[9]) * 0x100
                    + charTobyte(str[10]) * 0x10 + charTobyte(str[11]);
        // the number of bytes each line contains
        Line_Length = (charTobyte(str[2])*0x10 + charTobyte(str[3]));
        for(char_index = 0; char_index < (2 *(Line_Length-5)); char_index = char_index + 2)
        {
          dataBuffer[buff_index++] = (charTobyte(str[char_index + 12])*0x10 + charTobyte(str[char_index + 13]));
        }
      }
      else if((str[0] == 'S') && (str[1] == '2'))
      {
        // memory address char 4 to 9
        mem_Address = charTobyte(str[4]) * 0x100000 + charTobyte(str[5]) * 0x10000
                    + charTobyte(str[6]) * 0x1000 + charTobyte(str[7]) * 0x100
                    + charTobyte(str[8]) * 0x10 + charTobyte(str[9]);
        // the number of bytes each line contains
        Line_Length = (charTobyte(str[2])*0x10 + charTobyte(str[3]));
        for(char_index = 0; char_index < (2 *(Line_Length-4)); char_index = char_index + 2)
        {
          dataBuffer[buff_index++] = (charTobyte(str[char_index + 10])*0x10 + charTobyte(str[char_index + 11]));
        }
      }
      else
      {
          /* do nothing */
      }
    }
  }
  else
  {
    writeDbgLevel(5, "读取文件失败");
  }
  fileClose(file_handle);
}

byte charTobyte(char ch)
{
  byte val = 0;
  if( ch >= '0' && ch <= '9')
  {
    val = ch - '0';
  }
  if( ch >= 'A' && ch <= 'F')
  {
    val = (ch - 'A') + 10;
  }
  if( ch >= 'a' && ch <= 'f')
  {
    val = (ch - 'a') + 10;
  }
  
  return val;
}

/// <DiagService/DownloadFile>
int RequestDownload(byte DataFormat, byte AddrAndSize, dword StartAddr, dword Size)
{
  int i, result;
  int AddrLen, SizeLen;
  byte Address[4], Sz[4];
  
  byte req[1024];
  req[0] = 0x34;
  req[1] = DataFormat;
  req[2] = AddrAndSize;
  
  AddrLen = (AddrAndSize >> 4) & 0xF;
  SizeLen = (AddrAndSize) & 0xF;
  
  Address[0] = (StartAddr >> 24) & 0xFF;
  Address[1] = (StartAddr >> 16) & 0xFF;
  Address[2] = (StartAddr >> 8) & 0xFF;
  Address[3] = (StartAddr) & 0xFF;
  Sz[0] = (Size >> 24) & 0xFF;
  Sz[1] = (Size >> 16) & 0xFF;
  Sz[2] = (Size >> 8) & 0xFF;
  Sz[3] = (Size) & 0xFF;
  
  for(i = 0; i < AddrLen; i++){
    req[3+i] = Address[i];
  }
  for(i = 0; i < SizeLen; i++)
  {
    req[3+AddrLen + i] = Sz[i];
  }
  result = CanReqSend(req, 3+AddrLen+SizeLen, PhyAddr);
  
  return result;
}

/// <DiagService/DownloadFile>
int TransferData(int blockSequenceNumber, byte buff[], dword ByteNum)
{
  int i, result, flag;
  byte req[4096];
  req[0] = 0x36;
  
  req[1] = blockSequenceNumber % 256;

  for(i = 0; i < ByteNum; i++)
  {
    req[2+i] = buff[i];
  }
  result = CanReqSend(req, 2+ByteNum, PhyAddr);
  
  return result;
}

/// <DiagService/DownloadFile>
int RequestTransferExit()
{
  int result;
  byte req[1];
  req[0] = 0x37;
  result = CanReqSend(req, elcount(req), PhyAddr);
  
  return result;
}

/// <DiagService/DownloadFile>
int DownloadAppFile()
{
  char AppDownloadProgressNameSpace[100] = "FBLFlash";
  char AppDownloadProgressVar[100] = "AppDownloadProgress";
  
  int i, result;
  char appFilePath[1024];
  dword appStartAddress, appSize;
  long blockNum, allBytesNum;
  
  testStep("", "下载APP");
  CurrentFlashedBlk = FlashAppBlk;
  sysGetVariableString(sysvar::FBLFlash::AppFile, appFilePath, elCount(appFilePath));
  writeDbgLevel(5, "App File : %s", appFilePath);
  blockNum = CAPL_ParseFlashFile(appFilePath);
  writeDbgLevel(5, "block Num : %d", blockNum);
  allBytesNum = CAPL_GetAllByteNumber();
  writeDbgLevel(5, "Bytes Num : 0x%X", allBytesNum);
  
  for(i = 0; i < blockNum; i++)
  {
    appStartAddress = CAPL_GetBlockStartAddress(i);
    writeDbgLevel(5, "block %d start address : 0x%X", i, appStartAddress);
    appSize = CAPL_GetBlockByteNumber(i);
    writeDbgLevel(5, "block %d byte num : 0x%X", i, appSize);

    /*例程擦除开始前通信中断*/
    if(gComInterruptBeforeErase == 1)
    {
      DUTPowerOff();
      testWaitForTimeout(3000);
      return -101;
    }
    
    /*无效的擦除地址*/
    if(gEraseAddressInvalid == 1)
    {
      appStartAddress = appStartAddress + 1; 
    }
    
    /*无效的擦除大小*/
    if(gEraseLengthInvalid == 1)
    {
      appSize = appSize + 1; 
    }
    
    if(gSkipEraseMemory == 0)
    {
      result = EraseMemory(appStartAddress, appSize);
      if(result != 1)
      {
        testStepFail("", "擦除Memory失败");
        return -100;
      }
      else
      {
        testStepPass("", "擦除Memory成功");
      }
    }
    else
    {
      testStepPass("", "跳过擦除Memory");
    }
    
    if(gDownloadwithFblFileOnly == 0)
    {
      result = DownloadFile(appFilePath, appStartAddress, appSize, allBytesNum, 
      AppDownloadProgressNameSpace, AppDownloadProgressVar);
      
      if(result != 1)
      {
        return result;
      }
    }
  }
  
 /* if(gSkipCheckMemoryRoutine == 0)
  {
    result = checkProgrammingIntegrity(1);*/    /* 1 represent app */
    /*if(result == 1)
    {
      testStepPass("","CRC校验成功");
    }
    else
    {
      testStepFail("","CRC校验失败");
      return -1;
    }  
  }
  else
  {
    testStepPass("","跳过CRC校验");
  }*/
  
  return result;
}

/// <DiagService/DownloadFile>
int DownloadFblFile()
{
  char FblDownloadProgressNameSpace[100] = "FBLFlash";
  char FblDownloadProgressVar[100] = "FblDownloadProgress";
  
  int i, result;
  char fblFilePath[1024];
  dword fblStartAddress, fblSize;
  long blockNum, allBytesNum;
  
  testStep("", "下载FBL");
  CurrentFlashedBlk = FlashFBLBlk;
  sysGetVariableString(sysvar::FBLFlash::FblFile, fblFilePath, elCount(fblFilePath));
  writeDbgLevel(5, "Fbl File : %s", fblFilePath);
  blockNum = CAPL_ParseFlashFile(fblFilePath);
  writeDbgLevel(5, "block Num : %d", blockNum);
  allBytesNum = CAPL_GetAllByteNumber();
  writeDbgLevel(5, "Bytes Num : 0x%X", allBytesNum);
  
  for(i = 0; i < blockNum; i++)
  {
    fblStartAddress = CAPL_GetBlockStartAddress(i);
    writeDbgLevel(5, "block %d start address : 0x%X", i, fblStartAddress);
    fblSize = CAPL_GetBlockByteNumber(i);
    writeDbgLevel(5, "block %d byte num : 0x%X", i, fblSize);

    
    /*无效的擦除地址*/
    if(gEraseAddressInvalid == 1)
    {
      fblStartAddress = fblStartAddress + 1; 
    }
    
    /*无效的擦除大小*/
    if(gEraseLengthInvalid == 1)
    {
      fblSize = fblSize + 1; 
    }
    
    if(gSkipEraseMemory == 0)
    {
      result = EraseMemory(fblStartAddress, fblSize);
      if(result != 1)
      {
        testStepFail("", "擦除Memory失败");
        return -100;
      }
      else
      {
        testStepPass("", "擦除Memory成功");
      }
    }
    else
    {
      testStepPass("", "跳过擦除Memory");
    }
    
   /* if(gPoweroffDuringEraseMemory == 1)
    {
      DUTPowerOff();
      testWaitForTimeout(3000);
      return -101;
    }
   */ 
    
    result = DownloadFile(fblFilePath, fblStartAddress, fblSize, allBytesNum, 
    FblDownloadProgressNameSpace, FblDownloadProgressVar);
    
    if(result != 1)
    {
      return result;
    }

  }
  
  /*if(gSkipCheckMemoryRoutine == 0)
  {
    result = checkProgrammingIntegrity(2); */   /* 2 represent fbl */
    /*if(result == 1)
    {
      testStepPass("","CRC校验成功");
    }
    else
    {
      testStepFail("","CRC校验失败");
      return -1;
    }  
  }
  else
  {
    testStepPass("","跳过CRC校验");
  }*/
  
  return result;  
}

/// <DiagService/DownloadFile>
int DownloadCalFile()
{
  char CalDownloadProgressNameSpace[100] = "FBLFlash";
  char CalDownloadProgressVar[100] = "CalDownloadProgress";
  
  int i, result;
  char calFilePath[1024];
  dword calStartAddress, calSize;
  long blockNum, allBytesNum;
  
  testStep("", "下载Calibration");
  CurrentFlashedBlk = FlashCodBlk;
  sysGetVariableString(sysvar::FBLFlash::CalFile, calFilePath, elCount(calFilePath));
  writeDbgLevel(5, "Calibration File : %s", calFilePath);
  blockNum = CAPL_ParseFlashFile(calFilePath);
  writeDbgLevel(5, "block Num : %d", blockNum);
  allBytesNum = CAPL_GetAllByteNumber();
  writeDbgLevel(5, "Bytes Num : 0x%X", allBytesNum);
  
  for(i = 0; i < blockNum; i++)
  {
    calStartAddress = CAPL_GetBlockStartAddress(i);
    writeDbgLevel(5, "block %d start address : 0x%X", i, calStartAddress);
    calSize = CAPL_GetBlockByteNumber(i);
    writeDbgLevel(5, "block %d byte num : 0x%X", i, calSize);

    
    /*无效的擦除地址*/
    if(gEraseAddressInvalid == 1)
    {
      calStartAddress = calStartAddress + 1; 
    }
    
    /*无效的擦除大小*/
    if(gEraseLengthInvalid == 1)
    {
      calSize = calSize + 1; 
    }
    
    if(gSkipEraseMemory == 0)
    {
      result = EraseMemory(calStartAddress, calSize);
      if(result != 1)
      {
        testStepFail("", "Calibration擦除Memory失败");
        return -100;
      }
      else
      {
        testStepPass("", "Calibration擦除Memory成功");
      }
    }
    else
    {
      testStepPass("", "Calibration跳过擦除Memory");
    }
    
   /* if(gPoweroffDuringEraseMemory == 1)
    {
      DUTPowerOff();
      testWaitForTimeout(3000);
      return -101;
    }
   */ 
    
    result = DownloadFile(calFilePath, calStartAddress, calSize, allBytesNum, 
    CalDownloadProgressNameSpace, CalDownloadProgressVar);
    
    if(result != 1)
    {
      return result;
    }

  }
  
  /*if(gSkipCheckMemoryRoutine == 0)
  {
    result = checkProgrammingIntegrity(3);*/    /* 3 represent cal */
    /*if(result == 1)
    {
      testStepPass("","Calibration CRC校验成功");
    }
    else
    {
      testStepFail("","Calibration CRC校验失败");
      return -1;
    }  
  }
  else
  {
    testStepPass("","跳过Calibration CRC校验");
  }*/
  
  return result;  
}

/// <DiagService/WriteIdentification_2E>
int writeFingerPrint()
{
  int result;
  byte FingerPrintID[2] = {0xF1, 0x84};
  
  byte tmpFingerPrint[7];
  byte serialNum[9];
  long copiedBytes;
  char s_year[5] = "0x";
  char s_month[5] = "0x";
  char s_day[5] = "0x";
  char tmp_char[3];
  dword tmp_dword;
  
  tmpFingerPrint[0] = @FBLFlash::FingerPrint_ProgrammingDateYear;
  tmpFingerPrint[1] = @FBLFlash::FingerPrint_ProgrammingDateMonth;
  tmpFingerPrint[2] = @FBLFlash::FingerPrint_programmingDateDay;
  
  /* dec to string */
  ltoa(tmpFingerPrint[0],tmp_char,10);
  s_year[2] = tmp_char[0];s_year[3] = tmp_char[1];
  ltoa(tmpFingerPrint[1],tmp_char,10);
  s_month[2] = tmp_char[0];s_month[3] = tmp_char[1];
  ltoa(tmpFingerPrint[2],tmp_char,10);
  s_day[2] = tmp_char[0];s_day[3] = tmp_char[1];
  
  /* string to hex */
  strtoul(s_year,tmp_dword); tmpFingerPrint[0] = (byte)tmp_dword;
  strtoul(s_month,tmp_dword); tmpFingerPrint[1] = (byte)tmp_dword;
  strtoul(s_day,tmp_dword); tmpFingerPrint[2] = (byte)tmp_dword;
  
  sysGetVariableData(sysvar::FBLFlash::FingerPrint_TesterSerialNumber, serialNum, copiedBytes);
  tmpFingerPrint[3] = serialNum[0];
  tmpFingerPrint[4] = serialNum[1];
  tmpFingerPrint[5] = serialNum[2];
  tmpFingerPrint[6] = serialNum[3];
  
  result = writeIdentification(FingerPrintID, tmpFingerPrint, PhyAddr);
  
  return result;
}

/// <DiagService/ReadIdentification_22>
int readFingerPrint()
{
  int result;
  byte req[3];
  req[0] = 0x22;
  req[1] = 0xF1;
  req[2] = 0x5B;
  
  result = CanReqSend(req,elcount(req), PhyAddr);
  
  return result;
}

/// <DiagService/ReadIdentification_22>
void readBootDIDInfo()
{
  byte reqBootVer[3];
  byte reqHardVer[3];
  byte reqSoftVer[3];
  
  reqBootVer[0] = 0x22;
  reqBootVer[1] = 0xF1;
  reqBootVer[2] = 0x50;
  CanReqSend(reqBootVer,elcount(reqBootVer), PhyAddr);
  testWaitForTimeout(1000);
  
  reqHardVer[0] = 0x22;
  reqHardVer[1] = 0xF1;
  reqHardVer[2] = 0x10;
  CanReqSend(reqHardVer,elcount(reqHardVer), PhyAddr);
  testWaitForTimeout(1000);
  
  reqSoftVer[0] = 0x22;
  reqSoftVer[1] = 0xF1;
  reqSoftVer[2] = 0x18;
  CanReqSend(reqSoftVer,elcount(reqSoftVer), PhyAddr);
  testWaitForTimeout(1000);
}

/// <DiagService/WriteIdentification_2E>
int writeIdentification(byte WriteDid[], byte DidOption[], dword Addr)
{
  int i, result;
  byte req[1024];
  req[0] = 0x2E;
  req[1] = WriteDid[0];
  req[2] = WriteDid[1];
  for(i = 0; i < elCount(DidOption); i++)
  {
    req[i+3] = DidOption[i];
  }
  result = CanReqSend(req, 3+elcount(DidOption), Addr);
  
  return result;
}

/// <DiagService/ECUReset>
int Reset(byte resetType)
{
  int result;
  byte req[2];
  req[0] = 0x11;
  req[1] = resetType;
  result = CanReqSend(req, elcount(req), PhyAddr);
  
  return result;
}

on message 0x791
{
  if((this.byte(0) == 0x01) && (this.byte(1) == 0x77)) write( "1");
  
}
