Advertisement
Guest User

Untitled

a guest
Feb 17th, 2020
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 12.14 KB | None | 0 0
  1. program UsbDriveEraser_SearchForErrors;
  2.  
  3. {$mode delphi}
  4. {$H+}
  5.  
  6. uses
  7.   RaspberryPi,
  8.   GlobalConst,
  9.   GlobalTypes,
  10.   Platform,
  11.   Threads,
  12.   Console,
  13.   Framebuffer,
  14.   SysUtils,
  15.   Classes,
  16.   Devices,
  17.   Storage,
  18.   FileSystem,
  19.   Ultibo,
  20.  
  21.   HTTP,
  22.   WebStatus,
  23.  
  24.   RemoteShell,
  25.   ShellFilesystem,
  26.   ShellUpdate,
  27.  
  28.   GPIO;
  29.  
  30. const
  31.  {Define constants for the states of our switch (On or Off)}
  32.  FORMAT_SWITCH_STATE_OFF = 0;
  33.  FORMAT_SWITCH_STATE_ON  = 1;
  34.  
  35. var
  36.  UserInput:String;
  37.  WindowHandle:TWindowHandle;
  38.  HTTPListener:THTTPListener;
  39.  
  40.  CurrentDiskDevice:TDiskDevice;
  41.  CurrentStorageDevice:PStorageDevice;
  42.  
  43.  FormatSwitchState:LongWord;
  44.  
  45. function NotifyStorageDevice(Device:PDevice;Data:Pointer;Notification:LongWord):LongWord;
  46. {This function will be called when a storage device event that we have registered for occurs}
  47. var
  48.  Count:Integer;
  49.  DiskDevice:TDiskDevice;
  50. begin
  51.  Result:=ERROR_SUCCESS;
  52.  
  53.  {Check Device}
  54.  if Device = nil then Exit;
  55.  
  56.  {Check Notification}
  57.  if (Notification and DEVICE_NOTIFICATION_INSERT) <> 0 then
  58.   begin
  59.    ConsoleWindowWriteLn(WindowHandle,'Storage Device inserted');
  60.  
  61.    {Get (and Lock) Device}
  62.    Count:=0;
  63.    DiskDevice:=FileSysDriver.GetDeviceByStorage(PStorageDevice(Device),True,FILESYS_LOCK_READ);
  64.    while DiskDevice = nil do
  65.     begin
  66.      {Sleep to allow time for the filesystem to mount the device}
  67.      Sleep(500);
  68.  
  69.      {Try to get the device again}
  70.      DiskDevice:=FileSysDriver.GetDeviceByStorage(PStorageDevice(Device),True,FILESYS_LOCK_READ);
  71.  
  72.      Inc(Count);
  73.      if Count >= 5 then Break;
  74.     end;
  75.  
  76.    try
  77.     if DiskDevice <> nil then
  78.      begin
  79.       ConsoleWindowWriteLn(WindowHandle,'Device Name: ' + DiskDevice.Name);
  80.  
  81.       {Check for a USB device}
  82.       if Device.DeviceBus = DEVICE_BUS_USB then
  83.        begin
  84.         ConsoleWindowWriteLn(WindowHandle,'USB device detected');
  85.  
  86.         {Save the details for later}
  87.         CurrentDiskDevice:=DiskDevice;
  88.         CurrentStorageDevice:=PStorageDevice(Device);
  89.        end
  90.       else
  91.        begin
  92.         ConsoleWindowWriteLn(WindowHandle,'Device is not USB');
  93.        end;
  94.      end
  95.     else
  96.      begin
  97.       ConsoleWindowWriteLn(WindowHandle,'Device Name: <Unknown>');
  98.      end;
  99.    finally
  100.     {Unlock Device}
  101.     DiskDevice.ReaderUnlock;
  102.    end;
  103.   end
  104.  else if (Notification and DEVICE_NOTIFICATION_EJECT) <> 0 then
  105.   begin
  106.    ConsoleWindowWriteLn(WindowHandle,'Storage Device ejected');
  107.  
  108.    {Check Device}
  109.    if PStorageDevice(Device) = CurrentStorageDevice then
  110.     begin
  111.      ConsoleWindowWriteLn(WindowHandle,'Current USB device ejected');
  112.  
  113.      {Clear the details}
  114.      CurrentDiskDevice:=nil;
  115.      CurrentStorageDevice:=nil;
  116.     end
  117.    else
  118.     begin
  119.      ConsoleWindowWriteLn(WindowHandle,'Other device ejected');
  120.     end;
  121.   end;
  122. end;
  123.  
  124. function PartitionTypeToFileSysType(PartitionType:Byte):TFileSysType;
  125. {A little function to determine the file system type from the partition id}
  126. begin
  127.  Result:=fsUNKNOWN;
  128.  
  129.  case PartitionType of
  130.   pidFAT12:Result:=fsFAT12;
  131.   pidFAT16,pidFAT16HUGE,pidFAT16LBA:Result:=fsFAT16;
  132.   pidFAT32,pidFAT32LBA:Result:=fsFAT32;
  133.   pidHPFSNTFS:Result:=fsNTFS51;
  134.  end;
  135. end;
  136.  
  137. procedure FlashFormattingLED;
  138. {This procedure will toggle the LED GPIO on and off}
  139. begin
  140.  while True do
  141.   GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
  142.   Sleep(250);
  143.   GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
  144.   Sleep(250);
  145.  end;
  146.  
  147. procedure FormatDiskDevice(DiskDevice:TDiskDevice;StorageDevice:PStorageDevice);
  148. {This procedure will format each partition found on the supplied disk device}
  149. var
  150.  Count:Integer;
  151.  
  152.  Volumes:TList;
  153.  Partitions:TList;
  154.  DiskVolume:TDiskVolume;
  155.  DiskPartition:TDiskPartition;
  156.  
  157.  FloppyType:TFloppyType;
  158.  FileSysType:TFileSysType;
  159. begin
  160.  ConsoleWindowWriteLn(WindowHandle,'Formatting Disk Device');
  161.  
  162.  {Start flashing of Formatting-in-Progress LED}
  163.  FlashFormattingLED();
  164.  
  165.  {Lock Device}
  166.  if FileSysDriver.CheckDevice(DiskDevice,True,FILESYS_LOCK_READ) then
  167.   begin
  168.    try
  169.     ConsoleWindowWriteLn(WindowHandle,'Checking device ' + DiskDevice.Name);
  170.  
  171.     {Get Partitions}
  172.     Partitions:=FileSysDriver.GetPartitionsByDevice(DiskDevice,False,FILESYS_LOCK_NONE);
  173.     try
  174.      if Partitions.Count > 0 then
  175.       begin
  176.        {Check Partitions}
  177.        for Count:=0 to Partitions.Count - 1 do
  178.         begin
  179.          DiskPartition:=Partitions.Items[Count];
  180.          if FileSysDriver.CheckPartition(DiskPartition,True,FILESYS_LOCK_READ) then
  181.           begin
  182.            try
  183.             ConsoleWindowWriteLn(WindowHandle,'Checking partition ' + DiskPartition.Path);
  184.  
  185.             {Get Volume}
  186.             DiskVolume:=FileSysDriver.GetVolumeByPartition(DiskPartition,True,FILESYS_LOCK_WRITE);
  187.             if DiskVolume <> nil then
  188.              begin
  189.               try
  190.                ConsoleWindowWriteLn(WindowHandle,'Formatting volume ' + DiskVolume.Name);
  191.  
  192.                {Get Format Type}
  193.                FileSysType:=DiskVolume.FileSysType;
  194.                if FileSysType = fsUNKNOWN then FileSysType:=PartitionTypeToFileSysType(DiskPartition.PartitionId);
  195.                if FileSysType <> fsUNKNOWN then
  196.                 begin
  197.                  {Get Floppy Type}
  198.                  FloppyType:=DiskDevice.FloppyType;
  199.  
  200.                  {Format Volume}
  201.                  if DiskVolume.FormatVolume(FloppyType,FileSysType) then
  202.                   begin
  203.                    ConsoleWindowWriteLn(WindowHandle,'Format completed ' + DiskVolume.Name);
  204.                   end
  205.                  else
  206.                   begin
  207.                    ConsoleWindowWriteLn(WindowHandle,'Could not format ' + DiskVolume.Name);
  208.                   end;
  209.                 end
  210.                else
  211.                 begin
  212.                  ConsoleWindowWriteLn(WindowHandle,'Unrecognized type for volume ' + DiskVolume.Name);
  213.                 end;
  214.               finally
  215.                {Unlock Volume}
  216.                DiskVolume.WriterUnlock;
  217.               end;
  218.              end
  219.             else
  220.              begin
  221.               ConsoleWindowWriteLn(WindowHandle,'No volume found to format on partition ' + DiskPartition.Path);
  222.  
  223.               {Illuminate Error LED}
  224.               GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_HIGH);
  225.              end;
  226.            finally
  227.             {Unlock Partition}
  228.             DiskPartition.ReaderUnlock;
  229.            end;
  230.           end;
  231.         end;
  232.       end
  233.      else
  234.       begin
  235.        {Get Volumes}
  236.        Volumes:=FileSysDriver.GetVolumesByDevice(DiskDevice,False,FILESYS_LOCK_NONE);
  237.        try
  238.         if Volumes.Count > 0 then
  239.          begin
  240.           {Check Volumes}
  241.           for Count:=0 to Volumes.Count - 1 do
  242.            begin
  243.             DiskVolume:=Volumes.Items[Count];
  244.             if FileSysDriver.CheckVolume(DiskVolume,True,FILESYS_LOCK_WRITE) then
  245.              begin
  246.               try
  247.                ConsoleWindowWriteLn(WindowHandle,'Formatting volume ' + DiskVolume.Name);
  248.  
  249.                {Get Format Type}
  250.                FileSysType:=DiskVolume.FileSysType;
  251.                if FileSysType = fsUNKNOWN then FileSysType:=fsFAT32;
  252.  
  253.                {Get Floppy Type}
  254.                FloppyType:=DiskDevice.FloppyType;
  255.  
  256.                {Format Volume}
  257.                if DiskVolume.FormatVolume(FloppyType,FileSysType) then
  258.                 begin
  259.                  ConsoleWindowWriteLn(WindowHandle,'Format completed ' + DiskVolume.Name);
  260.                 end
  261.                else
  262.                 begin
  263.                  ConsoleWindowWriteLn(WindowHandle,'Could not format ' + DiskVolume.Name);
  264.                 end;
  265.               finally
  266.                {Unlock Volume}
  267.                DiskVolume.WriterUnlock;
  268.               end;
  269.              end;
  270.            end;
  271.          end
  272.         else
  273.          begin
  274.           ConsoleWindowWriteLn(WindowHandle,'No volume found to format on device ' + DiskDevice.Name);
  275.  
  276.           {Illuminate Error LED}
  277.           GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_HIGH);
  278.          end;
  279.        finally
  280.         Volumes.Free;
  281.        end;
  282.       end;
  283.     finally
  284.      Partitions.Free;
  285.     end;
  286.    finally
  287.     {Unlock Device}
  288.     DiskDevice.ReaderUnlock;
  289.  
  290.     {Stop flashing of Formatting-in-Progress LED}
  291.     GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
  292.  
  293.     {Illuminate Wipe completion LED}
  294.     GPIOOutputSet(GPIO_PIN_19,GPIO_LEVEL_HIGH);
  295.    end;
  296.   end;
  297. end;
  298.  
  299. {This is the function called when a GPIO event occurs}
  300. procedure GPIOEventFunction(Data:Pointer;Pin,Trigger:LongWord);
  301. begin
  302.  {Sleep for a few milliseconds to allow the switch to settle}
  303.  Sleep(10);
  304.  
  305.  {Read the current state of the switch (High or Low)}
  306.  if GPIOInputGet(GPIO_PIN_12) = GPIO_LEVEL_LOW then
  307.   begin
  308.    {If the state is Low the switch is On so update the state variable}
  309.    FormatSwitchState:=FORMAT_SWITCH_STATE_ON;
  310.  
  311.    {Print a message on the console in green to say the switch is on}
  312.    ConsoleWindowSetForecolor(WindowHandle,COLOR_GREEN);
  313.    ConsoleWindowWriteLn(WindowHandle,'Format switch is ON');
  314.  
  315.    {Reregister this function to be called when the state changes to High}
  316.    GPIOInputEvent(GPIO_PIN_12,GPIO_TRIGGER_HIGH,INFINITE,@GPIOEventFunction,nil);
  317.   end
  318.  else
  319.   begin
  320.    {The level is High so the switch must be Off, save that to the state variable}
  321.    FormatSwitchState:=FORMAT_SWITCH_STATE_OFF;
  322.  
  323.    {Print the switch is off message in red}
  324.    ConsoleWindowSetForecolor(WindowHandle,COLOR_RED);
  325.    ConsoleWindowWriteLn(WindowHandle,'Format switch is OFF');
  326.  
  327.    {And register again for an event when the level changes to Low}
  328.    GPIOInputEvent(GPIO_PIN_12,GPIO_TRIGGER_LOW,INFINITE,@GPIOEventFunction,nil);
  329.   end;
  330. end;
  331.  
  332. begin
  333.  HTTPListener:=THTTPListener.Create;
  334.  HTTPListener.Active:=True;
  335.  WebStatusRegister(HTTPListener,'','',True);
  336.  
  337.  {Create a console window at full size}
  338.  WindowHandle:=ConsoleWindowCreate(ConsoleDeviceGetDefault,CONSOLE_POSITION_FULL,True);
  339.  
  340.  {Output some welcome text on the console window}
  341.  ConsoleWindowWriteLn(WindowHandle,'Disk detection and formatting example');
  342.  
  343.   {Set GPIO pin 18 (our switch) to Pull Up so the pin will be High when the switch
  344.  is off and Low when the switch is On. Then set the function of pin 18 to be an
  345.  Input so we can read the switch state using the GPIOInputGet() function}
  346.  GPIOPullSelect(GPIO_PIN_18,GPIO_PULL_UP);
  347.  GPIOFunctionSelect(GPIO_PIN_18,GPIO_FUNCTION_IN);
  348.  
  349.  {Set GPIO pin 5 (System Ready LED) to Pull None and make the function of the pin an Output
  350.  so we can set the level to High or Low to turn the LED On or Off. After setting
  351.  the function we also set the current level to Low so the LED is Off}
  352.  GPIOPullSelect(GPIO_PIN_5,GPIO_PULL_NONE);
  353.  GPIOFunctionSelect(GPIO_PIN_5,GPIO_FUNCTION_OUT);
  354.  GPIOOutputSet(GPIO_PIN_5,GPIO_LEVEL_LOW);
  355.  
  356.  {Do the same for GPIO pins 6, 13, 19 and 26 (the USB Drive Mounted, Wipe-in-Progress, Wipe Complete and Error LEDs)}
  357.  GPIOPullSelect(GPIO_PIN_6,GPIO_PULL_NONE);
  358.  GPIOFunctionSelect(GPIO_PIN_6,GPIO_FUNCTION_OUT);
  359.  GPIOOutputSet(GPIO_PIN_6,GPIO_LEVEL_LOW);
  360.  GPIOPullSelect(GPIO_PIN_13,GPIO_PULL_NONE);
  361.  GPIOFunctionSelect(GPIO_PIN_13,GPIO_FUNCTION_OUT);
  362.  GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
  363.  GPIOPullSelect(GPIO_PIN_19,GPIO_PULL_NONE);
  364.  GPIOFunctionSelect(GPIO_PIN_19,GPIO_FUNCTION_OUT);
  365.  GPIOOutputSet(GPIO_PIN_19,GPIO_LEVEL_LOW);
  366.  GPIOPullSelect(GPIO_PIN_26,GPIO_PULL_NONE);
  367.  GPIOFunctionSelect(GPIO_PIN_26,GPIO_FUNCTION_OUT);
  368.  GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_LOW);
  369.  
  370.  {Register for Insert and Eject notifications for Storage Devices}
  371.  StorageDeviceNotification(nil,NotifyStorageDevice,nil,DEVICE_NOTIFICATION_EJECT or DEVICE_NOTIFICATION_INSERT,NOTIFIER_FLAG_WORKER);
  372.  
  373.  {Loop waiting for a device}
  374.  while True do
  375.   begin
  376.    if (CurrentDiskDevice <> nil) and (CurrentStorageDevice <> nil) then
  377.     begin
  378.      {Prompt the user to format the device, this uses the keyboard but it could be a GPIO input or something else}
  379.      ConsoleWindowWriteLn(WindowHandle,'USB device detected, type FORMAT to proceed');
  380.      ConsoleReadLn(UserInput);
  381.      if UserInput = 'FORMAT' or FormatSwitchState = 1 then
  382.       begin
  383.        {Proceed with format}
  384.        FormatDiskDevice(CurrentDiskDevice,CurrentStorageDevice);
  385.       end;
  386.     end;
  387.  
  388.  
  389.    {Sleep on each loop}
  390.    Sleep(500);
  391.   end;
  392.  
  393.  {Halt the thread}
  394.  ThreadHalt(0);
  395. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement