unit UnitMisc;

interface

uses sysutils, HexUtils, classes, boots, dialogs ;

type TPhInfoRecord = record
     Name:string;
     PhType:string;
     Model:string;
     MCUSW:string;
     PPMInfo:string;
     HWID:string;
     PCI:string;
     APETest:string;
     RFIC:string;
     DSP:string;
     APECoreSW:string;
     APEVariant:string;
     Retu:string;
     Tahvo:string;
     CNT : string;
     APEHW:string;
     APEADSPSW:string;
     LSN:string;
     APEBT:string;
     PrdSerial:string;
     ProductCode:string;
     ModuleCode:string;
     BisicPrdCode:string;
     IMEIPlain:string;
     IMEI2Net:string;
     IMEISv2Net:string;
     Bat:string;
     Cam:string;
     CMTbtver:string;
     LCD:string;
     FLic:string;
     CRR:string; //результат сброса кода на дефолтный
     PrdCok:string; // результат записи продукт кода. Стоит перманентный - проверка реализована в коде.
     APEic:string;
     end;


type TRPLRecord = record
     NPC:string;
     CCC:string;
     HWC:string;
     SIMLOCK:string;
     SIMLOCK_KEY:string;
     SUPERDONGLE_KEY:string;
     CMLA_KEY:string;
     WMDRM_PD:string;
     end;

function PhModeToStr (mode:integer):string ;
function rawtotemp(raw:Integer):string;
function PathConv(path:string):string;
function FindDescr(filename:string):string ;
function FindNam(filename:string):boolean ;
procedure repairdata();
function getkeycode(kw:Word):string;
function getkeystatus(data:Word):string;
function convertcnt(imname:string):boolean;
function SelLoaders(IdR:string):boolean;
function affenabled():Boolean;
function SecondToTime(const Seconds: Cardinal): Double;
function showtime(time:cardinal):string;
procedure endtimecount();
procedure starttime();

var
  RPLRecord:TRPLRecord;
  PhInfoRecord:TPhInfoRecord;
  Smart:boolean;
  ConMode:integer; //0=USB, 1=COM, 2=...
  RM:string;
  typeinf,Generation,Crypted,datapos:string;
  fileexist:Boolean;
  //filesize:Int64;
  currproduct:string;
  M:TMemoryStream;
  zad:Integer;
  TypePHstr:string;
  csbyte1,csbyte2,csbyte3,csbyte4 : Byte;
  SWver:string;
  Floader,Sloader:string;
  StartDir:string;
  tmsstart,tmsstop,tmsres, opstart, opend : Cardinal;
  fbdev:integer;

implementation
uses Unit1, forms, UsbMain, windows, UnitE1;
const
  SecPerDay = 86400;
  SecPerHour = 3600;
  SecPerMinute = 60;

function SecondToTime(const Seconds: Cardinal): Double;
var    
  ms, ss, mm, hh, dd: Cardinal;    
begin    
  dd := Seconds div SecPerDay;
  hh := (Seconds mod SecPerDay) div SecPerHour;    
  mm := ((Seconds mod SecPerDay) mod SecPerHour) div SecPerMinute;
  ss := ((Seconds mod SecPerDay) mod SecPerHour) mod SecPerMinute;    
  ms := 0;    
  Result :=EncodeTime(hh, mm, ss, ms);    
end;


function SelLoaders(IdR:string):boolean;
var s,s1:string;
begin
   Result:=false;
   Floader:='';
   Sloader:='';
   if Pos (IdR,'0003192103002107000C1921030021070003192103012107000C192103012107000C1921030221070003192103022107')<>0 then begin
     Floader:=StartDir+'Flash\RAPUv21_2nd.fg';
     Sloader:=StartDir+'Flash\RAPUv21_XSR17_alg.fg';
     Result:=true;
     exit;
   end;
   if Pos (IdR,'4003192102001104400C1921020011046003192102001104600C1921020011046003192102011104600C1921020111046003192102021104600C1921020211046003192102031104600C192102031104')<>0 then begin
     Floader:=StartDir+'Flash\RAPUv11_2nd.fg';
     Sloader:=StartDir+'Flash\RAPUv11_XSR17_alg.fg';
     Result:=true;
     exit;
   end;
   s:='0203192102004000020C1921020040000203192102024000020C192102024000020C1921020041000203192102004100020C1921020141000203192102014100020C1921020140000203192102014000';
   s1:='020C19210203400002031921020340000203192102024100020C1921020241000203192102034100020C1921020341000203192102054100020C1921020541000203192102044100020C192102044100';
   s:=s+s1;
   if Pos (IdR,s)<>0 then begin
     Floader:=StartDir+'Flash\RAP3Gv40_2nd.fg';
     Sloader:=StartDir+'Flash\RAP3Gv40_XSR17_alg.fg';
     Result:=true;
     exit;
   end;
   if Pos (IdR,'22000209200C0000220002092003000022000509200C00002200050920030000')<>0 then begin
     Floader:=StartDir+'Flash\BCM21351_usb2nd.fg';
     Sloader:=StartDir+'Flash\BCM21351_XSR16_usbalg.fg';
     Result:=true;
     exit;
   end;
   if Pos (IdR,'220000092003000022000009200C000022000109200C00002200010920030000')<>0 then begin
     Floader:=StartDir+'Flash\BCM21351_D0_usb2nd.fg';
     Sloader:=StartDir+'Flash\BCM21351_D0_XSR16_usbalg.fg';
     Result:=true;
     exit;
   end;
   if Pos (IdR,'22000209200C0000220002092003000022000309200C00002200030920030000')<>0 then begin
     Floader:=StartDir+'Flash\BCM21351_E0_usb2nd.fg';
     Sloader:=StartDir+'Flash\BCM21351_E0_XSR16_usbalg.fg';
     Result:=true;
     exit;
   end;
   if Pos (IdR,'22000209200C0000220002092003000022000309200C00002200030920030000')<>0 then begin
     Floader:=StartDir+'Flash\BCM21351_E0N_usb2nd.fg';
     Sloader:=StartDir+'Flash\BCM21351_E0N_XSR16_usbalg.fg';
     Result:=true;
     exit;
   end;
end;

function PathConv(path:string):string;
var
Len:integer;
s:string;
sw:WideString;
begin
          sw:=UTF8Decode(path);
          Len:=(Length(sw) shl 1)+2;
          Result:='';
          s:='';
          SetLength(s,2);
          word ((@s[1])^):=Len;
          WordSwap(@s[1]);
          SetLength(Result,Len+2);
          BufCopySwapWord(@sw[1],@Result[1],Len);
          Result:=s+Result;
end;

function PhModeToStr (mode:integer):string ;
begin
        case mode of
        0 : Result := 'PowerOFF';
        1 : Result := 'Normal';
        2 : Result := 'Charging';
        3 : Result := 'Alarm';
        4 : Result := 'Test';
        5 : Result := 'Local';
        6 : Result := 'Warranty';
        7 : Result := 'Reliability';
        8 : Result := 'SelftestFail';
        9 : Result := 'SwDl';
       10 : Result := 'RfInactive';
       11 : Result := 'IdWrite';
       12 : Result := 'Discharging';
       13 : Result := 'SwReset';
        end;
end;

function rawtotemp(raw:Integer):string;
var
temp:integer;
begin
   case raw of
                // temperature from raw
570..579:temp:=0;
560..569:temp:=1;
550..559:temp:=2;
540..549:temp:=3;
530..539:temp:=4;
520..529:temp:=5;
510..519:temp:=6;
500..509:temp:=7;
490..499:temp:=8;
480..489:temp:=9;
470..479:temp:=10;
460..469:temp:=11;
450..459:temp:=12;
440..449:temp:=13;
430..439:temp:=14;
420..429:temp:=15;
410..419:temp:=16;
400..409:temp:=17;
390..399:temp:=18;
380..389:temp:=19;
370..379:temp:=20;
360..369:temp:=21;
350..359:temp:=22;
340..349:temp:=23;
330..339:temp:=24;
320..329:temp:=25;
310..319:temp:=26;
300..309:temp:=27;
290..299:temp:=28;
280..289:temp:=29;
270..279:temp:=30;
260..269:temp:=31;
250..259:temp:=32;
240..249:temp:=33;
230..239:temp:=34;
220..229:temp:=35;
210..219:temp:=36;
200..209:temp:=37;
190..199:temp:=38;
180..189:temp:=39;
170..179:temp:=40;
160..169:temp:=41;
150..159:temp:=42;
140..149:temp:=43;
130..139:temp:=44;
120..129:temp:=45;
110..119:temp:=46;
100..109:temp:=47;
90..99:temp:=48;
80..89:temp:=49;
70..79:temp:=50;
60..69:temp:=51;
50..59:temp:=52;
40..49:temp:=53;
30..39:temp:=54;
20..29:temp:=55;
10..19:temp:=56;
0..9:temp:=57
else temp:=0;
               end;
          Result:=inttostr(temp)+' C';
