Advertisement
Guest User

Untitled

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