unit UsbMain;

interface
uses
  Windows, Messages, forms, SysUtils, Variants, Classes, StdCtrls, Registry, Masks, Boots, HexUtils, UnitMisc, Spin;

const
  DIGCF_DEFAULT         = $00000001;
  {$EXTERNALSYM DIGCF_DEFAULT}
  DIGCF_PRESENT         = $00000002;
  {$EXTERNALSYM DIGCF_PRESENT}
  DIGCF_ALLCLASSES      = $00000004;
  {$EXTERNALSYM DIGCF_ALLCLASSES}
  DIGCF_PROFILE         = $00000008;
  {$EXTERNALSYM DIGCF_PROFILE}
  DIGCF_DEVICEINTERFACE = $00000010;
  {$EXTERNALSYM DIGCF_DEVICEINTERFACE}
  ANYSIZE_ARRAY = 1;

var
  hDevice: THANDLE;
  rxBuf: array of byte;
  txBuf: array[0..$FFFF] of byte;
  CurrDev: String;
  flag:boolean;
  Ucont: boolean ;
  size:Integer;
  success: boolean;
  devicehandle: THandle;
  cntT,cntF,cntU : word;
  
type TDeviceNames = record
  Real,
  Device : string[255];
end;
 {$IFDEF UNICODE}
 LPCTSTR = PWideChar;
 LPTSTR  = PWideChar;
 PCTSTR  = PWideChar;
 PTSTR   = PWideChar;
 TCHAR   = WideChar;
 {$ELSE}
 LPCTSTR = PAnsiChar;
 LPTSTR  = PAnsiChar;
 PCTSTR  = PAnsiChar;
 PTSTR   = PAnsiChar;
 TCHAR   = Char;
 {$ENDIF UNICODE}
 {$EXTERNALSYM LPCTSTR}
 {$EXTERNALSYM LPTSTR}
 {$EXTERNALSYM PCTSTR}
 PPWSTR = ^PWideChar;
 PPASTR = ^PAnsiChar;
 PPSTR  = ^PTSTR;
 {$EXTERNALSYM PTSTR}
 ULONG_PTR = ^ ULONG;
 HDEVINFO = Pointer;
 PSPDevInfoData = ^TSPDevInfoData;
 SP_DEVINFO_DATA = packed record
  cbSize: DWORD;
  ClassGuid: TGUID;
  DevInst: DWORD;
  Reserved: ULONG_PTR;
end;
 {$EXTERNALSYM SP_DEVINFO_DATA}
 TSPDevInfoData = SP_DEVINFO_DATA;
 PSPDeviceInterfaceData = ^TSPDeviceInterfaceData;
 SP_DEVICE_INTERFACE_DATA = packed record
  cbSize: DWORD;
  InterfaceClassGuid: TGUID;
  Flags: DWORD;
  Reserved: ULONG_PTR;
end;
 {$EXTERNALSYM SP_DEVICE_INTERFACE_DATA}
 TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA;
 PSPDeviceInterfaceDetailDataA = ^TSPDeviceInterfaceDetailDataA;
 PSPDeviceInterfaceDetailDataW = ^TSPDeviceInterfaceDetailDataW;
 SP_DEVICE_INTERFACE_DETAIL_DATA_A = packed record
  cbSize: DWORD;
  DevicePath: array [0..ANYSIZE_ARRAY - 1] of AnsiChar;
end;
 {$EXTERNALSYM SP_DEVICE_INTERFACE_DETAIL_DATA_A}
 SP_DEVICE_INTERFACE_DETAIL_DATA_W = packed record
  cbSize: DWORD;
  DevicePath: array [0..ANYSIZE_ARRAY - 1] of WideChar;
end;

 {$EXTERNALSYM SP_DEVICE_INTERFACE_DETAIL_DATA_W}
 TSPDeviceInterfaceDetailDataA = SP_DEVICE_INTERFACE_DETAIL_DATA_A;
 TSPDeviceInterfaceDetailDataW = SP_DEVICE_INTERFACE_DETAIL_DATA_W;
 {$IFDEF UNICODE}
 TSPDeviceInterfaceDetailData = TSPDeviceInterfaceDetailDataW;
 PSPDeviceInterfaceDetailData = PSPDeviceInterfaceDetailDataW;
 {$ELSE}
 TSPDeviceInterfaceDetailData = TSPDeviceInterfaceDetailDataA;
 PSPDeviceInterfaceDetailData = PSPDeviceInterfaceDetailDataA;
 {$ENDIF UNICODE}
function SetupDiGetClassDevs(ClassGuid: PGUID; const Enumerator: PTSTR;
    hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external 'SetupApi.dll' name 'SetupDiGetClassDevsA';
function SetupDiEnumDeviceInterfaces(DeviceInfoSet: HDEVINFO;
    DeviceInfoData: PSPDevInfoData; const InterfaceClassGuid: TGUID;
    MemberIndex: DWORD; var DeviceInterfaceData: TSPDeviceInterfaceData): BOOL; stdcall; external 'SetupApi.dll';
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall; external 'SetupApi.dll';
function SetupDiGetDeviceInterfaceDetail(DeviceInfoSet: HDEVINFO;
    DeviceInterfaceData: PSPDeviceInterfaceData;
    DeviceInterfaceDetailData: PSPDeviceInterfaceDetailData;
    DeviceInterfaceDetailDataSize: DWORD; var RequiredSize: DWORD;
    Device: PSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailA';

type ADeviceNames = array of TDeviceNames;

procedure PhInfoClear();
function scandev :boolean;
Function USBClosePort():Boolean;
Function USBOpenPort(PortName:String;TimeOut:Integer):Boolean;
Function USBBulkWritePort(Buffer:Pointer;Length:Integer):Integer;
function USBBulkReadPort(num: dword):boolean;
Function ReadUBUSData:word;
function BB5_USB_ScanAndOpenConnection(DevType, Filter: String; Verbose:boolean):byte;
function BufToStr(Buf:Pointer; BufLen: longword): string;
function UsbReadPhName():string;
procedure UsbReadPhInfo();
procedure UsbReadPhInfoAll();
function UsbReadMcuSw():string;
function UsbReadIMEIPl():string;
function UsbReadPhMode():string;
function UsbReadAPECoreSW():string;
function UsbReadPPMversioninfo():string;
function UsbReadCNTinfo():string;
function UsbReadApeVarVer():string;
function UsbReadApetest():string;
function UsbReadAPEAdsp():string;
function UsbReadPSN():string;
function UsbReadProductCode():string;
function UsbReadBasicProductionCode():string;
function UsbReadMcode():string;
function UsbReadLSN():string;
function UsbReadHWID():string;
function UsbReadTahvo():string;
function UsbReadRetu():string;
function UsbReadBatvalue():string;
function UsbReadCamver():string;
function UsbReadBTver():string;
function UsbReadAPEBT():string;
function UsbReadAPEHW():string;
function UsbReadDSP():string;
function UsbReadLCD():string;
function ReadFlashIc(cmtflash:dword;apeflash:dword):string;
function UsbResetUcode():string;
function UsbWritePRdcode():string;
function UsbReadAsk():string;
function UsbExecModeComand(comand:pointer;Len:integer):string;
function UsbSetPhoneMode(mode:integer):string;
function UsbPmGetRecCou(Field:word):integer;
function UsbPmGetRecLen(Field:word;Rec:word):dword;
function UsbPmReadRecord(Field:word;Rec:word;Len:dword):string;
function UsbFullFactorySet():boolean;
function UsbSWupgrDef():boolean;
function UsbServiceCentreDef():boolean;
function UsbPrdTuneSet():boolean;
function UsbUserDefSet():boolean;
function UsbLeaveFactSet():boolean;
function UsbResetLifeTimer():string;
function UsbReadLifeTimer():string;
function UsbPmWriteRecord(Field:word;Rec:word;s:string):string;
function UsbPmWriteRecBuf(Field:word;Rec:word;Buf:Pointer;Len:word):string;
function UsbReadPPItem(Item:byte):string;
function UsbWritePPItem(Item:byte;Data:byte):string; // запись РР по итемам
function SmartAlgoFsinit():string;   // инициализация ФС
function writeLifeTime():string;  // Зпапись лайфтайма
function USBreadIMEItoNet():string; //чтение имени к сети
function USBreadIMEIsvnet():string; //чтение имени к сети
function ReadIMEI2net():string;  // Чтение имени к сети
function ReadIMEISV2net():string; // Чтение име Св к сети
function getproviderstring():string; // получение информации о провайдере
function UsbResetUcodeOldBB5():string; // Резет кода на старых ББ5
function scandrives():string; // получаем список дисков
function currenteat():string;
function USBRawCharge():string;
function GetTemp():string;
function preformatS40():string;
function formats40(drive:string):string;
function formatS60cycle():string;
function formats601st(a:byte):string;
function sendNCK():string;
function check3stage():string;
function starttest():string;
function scandriveS40():string;
function GetFileSizeS40(path:string):dword;
function extractfileS40(F:TMemoryStream;fullpath:string;len:dword;info:integer):boolean;
function getfilesizes60(fullpath:string):DWORD;
function extractfileS60(F:TMemoryStream;fullpath:string;len:dword;info:integer):boolean;
function UsbGetS40PhbCou():integer;
function UsbGetS40PhbRecord(RecNum:word):string;
function UsbS40PhbRecWr(Buf:pointer;Len:word):string;
function UsbSetPat(pat:word):string;
function USbWriteFileS60(InFile:TMemoryStream;filewithpath:string;info:integer):boolean;
function initialiseFS():string;
function S60deletefile(path:string):Boolean;
function gets40drv():Boolean;
function Light(state:string):boolean;
function listfolder(folder:string):string;
function APEtestrun():string;
function getlockfield():string;
function USBFSwriteS40Uni(InFile:TMemoryStream;filewithpath:string;info:integer):boolean;
function USBS40DeleteFile(filepath:string):Boolean;
function readport():boolean;
function listfolderS40(path:string):string;
function UsbS40ListFile(path:string):string;
function UsbS60ListFile(path:string):string;
function GetUsbDir(path:string):string;
function UsbS40ContList(path:string):string;
function UsbS60ContList(path:string):string;
function UsbRplsimlockdata(s:string):string;
function UsbWriteSimLokkey(s:string):string;
function UsbWriteSDDkey(s:string):string;
function uncksend(code:string;level:Integer):string;
procedure preflashread ();
function newSelftestitem(testid:string):string;
function verifyadl():word;
function s60startkeybtest () : Boolean;  //s60
function checkkeys60 () : Boolean;    //s60
function finkeybtests60 () : Boolean;  //s60
function getkeyboardstatus () :Boolean; //s40
function KBtestEnd () :boolean;     //s40
function KBstest () :Boolean;     //s40
function usbs40chr(level:word; filepath:string):Boolean;
procedure s60preflashread();
function find_device(): String;
function catchdevice():Byte;
function DevPresent():Boolean;
function ResetPhone():boolean;
function UsbReadFileS60(F:TStream;fullpath:string):boolean;
function USBBulkReadPortInt(num: dword):integer;
function WriteLTnew(lt:Integer;position:integer):Boolean;
Function S40CreateDir(Dir:string):byte;
function GetPBstatus():Dword;
function UsbWriteCLMA(key:string):boolean;
function UsbSx4st1():string;
function UsbSx4st2(s:string):string;
function UsbSx4st3(s:string):string;
function UsbSx4chst():string;

implementation
uses Unit1, UnitAndrey, UnitE1;

function UsbSx4chst():string;
var
  buf:string;
begin
   buf:='Error';
   USBBulkWritePort(@uSx4chst, Length(uSx4chst));
          if USBBulkReadPort($FFFF) then
         if rxBuf[11]=0 then buf:='Ok';
  Result:=buf;
end;

function UsbSx4st3(s:string):string;
var
  buf,kom:string;
begin
   buf:='Error';
   kom:='';
   SetLength(kom,Length(uSx43st));
   BufCopy(@uSx43st,@kom[1],Length(uSx43st));
   kom:=kom+s;
   USBBulkWritePort(@kom[1], Length(kom));
          if USBBulkReadPort($FFFF) then
         if rxBuf[11]=0 then buf:='Ok';
  Result:=buf;
end;

function UsbSx4st2(s:string):string;
var
  buf,kom:string;
begin
   buf:='Error';
   kom:='';
   SetLength(kom,Length(uSx42st));
   BufCopy(@uSx42st,@kom[1],Length(uSx42st));
   kom:=kom+s;
   USBBulkWritePort(@kom[1], Length(kom));
          if USBBulkReadPort($FFFF) then
         if rxBuf[11]=0 then buf:=BufToHexStr(@rxBuf[12],24);
  Result:=buf;
end;

function UsbSx4st1():string;
var
  buf:string;
begin
   buf:='Error';
   USBBulkWritePort(@uSx41st, Length(uSx41st));
          if USBBulkReadPort($FFFF) then
         if rxBuf[11]=0 then buf:=BufToHexStr(@rxBuf[12],16);
  Result:=buf;
end;

function UsbReadFileS60(F:TStream;fullpath:string):boolean;
var
i:integer;
kom:string;
sw:WideString;
Len:byte;
begin
  Result:=false;
          kom:='';
          for i:=0 to Length(Get60File) do kom:=kom+Chr(Get60File[i]);
          sw:=UTF8Decode(fullpath);
          Len:=Length(sw);
          byte ((@kom[18])^):=Len;
          Len:=Len shl 1;
          SetLength(kom,Length(kom)+Len-1);
          BufCopySwapWord(@sw[1],@kom[19],Len);
//          kom:=kom+chr(0)+chr(0); ///  -> ну собственно два байта добавляем
          word ((@kom[5])^):=Len+12;   //в конце необходимо добавлять 2 байта 0 прибавляем их к длинне
          WordSwap(@kom[5]);
          word ((@kom[15])^):=length(kom)-10; // хидер-длина универсальный тип - подходит ко всем генерациям ( в каждой версии длина разная ) - я использовал общее среднее-  работает
          WordSwap(@kom[15]);

          USBBulkWritePort(@kom[1], Length(kom));
          if not USBBulkReadPort($FFFF) then exit;


          Result:=true;
end;

function uncksend(code:string;level:Integer):string;
var
  i:Integer;
  sw:WideString;
begin
          Result:='Error';
          sw:=UTF8Decode(code);
          i:=(Length(sw) shl 1)+2;
          BufCopySwapWord(@sw[1],@NCKput[20],i);
          NCKput[10]:=level;
          USBBulkWritePort(@NCKput, Length(NCKput));
          if USBBulkReadPort($FFFF) then

  i:=rxBuf[10];
  case i of
 0: result:='Unlock code Accepted! :)';
 8: result:='Bad Code... :(';
 $0C: result:='Retries blocked! Counter full! :(';
 9: result:='Phone already unlocked! :)';
 end;
end;


function GetUsbDir(path:string):string;
Label cont;
var
i:integer;
s,kom:string;
sw:WideString;
Len:word;
begin
  Result:='';
          kom:='';
          for i:=0 to Length(Get40ChDir) do kom:=kom+Chr(Get40ChDir[i]);
          sw:=UTF8Decode(Copy(path,1,Length(path)-1));
          Len:=(Length(sw) shl 1)+2;
          word ((@kom[11])^):=Len;
          WordSwap(@kom[11]);
          SetLength(kom,Length(kom)+Len-1);
          BufCopySwapWord(@sw[1],@kom[13],Len);;
          word ((@kom[5])^):=Len+6;
          WordSwap(@kom[5]);
          USBBulkWritePort(@kom[1],Length(kom));
          if USBBulkReadPort($FFFF) then
          Result:=BufToHexStr(@rxBuf[0],Length(rxBuf));
end;

function UsbS40ContList(path:string):string;
var
i,Len:integer;
s:string;
begin
     Result:='';
     if not Ucont then begin Ucont:=true; exit; end;
          if not USBBulkReadPort($FFFF) then exit;
          if rxBuf[10]=0 then Ucont:=false;
          if rxBuf[15]=0 then begin Ucont:=false; exit; end;
          Len:=byte((@rxBuf[37])^);
          i:=38;
          while word((@rxBuf[i])^)<>0 do begin
          WordSwap(@rxBuf[i]);
          i:=i+2;
          end;
          SetLength(s,255);
          i:=UnicodeToUtf8(@s[1],255,@rxBuf[38],Len);
          SetLength(s,i-2);
          if s='' then exit;
          DwordSwap(@rxBuf[16]);
          Len:=dword((@rxBuf[16])^);
          if Len=0 then s:=s+Chr($5C);
          Result:=path+s;
end;

function UsbS60ListFile(path:string):string;
Label cont;
var
i:integer;
kom:string;
sw:WideString;
Len:byte;
begin
  Result:='';
          kom:='';
          Ucont := true;
          for i:=0 to Length(Get60ListGal) do kom:=kom+Chr(Get60ListGal[i]);
          sw:=UTF8Decode(path);
          Len:=Length(sw);
          byte ((@kom[18])^):=Len;
          Len:=Len shl 1;
          SetLength(kom,Length(kom)+Len-1);
          BufCopySwapWord(@sw[1],@kom[19],Len);
          kom:=kom+chr(0)+chr(0); ///  -> ну собственно два байта добавляем
          word ((@kom[5])^):=Len+14;   //в конце необходимо добавлять 2 байта 0 прибавляем их к длинне
          WordSwap(@kom[5]);
          word ((@kom[15])^):=length(kom)-12; // хидер-длина универсальный тип - подходит ко всем генерациям ( в каждой версии длина разная ) - я использовал общее среднее-  работает
          WordSwap(@kom[15]);
          USBBulkWritePort(@kom[1],Length(kom));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]=$0F then begin Ucont:=false; Result:=''; exit; end;
          Result:='Ok';
end;

function UsbS60ContList(path:string):string;
begin
     Result:='';
     if not Ucont then begin Ucont:=true; exit; end;
          if not USBBulkReadPort($FFFF) then exit;
          if rxBuf[10]=$0F then begin Ucont:=false; Result:=''; exit; end;
          Result:='Ok';
end;

function UsbS40ListFile(path:string):string;
Label cont;
var
i:integer;
s,kom:string;
sw:WideString;
Len:word;
begin
  Result:='';
          kom:='';
          Ucont :=true;
          for i:=0 to Length(Get40ListGal) do kom:=kom+Chr(Get40ListGal[i]);
          sw:=UTF8Decode(path+'*');
          Len:=(Length(sw) shl 1)+2;
          word ((@kom[11])^):=Len;
          WordSwap(@kom[11]);
          SetLength(kom,Length(kom)+Len-1);
          BufCopySwapWord(@sw[1],@kom[13],Len);;
          word ((@kom[5])^):=Len+6;
          WordSwap(@kom[5]);
          USBBulkWritePort(@kom[1],Length(kom));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]=0 then Ucont:=false;
          if rxBuf[15]=0 then begin Ucont:=false; exit; end;
          Len:=byte((@rxBuf[37])^);
          i:=38;
          while word((@rxBuf[i])^)<>0 do begin
          WordSwap(@rxBuf[i]);
          i:=i+2;
          end;
          SetLength(s,255);
          i:=UnicodeToUtf8(@s[1],255,@rxBuf[38],Len);
          SetLength(s,i-2);
          if s='' then exit;
          DwordSwap(@rxBuf[16]);
          Len:=dword((@rxBuf[16])^);
          if Len=0 then s:=s+Chr($5C);
          Result:=path+s;
end;

function UsbSetPat(pat:word):string;
begin
     Result:='Error';
          word((@LCDpat[14])^):=pat;
          USBBulkWritePort(@LCDpat, Length(LCDpat));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<> 0 then exit;
          Result:='Ok';
end;

function UsbS40PhbRecWr(Buf:pointer;Len:word):string;
begin
     Result:='Error';
     BufCopy (@S40PhbRecWr,@txBuf,Length(S40PhbRecWr));
     BufCopy (Buf,@txBuf[26],Len);
     word((@txBuf[4])^):=Len+$14;
     WordSwap(@txBuf[4]);
          USBBulkWritePort(@txBuf, Len+26);
          if USBBulkReadPort($FFFF) then
           if rxBuf[10]<>0 then exit;
            USBBulkWritePort(@S40PhbRecWrEnd,Length(S40PhbRecWrEnd));
          if USBBulkReadPort($FFFF) then
           if rxBuf[10]<>0 then exit;
            WordSwap(@rxBuf[26]);
            Result:=IntToStr(word((@rxBuf[26])^));
end;

function UsbGetS40PhbRecord(RecNum:word):string;
var
Len:integer;
begin
          Result:='';
          word((@GetS40PhbRecC[20])^):=RecNum;
          WordSwap(@GetS40PhbRecC[20]);
          USBBulkWritePort(@GetS40PhbRecC, Length(GetS40PhbRecC));
          if USBBulkReadPort($FFFF) then
          if word((@rxBuf[18])^)= 0 then exit;
          WordSwap(@rxBuf[4]);
          Len:= word((@rxBuf[4])^)-20;
          Result:=BufToHexStr(@rxBuf[26],Len);
end;

function UsbGetS40PhbCou():integer;
begin
          Result:=0;
          USBBulkWritePort(@GetS40PhbCouC, Length(GetS40PhbCouC));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<> 0 then exit;
          WordSwap(@rxBuf[26]);
          Result:=word((@rxBuf[26])^);
end;

function UsbWritePPItem(Item:byte;Data:byte):string;
begin
     Result:='Error';
          WrPPItem[8]:=ISIheadertransid;
          WrPPItem[16]:=Item;
          WrPPItem[17]:=Data;
          USBBulkWritePort(@WrPPItem, Length(WrPPItem));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<> 0 then exit;
          Result:='Ok';
end;

function UsbReadPPItem(Item:byte):string;
begin
     Result:='Error';
          RdPPItem[16]:=Item;
          RdPPItem[8]:=ISIHeaderTransId;
          USBBulkWritePort(@RdPPItem, Length(RdPPItem));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]= $2 then exit;
          Result:=IntToStr(rxBuf[17]);
end;

function UsbPmWriteRecBuf(Field:word;Rec:word;Buf:Pointer;Len:word):string;
begin
     Result:='Error';
     BufCopy (@WritePmFieldRec,@txBuf,Length(WritePmFieldRec));
     BufCopy (Buf,@txBuf[20],Len);
     word((@txBuf[10])^):=Field;
     word((@txBuf[12])^):=Rec;
     WordSwap(@txBuf[10]);
     WordSwap(@txBuf[12]);
     word((@txBuf[18])^):=Len;
     WordSwap(@txBuf[18]);
     word((@txBuf[4])^):=Len+$0E;
     WordSwap(@txBuf[4]);
          USBBulkWritePort(@txBuf, Len+20);
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]= $13 then exit;
//          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Result:='Ok';
end;

function UsbPmWriteRecord(Field:word;Rec:word;s:string):string;
var
Len:word;
begin
     Result:='Error';
     BufCopy (@WritePmFieldRec,@txBuf,Length(WritePmFieldRec));
     Len:=StrToBufHex(s,@txBuf[20]);
     word((@txBuf[10])^):=Field;
     word((@txBuf[12])^):=Rec;
     WordSwap(@txBuf[10]);
     WordSwap(@txBuf[12]);
     word((@txBuf[18])^):=Len;
     WordSwap(@txBuf[18]);
     word((@txBuf[4])^):=Len+$0E;
     WordSwap(@txBuf[4]);
          USBBulkWritePort(@txBuf, Len+20);
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]= $13 then exit;
//          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Result:='Ok';
end;

function UsbPmReadRecord(Field:word;Rec:word;Len:dword):string;
var
Tlen:dword;  // смещение у нас дворд это значение с которой позиции будет читатся блок данных
i:integer;
begin
          Result:='';
          dword((@GetBlRecData[16])^):=0;  // так как всегда используется один и тотже буфер в команде - чистим
          word((@GetBlRecData[10])^):=Field; // номер поля имеет тип ворд, таким образом мы вписываем два байта
          word((@GetBlRecData[12])^):=Rec;   // номер записи имеет тип ворд, таким образом мы вписываем два байта
          WordSwap(@GetBlRecData[10]);     // так как они ногами вперед, переворачиваем их
          WordSwap(@GetBlRecData[12]);     // и второй тоже
          if Len>$400 then begin    // если длина больше, чем один блок то
          i:=Len div $400;       //имеем количество полных блоков
          Len:=Len mod $400;     // имеем остаток
          Tlen:=0;    // смещение изначально у нас 0, т.е. читаем мы сначала файла (блока данных)
          word((@GetBlRecLongData[10])^):=Field;   //
          word((@GetBlRecLongData[12])^):=Rec;     // теже яйца - только для другой команды
          WordSwap(@GetBlRecLongData[10]);         // просто для простоты сделал две команды, одна читает 400хекс байт
          WordSwap(@GetBlRecLongData[12]);         // а вторая читает меньше, вернее то, что остается или если меньше чем 400 изначально
            while i<>0 do begin                    // если полных блоков не 0 то
            dword((@GetBlRecLongData[16])^):=Tlen; // вписываем текущее смещение в команду и
            DWordSwap(@GetBlRecLongData[16]);     //  переворачиваем его ногами вперед
            USBBulkWritePort(@GetBlRecLongData, Length(GetBlRecLongData));  //
            if USBBulkReadPort($FFFF) then                                  // читаем свои 400 байт (эта длина физически забита в команде
             Result:=Result+BufToHexStr(@rxBuf[24],$400);                   // добавляем его к тому, что прочли
             i:=i-1;        // уменьшаем кол-во блоков, т.к. прочли
             Tlen:=Tlen+$400; // смещение увеличиваем на значение прочитанных байт, т.е. следущий кусок читать будем с этого смещения
             byte((@GetBlRecLongData[8])^):=byte((@GetBlRecLongData[8])^)+1; // это изврат с номером фрейма
            end;  // прочли все полные блоки
            byte((@GetBlRecData[8])^):=byte((@GetBlRecLongData[8])^)+1; // извратили фрейм
            dword((@GetBlRecData[16])^):=Tlen; // получили текущее значение смещения  и пихаем его в команду, которая читает короткие блоки
            DWordSwap(@GetBlRecData[16]);      // ну и ногами вперед
          end;
          dword((@GetBlRecData[20])^):=Len; //  имеем остаток или не полный блок при короткой длине
          DWordSwap(@GetBlRecData[20]);     //  ногами вперед
          USBBulkWritePort(@GetBlRecData, Length(GetBlRecData));  //
          if USBBulkReadPort($FFFF) then                          // и читаем его
          Result:=Result+BufToHexStr(@rxBuf[24],Len);             //  все, писец
end;

function UsbPmGetRecLen(Field:word;Rec:word):dword;
begin
          Result:=$F0000000;
          word((@GetBlockXXXFieldXXX[10])^):=Field;
          word((@GetBlockXXXFieldXXX[12])^):=Rec;
          WordSwap(@GetBlockXXXFieldXXX[10]);
          WordSwap(@GetBlockXXXFieldXXX[12]);
          USBBulkWritePort(@GetBlockXXXFieldXXX, Length(GetBlockXXXFieldXXX));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<>0 then exit;
          DWordSwap(@rxBuf[16]);
          Result:=dword((@rxBuf[16])^);
end;

function UsbPmGetRecCou(Field:word):integer;
begin
          Result:=0;
          word((@GetBlock[10])^):=Field ;
          WordSwap(@GetBlock[10]);
          USBBulkWritePort(@GetBlock, Length(GetBlock));
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]= $4 then exit;
          WordSwap(@rxBuf[14]);
          Result:=word((@rxBuf[14])^);
end;

procedure UsbReadPhInfo();
begin
    PhInfoRecord.APECoreSW:= UsbReadAPECoreSW;
    PhInfoRecord.Name:= UsbReadPhName;
    PhInfoRecord.PPMInfo:= UsbReadPPMversioninfo;
    PhInfoRecord.MCUSW:=UsbReadMcuSw;
    PhInfoRecord.IMEIPlain:= UsbReadIMEIPl;
    PhInfoRecord.ProductCode:= UsbReadProductCode;
end;

procedure UsbReadPhInfoAll();
begin
    PhInfoRecord.APECoreSW:= UsbReadAPECoreSW;
    PhInfoRecord.Name:= UsbReadPhName;
    PhInfoRecord.MCUSW:=UsbReadMcuSw;
    PhInfoRecord.IMEIPlain:= UsbReadIMEIPl;
    PhInfoRecord.APEVariant:= UsbReadApeVarVer;
    PhInfoRecord.APEADSPSW:= UsbReadAPEAdsp;
    PhInfoRecord.DSP:= UsbReadDSP;
    PhInfoRecord.APETest:= UsbReadApetest;
    PhInfoRecord.PPMInfo:= UsbReadPPMversioninfo;
    PhInfoRecord.CNT:= UsbReadCNTinfo;
    PhInfoRecord.PrdSerial:= UsbReadPSN;
    PhInfoRecord.ProductCode:= UsbReadProductCode;
    PhInfoRecord.BisicPrdCode:= UsbReadBasicProductionCode;
    PhInfoRecord.ModuleCode:= UsbReadMcode;
    PhInfoRecord.LSN:= UsbReadLSN;
    PhInfoRecord.HWID:= UsbReadHWID;
    PhInfoRecord.Retu:= UsbReadRetu;
    PhInfoRecord.Tahvo:= UsbReadTahvo;
    PhInfoRecord.Bat:= UsbReadBatvalue;
    PhInfoRecord.CMTBtver:= UsbReadBTver;
    PhInfoRecord.APEBT:= UsbReadAPEBT;
    PhInfoRecord.APEHW:= UsbReadAPEHW;
    PhInfoRecord.LCD:= UsbReadLCD;
    ReadIMEI2net;
    ReadIMEISV2net;
end;


function check3stage():string;
var
  a:string;
begin
   USBBulkWritePort(@check1st, Length(check1st));
          if USBBulkReadPort($FFFF) then
     a:=Hex2Chr(Byte2Str(RxBuf[5])+Byte2Str(RxBuf[7])+Byte2Str(RxBuf[9])+Byte2Str(RxBuf[11]));
       USBBulkWritePort(@check2nd, Length(check2nd));
        if USBBulkReadPort($FFFF) then
      Result:=a;
end;

function UsbSetPhoneMode(mode:integer):string;
begin
          byte((@SetMode[10])^):=mode;
          Result:=UsbExecModeComand(@SetMode,Length(SetMode));
end;


function UsbReadPhMode():string;
begin
          Result:=UsbExecModeComand(@ChkPhMode,Length(ChkPhMode));
end;

function UsbExecModeComand(comand:pointer;Len:integer):string;
begin
  try
          Result:='Error';
          USBBulkWritePort(comand,Len);
          if USBBulkReadPort($FFFF) then
          Result:=PhModeToStr(byte((@rxBuf[11])^));
//          Result:=BufToHexStr(@rxBuf[0], Length(rxBuf));
 except
 result:='Error';
 end;
end;

function UsbReadIMEIPl():string;
begin
          Result:='Error';
          USBBulkWritePort(@IMEIplain, Length(IMEIplain));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadMcuSw():string;
begin
          Result:='Error';
          USBBulkWritePort(@SowtwareInfo, Length(SowtwareInfo));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadPhName():string;
begin
          Result:='Error';
          USBBulkWritePort(@PhoneName, Length(PhoneName));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadAPECoreSW():string;
begin
          Result:='Error';
          USBBulkWritePort(@ApeVer, Length(ApeVer));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadPPMversioninfo():string;
begin
          Result:='Error';
          USBBulkWritePort(@PPMversioninfo, Length(PPMversioninfo));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadCNTinfo():string;
begin
          Result:='Error';
          USBBulkWritePort(@CNTinfo, Length(CNTinfo));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadApeVarVer():string;
begin
          Result:='Error';
          USBBulkWritePort(@ApeVarVer, Length(ApeVarVer));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadApetest():string;
begin
          Result:='Error';
          USBBulkWritePort(@Apetest, Length(Apetest));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadAPEAdsp():string;
begin
          Result:='Error';
          USBBulkWritePort(@APEAdsp, Length(APEAdsp));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadProductCode():string;
begin
          Result:='Error';
          USBBulkWritePort(@ProductCode, Length(ProductCode));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadPSN():string;
begin
          Result:='Error';
          USBBulkWritePort(@ProductionSerialnumber, Length(ProductionSerialnumber));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadBasicProductionCode():string;
begin
          Result:='Error';
          USBBulkWritePort(@BasicProductionCode, Length(BasicProductionCode));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadMcode():string;
begin
          Result:='Error';
          USBBulkWritePort(@Mcode, Length(Mcode));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadLSN():string;
begin
          Result:='Error';
          USBBulkWritePort(@LSN, Length(LSN));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadHWID():string;
begin
          Result:='Error';
          USBBulkWritePort(@HWversion, Length(HWVersion));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadRetu():string;
begin
          Result:='Error';
          USBBulkWritePort(@RetuVersion, Length(RetuVersion));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadTahvo():string;
begin
          Result:='Error';
          USBBulkWritePort(@TahvoVersion, Length(TahvoVersion));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadBatvalue():string;
begin
          Result:='Error';
          USBBulkWritePort(@Batvalue, Length(Batvalue));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Delete(Result,1,42);
          Delete(Result,3,1);
          Delete(Result,5,5);
          Result:=IntToStr(HexToInt('$'+Result));
end;

function UsbReadCamver():string;
begin
          Result:='Error';
          USBBulkWritePort(@CamVer, Length(CamVer));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadBTver():string;
begin
          Result:='Error';
          USBBulkWritePort(@Btversion, Length(Btversion));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadAPEBT():string;
begin
          Result:='Error';
          USBBulkWritePort(@Apebt, Length(Apebt));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadAPEHW():string;
begin
          Result:='Error';
          USBBulkWritePort(@Apehw, Length(Apehw));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadDSP():string;
begin
          Result:='Error';
          USBBulkWritePort(@DSPinf, Length(DSPinf));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadLCD():string;
begin
          Result:='Error';
          USBBulkWritePort(@LCDver, Length(LCDver));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function UsbReadRFic():string;
begin
          Result:='Error';
          USBBulkWritePort(@RFic, Length(RFic));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function ReadFlashIc(cmtflash:dword;apeflash:dword):string;
var
  buf,fl,buf1,afl:string;
  res:string;
begin
              case cmtflash of
                // bad flash
               $0000FFFF:fl:='Bad Flash Type , if MMC - It Ok';
               //Samsung SEC Flash ic
               $003000EC:fl:='SAMSUNG [SEC] => K5W1G13ACB';
               $22E800EC:fl:='SAMSUNG [SEC] => K5G2829ATC';
               $22FE00EC:fl:='SAMSUNG [SEC] => K8S5615ETA';
               $220C00EC:fl:='SAMSUNG [SEC] => K5G1257ATM';
               $003500EC:fl:='SAMSUNG [SEC] => K5E5657ACB';
               $225000EC:fl:='SAMSUNG [SEC] => K8S6415ETB';
               $00A100EC:fl:='SAMSUNG [SEC] => K5E1G12ACM';
               $220800EC:fl:='SAMSUNG [SEC] => K8F5615ETM\K5G5629ATD';
               $003600EC:fl:='SAMSUNG [SEC] => K5E1212ACM';
               $22FA00EC:fl:='SAMSUNG [SEC] => K8S6415ETA';
               $004000EC:fl:='SAMSUNG [SEC] => KAT00F00RA [NAND]';
               $226800EC:fl:='SAMSUNG [SEC] => K8S3215ETE';
               $002000EC:fl:='SAMSUNG [SEC] => KAK13N00GC [NAND]';
               $00300098:fl:='SAMSUNG => Not in base';
               //Samsung Flash ic
               $00780098:fl:='SAMSUNG => K5E1G12ACM';
               //Intel flash ic
               $88740089:fl:='INTEL => 28F640W18TE';
               $89820089:fl:='INTEL => 0046L0Y1GG/NU48F512'; //
               $89810089:fl:='INTEL => NU48F256'; //
               //ST flash ic
               $881C0020:fl:='ST => M39L0R807';
               $00400020:fl:='ST => M39BORBOAD';
               //Spansion Flash ic
               $002F0001:fl:='SPANSION => 72NS256N';
               $00350001:fl:='SPANSION => 72NS128N';
               $2C7E0001:fl:='SPANSION => 72NS128N';
               $327E0001:fl:='SPANSION => 71NS128P';
               $307E0001:fl:='SPANSION => 72NS512P';
               $003F0001:fl:='SPANSION => 72NS512P';
               $2D7E0001:fl:='SPANSION => 72NS256NOP';
               $317E0001:fl:='SPANSION => 72NS256PD';
               $00410001:fl:='SPANSION => 72NS256PD';
               //Not recognized for now
               $00000000:fl:='Not detected';
               $00010000:fl:='Not used';
               else
               fl:='UNKNOW [NOT IN BASE]';
              end;

              if FL<>'Not detected' then form1._msg('CMT Flash ID : '+inttohex(cmtflash, 8)+' < '+fl);

               case apeflash of
                // bad flash
               $0000FFFF:afl:='Bad Flash Type , if MMC - It Ok';
               //Samsung SEC Flash ic
               $003000EC:afl:='SAMSUNG [SEC] => K5W1G13ACB';
               $22E800EC:afl:='SAMSUNG [SEC] => K5G2829ATC';
               $22FE00EC:afl:='SAMSUNG [SEC] => K8S5615ETA';
               $220C00EC:afl:='SAMSUNG [SEC] => K5G1257ATM [NAND]';
               $003500EC:afl:='SAMSUNG [SEC] => K5E5657ACB';
               $225000EC:afl:='SAMSUNG [SEC] => K8S6415ETB';
               $00A100EC:afl:='SAMSUNG [SEC] => K5E1G12ACM [NAND]';
               $220800EC:afl:='SAMSUNG [SEC] => K8F5615ETM\K5G5629ATD';
               $003600EC:afl:='SAMSUNG [SEC] => K5E1212ACM [NAND]';
               $22FA00EC:afl:='SAMSUNG [SEC] => K8S6415ETA';
               $004000EC:afl:='SAMSUNG [SEC] => KAT00F00RA [NAND]';
               $226800EC:afl:='SAMSUNG [SEC] => K8S3215ETE';
               $002000EC:afl:='SAMSUNG [SEC] => KAK13N00GC [NAND]';
               //Samsung Flash ic
               $00780098:afl:='TOSHIBA => K5E1G12ACM';
               //Intel flash ic
               $88740089:afl:='INTEL => 28F640W18TE';
               //ST flash ic
               $881C0020:afl:='ST => M39L0R807';
               $00400020:afl:='ST => M39BORBOAD';
               $00B10020:afl:='ST => 1GB';
               //Spansion Flash ic
               $002F0001:afl:='SPANSION => 72NS256N';
               $00350001:afl:='SPANSION => 72NS128N';
               $2C7E0001:afl:='SPANSION => 72NS128N';
               $327E0001:afl:='SPANSION => 71NS128P';
               $307E0001:afl:='SPANSION => 72NS512P';
               $2D7E0001:afl:='SPANSION => 72NS256NOP';
               //Not recognized for now
               $00000000:afl:='Not detected';
               $00010000:afl:='Not used';
               else
               afl:='UNKNOW [NOT IN BASE]';
               end;
     if afl<>'Not detected' then form1._msg('APE Flash ID : '+inttohex(apeflash, 8)+' < '+afl);


end;

function USBPreCheck():string;
begin

end;

function UsbResetUcode():string;
begin
  Result:=PmWriteRecord(308,5,'31323334350000000000');
end;

function UsbResetUcodeOldBB5():string;
var
  buf:string;
begin
          Result:='Error';
          USBBulkWritePort(@ResetOldBB5User, Length(ResetOldBB5User));
          if USBBulkReadPort($FFFF) then
          buf:=byte2str(rxbuf[13])+byte2str(rxbuf[14]);
          Result:= buf;
end;


function UsbWritePRdcode():string;
begin
 Result:='Error';
          USBBulkWritePort(@WriteProductCode, Length(WriteProductCode));
          if USBBulkReadPort($FFFF) then
          Result:='[OK]';
end;

function UsbReadAsk():string;
begin
  Result:='Error';
          USBBulkWritePort(@GetASK, Length(GetASK));
          if USBBulkReadPort($FFFF) then
          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
end;

function USBreadIMEIsvnet():string;
var
  buf:string;
  i:Integer;
begin
USBBulkWritePort(@IMEISv2Net, Length(IMEISv2Net));
    if USBBulkReadPort($FFFF) then
      for i := 16 to 24 do
      begin
          buf := buf + BYTE2STR(rxBuf[i]) + ' ';
      end;
Result:=buf;
end;

function USBreadIMEItoNet():string;
var
  buf:string;
  I:integer;
begin
 USBBulkWritePort(@IMEI2net, Length(IMEI2net));
    if USBBulkReadPort($FFFF) then
      for i := 16 to 23 do
      begin
          buf := buf + BYTE2STR(rxBuf[i]) + ' ';
      end;
Result:=buf;
end;

function getproviderstring():string;
var
  buf:string;
begin
   USBBulkWritePort(@Spcheck, Length(Spcheck));
          if USBBulkReadPort($FFFF) then
         buf:=BufToStr(@rxBuf[0], Length(rxBuf));
  Result:=buf;
end;


procedure PhInfoClear();
begin
     PhInfoRecord.Name:='';
     PhInfoRecord.PhType:='';
     PhInfoRecord.Model:='';
     PhInfoRecord.MCUSW:='';
     PhInfoRecord.PPMInfo:='';
     PhInfoRecord.HWID:='';
     PhInfoRecord.PCI:='';
     PhInfoRecord.RFIC:='';
     PhInfoRecord.DSP:='';
     PhInfoRecord.APECoreSW:='';
     PhInfoRecord.APEVariant:='';
     PhInfoRecord.Retu:='';
     PhInfoRecord.Tahvo:='';
     PhInfoRecord.APEHW:='';
     PhInfoRecord.APEADSPSW:='';
     PhInfoRecord.APEBT:='';
     PhInfoRecord.PrdSerial:='';
     PhInfoRecord.ProductCode:='';
     PhInfoRecord.ModuleCode:='';
     PhInfoRecord.BisicPrdCode:='';
     PhInfoRecord.IMEIPlain:='';
     PhInfoRecord.IMEI2Net:='';
     PhInfoRecord.IMEISv2Net:='';
     PhInfoRecord.APETest:='';
     PhInfoRecord.LSN:='';
     PhInfoRecord.Bat:='';
     PhInfoRecord.Cam:='';
     PhInfoRecord.CMTBtver:='';
     PhInfoRecord.APEBT:='';
     PhInfoRecord.APEHW:='';
     PhInfoRecord.LCD:='';
     PhInfoRecord.DSP:='';
     PhInfoRecord.FLic:='';
     PhInfoRecord.CRR:='';


end;

Function USBClosePort():Boolean;
begin
  try
  CloseHandle(hDevice);
  hDevice:=INVALID_HANDLE_VALUE;
  Result:=hDevice=INVALID_HANDLE_VALUE;
  except
  result:=false;
  end;
end;

Function USBOpenPort(PortName:String;TimeOut:Integer):Boolean;
var TimeOutCount:Integer;
begin
//     Application.ProcessMessages;
     USBClosePort();
     TimeOutCount:=0;
     repeat
           hDevice := CreateFile( PChar( PortName ),
           GENERIC_READ or GENERIC_WRITE,
           0,
           NIL,
           OPEN_EXISTING,
           FILE_ATTRIBUTE_NORMAL,
           0);
  if hDevice <> INVALID_HANDLE_VALUE then Break;
  Inc(TimeOutCount);
//  Application.ProcessMessages;
  Sleep(10);
until ((TimeOutCount*10)>=TimeOut);
//Application.ProcessMessages;
Result:=hDevice <> INVALID_HANDLE_VALUE;
end;

Function USBBulkWritePort(Buffer:Pointer;Length:Integer):Integer;
var
count:longword;
begin
Result:=0;
//Application.ProcessMessages;
if hDevice = INVALID_HANDLE_VALUE then exit;
if not WriteFile(hDevice, Buffer^, Length, Count, nil) then exit;
//Application.ProcessMessages;
Result:=Count;
end;

function USBBulkReadPort(num: dword):boolean;
var
     Buffer   : array[0..$FFFE] of byte;
     Count    : longword;
     i        : integer;
     buf,buf1 : string;
begin
     Result:=false;
     rxBuf:=nil;
//     Application.ProcessMessages;
     if hDevice = INVALID_HANDLE_VALUE then exit;
     if not ReadFile(hDevice, Buffer, num, Count, nil) then exit;
     Result:=true;
     SetLength(rxBuf, Count);
//     Application.ProcessMessages;
     for i := 0 to Count - 1 do rxBuf[i]:=Buffer[i];

end;

function USBBulkReadPortInt(num: dword):integer;
var
     Buffer   : array[0..$FFFE] of byte;
     Count    : longword;
     i        : integer;
     buf,buf1 : string;
begin
     Result:=0;
     rxBuf:=nil;
//     Application.ProcessMessages;
     if hDevice = INVALID_HANDLE_VALUE then exit;
     if not ReadFile(hDevice, Buffer, num, Count, nil) then exit;
     SetLength(rxBuf, Count);
//     Application.ProcessMessages;
     for i := 0 to Count - 1 do rxBuf[i]:=Buffer[i];
     Result:=count;
end;

Function ReadUBUSData:word;
begin
Result:=0;
USBBulkReadPort(1);
//_msg(inttohex(rxBuf[0], 2));
if rxBuf[0]<>$1B then exit;
USBBulkReadPort(5);
if (rxBuf[0]<>$10) or (rxBuf[1]<>$00) then exit;
Result:=(rxBuf[3] * $100) + rxBuf[4];
USBBulkReadPort(Result);
end;


function sBreakApart(BaseString, BreakString: string; StringList: TStringList): TStringList;
var
  EndOfCurrentString: LongInt;
begin
  repeat
    EndOfCurrentString := Pos(BreakString, BaseString);
    if EndOfCurrentString = 0 then
      StringList.add(BaseString)
    else
      StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
    BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);

  until EndOfCurrentString = 0;
  result := StringList;
end;


function BB5_USB_ScanAndOpenConnection(DevType, Filter: String; Verbose:boolean):byte;
begin
Result:=catchdevice;
end;

function BufToStr(Buf:Pointer; BufLen: longword): string;
var
     b      : boolean;
     i,len  : integer;
     defHex : string;
begin
     defHex:='';
     if (Byte(Buf^)<>$1B)   then exit;
     inc(Integer(Buf));
     if (Word(Buf^)<>$0010) then
     if (Word(Buf^)<>$1000) then exit;
     inc(Integer(Buf),2);
     case Byte(Buf^) of
     $1B:
     begin
          inc(Integer(Buf));
          len:=Swap(Word(Buf^));
          inc(Integer(Buf),2);
          if BufLen<(len) then exit;
          inc(Integer(Buf),10);

          i:=$10; b:=true;
          while i<=BufLen-1 do
          begin
               if (Byte(Buf^)>$20) and (Byte(Buf^)<$7A) then defHex:=defHex+Char(Buf^) else
               if (Byte(Buf^)<>$00) then defHex:=defHex+' ';
               inc(Dword(Buf));
               inc(i);
          end;
          Result := defHex;
     end;

     $08:
     begin
          inc(Integer(Buf));
          len:=Swap(Word(Buf^));
          inc(Integer(Buf),2);
          if BufLen<len then exit;
          inc(Integer(Buf),22);

          i:=$20; b:=true;
          while i<=BufLen-1 do
          begin
               defHex:=defHex+inttohex(Byte(Buf^), 2);
               inc(integer(Buf));
               inc(i);
          end;
          Result := defHex;
     end else
     begin
          defHex:='1B 10 00 '+inttohex(Byte(Buf^), 2);
          inc(Integer(Buf));
          len:=Swap(Word(Buf^));
          inc(Integer(Buf),2);
          if BufLen<len then exit;
          defHex:=defHex+' '+inttohex(hi(len),2)+' '+inttohex(lo(len),2);
          i:=6;
          while i<=BufLen-1 do
          begin
               defHex:=defHex+' '+inttohex(Byte(Buf^), 2);
               inc(integer(Buf));
               inc(i);
          end;
          Result := defHex;
     end;


     end;
end;

//Dev search
function scandev :boolean;
begin
     flag:=false;
     result:=false;
     //BB5_USB_ScanAndOpenConnection('BB5', '*VID_0421*IF_OTH*', False);
Repeat
      sleep(50);
      if flag=true then //_msg('Error! TimeOut for connection...');
      begin
           Result:=False;
           exit;
      end;
      //until (BB5_USB_ScanAndOpenConnection('BB5', '*VID_0421*IF_OTH*', False)= True);
until (DevPresent=true);
      sleep(50);
      Result:=True;
      //_msg('Phone found!');
end;

function UsbFullFactorySet():boolean;
begin
          Result:=false;
          USBBulkWritePort(@FullFactory, Length(FullFactory));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Application.ProcessMessages;
          sleep(500);
          Application.ProcessMessages;
          USBBulkWritePort(@FullFactory, Length(FullFactory));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Application.ProcessMessages;
          sleep(500);
          Application.ProcessMessages;
          Result:=true;
end;

function UsbSWupgrDef():boolean;
begin
          Result:=false;
          USBBulkWritePort(@Softupgr, Length(Softupgr));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Result:=true;
end;

function UsbServiceCentreDef():boolean;
begin
          Result:=false;
          USBBulkWritePort(@ServiceCentre, Length(ServiceCentre));
         if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Result:=true;
end;

function UsbPrdTuneSet():boolean;
begin
          Result:=false;
          USBBulkWritePort(@ProductTune, Length(ProductTune));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Result:=true;
end;

function UsbUserDefSet():boolean;
begin
          Result:=false;
          USBBulkWritePort(@UserDataRes, Length(UserDataRes));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Result:=true;
end;

function UsbLeaveFactSet():boolean;
begin
          Result:=false;
          USBBulkWritePort(@Leavefactoryset, Length(Leavefactoryset));
          if USBBulkReadPort($FFFF) then begin if rxBuf[9]<>2 then exit; end else exit;
          Result:=true;
end;

function UsbResetLifeTimer():string;
var
bf:string;
begin
  result:='Error!';
 USBBulkWritePort(@ResetLifeTimer, Length(ResetLifeTimer));
          if USBBulkReadPort($FFFF) then
         // bf:=BufToStr(@rxBuf[0], Length(rxBuf));
           bf:=Byte2str(rxBuf[9]);
           if bf='03' then result:='Ok!';
end;

function UsbReadLifeTimer():string;
var
  bf:string;
begin
    USBBulkWritePort(@readLTFull, Length(readLTFull)); //читает общее время жизни
          if USBBulkReadPort($FFFF) then
         // bf:=BufToStr(@rxBuf[0], Length(rxBuf));
           bf:=Byte2str(rxBuf[20])+Byte2str(rxBuf[21])+Byte2str(rxBuf[22])+Byte2str(rxBuf[23]);
           result:=bf;
end;

function SmartAlgoFsinit():string;    // получение списка дисков
var
  bf:string;
begin
    USBBulkWritePort(@Fsscan2, Length(Fsscan2));
   if USBBulkReadPort($FFFF) then
          bf:=BufToStr(@rxBuf[0], Length(rxBuf));
          if pos('43 FF',bf)>0 then begin
          bf:='43FF';
          end
          else begin
            bf:='FFFF';
            end;
    result:=bf;
end;



function writeLifeTime():string;     // запись лайфтайма
var
  bf:string;
begin
  USBBulkWritePort(@WriteLTframe, Length(WriteLTframe));
   if USBBulkReadPort($FFFF) then
          bf:=BufToStr(@rxBuf[0], Length(rxBuf));
  if Pos('04', bf)>0 then result:='Ok' else result:='Error';
  end;


function ReadIMEI2net():string;
var
  a:string;
begin
  a:=USBreadIMEItoNet;
  if a<>'' then begin
  result:=a;
  PhInfoRecord.IMEI2Net:=a;
  end
  else begin result:='Error!';
  PhInfoRecord.IMEI2Net:=a;
  end;
end;

function ReadIMEISV2net():string;
var
  a:string;
begin
  a:=USBreadIMEIsvnet;
  if a<>'' then begin
  result:=a;
  PhInfoRecord.IMEISv2Net:=a;
  end
  else begin result:='Error!';
  PhInfoRecord.IMEISv2Net:=a;
  end;
end;

function scandrives():string;
var
  bf:string;
  i,i2:Integer;
begin
    USBBulkWritePort(@initFS, Length(initFS));
   if USBBulkReadPort($FFFF) then
   i2:=hextoint(byte2str(rxbuf[5]));
   bf:='';
   for i:=11 to i2 do
   begin
    bf:=bf+byte2str(Rxbuf[i]);
   end;
   Result:=bf;

end;

function scandriveS40():string;
var
  bf:string;
  i,i2:integer;
begin             
 // USBBulkWritePort(@initFs40prep, Length(initFs40prep));
   // USBBulkWritePort(@initFs401st, Length(initFs401st));
 USBBulkWritePort(@initFS40, Length(initFS40));
   if USBBulkReadPort($FFFF) then
   Result:=BufToHexStr(@rxBuf[1], Length(rxBuf));
end;


function GetTemp():string;
var
  temp:integer;
inf:string;
begin
   USBBulkWritePort(@RAWtemp, Length(RAWtemp));
          if USBBulkReadPort($FFFF) then
          inf:=buftostr(@rxBuf[0], Length(rxBuf));
          Delete(inf,1,42);
          Delete(inf,3,1);
          Delete(inf,5,5);
          inf:=IntToStr(HexToInt('$'+inf));
          if inf='' then begin
          Result:='';
          Exit;
          end
          else begin
            temp:=StrToInt(inf);
             case temp 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;
               end;
          Result:=inttostr(temp)+' C';
          end;

end;

function USBRawCharge():string;
var
  inf:string;
begin
 USBBulkWritePort(@RAWcharge, Length(RAWcharge));
          if USBBulkReadPort($FFFF) then
          inf:=buftostr(@rxBuf[0], Length(rxBuf));
          Delete(inf,1,42);
          Delete(inf,3,1);
          Delete(inf,5,5);
          inf:=IntToStr(HexToInt('$'+inf));
          if inf='' then
          result:=''
          else
result:=inf;
          end;


function currenteat():string;
var
  inf:string;
begin
   USBBulkWritePort(@RAWcurrent, Length(RAWcurrent));
      if USBBulkReadPort($FFFF) then
          inf:=buftostr(@rxBuf[0], Length(rxBuf));
      Delete(inf,1,42);
      Delete(inf,3,1);
      Delete(inf,5,5);
      inf:=IntToStr(HexToInt('$'+inf));
      if Length(inf)<=2 then begin
        inf:='00'+inf;
        end;
      if StrToInt(inf)>2000 then begin
        Delete(inf,0,2);
        Delete (inf,1,2);
        inf:='-'+inf;
       end;
      Result:=inf;
end;

function preformats40():string;
begin
   USBBulkWritePort(@s40preformat, Length(s40preformat));
      if USBBulkReadPort($FFFF) then
       Result:=buftostr(@rxBuf[0], Length(rxBuf));
end;

function formats40(drive:string):string;
var
  a:string;
begin
  if drive='C' then begin
  S40format[11]:=$43;
  end;
  if drive='S' then begin
  S40format[11]:=$53;
  end;
  USBBulkWritePort(@S40format, Length(S40format));
      if USBBulkReadPort($FFFF) then
          a:=buftostr(@rxBuf[0], Length(rxBuf));

   Result:=a;
end;


function formats601st(a:byte):string;
begin
   S60formatC1st[11]:=a;
  USBBulkWritePort(@S60formatC1st, Length(S60formatC1st));
      if USBBulkReadPort($FFFF) then
       if rxBuf[9]=$4D then result:='OK'
       else result:='Error';
end;

function formatS60cycle():string;
var
  a:string;
  cycle:Boolean;
  full:Boolean;
begin
  cycle:=True;
       repeat
         USBBulkWritePort(@S60formatcycle, Length(S60formatcycle));
         if USBBulkReadPort($FFFF) then
         begin
         S60formatcycle[8]:=S60formatcycle[8]+$01;
         if  S60formatcycle[8]=$FF then full:=True;
         if rxbuf[11]=$4B then cycle:=True
         else cycle:=false;

         end;
         form1.Pb1.Progress:=form1.Pb1.Progress+2;
       if full=True then  S60formatcycle[8]:=$00;

      until cycle=True;
if cycle=True then result:='OK'
else result:='Error';

end;



function sendNCK():string;
begin
    USBBulkWritePort(@NCKMasc, Length(NCKMasc));
          if USBBulkReadPort($FFFF) then

          if rxBuf[10]<>$08 then result:='OK'
          else result:='Error';
end;

function starttest():string;
var
  a:string;
  b:Integer;
  i:integer;
  c:integer;
  begin
  USBBulkWritePort(@st1, Length(st1));
          if USBBulkReadPort($FFFF) then
       USBBulkWritePort(@st2, Length(st2));
        if USBBulkReadPort($FFFF) then
       USBBulkWritePort(@st3, Length(st3));
        if USBBulkReadPort($FFFF) then
      USBBulkWritePort(@selftestsinit, Length(selftestsinit));
        if USBBulkReadPort($FFFF) then
        c:=hextoint(byte2str(rxbuf[4])+byte2str(rxbuf[5]))+6;
    a:='';
    for i:=0 to c do
    begin
      a:=a+Chr(rxbuf[i]);
  end;

   USBBulkWritePort(@quicktesting, Length(quicktesting));
        if USBBulkReadPort($FFFF) then
        begin
          end;
  result:=a;
end;

function GetFileSizeS40(path:string):dword;
var
  a,s,s2,hider:string;
  i,sz,n:Integer;
  sizz,framelen:Word;
begin
 s:='';  hider:=''; result:=0;
hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr($01)+chr($6C);
hider:=hider+PathConv(path)+chr(0)+chr(0);
s:=hider;

framelen:=Length(s)-6;
word((@s[5])^):=framelen;
WordSwap(@s[5]);
Word((@s[11])^):=Length(path)+1;
WordSwap(@s[11]);
   USBBulkWritePort(@s[1], Length(s));
   if USBBulkReadPort($FFFF) then begin
   DWordSwap(@RxBuf[16]);
   result:=dword((@rxbuf[16])^);
   end;

end;

function getfilesizes60(fullpath:string):DWORD;
var
  framelen,pathlen,blk,strlen:Word;
  a,s,s2,hider:string;
  i,sz,fsize:Integer;
begin
result:=0;
a:=fullpath; s:=''; s2:=Copy(PathConv(fullpath),3,Length(PathConv(fullpath))-4);
//for i:=1 to Length(a) do s2:=s2+Chr(0)+a[i];
sz:=Length(s2)+18;
strlen:=length(s2);
Application.ProcessMessages;
//hider 1B 00 10 58 {01 5E}len 00 11 {2A}framenum 19 00 01 F5 00 {01 58}blck(len(framelen-6)) 80 {A8}indidedatalen 00
hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($05)+chr(0)+chr($19)+chr(0)+chr($01)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr(( Length(s2) shr 1)-1);
s:=hider+s2;

framelen:=Length(s)-6;
word((@s[5])^):=framelen;
WordSwap(@s[5]);
pathlen:=Length(s)-12;
word((@s[15])^):=pathlen;
WordSwap(@s[15]);

     USBBulkWritePort(@s[1], sz);
    if USBBulkReadPort($FFFF) then begin
    WordSwap(@rxBuf[4]);
    blk:=word((@rxBuf[4])^);
    if blk>$6 then begin
   fsize:=hextoint(byte2str(rxbuf[32])+byte2str(rxbuf[33])+byte2str(rxbuf[34])+byte2str(rxbuf[35]));
 //  form1._msg('File size is : '+inttostr(fsize)+' bytes...');
   DWordSwap(@RxBuf[32]);
   result:=dword((@rxbuf[32])^);
   end
   else begin
      // form1._msg('If programm freeze - reconnect the phone...');
   result:=0;
   end;
  end;
end;

function extractfileS60(F:TMemoryStream;fullpath:string;len:dword;info:integer):boolean;
var
  i,sz:Integer;
  framelen,pathlen,strlen,ostlen,errcor:Word;
  a,s,s2,hider,ape:string;
  Tlen:DWORD;
begin
result:=false;
a:=fullpath; s:=''; s2:=Copy(PathConv(fullpath),3,Length(PathConv(fullpath))-4);
sz:=Length(s2)+26; strlen:=length(s2);
//hider 1B 00 10 58 {01 5E}len 00 11 {2A}framenum 19 00 01 F5 00 {01 58}blck(len(framelen-6)) 80 {A8}indidedatalen 00
hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($0D)+chr(0)+chr($02)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr(( Length(s2) shr 1)-1);
s:=hider+s2+chr($F8)+chr($08)+chr(0)+chr(0)+chr($04)+chr(0)+chr($0)+chr($01);
framelen:=Length(s)-6;
word((@s[5])^):=framelen;
WordSwap(@s[5]);
pathlen:=Length(s)-20;
word((@s[15])^):=pathlen;
WordSwap(@s[15]);
Tlen:=0;
   if len>$400 then begin
     i:=Len div $400;
     case info of
	   1: begin
	      Form1.pb1.MaxValue:=i+1;
        form1._msg('Will read '+inttostr(i+1)+' blocks...');
        end;
	   2: Form1.pbsm1.MaxValue:=i+1;
	   3: Application.ProcessMessages;
	   end;
	    ostlen:=len mod $400;
        Application.ProcessMessages;
        USBBulkWritePort(@s[1], sz);
      if USBBulkReadPort($FFFF) then begin
       WordSwap(@rxBuf[4]);
       errcor:=word((@rxbuf[4])^);
        if errcor<$7 then begin
        form1._msg('Sorry, FS error : Phone not answer... :(');
	       case info of
	       1: form1.pb1.progress:=0;
	       2: form1.pbsm1.progress:=0;
	       3: Application.ProcessMessages;
	       end;
	       result:=false;
         Exit;
        end;
        DWordSwap(@rxbuf[20]);
        Tlen:=dword((@rxbuf[20])^);
        F.Write(rxBuf[24],Tlen);
       end;
     DWord((@s60readcycle[20])^):=Tlen;
     DWordSwap(@s60readcycle[20]);
       if i=1 then begin
       if ostlen>0 then begin
       USBBulkWritePort(@s60readcycle, Length(s60readcycle));
        if USBBulkReadPort($FFFF) then begin
        DWordSwap(@rxbuf[20]);
        Tlen:=dword((@rxbuf[20])^);
          F.Write(rxBuf[24],ostlen);
        DWord((@s60readcycle[20])^):=Tlen;
        DWordSwap(@s60readcycle[20]);
        USBBulkWritePort(@s60readcycle, Length(s60readcycle));
        result:=true;
        exit;
         end;
        end;
       end;
     while i<>1 do
     begin
	     Application.ProcessMessages;
       if USBBulkWritePort(@s60readcycle, Length(s60readcycle))<>Length(s60readcycle) then exit;
        if USBBulkReadPort($FFFF) then begin
        DWordSwap(@rxbuf[20]);
        Tlen:=dword((@rxbuf[20])^);
          if Tlen>(Len-ostlen) then begin
          F.Write(rxBuf[24],ostlen);
          end
          else begin
          F.Write(rxBuf[24],1024);
          end;
          DWord((@s60readcycle[20])^):=Tlen;
          DWordSwap(@s60readcycle[20]);
	        case info of
	        1: Form1.pb1.progress:=Form1.pb1.progress+1;
	        2: Form1.pbsm1.progress:=form1.pbsm1.Progress+1;
	        3: Application.ProcessMessages;
	        end;
         if Tlen=len then begin
          USBBulkWritePort(@s60readcycle, Length(s60readcycle));
           case info of
	        1: Form1.pb1.progress:=0;
	        2: Form1.pbsm1.progress:=0;
	        3: Application.ProcessMessages;
	        end;
	      Application.ProcessMessages;
        result:=True;
        Exit;
        end;
       end
       else Exit;
     end;
    end
   else begin
    Application.ProcessMessages;
     if info=1 then form1._msg('Will read 1 block...');
        USBBulkWritePort(@s[1], sz);
     if USBBulkReadPort($FFFF) then begin
           WordSwap(@rxBuf[4]);
           errcor:=word((@rxbuf[4])^);
           if errcor<$7 then begin
           form1._msg('Sorry, FS error : Phone not answer... :(');
		        case info of
	          1: form1.pb1.progress:=0;
	          2: form1.pbsm1.progress:=0;
	          3: Application.ProcessMessages;
	          end;
	         result:=false;
           Exit;
           end;
     DWordSwap(@rxbuf[20]);
     Tlen:=dword((@rxbuf[20])^);
     F.Write(rxBuf[24],Tlen);
     DWord((@s60readcycle[20])^):=Tlen;
     DWordSwap(@s60readcycle[20]);
     UsbBulkWritePort(@s60readcycle, Length(s60readcycle));
     end else exit;
   end;
 Result:=True;
end;

function USbWriteFileS60(InFile:TMemoryStream;filewithpath:string;info:integer):boolean;
var
  Ms:TmemoryStream;
  framelen,pathlen,bufsent,len,ost:word;
  Sentlen,filelen,ostflen:Dword;
  intlen,i,ilen:integer;
  hider,s,s1,s2,s3,posthider:string;
begin
  result:=False;
 s:=''; s2:=''; hider:='';
  //создаем поток
Ms:=TmemoryStream.Create;
Ms.LoadfromStream(inFile);
 //получаем размер файла
 filelen:=ms.size;
 intlen:=ms.size;
 // выводим для информации
 if info=1 then form1._msg('File size is : '+inttostr(intlen)+' bytes');
 //считаем блоки и остаток
 ilen:=filelen div $400;
 ost:=filelen mod $400;
 case info of
 1: begin
    Form1.pb1.Maxvalue:=filelen div $400;
    if ost>0 then Form1.pb1.Maxvalue:=Form1.pb1.Maxvalue+1;
    end;
 2: begin
    Form1.pbsm1.Maxvalue:=filelen div $400;
    if ost>0 then Form1.pbsm1.Maxvalue:=Form1.pbsm1.Maxvalue+1;
    end;
 3: Begin
    Application.ProcessMessages; 
    end;
 end;
 //создаем заголовок
 s2:=Copy(PathConv(filewithpath),3,Length(PathConv(filewithpath))-4);
hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($0F)+chr(0)+chr($04)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr((Length(s2) div 2)-1);
posthider:=chr($04)+chr($04)+chr($0C)+chr($0E)+chr(0)+chr(0)+chr($04)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
s2:=s2+posthider;
pathlen:=Length(s2)-6;
//присваиваем данные
 case info of
 1: begin
    form1._msg('Will write '+inttostr(ilen+1)+' blocks...');
    form1._msg('Patch header... Writing data...');
    end;
 2: Application.ProcessMessages;
 3: Application.ProcessMessages;
 end;
 if ilen>0 then begin
 s:=hider+s2;
 SetLength(s,Length(s)+1024);
 Ms.read(s[Length(hider+s2)+1],$400);
 s3:=Chr($F8)+chr($08)+chr(0)+chr(0)+chr($04)+chr(0)+chr(0)+chr($01)+chr($F1)+chr($04)+chr($01)+chr(0);
 s:=s+s3;
 framelen:=Length(s)-6;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
 word((@s[15])^):=pathlen;
 WordSwap(@s[15]);
 UsbBulkWritePort(@s[1], Length(s));
   if USBbulkReadPort($FFFF) then 
    begin
      if rxBuf[5]=$06 then Exit;
    DWordSwap(@RxBuf[20]);
    sentlen:=dword((@rxbuf[20])^);
    Application.ProcessMessages;
        case info of
        1: Form1.pb1.Progress:=1;
        2: Form1.pbsm1.Progress:=1;
        3: Application.ProcessMessages;
        end; 
    end;
  while ilen<>1 do
  begin
  s:=''; hider:='';
  SetLength(s,24);
  hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($12)+chr($02)+chr($0F)+chr(0)+chr($01)+chr($04)+chr($04)+chr($0C)+chr($0E)+chr(0)+chr(0)+chr($04)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
  SetLength(s,1048);
  s:=hider+s;
  Ms.read(s[Length(hider)+1],$400);
   framelen:=$412;
   word((@s[5])^):=framelen;
   WordSwap(@s[5]);
   Dword((@s[21])^):=sentlen;
   DWordSwap(@s[21]);
   UsbBulkWritePort(@s[1], $418);
   if USBbulkReadPort($FFFF) then begin
   DWordSwap(@RxBuf[20]);
   sentlen:=dword((@rxbuf[20])^);
   end;
  ilen:=ilen-1;
  Application.ProcessMessages;
    case info of
        1: Form1.pb1.Progress:=Form1.pb1.Progress+1;
        2: Form1.pbsm1.Progress:=Form1.pbsm1.Progress+1;
        3: Application.ProcessMessages;
        end;
   Application.ProcessMessages;
  end;
  if ost>0 then begin
 s:=''; hider:='';
  SetLength(s,24);
  hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($12)+chr($02)+chr($0F)+chr(0)+chr($01)+chr($04)+chr(0)+chr(0)+chr($0F)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
  SetLength(s,ost);
  s:=hider+s;
  Ms.read(s[Length(hider)+1],ost);
  s:=s+chr(0)+chr(0);
   framelen:=Length(s)-6;
   word((@s[5])^):=framelen;
   WordSwap(@s[5]);
   word((@s[14])^):=framelen-$06;
   Wordswap(@s[14]);
   word((@s[19])^):=ost;
   WordSwap(@s[19]);
   Dword((@s[21])^):=sentlen;
   DWordSwap(@s[21]);
   UsbBulkWritePort(@s[1], Length(s));
   if USBbulkReadPort($FFFF) then begin
   DWordSwap(@RxBuf[20]);
   sentlen:=dword((@rxbuf[20])^);
   end;
  case info of
        1: Form1.pb1.Progress:=Form1.pb1.Progress+1;
        2: Form1.pbsm1.Progress:=Form1.pbsm1.Progress+1;
        3: Application.ProcessMessages;
        end;
   Application.ProcessMessages;
  end;

 end
 else begin
   posthider:=''; hider:=''; pathlen:=0; s2:='';
  s2:=Copy(PathConv(filewithpath),3,Length(PathConv(filewithpath))-4);
  hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($0F)+chr(0)+chr($03)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr((Length(s2) div 2)-1);
   //form1._msg('Will write 1 block...');
   Application.ProcessMessages;
   posthider:=chr(0)+chr(0)+chr($04)+chr(0)+chr(0)+chr($0F)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
   word((@posthider[4])^):=ost+$D;
   wordswap(@posthider[4]);
   Dword((@posthider[7])^):=ost;
   DWordSwap(@posthider[7]);
 s2:=s2+posthider;
 pathlen:=Length(s2)-6;
 s:=hider+s2;
 SetLength(s,Length(s)+ost);
 Ms.read(s[Length(hider+s2)+1],ost);
 s3:=chr(0)+Chr($F8)+chr($08)+chr(0)+chr(0)+chr($04)+chr(0)+chr(0)+chr($01);
 s:=s+s3;
 framelen:=Length(s)-6;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
 word((@s[15])^):=pathlen;
 WordSwap(@s[15]);
 UsbBulkWritePort(@s[1], Length(s));
   if USBbulkReadPort($FFFF) then begin
  DWordSwap(@RxBuf[20]);
  sentlen:=dword((@rxbuf[20])^);
  Application.ProcessMessages;
    case info of
        1: Form1.pb1.Progress:=0;
        2: Form1.pbsm1.Progress:=0;
        3: Application.ProcessMessages;
        end;
    end;
 end;
 if Sentlen=filelen then result:=True
 else result:=False;
 Ms.free;
 case info of
        1: Form1.pb1.Progress:=0;
        2: Form1.pbsm1.Progress:=0;
        3: Application.ProcessMessages;
 end;
end;


function initialiseFS():string;
begin
 UsbBulkWritePort(@InitFS1st, Length(InitFS1st));
 if USBBulkReadport($FFFF) then
  UsbBulkWritePort(@InitFS2nd, Length(InitFS2nd));
   if USBBulkReadport($FFFF) then begin
   Result:=BufToHexStr(@rxBuf[6],HexToInt(Byte2Str(rxbuf[5])));
 end;
 end;

function writes602nd(path:string;f:TFileStream):Boolean;
var
  hider,s,s1,s2:string;
  pathlen,framelen:Word;
  filelen:DWORD;
begin



end;

function S60deletefile(path:string):Boolean;
var
  frame,header,s,s2:string;
  i,i2,si:Integer;
  framelen, pathlen:Word;
begin
  s2:=''; result:=False;
  s2:=Copy(PathConv(path),3,Length(PathConv(path))-4);
  header:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($05)+chr($01)+chr($15)+chr($01)+chr($01)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr((Length(s2) div 2)-1);;
  //header[18]:=chr(Length(path));
  frame:=header+s2;
  pathlen:=Length(s2)+6;
  Word((@frame[15])^):=pathlen;
  WordSwap(@frame[15]);
  framelen:=Length(frame)-6;
  Word((@frame[5])^):=framelen;
  WordSwap(@frame[5]);
  USBBulkWritePort(@frame[1],length(frame));
  if USBBulkReadPort($FFFF) then begin
  if rxBuf[9]=$16 then begin
    if rxBuf[10]=$00 then result:=True
    else result:=false;
  end
  else result:=False;
  end;
  end;

function gets40drv():Boolean;
var
  a:string;
begin
  USBBulkWritePort(@S40getdrive,Length(S40getdrive));
  if USBBulkReadPort($FFFF) then begin
   a:=BufToHexStr(@rxBuf[11], HexToInt(Byte2Str(rxbuf[5])));
   if Pos('53',a)>0 then result:=True else result:=False;
  end;
end;

function Light(state:string):boolean;
begin
  result:=False;
 if state='on' then begin
   usbbulkwriteport(@lighton, Length(lighton));
   if USBBulkReadPort($FFFF) then result:=True;
 end;
 if state='off' then begin
   USBBulkWritePort(@lightoff, Length(lightoff));
   if usbbulkreadport($FFFF) then result:=True;
 end;
end;


function listfolder(folder:string):string;
var
hider:string;
i:Integer;
s,s1,s2:string;
framelen,pathlen:Word;
begin
  hider:=chr($1B)+chr(0)+chr($10)+chr($58)+chr(0)+chr(0)+chr(0)+chr($05)+chr(0)+chr($0B)+chr(0)+chr($01)+chr($F5)+chr(0)+chr(0)+chr(0)+chr($80)+chr(Length(folder));
for i:=1 to Length(folder) do s2:=s2+Chr(0)+folder[i];
s:=hider+s2;
framelen:=Length(s)-6;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
 pathlen:=Length(s)-12;
 word((@s[15])^):=pathlen;
 WordSwap(@s[15]);
 UsbBulkWritePort(@s[1], Length(s));
 if USBbulkReadPort($FFFF) then begin

 end;
 end;

function APEtestrun():string;
var
  a:string;
begin
USBBulkWritePort(@APEtestrunsrv,length(APEtestrunsrv));
if USBBulkReadPort($FFFF) then
  a:=BufToHexStr(@rxBuf[18],Length(rxBuf)-18);
  if a<>'' then begin
    Result:='Running : '+Hex2Chr(a);
  end
  else begin
    Result:='APE Server Run fail! FS breaked... :(';
  end;
end;

function getlockfield():string;
var
  str,blk:string;
  len:word;
begin
  str:='';
 getlockdata[8]:=$01;
 getlockdata[10]:=$0D;
 UsbBulkWritePort(@getlockdata,Length(getlockdata));
 if usbbulkreadport($FFFF) then begin
 WordSwap(@RxBuf[28]);
 len:=word((@rxbuf[28])^);
 str:=BufToHexStr(@rxBuf[30],Length(rxBuf)-30);
 if len>100 then application.Processmessages
 else begin
   repeat
   getlockdata[8]:=getlockdata[8]+$01;
   getlockdata[10]:=getlockdata[10]+$01;
   UsbBulkWritePort(@getlockdata,Length(getlockdata));
   if usbbulkreadport($FFFF) then begin
    WordSwap(@RxBuf[28]);
    len:=word((@rxbuf[28])^);
    str:=str+BufToHexStr(@rxBuf[30],Length(rxBuf)-30);
     end;

   until (len<>$44) or (getlockdata[10]=$1A) ;

 end;
 end;
Result:=str;
end;


function extractfileS40(F:TMemoryStream;fullpath:string;len:dword;info:integer):boolean;
var
  a,s,hider:string;
  i,sz:Integer;
  read,ostlen,framelen,sizz:Word;
  Tlen,control,readedlen:DWORD;
begin
ostlen:=0;
Tlen:=0;
Application.ProcessMessages;
Form1.pbsm1.Progress:=0;
    Result:=false;
 s:=''; hider:='';
hider:=Chr($1B)+Chr(0)+Chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(02)+chr($72)+chr(0)+chr($01);
hider:=hider+PathConv(fullpath);
    a:=fullpath;
s:=hider;
framelen:=Length(s)-6;
word((@s[5])^):=framelen;
WordSwap(@s[5]);
 try
   USBBulkWritePort(@s[1], Length(s));
   if USBBulkReadPort($FFFF) then begin
   DWordSwap(@RxBuf[12]);
   control:=Dword((@rxbuf[12])^);
    if control=$FFFFFFFF then begin
     form1._msg('Error in CS key! Can'+#39+'t read file :(');
     result:=false;
     exit;
    end;
   end;

 Dword((@ReadS40cycle[12])^):=control;
 DWordSwap(@ReadS40cycle[12]);
 Read:=$4000;
 ostLen:=Len mod $4000;

 if len>$4000 then
 begin
    i:=Len div $4000;
    case info of
    1: begin	
	      form1.pb1.maxvalue:=i;
        if ostlen>0 then form1.pb1.maxvalue:=form1.pb1.maxvalue+1;
       end;
	  2: begin
	        form1.pbsm1.maxvalue:=i;
          if ostlen>0 then form1.pbsm1.maxvalue:=form1.pbsm1.maxvalue+1;
       end;
	  3: Application.ProcessMessages;
	end;
	Application.Processmessages;
    try
    Tlen:=0;
    ReadS40cycle[16]:=Tlen;
    word((@ReadS40cycle[22])^):=Read;
    word((@ReadS40cycle[26])^):=Read;
    WordSwap(@ReadS40cycle[22]);
    WordSwap(@ReadS40cycle[26]);
     while i<>0 do begin                    // если полных блоков не 0 то
            Application.ProcessMessages;
            dword((@ReadS40cycle[16])^):=Tlen; // вписываем текущее смещение в команду и
            DWordSwap(@ReadS40cycle[16]);     //  переворачиваем его ногами вперед
            USBBulkWritePort(@ReadS40cycle, Length(ReadS40cycle));  //
            if USBBulkReadPort($FFFF) then                                 // читаем свои 4000 байт
             begin
             DWordSwap(@RxBuf[12]);
             readedLen:=dword((@rxbuf[12])^);
             if readedlen<>$4000 then
               begin
               result:=False;
               form1.pbsm1.progress:=0;
               Exit;
               end;
             end;
             F.Write(rxBuf[16],$4000);                   // добавляем его к тому, что прочли
             i:=i-1;        // уменьшаем кол-во блоков, т.к. прочли
             Tlen:=Tlen+$4000; // смещение увеличиваем на значение прочитанных байт, т.е. следущий кусок читать будем с этого смещения
             byte((@ReadS40cycle[8])^):=byte((@ReadS40cycle[8])^)+1; // это изврат с номером фрейма
          Application.ProcessMessages;
		      case info of
          1: form1.pb1.progress:=form1.pb1.progress+1;
          2: form1.pbsm1.progress:=form1.pbsm1.progress+1;
		      3: Application.ProcessMessages;
		      end;
		 end;  // прочли все полные блоки

          if ostlen>0 then begin
          Application.ProcessMessages;
          byte((@ReadS40cycle[8])^):=byte((@ReadS40cycle[8])^)+1; // извратили фрейм
          dword((@ReadS40cycle[16])^):=Tlen; // получили текущее значение смещения  и пихаем его в команду, которая читает короткие блоки
          DWordSwap(@ReadS40cycle[16]);      // ну и ногами вперед
          word((@ReadS40cycle[22])^):=ostLen; //  имеем остаток или не полный блок при короткой длине
          word((@ReadS40cycle[26])^):=ostLen;
          WordSwap(@ReadS40cycle[22]);     //  ногами вперед
          WordSwap(@ReadS40cycle[26]);
          USBBulkWritePort(@ReadS40cycle, Length(ReadS40cycle));  //
          if USBBulkReadPort($FFFF) then                         // и читаем его
          begin
             DWordSwap(@RxBuf[12]);
             readedLen:=dword((@rxbuf[12])^);
             if readedlen<>ostlen then
               begin
               result:=False;
               form1.pbsm1.progress:=0;
               Exit;
               end;
          end;
          F.Write(rxBuf[16],ostLen);
          case info of
          1: form1.pb1.progress:=form1.pb1.progress+1;
          2: form1.pbsm1.progress:=form1.pbsm1.progress+1;
		      3: Application.ProcessMessages;
		      end;
		      Application.ProcessMessages;
         end;
    except
    result:=False;
    form1.pbsm1.progress:=0;
    Exit;
    end;
          end
 else
 begin
          case info of
          1: form1.pb1.maxvalue:=1;
	        2: form1.pbsm1.maxvalue:=1;
	        3: Application.ProcessMessages;
	        end;
          Application.ProcessMessages;
          byte((@ReadS40cycle[8])^):=byte((@ReadS40cycle[8])^)+1; // извратили фрейм
          dword((@ReadS40cycle[16])^):=Tlen; // получили текущее значение смещения  и пихаем его в команду, которая читает короткие блоки
          DWordSwap(@ReadS40cycle[16]);      // ну и ногами вперед
          word((@ReadS40cycle[22])^):=ostLen; //  имеем остаток или не полный блок при короткой длине
          word((@ReadS40cycle[26])^):=ostLen;
          WordSwap(@ReadS40cycle[22]);     //  ногами вперед
          WordSwap(@ReadS40cycle[26]);
          USBBulkWritePort(@ReadS40cycle, Length(ReadS40cycle));  //
          if USBBulkReadPort($FFFF) then                         // и читаем его
          begin
             DWordSwap(@RxBuf[12]);
             readedLen:=dword((@rxbuf[12])^);
             if readedlen<>ostlen then
               begin
               result:=False;
               form1.pbsm1.progress:=0;
               Exit;
               end;
          end;
          F.Write(rxBuf[16],ostLen);
          Application.ProcessMessages;
          case info of
          1: form1.pb1.progress:=form1.pb1.progress+1;
          2: form1.pbsm1.progress:=form1.pbsm1.progress+1;
		      3: Application.ProcessMessages;
		      end;
 end;

         // заканчиваем читать - посылаем команды освобождения потока
         Dword((@S40readendst[12])^):=control;
         DWordSwap(@S40readendst[12]);
         USBBulkWritePort(@S40readendst, Length(S40readendst));  //
         if USBBulkReadPort($FFFF) then
         S40readendst[9]:=$74;
         USBBulkWritePort(@S40readendst, Length(S40readendst));  //
         if USBBulkReadPort($FFFF) then
         case info of
          1: form1.pb1.progress:=0;
          2: form1.pbsm1.progress:=0;
		      3: Application.ProcessMessages;
		      end;
         Result:=true;             //  все, писец
 except
   result:=False;
 end;
end;

function USBFSwriteS40Uni(InFile:TMemoryStream;filewithpath:string;info:integer):boolean;
var
  Ms:TmemoryStream;
  framelen,len,ost:word;
  filelen:Dword;
  intlen,i,ilen,i2,i3:integer;
  hider,s,s2:string;
  sessionkey:dword;
  b:byte;
begin
 s:=''; s2:=''; hider:='';  sessionkey:=0;
  //создаем поток
Ms:=TmemoryStream.Create;
Ms.LoadfromStream(inFile);
 //получаем размер файла
 filelen:=ms.size;
 intlen:=ms.size;
 // выводим для информации
 if info=1 then form1._msg('Size is : '+inttostr(intlen)+' bytes');
 //считаем блоки и остаток
 ilen:=filelen div $4000;
 ost:=filelen mod $4000;
  case info of
   1: begin
      Form1.pb1.Maxvalue:=filelen div $4000;
      if ost>0 then Form1.pb1.Maxvalue:=Form1.pb1.Maxvalue+1;
      end;
   2: begin
      Form1.pbsm1.Maxvalue:=filelen div $4000;
      if ost>0 then Form1.pbsm1.Maxvalue:=Form1.pbsm1.Maxvalue+1;
      end;
   3: Begin
      Application.ProcessMessages; 
      end;
   end;
 Application.ProcessMessages;
// создаем "шапку" фрейма
hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($72)+chr($31)+chr($01);
hider:=hider+PathConv(filewithpath);
framelen:=Length(hider)-6;
s:=hider;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
if ost>0 then i3:=1 else i3:=0;
//присваиваем данные
 UsbBulkWritePort(@s[1], Length(s));
 if USBbulkReadPort($FFFF) then begin
 DwordSwap(@rxbuf[12]);
 sessionkey:=Dword((@rxbuf[12])^);
       if sessionkey=$FFFFFFFF then begin
       form1._msg('Invalid CSkey! Can'+#39+'t write file!');
       result:=false;
       ms.free;
       exit;
       end;
    if ilen>0 then begin
   case info of
    1: form1._msg('Will write '+inttostr(ilen+i3)+' blocks...');
    2: Application.ProcessMessages;
    3: Application.ProcessMessages;
    end;
     Application.ProcessMessages;
    b:=$01;
     for i2:=1 to ilen do
       begin
      hider:=''; s:='';
      hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($58)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr($40)+chr(0);
      s:=hider;
      SetLength(s,Length(s)+$4000);
      Ms.read(s[Length(hider)+1],$4000);
      framelen:=Length(s)-6;
      word((@s[5])^):=framelen;
      WordSwap(@s[5]);
      Dword((@s[13])^):=sessionkey;
      DwordSwap(@s[13]);
      s[9]:=chr(b);
      b:=b+$01;
      UsbBulkWritePort(@s[1], Length(s));
       if usbbulkreadport($FFFF) then begin
       if (rxbuf[9]=$59) and (rxBuf[10]=$00) then Application.ProcessMessages
       else begin
         form1._msg('BLK write error!!!');
         result:=false;
         case info of
         1: Form1.pb1.Progress:=0;
         2: Form1.pbsm1.Progress:=0;
         3: Application.ProcessMessages;
         end;
		 ms.free;
         exit;
         end;
       end;
        Application.ProcessMessages;
        case info of
        1: Form1.pb1.Progress:=Form1.pb1.Progress+1;
        2: Form1.pbsm1.Progress:=Form1.pbsm1.Progress+1;
        3: Application.ProcessMessages;
        end;
        Application.ProcessMessages;
      end;

     if ost>0 then begin
     hider:=''; s:='';
      hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($58)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
      s:=hider;
      SetLength(s,Length(s)+ost);
      Ms.read(s[Length(hider)+1],ost);
      framelen:=Length(s)-6;
      word((@s[5])^):=framelen;
      WordSwap(@s[5]);
      Dword((@s[13])^):=sessionkey;
      DwordSwap(@s[13]);
      s[9]:=chr(b);
      word((@s[19])^):=ost;
      wordswap(@s[19]);
      b:=b+$01;
      UsbBulkWritePort(@s[1], Length(s));
       if usbbulkreadport($FFFF) then begin
       if (rxbuf[9]=$59) and (rxBuf[10]=$00) then Application.ProcessMessages
       else begin
         form1._msg('BLK write error!!!');
         result:=false;
         case info of
         1: Form1.pb1.Progress:=0;
         2: Form1.pbsm1.Progress:=0;
         3: Application.ProcessMessages;
         end;
		 ms.free;
         exit;
         end;
       end;
        Application.ProcessMessages;
        case info of
        1: Form1.pb1.Progress:=Form1.pb1.Progress+1;
        2: Form1.pbsm1.Progress:=Form1.pbsm1.Progress+1;
        3: Application.ProcessMessages;
        end;
        Application.ProcessMessages;
     end;
     Ms.Free;
     hider:='';
     hider:=chr($1B)+chr($00)+chr($10)+chr($6D)+chr($00)+chr($0A)+chr($00)+chr($12)+chr(0)+chr($66)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
      framelen:=Length(hider)-6;
      word((@hider[5])^):=framelen;
      WordSwap(@hider[5]);
      Dword((@hider[13])^):=sessionkey;
      DwordSwap(@hider[13]);
      hider[9]:=chr(b);
      UsbBulkWritePort(@hider[1], Length(hider));
       if usbbulkreadport($FFFF) then begin
       hider[10]:=chr($74);
        UsbBulkWritePort(@hider[1], Length(hider));
       USBBulkReadPort($FFFF);
        end;
   result:=true;
    case info of
    1: Form1.pb1.Progress:=0;
    2: Form1.pbsm1.Progress:=0;
    3: Application.ProcessMessages;
    end;
   end
   else begin
    if info=1 then form1._msg('Will write 1 block...');
      hider:=''; s:='';
      hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($58)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
      s:=hider;
      SetLength(s,Length(s)+ost);
      Ms.read(s[Length(hider)+1],ost);
      framelen:=Length(s)-6;
      word((@s[5])^):=framelen;
      WordSwap(@s[5]);
      Dword((@s[13])^):=sessionkey;
      DwordSwap(@s[13]);
      s[9]:=chr(b);
      word((@s[19])^):=ost;
      wordswap(@s[19]);
      b:=b+$01;
      UsbBulkWritePort(@s[1], Length(s));
       if usbbulkreadport($FFFF) then begin
       if (rxbuf[9]=$59) and (rxBuf[10]=$00) then Application.ProcessMessages
       else begin
         form1._msg('BLK write error!!!');
         result:=false;
		 case info of
         1: Form1.pb1.Progress:=0;
         2: Form1.pbsm1.Progress:=0;
         3: Application.ProcessMessages;
         end;
         ms.free;
         exit;
         end;
		Application.ProcessMessages;
        case info of
        1: Form1.pb1.Progress:=Form1.pb1.Progress+1;
        2: Form1.pbsm1.Progress:=Form1.pbsm1.Progress+1;
        3: Application.ProcessMessages;
        end;
        Application.ProcessMessages; 
       end;
       ms.Free;
     hider:='';
     hider:=chr($1B)+chr($00)+chr($10)+chr($6D)+chr($00)+chr($0A)+chr($00)+chr($12)+chr(0)+chr($66)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0)+chr(0);
      framelen:=Length(hider)-6;
      word((@hider[5])^):=framelen;
      WordSwap(@hider[5]);
      Dword((@hider[13])^):=sessionkey;
      DwordSwap(@hider[13]);
      hider[9]:=chr(b);
      UsbBulkWritePort(@hider[1], Length(hider));
       if usbbulkreadport($FFFF) then begin
       hider[10]:=chr($74);
        UsbBulkWritePort(@hider[1], Length(hider));
       USBBulkReadPort($FFFF);
        end;
    result:=true;
     case info of
     1: Form1.pb1.Progress:=0;
     2: Form1.pbsm1.Progress:=0;
     3: Application.ProcessMessages;
     end;
    end;
  end

  else begin
  Ms.Free;
  result:=False;
  end;
result:=True;
end;

function USBS40DeleteFile(filepath:string):Boolean;
var
  hider,s,s2:string;
  i:integer;
  framelen:Word;
begin
hider:=chr($1B)+chr($00)+chr($10)+chr($6D)+chr($00)+chr($00)+chr($00)+chr($12)+chr($00)+chr($62)+chr(0)+chr(0);
s2:=Copy(PathConv(filepath),3,Length(PathConv(filepath))-4);
word((@hider[11])^):=Length(filepath)+1;
WordSwap(@hider[11]);
hider:=hider+s2;
framelen:=Length(hider)-6;
s:=hider;
 framelen:=Length(s)-6;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
 {Word((@s[11])^):=Length(filewithpath)+1;
 WordSwap(@s[11]);  }
USBBulkWritePort(@s[1], Length(s));
  if USBBulkReadPort($FFFF) then begin
    case rxBuf[10] of
  $00: begin
       //form1._msg('Delete Ok!');
       result:=true;
       end;
  $06: begin
       form1._msg('No data, delete skipped');
       result:=true;
       end;
  $03: begin
       Form1._msg('Acces denined! Try reset...');
       result:=false;
       end
   else result:=false;
 end;
end;

end;

function listfolderS40(path:string):string;
var
  hider,s,s2:string;
  framelen:Word;
  i:integer;
  mega:string;
  begin
    Mega:='';
hider:=''; s:=''; s2:='';
hider:=chr($1B)+chr($00)+chr($10)+chr($6D)+chr($00)+chr($00)+chr($00)+chr($12)+chr($00)+chr($68)+chr(0)+chr(0);
for i:=1 to Length(path) do s2:=s2+Chr(0)+path[i];
s:=hider+s2+chr(0)+chr(0);
 framelen:=Length(s)-6;
 word((@s[5])^):=framelen;
 WordSwap(@s[5]);
 Word((@s[11])^):=Length(path)+1;
 WordSwap(@s[11]);
USBBulkWritePort(@s[1], Length(s));
  if USBBulkReadPort($FFFF) then begin

  end;
end;

function readport():boolean;
begin
 if USBBulkReadPort($4000) then result:=True else result:=False;
end;

function UsbRplsimlockdata(s:string):string;
var
Len:word;
begin
     Result:='Error';
     BufCopy (@RplWriteSimData,@txBuf,Length(RplWriteSimData));
     Len:=StrToBufHex(s,@txBuf[114]);
     word((@txBuf[112])^):=Len-$90;
     WordSwap(@txBuf[112]);
     Len:=Len-$24;
     word((@txBuf[4])^):=Len;
     WordSwap(@txBuf[4]);
          USBBulkWritePort(@txBuf, Len+6);
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<>$00 then exit;
//          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Result:='Ok!';
end;

function UsbWriteSimLokkey(s:string):string;
var
  len : Word;
begin
   Result:='Error';
   if length(s)<=200 then begin
     BufCopy (@RplWriteSimlockkeyslX,@txBuf,Length(RplWriteSimlockkeyslX));
     Len:=StrToBufHex(s,@txBuf[12]);
     word((@txBuf[4])^):=$FC;
     WordSwap(@txBuf[4]);
      USBBulkWritePort(@txBuf, $102);
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]=$07 then exit;
//          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Result:='Ok!';
          end;
end;


function UsbWriteSDDkey(s:string):string;
var
  len : Word;
begin
   Result:='Error';
     BufCopy (@RplWriteSD,@txBuf,Length(RplWriteSD));
     Len:=StrToBufHex(s,@txBuf[16]);
     word((@txBuf[4])^):=len+$0A;
     WordSwap(@txBuf[4]);
     word((@txbuf[14])^):=len;
     wordswap(@txbuf[14]);
      USBBulkWritePort(@txBuf, len+$10);
          if USBBulkReadPort($FFFF) then
          if rxBuf[10]<>$01 then exit;
//          Result:=BufToStr(@rxBuf[0], Length(rxBuf));
          Result:='Ok!';

end;

procedure preflashread ();
begin
          ProductCode[7]:=msgid;
          ProductCode[8]:=ISIHeaderTransId;
          ProductCode[9]:=ISIHeaderMsgBody;
          USBBulkWritePort(@ProductCode, Length(ProductCode));
          USBBulkReadPort($FFFF);
          //Getting IMEI
          IMEI[7]:=msgid;
          IMEI[8]:=ISIHeaderTransId;
          IMEI[9]:=$00;
          USBBulkWritePort(@IMEI, Length(IMEI));
          USBBulkReadPort($FFFF);
          //Get MCUSW version
          MCUSW[7]:=msgid;
          MCUSW[8]:=$00;
          MCUSW[9]:=$03;
          USBBulkWritePort(@MCUSW, Length(MCUSW));
          USBBulkReadPort($FFFF);
          //Check 2nd
          TransId:=$60; MsgBody:=$FF;
          check2nd[7]:=msgid;
          check2nd[8]:=ISIHeaderTransId;
          check2nd[9]:=ISIHeaderMsgBody;
          USBBulkWritePort(@check2nd, Length(check2nd));
          USBBulkReadPort($FFFF);
          //GetRoot
          GetRoot[7]:=msgid;
          GetRoot[8]:=ISIHeaderTransId;
          GetRAPInfo;
end;

procedure s60preflashread();
begin
          //GetRoot
          GetRoot[7]:=msgid;
          GetRoot[8]:=ISIHeaderTransId;
          GetRAPInfo;
end;

function newSelftestitem(testid:string):string;
var
  res:string;
  testres:DWORD;
begin
doselftest[16]:=Str2Byte(testid);
//form1._msg(testid);
 USBBulkWritePort(@doselftest, Length(doselftest));
 if USBBulkReadPort($FFFF) then begin
 DWordSwap(@RxBuf[8]);
 testres:=dword((@rxbuf[8])^);
  Application.Processmessages;
 case testres of
 $00010000:res:='PASSED';
 $00010A01:res:='->ERROR';  
 $00010001: begin
            case rxBuf[15] of
            $03:res:='NOT EXECUTED';
            $04:res:='NOT RUN';
            $01:res:='->ERROR';
            $0D:res:='MINOR'
            else res:='UNKNOW';
            end;
            end;
 $00010C01: begin
            case rxBuf[15] of
            $03:res:='NOT EXECUTED';
            $04:res:='NOT RUN';
            $01:res:='->ERROR';
            $0D:res:='MINOR'
            else res:='UNKNOW';
            end;
            end;
  else res:='UNKNOW';
  end;
    result:=res;
   end;
 end;

function verifyadl():word;
begin
UsbbulkWriteport(@verifyadlb, Length(verifyadlb));
 if UsbBulkReadPort($FF) then begin
 wordswap(@rxbuf[10]);
 result:=word((@rxbuf[10])^);
 end;
end;

function KBstest():Boolean;
begin
result:=False;
 //USBBulkWritePort(@keybTesst, Length(keybTesst));
 //USBBulkReadPort($FF);
 USBBulkWritePort(@keybTest2nd, Length(keybTest2nd));
 if USBBulkReadPort($FFFF) then begin
 if rxBuf[9]=$16 then begin
  if rxbuf[10]=$00 then result:=True else result:=False;
 end
 else result:=false;
 end;
end;

function KBtestEnd():boolean;
begin
  result:=false;
  USBBulkWritePort(@keybTestend, Length(keybTestend));
   if usbbulkreadport($FFFF) then begin
     if rxbuf[10]=$00 then form1._msg('Released Ok!');
    result:=true;
    end;
end;

function getkeyboardstatus():Boolean;
var
  keycnt,i,i2:Integer;
  data,key,len:Word;
begin
  result:=False;
USBBulkWritePort(@checkkeybdata, Length(checkkeybdata));
        if usbbulkreadport($FFFF) then begin
         // Form1._msg(Buftohexstr(@rxBuf[1], Length(rxbuf)));
        if rxBuf[11]=$01 then begin
                keycnt:=HexToInt(Byte2Str(rxbuf[19]));
                Form1._msg('Total pressed keys : '+inttostr(keycnt));
                  if keycnt>0 then begin
                   i2:=20;
                   Form1._msg('');
                   for i:=1 to keycnt do
                   begin
                  WordSwap(@rxBuf[i2]);
                  key:=word((@rxbuf[i2])^);
                  WordSwap(@rxBuf[i2+2]);
                  data:=word((@rxbuf[i2+2])^);
                  form1._msg(getkeystatus(data)+' : '+getkeycode(key));
                  i2:=i2+4;
                   end;
                  Form1._msg('');
                  end else Form1._msg('No any key was pressed :(');
              result:=True;
        end
           else begin
            Form1._msg('No any key was pressed :(');
            Exit;
           end;
  end;
end;

function s60startkeybtest () : Boolean;
begin
 result:=false;
 UsbbulkWriteport(@s60keybtststart, Length(s60keybtststart));
 usbbulkreadport($FF);
 UsbBulkwriteport(@s60keybTst2nd, Length(s60keybTst2nd));
 if usbbulkreadport($FF) then begin
  if rxbuf[9]=$01 then result:=true;
  end;
end;

function checkkeys60 () : Boolean;
var
  keycnt,i,i2:Integer;
  data,key,len:Word;
begin
 UsbBulkwriteport(@s60keybCheck, Length(s60keybCheck));
 if usbbulkreadport($FFFF) then begin
        if rxBuf[14]=$01 then begin
                keycnt:=HexToInt(Byte2Str(rxbuf[15]));
                Form1._msg('Total pressed keys : '+inttostr(keycnt));
                if keycnt>0 then begin
                   i2:=16;
                   Form1._msg('');
                   for i:=1 to keycnt do
                   begin
                  WordSwap(@rxBuf[i2]);
                  key:=word((@rxbuf[i2])^);
                  WordSwap(@rxBuf[i2+2]);
                  data:=word((@rxbuf[i2+2])^);
                  form1._msg(getkeystatus(data)+' : '+getkeycode(key));
                  i2:=i2+4;
                   end;
                  Form1._msg('');
                  end else Form1._msg('No any key was pressed :(');
              result:=True;
                end;
   end;
end;

function finkeybtests60 () : Boolean;
begin
  result:=False;
  UsbBulkwriteport(@s60keytestfree, Length(s60keytestfree));
 if usbbulkreadport($FF) then begin
 UsbbulkWriteport(@s60keybtststart, Length(s60keybtststart));
 usbbulkreadport($FF);
  result:=true;
  end;
end;

function usbs40chr(level:word; filepath:string):Boolean;
var
  hider,s2:string;
  framelen:word;
begin
  result:=false; s2:='';
///build frame
s2:=Copy(PathConv(filepath),3,Length(PathConv(filepath))-4);
hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($12)+chr(0)+chr($6E)+chr(0)+chr(Length(filepath)+1)+chr(0)+chr(0)+chr(0)+chr(0);
Word((@hider[16])^):=level;
hider:=hider+s2+chr(0)+chr(0)+chr(0)+chr(0);
framelen:=Length(hider)-6;
word((@hider[5])^):=framelen;
WordSwap(@hider[5]);
UsbbulkWriteport(@hider[1], Length(hider));
    if USBBulkReadPort($FFFF) then
    begin
     if rxbuf[10]=$00 then result:=True {Form1._msg('CHR : Ok!');} else result:=false;
    //Form1._msg(BufToHexStr(@rxBuf[0],Length(rxBuf)));
    end;
end;

function find_device(): String;
const
 guid: TGUID = '{4f919102-4adf-11d5-882d-00b0d02fe381}';
var
 memberIndex: integer;
 bufferSize: Cardinal;
 deviceInfoSet: HDEVINFO;
 deviceInterfaceData: SP_DEVICE_INTERFACE_DATA;
 deviceInterfaceDetailData: PSPDeviceInterfaceDetailData;
begin
try
 deviceInfoSet := SetupDiGetClassDevs(@guid,nil,0,DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
 memberIndex := 0;
 deviceInterfaceData.cbSize:= SizeOf(deviceInterfaceData);
 success := SetupDiEnumDeviceInterfaces(deviceInfoSet,nil,guid,memberIndex,deviceInterfaceData);
if success then begin
 success := SetupDiGetDeviceInterfaceDetail(deviceInfoSet,@deviceInterfaceData,nil,0,bufferSize,nil);
try
 GetMem(deviceInterfaceDetailData, bufferSize);
 deviceInterfaceDetailData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
 success := SetupDiGetDeviceInterfaceDetail(deviceInfoSet,@deviceInterfaceData,deviceInterfaceDetailData,bufferSize,bufferSize,nil);
if success then result := PChar(@DeviceInterfaceDetailData.DevicePath)
else result:='';
finally
 FreeMem(DeviceInterfaceDetailData);
end;
end else result:=''
finally
 SetupDiDestroyDeviceInfoList(deviceInfoSet);
end;
end;


function DevPresent():boolean ;
begin
     //Result:=BB5_USB_ScanAndOpenConnection('','',False);
     if catchdevice=0 then Result:=false else
                           Result:=true;
end;

function catchdevice():Byte;
var
     s        : string;
     R        : Boolean;
     devmode  : byte;//00 - error, 01 - NonFlashing, 02 - Flashing Mode
begin
//----------------------------------------------------------------------------------------
//Flashing mode:
//VID_0421&PID_0103        - ADL Flashing Engine AVALON Parent
//VID_0421&PID_0104        - Nokia ADL USB Re-Flashing Engine Parent
//VID_0421&PID_0105        - Nokia BB5 ADL Loader USB Phone Parent
//VID_0421&PID_0106        - Nokia USB Flashing Parent
//
//VID_0421&PID_0103&IF_OTH - ADL Flashing Engine AVALON Generic
//VID_0421&PID_0103&IF_LC  - ADL Flashing Engine AVALON LCIF
//VID_0421&PID_0104&IF_OTH - Nokia ADL USB Re-Flashing Engine Generic
//VID_0421&PID_0105&IF_OTH - Nokia BB5 ADL Loader USB Generic
//VID_0421&PID_0105&IF_LC  - Nokia BB5 ADL Loader USB LCIF
//VID_0421&PID_0106&IF_OTH - Nokia USB Flashing Generic
//VID_0421&PID_0106&IF_LC  - Nokia USB Flashing LCIF
//----------------------------------------------------------------------------------------
     result:=$00;
     R:=False;
     s:='';
     devmode:=$00;
     s:=find_device;
     if s='' then exit;
     if not MatchesMask(s, '*VID_0421&PID_*') then exit;

     if (not MatchesMask(s, '*VID_0421&PID_0103*')) and
        (not MatchesMask(s, '*VID_0421&PID_0104*')) and
        (not MatchesMask(s, '*VID_0421&PID_0105*')) and
        (not MatchesMask(s, '*VID_0421&PID_0106*')) then devmode:=$01 //не флеш-мод
                                                    else devmode:=$02;//флеш-мод
     //Form1._msg('mode is: '+inttostr(devmode));
     R:=USBOpenPort(s, 0);
     if R=True then result:=devmode else begin result:=$00; UsbClosePort; end;
end;


function ResetPhone():boolean;
begin
result:=false;
UsbbulkWriteport(@SetNlmode,length(SetNlmode));
 If usbbulkreadport($FFFF) then begin
  if rxbuf[10]<>$02 then result:=true;
 end;
end;

function WriteLTnew(lt:Integer;position:Integer):Boolean;
var
  s:string;
  d:DWORD;
begin
 result:=false;
 d:=lt;
 dwordswap(@d);
 case position of
 2:
  begin
  if PmWriteRecord(373,0,'000000000000000000000000000000000000000000000000000000000000000000000000'+IntToHex(d,8)+'01FF0000')<>'Ok' then exit;
  if pmWriteRecord(374,0,IntToHex(d,8))<>'Ok' then exit;
  end;
 3:
  begin
  dwordswap(@d);
  if pmWriteRecord(382,1,IntToHex(d,8))<>'Ok' then exit;
  end;
 else
  begin
   form1._msg('Error while collect info, break :(');
   Exit;
  end;
 end;
 result:=true;
end;

Function S40CreateDir(Dir:string):byte;
var
  a,s,s2,hider  :string;
  i,sz,n        :Integer;
  sizz,framelen :Word;
begin
 s:='';  hider:=''; //result:=0;
hider:=chr($1B)+chr(0)+chr($10)+chr($6D)+chr(0)+chr(0)+chr(0)+chr($05)+chr($10)+chr($64);
s2:=PathConv(Dir);
hider:=hider+copy(s2,1,length(s2)-3)+chr(0);
s:=hider;

framelen:=Length(s)-6;
word((@s[5])^):=framelen;
WordSwap(@s[5]);
Word((@s[11])^):=Length(dir)+1;
WordSwap(@s[11]);
   USBBulkWritePort(@s[1], Length(s));
   if USBBulkReadPort($FFFF) then result:=rxBuf[10];

end;

function GetPBstatus():Dword;
begin
 cntT:=0;
 cntU:=0;
 cntF:=0;
 USBBulkWritePort(@GetPBstat[0], Length(GetPBstat));
 if USBBulkReadPort($FFFF)
 then
 begin
 cntT:=HexToInt(IntToHex(rxbuf[24], 2)+IntToHex(rxbuf[25], 2));
 cntU:=HexToInt(IntToHex(rxbuf[26], 2)+IntToHex(rxbuf[27], 2));
 CNTf:=Cntt-CntU;
 Application.ProcessMessages;
 form1._msg('Cnt Server Info : '+inttostr(cntU)+'/'+inttostr(cntF)+'/'+inttostr(cntT));
 Application.ProcessMessages;
 end;
end;

function UsbWriteCLMA(key:string):boolean;
var
  i        : Integer;
  framelen : Word;
  b        : Word;
begin
  result:=False;
 //1B 00 10 08 0B D6 00 18 03 17 2B 33 00 00 0B CC
 BufCopy(@CLMahead[0],@txbuf[0],16);
 i:=StrToBufHex(key,@txbuf[16]);
 Word((@txBuf[14])^):=i;
 WordSwap(@txbuf[14]);
 Word((@txBuf[4])^):=i+$0A;
 WordSwap(@txbuf[4]);
 USBBulkWritePort(@txbuf[0],i+$10);
 if USBBulkReadPort($FFFF)
 then
 begin
 result:=True;
 Form1._msg(BufToHexStr(@rxBuf[0],10));
 end;

end;

end.
