Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- program UsbDriveEraser_SearchForErrors;
- {$mode delphi}
- {$H+}
- uses
- RaspberryPi,
- GlobalConst,
- GlobalTypes,
- Platform,
- Threads,
- Console,
- Framebuffer,
- SysUtils,
- Classes,
- Devices,
- Storage,
- FileSystem,
- Ultibo,
- HTTP,
- WebStatus,
- RemoteShell,
- ShellFilesystem,
- ShellUpdate,
- GPIO;
- const
- {Define constants for the states of our switch (On or Off)}
- FORMAT_SWITCH_STATE_OFF = 0;
- FORMAT_SWITCH_STATE_ON = 1;
- var
- UserInput:String;
- WindowHandle:TWindowHandle;
- HTTPListener:THTTPListener;
- CurrentDiskDevice:TDiskDevice;
- CurrentStorageDevice:PStorageDevice;
- FormatSwitchState:LongWord;
- function NotifyStorageDevice(Device:PDevice;Data:Pointer;Notification:LongWord):LongWord;
- {This function will be called when a storage device event that we have registered for occurs}
- var
- Count:Integer;
- DiskDevice:TDiskDevice;
- begin
- Result:=ERROR_SUCCESS;
- {Check Device}
- if Device = nil then Exit;
- {Check Notification}
- if (Notification and DEVICE_NOTIFICATION_INSERT) <> 0 then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Storage Device inserted');
- {Get (and Lock) Device}
- Count:=0;
- DiskDevice:=FileSysDriver.GetDeviceByStorage(PStorageDevice(Device),True,FILESYS_LOCK_READ);
- while DiskDevice = nil do
- begin
- {Sleep to allow time for the filesystem to mount the device}
- Sleep(500);
- {Try to get the device again}
- DiskDevice:=FileSysDriver.GetDeviceByStorage(PStorageDevice(Device),True,FILESYS_LOCK_READ);
- Inc(Count);
- if Count >= 5 then Break;
- end;
- try
- if DiskDevice <> nil then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Device Name: ' + DiskDevice.Name);
- {Check for a USB device}
- if Device.DeviceBus = DEVICE_BUS_USB then
- begin
- ConsoleWindowWriteLn(WindowHandle,'USB device detected');
- {Save the details for later}
- CurrentDiskDevice:=DiskDevice;
- CurrentStorageDevice:=PStorageDevice(Device);
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Device is not USB');
- end;
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Device Name: <Unknown>');
- end;
- finally
- {Unlock Device}
- DiskDevice.ReaderUnlock;
- end;
- end
- else if (Notification and DEVICE_NOTIFICATION_EJECT) <> 0 then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Storage Device ejected');
- {Check Device}
- if PStorageDevice(Device) = CurrentStorageDevice then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Current USB device ejected');
- {Clear the details}
- CurrentDiskDevice:=nil;
- CurrentStorageDevice:=nil;
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Other device ejected');
- end;
- end;
- end;
- function PartitionTypeToFileSysType(PartitionType:Byte):TFileSysType;
- {A little function to determine the file system type from the partition id}
- begin
- Result:=fsUNKNOWN;
- case PartitionType of
- pidFAT12:Result:=fsFAT12;
- pidFAT16,pidFAT16HUGE,pidFAT16LBA:Result:=fsFAT16;
- pidFAT32,pidFAT32LBA:Result:=fsFAT32;
- pidHPFSNTFS:Result:=fsNTFS51;
- end;
- end;
- procedure FlashFormattingLED;
- {This procedure will toggle the LED GPIO on and off}
- begin
- while True do
- GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
- Sleep(250);
- GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
- Sleep(250);
- end;
- procedure FormatDiskDevice(DiskDevice:TDiskDevice;StorageDevice:PStorageDevice);
- {This procedure will format each partition found on the supplied disk device}
- var
- Count:Integer;
- Volumes:TList;
- Partitions:TList;
- DiskVolume:TDiskVolume;
- DiskPartition:TDiskPartition;
- FloppyType:TFloppyType;
- FileSysType:TFileSysType;
- begin
- ConsoleWindowWriteLn(WindowHandle,'Formatting Disk Device');
- {Start flashing of Formatting-in-Progress LED}
- FlashFormattingLED();
- {Lock Device}
- if FileSysDriver.CheckDevice(DiskDevice,True,FILESYS_LOCK_READ) then
- begin
- try
- ConsoleWindowWriteLn(WindowHandle,'Checking device ' + DiskDevice.Name);
- {Get Partitions}
- Partitions:=FileSysDriver.GetPartitionsByDevice(DiskDevice,False,FILESYS_LOCK_NONE);
- try
- if Partitions.Count > 0 then
- begin
- {Check Partitions}
- for Count:=0 to Partitions.Count - 1 do
- begin
- DiskPartition:=Partitions.Items[Count];
- if FileSysDriver.CheckPartition(DiskPartition,True,FILESYS_LOCK_READ) then
- begin
- try
- ConsoleWindowWriteLn(WindowHandle,'Checking partition ' + DiskPartition.Path);
- {Get Volume}
- DiskVolume:=FileSysDriver.GetVolumeByPartition(DiskPartition,True,FILESYS_LOCK_WRITE);
- if DiskVolume <> nil then
- begin
- try
- ConsoleWindowWriteLn(WindowHandle,'Formatting volume ' + DiskVolume.Name);
- {Get Format Type}
- FileSysType:=DiskVolume.FileSysType;
- if FileSysType = fsUNKNOWN then FileSysType:=PartitionTypeToFileSysType(DiskPartition.PartitionId);
- if FileSysType <> fsUNKNOWN then
- begin
- {Get Floppy Type}
- FloppyType:=DiskDevice.FloppyType;
- {Format Volume}
- if DiskVolume.FormatVolume(FloppyType,FileSysType) then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Format completed ' + DiskVolume.Name);
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Could not format ' + DiskVolume.Name);
- end;
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Unrecognized type for volume ' + DiskVolume.Name);
- end;
- finally
- {Unlock Volume}
- DiskVolume.WriterUnlock;
- end;
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'No volume found to format on partition ' + DiskPartition.Path);
- {Illuminate Error LED}
- GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_HIGH);
- end;
- finally
- {Unlock Partition}
- DiskPartition.ReaderUnlock;
- end;
- end;
- end;
- end
- else
- begin
- {Get Volumes}
- Volumes:=FileSysDriver.GetVolumesByDevice(DiskDevice,False,FILESYS_LOCK_NONE);
- try
- if Volumes.Count > 0 then
- begin
- {Check Volumes}
- for Count:=0 to Volumes.Count - 1 do
- begin
- DiskVolume:=Volumes.Items[Count];
- if FileSysDriver.CheckVolume(DiskVolume,True,FILESYS_LOCK_WRITE) then
- begin
- try
- ConsoleWindowWriteLn(WindowHandle,'Formatting volume ' + DiskVolume.Name);
- {Get Format Type}
- FileSysType:=DiskVolume.FileSysType;
- if FileSysType = fsUNKNOWN then FileSysType:=fsFAT32;
- {Get Floppy Type}
- FloppyType:=DiskDevice.FloppyType;
- {Format Volume}
- if DiskVolume.FormatVolume(FloppyType,FileSysType) then
- begin
- ConsoleWindowWriteLn(WindowHandle,'Format completed ' + DiskVolume.Name);
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'Could not format ' + DiskVolume.Name);
- end;
- finally
- {Unlock Volume}
- DiskVolume.WriterUnlock;
- end;
- end;
- end;
- end
- else
- begin
- ConsoleWindowWriteLn(WindowHandle,'No volume found to format on device ' + DiskDevice.Name);
- {Illuminate Error LED}
- GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_HIGH);
- end;
- finally
- Volumes.Free;
- end;
- end;
- finally
- Partitions.Free;
- end;
- finally
- {Unlock Device}
- DiskDevice.ReaderUnlock;
- {Stop flashing of Formatting-in-Progress LED}
- GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
- {Illuminate Wipe completion LED}
- GPIOOutputSet(GPIO_PIN_19,GPIO_LEVEL_HIGH);
- end;
- end;
- end;
- {This is the function called when a GPIO event occurs}
- procedure GPIOEventFunction(Data:Pointer;Pin,Trigger:LongWord);
- begin
- {Sleep for a few milliseconds to allow the switch to settle}
- Sleep(10);
- {Read the current state of the switch (High or Low)}
- if GPIOInputGet(GPIO_PIN_12) = GPIO_LEVEL_LOW then
- begin
- {If the state is Low the switch is On so update the state variable}
- FormatSwitchState:=FORMAT_SWITCH_STATE_ON;
- {Print a message on the console in green to say the switch is on}
- ConsoleWindowSetForecolor(WindowHandle,COLOR_GREEN);
- ConsoleWindowWriteLn(WindowHandle,'Format switch is ON');
- {Reregister this function to be called when the state changes to High}
- GPIOInputEvent(GPIO_PIN_12,GPIO_TRIGGER_HIGH,INFINITE,@GPIOEventFunction,nil);
- end
- else
- begin
- {The level is High so the switch must be Off, save that to the state variable}
- FormatSwitchState:=FORMAT_SWITCH_STATE_OFF;
- {Print the switch is off message in red}
- ConsoleWindowSetForecolor(WindowHandle,COLOR_RED);
- ConsoleWindowWriteLn(WindowHandle,'Format switch is OFF');
- {And register again for an event when the level changes to Low}
- GPIOInputEvent(GPIO_PIN_12,GPIO_TRIGGER_LOW,INFINITE,@GPIOEventFunction,nil);
- end;
- end;
- begin
- HTTPListener:=THTTPListener.Create;
- HTTPListener.Active:=True;
- WebStatusRegister(HTTPListener,'','',True);
- {Create a console window at full size}
- WindowHandle:=ConsoleWindowCreate(ConsoleDeviceGetDefault,CONSOLE_POSITION_FULL,True);
- {Output some welcome text on the console window}
- ConsoleWindowWriteLn(WindowHandle,'Disk detection and formatting example');
- {Set GPIO pin 18 (our switch) to Pull Up so the pin will be High when the switch
- is off and Low when the switch is On. Then set the function of pin 18 to be an
- Input so we can read the switch state using the GPIOInputGet() function}
- GPIOPullSelect(GPIO_PIN_18,GPIO_PULL_UP);
- GPIOFunctionSelect(GPIO_PIN_18,GPIO_FUNCTION_IN);
- {Set GPIO pin 5 (System Ready LED) to Pull None and make the function of the pin an Output
- so we can set the level to High or Low to turn the LED On or Off. After setting
- the function we also set the current level to Low so the LED is Off}
- GPIOPullSelect(GPIO_PIN_5,GPIO_PULL_NONE);
- GPIOFunctionSelect(GPIO_PIN_5,GPIO_FUNCTION_OUT);
- GPIOOutputSet(GPIO_PIN_5,GPIO_LEVEL_LOW);
- {Do the same for GPIO pins 6, 13, 19 and 26 (the USB Drive Mounted, Wipe-in-Progress, Wipe Complete and Error LEDs)}
- GPIOPullSelect(GPIO_PIN_6,GPIO_PULL_NONE);
- GPIOFunctionSelect(GPIO_PIN_6,GPIO_FUNCTION_OUT);
- GPIOOutputSet(GPIO_PIN_6,GPIO_LEVEL_LOW);
- GPIOPullSelect(GPIO_PIN_13,GPIO_PULL_NONE);
- GPIOFunctionSelect(GPIO_PIN_13,GPIO_FUNCTION_OUT);
- GPIOOutputSet(GPIO_PIN_13,GPIO_LEVEL_LOW);
- GPIOPullSelect(GPIO_PIN_19,GPIO_PULL_NONE);
- GPIOFunctionSelect(GPIO_PIN_19,GPIO_FUNCTION_OUT);
- GPIOOutputSet(GPIO_PIN_19,GPIO_LEVEL_LOW);
- GPIOPullSelect(GPIO_PIN_26,GPIO_PULL_NONE);
- GPIOFunctionSelect(GPIO_PIN_26,GPIO_FUNCTION_OUT);
- GPIOOutputSet(GPIO_PIN_26,GPIO_LEVEL_LOW);
- {Register for Insert and Eject notifications for Storage Devices}
- StorageDeviceNotification(nil,NotifyStorageDevice,nil,DEVICE_NOTIFICATION_EJECT or DEVICE_NOTIFICATION_INSERT,NOTIFIER_FLAG_WORKER);
- {Loop waiting for a device}
- while True do
- begin
- if (CurrentDiskDevice <> nil) and (CurrentStorageDevice <> nil) then
- begin
- {Prompt the user to format the device, this uses the keyboard but it could be a GPIO input or something else}
- ConsoleWindowWriteLn(WindowHandle,'USB device detected, type FORMAT to proceed');
- ConsoleReadLn(UserInput);
- if UserInput = 'FORMAT' or FormatSwitchState = 1 then
- begin
- {Proceed with format}
- FormatDiskDevice(CurrentDiskDevice,CurrentStorageDevice);
- end;
- end;
- {Sleep on each loop}
- Sleep(500);
- end;
- {Halt the thread}
- ThreadHalt(0);
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement