Files
bds.mr.devmgr/src.devmgr/drv/usb/mr.drv.usb.notifier.pas
T
2026-01-08 19:04:51 +01:00

189 lines
5.3 KiB
ObjectPascal

unit mr.drv.usb.notifier;
interface
uses
System.Classes,
Winapi.Windows,
Winapi.Messages,
mr.drv.usb;
const
DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface class
DBT_DEVICEARRIVAL = $8000; // system detected a new device
DBT_DEVICEQUERYREMOVE = $8001;
DBT_DEVICEQUERYREMOVEFAILED= $8002;
DBT_DEVICEREMOVEPENDING = $8003;
DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone
DBT_DEVICETYPESPECIFIC = $8005;
type
TusbNotifyEvent = procedure( APath: string; ADriverClass: TUsbDriverClass) of object;
PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = packed record
dbch_size : DWORD;
dbch_devicetype: DWORD;
dbch_reserved : DWORD;
end;
PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
DEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size : DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved : DWORD;
dbcc_classguid : TGUID;
dbcc_name : char;
end;
type
TusbNotifier = class
private
fDeviceInterface : string;
fDriverClass : TUsbDriverClass;
fNotifyHandle : HDEVNOTIFY;
FWindowHandle : HWND;
FOnUSBArrival : TusbNotifyEvent;
FOnUSBRemove : TusbNotifyEvent;
procedure WndProc(var Msg: TMessage);
function USBRegister: Boolean;
protected
procedure WMDeviceChange(var Msg: TMessage); dynamic;
public
constructor Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass);
destructor Destroy; override;
public
property OnUSBArrival : TusbNotifyEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove : TusbNotifyEvent read FOnUSBRemove write FOnUSBRemove;
property DeviceInterface: string read fDeviceInterface;
end;
implementation
uses
Vcl.Forms,
System.SysUtils;
{ TusbNotifier }
// ================================================================================================
// constructor
//
// '{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}' [trinity.inf]
// ================================================================================================
constructor TusbNotifier.Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass);
begin
inherited Create;
fDeviceInterface := ADeviceInterface;
fDriverClass := ADriverClass;
fWindowHandle := AllocateHWnd(WndProc);
UsbRegister
end;
// ================================================================================================
// destructor
// ================================================================================================
destructor TusbNotifier.Destroy;
begin
if fNotifyHandle <> nil then
UnregisterDeviceNotification( fNotifyHandle);
DeallocateHWnd( fWindowHandle);
inherited
end;
// ================================================================================================
// UsbRegister
// ================================================================================================
function TusbNotifier.USBRegister: Boolean;
var
dbi : DEV_BROADCAST_DEVICEINTERFACE;
size : Integer;
begin
size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
ZeroMemory(@dbi, Size);
dbi.dbcc_size := Size;
dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_classguid := StringToGUID( fDeviceInterface);
dbi.dbcc_reserved := 0;
dbi.dbcc_name := #0;
fNotifyHandle := RegisterDeviceNotification( fWindowHandle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
result := fNotifyHandle <> nil
end;
// ================================================================================================
// WndProc
// ================================================================================================
procedure TusbNotifier.WndProc(var Msg: TMessage);
begin
if Msg.Msg = WM_DEVICECHANGE then
begin
try
WMDeviceChange(Msg)
except
Application.HandleException(Self)
end
end
else
Msg.Result := DefWindowProc( fWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam)
end;
// ================================================================================================
// WM Device Change
// ================================================================================================
procedure TusbNotifier.WMDeviceChange(var Msg: TMessage);
var
devType : Integer;
devHdr : PDevBroadcastHdr;
begin
if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE) then
begin
devHdr := PDevBroadcastHdr( Msg.lParam);
devType := devHdr^.dbch_devicetype;
if devType = DBT_DEVTYP_DEVICEINTERFACE then
begin // USB Device
var x := PDevBroadcastDeviceInterface( Msg.LParam);
var p := PChar( @x.dbcc_name);
var s := '';
while p^ <> #0 do
begin
s := s + p^;
INC(p)
end;
if Msg.wParam = DBT_DEVICEARRIVAL then
begin
if Assigned( fOnUSBArrival) then
FOnUSBArrival( s, fDriverClass)
end
else begin
if Assigned( fOnUSBRemove) then
FOnUSBRemove( s, fDriverClass)
end
end
end
end;
end.