end;

function FindNam(filename:string):boolean ;
Label vp1;
var
Fn: System.Text;
s,name,styp:string;
i:integer;
begin
       Result:=false;
       System.Assign (Fn , filename) ;
       System.Reset (Fn);
       while not EOF(Fn) do begin
       System.Readln(Fn,s);
       if Pos('<File>',s)<>0 then begin
       System.Readln(Fn,s);
         while Pos('</File>',s)=0 do begin
           if Pos ('<Name>',s)<> 0 then begin
              name:='';
              i:=Pos ('<Name>',s);
              i:=i+6;
              while s[i] <> '<' do begin name:=name+s[i]; i:=i+1 end;
           end;
           if Pos ('<FileSubType>',s)<> 0 then begin
              styp:='';
              i:=Pos ('<FileSubType>',s);
              i:=i+13;
              while s[i] <> '<' do begin styp:=styp+s[i]; i:=i+1 end;
               if styp='Mcu' then core:=name;
               if styp='Ppm' then if ppm<>'' then ppm1:=name else ppm:=name;

               if styp='Content' then if image<>'' then begin
                if ape<>'' then cnt3:=name else ape:=name;
               end else image:=name;
           end;
vp1:
          System.Readln(Fn,s);
         end;
       end;
       end;
       System.Close(Fn);
      if core<>'' then Result:=true;
end;

function FindDescr(filename:string):string ;
var
Fn: System.Text;
s,ProdName,ProdCode,ProdVer,orFN:string;
i:integer;
begin
       SWver:='';
       Result:='';
       ProdName:='';
       ProdCode:='';
       ProdVer:='';
       orFN:='';
       System.Assign (Fn , filename) ;
       System.Reset (Fn);
       while not EOF(Fn) do begin
       System.Readln(Fn,s);
       if Pos('<Description>',s)<>0 then begin
          i:= Pos('<Description>',s);
          i:=i+13;
          while s[i] <> '<' do begin ProdName:=ProdName+s[i]; i:=i+1 end;
       end;
       if Pos('<ProductCode>',s)<>0 then begin
          i:= Pos('<ProductCode>',s);
          i:=i+13;
          while s[i] <> '<' do begin ProdCode:=ProdCode+s[i]; i:=i+1 end;
       end;
       if Pos('<SwVersion>',s)<>0 then begin
          i:= Pos('<SwVersion>',s);
          i:=i+11;
          while s[i] <> '<' do begin ProdVer:=ProdVer+s[i]; i:=i+1 end;
       end;
       {if Pos('<OriginalFileName>',s)<>0 then begin
          i:= Pos('<OriginalFileName>',s);
          i:=i+18;
          while s[i] <> '<' do begin orFN:=OrFN+s[i]; i:=i+1 end; 

       end;}
       end;
       System.Close(Fn);
       Result:=ProdCode+' '+ProdName+' ver '+ProdVer ;
       if ProdVer<>'' then SWver:=Prodver;
end;


procedure repairdata();
begin
  GETRoot[9]:=$01;
  GetBlock[7]:=$0D;
  GetBlock[8]:=$00;
  GetBlock[9]:=$0E;
end;

function getkeycode(kw:Word):string;
begin
  case kw of
  $0030:result:='0 [DIGIT]';
  $0031:result:='1 [DIGIT]';
  $0032:result:='2 [DIGIT]';
  $0033:result:='3 [DIGIT]';
  $0034:result:='4 [DIGIT]';
  $0035:result:='5 [DIGIT]';
  $0036:result:='6 [DIGIT]';
  $0037:result:='7 [DIGIT]';
  $0038:result:='8 [DIGIT]';
  $0039:result:='9 [DIGIT]';
  $0023:result:='#';
  $002A:result:='*';
  $E001:result:='PWR';
  $E003:result:='LSoft';
  $E004:result:='RSoft';
  $E005:result:='SEND';
  $E006:result:='END';
  $E007:result:='UP';
  $E008:result:='DOWN';
  $E00A:result:='VOL+';
  $E00B:result:='VOL-';
  $E00C:result:='OK';
  $E00D:result:='LEFT';
  $E00E:result:='RIGHT';
  $0E5C:result:='CAM';
  $0008:result:='Clear [C]';
  $F852:result:='Menu';
  $F884:result:='Pen';
  $F842:result:='LSoft';
  $F843:result:='RSoft';
  $F80A:result:='DOWN';
  $F809:result:='UP';
  $F808:result:='RIGHT';
  $F807:result:='LEFT';
  $F883:result:='CAM';
  $F88F:result:='CPrew';
  $F881:result:='Fplay';
  $F886:result:='FfW';
  $F880:result:='FRew';
  $F845:result:='Ok/Select' ;
  $F863:result:='END';
  $E05C:result:='CAM';
  $E05D:result:='CFocus';
  $F862:result:='SEND';
  $E060:result:='Play/Pause';
  $E061:result:='Play[Rewind]';
  $E05F:result:='Play[Forward]';
  $F856:result:='Play[Forward]';
  $F854:result:='Play[Play/Pause]';
  $F855:result:='Play[Stop]';
  $F857:result:='Play[Rewind]';
  $F847:result:='Slide[Down]';
  $F84A:result:='Slide[Down|PlayMode]';
  $F84B:result:='Slide[Up|Close]';
  $F846:result:='Slide[Up|Open]';
  $F80B:result:='Pen';
  $F858:result:='MMedia key';
  $F840:result:='VOL+';
  $F841:result:='VOL-';
  $F887:result:='Camera Lens open';
  $F888:result:='Camera Lens close';
  $E002:result:='Slide Open/Close';
  else result:='UNKNOW KEY';
  end;
end;

function getkeystatus(data:Word):string;
begin
  case data of
  $000D:result:='Press, long press, repeat';
  $000F:result:='Press, Release, Long press, repeat';
  $0003:result:='Press, Release';
  $0001:result:='Press';
  $0007:result:='Press, Release, Long press';
  $0083:result:='Press, Release';
  $0010:result:='Slide up';
  $0020:result:='Slide down';
  $0030:result:='Slide down/up';
  $0048:result:='Slide down/up many times';
  //E0 0C 00 08 shorted
  $0008:result:='Possible shorted';
  else result:='UNKNOW';
  end;
end;

function convertcnt(imname:string):boolean;
var
     buf: array[0..$3FFFF] of byte;
     HdrLen,
     HdrSeems,
     CurrSeem,
     CurrSeemLen       : Integer;
     ImagePageSize     : Word;
     i                 : Integer;
     res, NeedConvert  : Boolean;
     fs                : TFileStream;
     ms                : TMemoryStream;
     f5                : Boolean;
begin
     imname:=image;
     Form1._msg('ConvertImage: Processing '+ExtractFileName(imname));
try
     currseem:=0;
     f5:=false;
     fs:=TFileStream.Create(imname,fmOpenRead);
     fs.Read(buf[0] ,1);
     if buf[0]<>$B2 then
     begin
          Form1._msg('ConvertImage: Image file is damaged');
          fs.Free;
          exit;
     end;

     fs.ReadBuffer(buf[0], 4);//Длина Flash-header'a
     HdrLen   := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2));
     fs.Seek(4,soFromCurrent);
     HdrSeems := HdrLen+5;
     while fs.Position<HdrSeems do
     begin
       Application.ProcessMessages;
       //Form1._msg(IntToStr(fs.Position));
          fs.ReadBuffer(CurrSeem, 1);
          //Form1._msg('curr : '+byte2str(CurrSeem));
          Application.ProcessMessages;
          if (CurrSeem=$E4) or (CurrSeem=$E5) or (CurrSeem=$EA) or
             (CurrSeem=$EE) or (CurrSeem=$F3) then
          begin
               fs.ReadBuffer(buf[0], 2);
               CurrSeemLen:=(buf[0]*$100)+buf[1];
               fs.Seek(CurrSeemLen, sofromCurrent);
          end else

          begin
               fs.ReadBuffer(buf[0], 1);
               CurrSeemLen:=buf[0];
               if CurrSeemLen<1 then fs.ReadBuffer(CurrSeemLen, 1);

               //Чтение текущей разметки image-файла
               if (CurrSeem=$F5) then
               begin
                    f5:=True;
                    if CurrSeemLen<>2 then form1._msg('Unknow Image-file');
                    fs.ReadBuffer(ImagePageSize, CurrSeemLen);

                    if ImagePageSize=$1100 then
                    begin
                         NeedConvert:=false;
                         Form1._msg('ConvertImage: Page Size is 128K, no need convert');
                         result:=false;
                         fs.Free;
                         Exit;
                    end else
                    if ImagePageSize=$1000 then
                    begin
                         NeedConvert:=true;
                         form1._msg('ConvertImage: Page Size is 64K, need convertion');
                         continue;
                    end else form1._msg('ConvertImage: Unknow Page Size :( ');
               end;
               fs.Seek(CurrSeemLen, sofromCurrent);
          end;
     end;
     fs.Free;
     if f5=false then begin
     Form1._msg('ConvertImage: cnt size not detected');
     exit;
     end;
     if NeedConvert then
     begin
          ms:=TMemoryStream.Create;
          Form1.Image64to128(imname, ms, Res);
          if Not Res then
          begin
               form1._msg('ConvertImage: Error converting to 128K Page Size');
               ms.free;
               Result:=false;
               exit;
          end;
          Form1._msg('ConvertImage: File converted');
          ms.Seek(0, sofrombeginning);
          ms.SaveToFile(imname+'_128');
          Result:=True;
          ms.Free;
     end;
except
        on E:Exception do
        begin
             fs.Free;
             Form1._msg('ConvertImage Error: '+E.Message);
             Result:=false;
        end;
    end;
end;

function affenabled():Boolean;
var
  i:Integer;
begin
 result:=True;
 if (Form1.chkCheckRead.Checked=True) or (Form1.chkReseLt.checked=true) or (Form1.ChkAFFset.checked=true) or (Form1.chkBootNormal.checked=true) then begin
     Application.ProcessMessages;
     Sleep(1000);
     Application.ProcessMessages;
     Sleep(1000);
     Application.ProcessMessages;

     i:=0;
     if catchdevice<>$01 then
     begin
          repeat
                Application.ProcessMessages;
                Sleep(1000);
                Inc(i);
                Application.ProcessMessages;
          until (catchdevice=$01) or (i=100);
     end;

      if (i=100) and (catchdevice<>$01) then begin
      Application.ProcessMessages;
      Sleep(200);
      Form1.SetReady;
      Form1.TimConChk.Enabled:=true;
      Form1._msg('Flashing Failed! :( Maybee HW error, or Downgrade try???!');
      Form1._msg('');
      Form1.DisconnectFill;
      Result:=false;
      Form1.chkPPMe.Enabled:=True;
      Form1.chkMCUen.Enabled:=True;
      Form1.chkPPM1e.Enabled:=True;
      Form1.chkCNTe.Enabled:=True;
      Form1.chkAPEe.Enabled:=True;
      Form1.chkcnt3.Enabled:=True;
      end;
   Form1.TimConChk.Enabled:=true;
   end;
end;

procedure starttime();
begin
 tmsstart:=0;
 tmsstart:=GetTickCount;
end;

procedure endtimecount();
begin
 tmsstop:=GetTickCount;
 tmsres:=tmsstop-tmsstart;
 fltime:=fltime+tmsres;
end;

function showtime(time:cardinal):string;
var
  sec:Integer;
begin
 sec:=0;
 sec:=(time div 1000);
 result:=FormatDateTime('hh:nn:ss',(SecondToTime(sec)));
end;

end.
