unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
FILE_DEVICE_UNKNOWN = $00000022;
FILE_DEVICE_USB = FILE_DEVICE_UNKNOWN;
USB_IOCTL_INTERNAL_INDEX = $0000;
USB_IOCTL_INDEX = $00ff;
METHOD_BUFFERED = 0;
FILE_ANY_ACCESS = 0;
IOCTL_USB_GET_NODE_INFORMATION = ((FILE_DEVICE_USB shl 16) or
((USB_IOCTL_INDEX+3) shl 2) or
METHOD_BUFFERED or
(FILE_ANY_ACCESS shl 14));
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION = ((FILE_DEVICE_USB shl 16) or
((USB_IOCTL_INDEX+4) shl 2) or
METHOD_BUFFERED or
(FILE_ANY_ACCESS shl 14));
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = ((FILE_DEVICE_USB shl 16) or
((USB_IOCTL_INDEX+5) shl 2) or
METHOD_BUFFERED or
(FILE_ANY_ACCESS shl 14));
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = ((FILE_DEVICE_USB shl 16) or
((USB_IOCTL_INDEX+9) shl 2) or
METHOD_BUFFERED or
(FILE_ANY_ACCESS shl 14));
IOCTL_GET_HCD_DRIVERKEY_NAME = ((FILE_DEVICE_USB shl 16) or
((USB_IOCTL_INDEX+10) shl 2) or
METHOD_BUFFERED or
(FILE_ANY_ACCESS shl 14));
USB_REQUEST_GET_DESCRIPTOR = $06;
USB_STRING_DESCRIPTOR_TYPE = $03;
USB_CONFIGURATION_DESCRIPTOR_TYPE = $02;
type
TUnicodeName = record
Length: DWORD;
UnicodeName: array[0..255] of Byte;
end;
TNodeType = record
ConnectionIndex: DWORD;
Length: DWORD;
UnicodeName: array[0..255] of byte
end;
THubDescriptor = record
Length: Byte;
HubType: Byte;
PortCount: Byte;
Characteristics: array[0..1] of Byte;
PowerOnToPowerGood: Byte;
HubControlCurrent: Byte;
RemoveAndPowerMask: array[0..63] of Byte;
end;
TNodeInformation = record
NodeType: DWORD;
NodeDescriptor: THubDescriptor;
HubIsBusPowered: Byte;
end;
TDeviceDescriptor = record
Length: Byte;
DescriptorType: Byte;
USBSpec: array[0..1] of Byte;
DeviceClass: Byte;
DeviceSubClass: Byte;
DeviceProtocol: Byte;
MaxPacketSize0: Byte;
VendorID: Word;//array[0..1] of Byte;
ProductID: Word; //array[0..1] of Byte;
DeviceRevision: array[0..1] of byte;
ManufacturerStringIndex: byte;
ProductStringIndex: Byte;
SerialNumberStringIndex: Byte;
ConfigurationCount: Byte;
end;
TEndPointDescriptor = record
Length: Byte;
DescriptorType: Byte;
EndpointAddress: Byte;
Attributes: Byte;
MaxPacketSize: WORD;
PollingInterval: Byte;
end;
TUSBPipeInfo = record
EndPointDescriptor: TEndpointDescriptor;
ScheduleOffset: DWORD;
end;
TNodeConnectionInformation = record
ConnectionIndex: DWORD;
ThisDevice: TDeviceDescriptor;
CurrentConfiguration: Byte;
LowSpeed: Byte;
DeviceIsHub: Byte;
DeviceAddress: array[0..1] of Byte;
NumberOfOpenEndPoints: array[0..3] of Byte;
ThisConnectionStatus: array[0..3] of Byte;
PipeList: array[0..31] of TUSBPipeInfo;
end;
TSetupPacket = record
bmRequest: Byte;
bRequest: Byte;
wValue: array[0..1] of Byte;
wIndex: array[0..1] of Byte;
wLength: array[0..1] of Byte;
end;
TDescriptorRequest = record
ConnectionIndex: DWORD;
SetupPacket: TSetupPacket;
ConfigurationDescriptor: array[0..2047] of Byte;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetDeviceName1(hDevice: THandle; IOCTL_Code: DWORD): string;
var
i: Integer;
NameBuffer: TUnicodeName;
BytesReturned: DWORD;
begin
Result:='';
if DeviceIoControl(hDevice,IOCTL_Code,@NameBuffer,SizeOf(NameBuffer),@NameBuffer,SizeOf(NameBuffer),BytesReturned,nil) then begin
i:=0;
while NameBuffer.UnicodeName[i]<>0 do begin
Result:=Result+Chr(NameBuffer.UnicodeName[i]);
Inc(i,2);
end;
end else
Result:=Format('Error: %s (%d)',[SysErrorMessage(GetLastError),GetLastError]);
end;
function GetDeviceName2(hDevice: THandle; PortIndex: DWORD; IOCTL_Code: DWORD): string;
var
i: Integer;
NameBuffer: TNodeType;
BytesReturned: DWORD;
begin
Result:='';
NameBuffer.ConnectionIndex:=PortIndex;
if DeviceIoControl(hDevice,IOCTL_Code,@NameBuffer,SizeOf(NameBuffer),@NameBuffer,SizeOf(NameBuffer),BytesReturned,nil) then begin
i:=0;
while NameBuffer.UnicodeName[i]<>0 do begin
Result:=Result+Chr(NameBuffer.UnicodeName[i]);
Inc(i,2);
end;
end else
Result:=Format('Error: %s (%d)',[SysErrorMessage(GetLastError),GetLastError]);
end;
function GetNodeInformation(hDevice: THandle; var Information: TNodeInformation): Integer;
var
BytesReturned: DWORD;
begin
if DeviceIoControl(hDevice,IOCTL_USB_GET_NODE_INFORMATION,nil,0,@Information,SizeOf(Information),BytesReturned,nil) and (BytesReturned<=256) then
Result:=0
else
Result:=GetLastError;
end;
function GetNodeConnection(hDevice: THandle; PortIndex: DWORD; var Connection: TNodeConnectionInformation): Integer;
var
BytesReturned: DWORD;
begin
Zeromemory(@Connection,SizeOf(Connection));
Connection.ConnectionIndex:=PortIndex;
if not DeviceIoControl(hDevice,IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,@Connection,SizeOf(Connection),@Connection,SizeOf(Connection),BytesReturned,nil) and (BytesReturned<=256) then
Result:=GetLastError
else
Result:=0;
end;
function GetStringDescriptor(HubHandle: THandle; PortIndex: DWORD; var LanguageID: Word; Index: Byte; var Str: shortstring): integer;
var
Packet: TDescriptorRequest;
BytesReturned: DWORD;
Success: boolean;
begin
Str:='';
Result:=0;
if (LanguageID=0) then begin
Packet.ConnectionIndex:=PortIndex;
Packet.SetupPacket.bmRequest:=$80;
Packet.SetupPacket.bRequest:=USB_REQUEST_GET_DESCRIPTOR;
Packet.SetupPacket.wValue[1]:=USB_STRING_DESCRIPTOR_TYPE;
Packet.SetupPacket.wLength[0]:=8;
{Success:=}DeviceIoControl(HubHandle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,@Packet,
sizeof(Packet),@Packet,sizeof(Packet),BytesReturned,nil);
{if not Success then
Result:=GetLastError;}
LanguageID:=Packet.ConfigurationDescriptor[2]+(Packet.ConfigurationDescriptor[3] shl 8);
end;
Packet.ConnectionIndex:=PortIndex;
Packet.SetupPacket.bmRequest:=$80;
Packet.SetupPacket.bRequest:=USB_REQUEST_GET_DESCRIPTOR;
Packet.SetupPacket.wValue[1]:=USB_STRING_DESCRIPTOR_TYPE;
Packet.SetupPacket.wValue[0]:=Index;
Packet.SetupPacket.wIndex[0]:=LanguageID and $FF;
Packet.SetupPacket.wIndex[1]:=(LanguageID shr 8) and $FF;
Packet.SetupPacket.wLength[0]:=255;
Success:=DeviceIoControl(HubHandle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,@Packet,
sizeof(Packet),@Packet,sizeof(Packet),BytesReturned,nil);
if not Success then
Result:=GetLastError
else begin
ZeroMemory(@Packet.ConfigurationDescriptor[2],255);
Packet.ConnectionIndex:=PortIndex;
Packet.SetupPacket.bmRequest:=$80;
Packet.SetupPacket.bRequest:=USB_REQUEST_GET_DESCRIPTOR;
Packet.SetupPacket.wValue[1]:=USB_STRING_DESCRIPTOR_TYPE;
Packet.SetupPacket.wValue[0]:=Index;
Packet.SetupPacket.wIndex[0]:=LanguageID and $FF;
Packet.SetupPacket.wIndex[1]:=(LanguageID shr 8) and $FF;
Packet.SetupPacket.wLength[0]:=255;
Success:=DeviceIoControl(HubHandle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,@Packet,
sizeof(Packet),@Packet,sizeof(Packet),BytesReturned,nil);
if not Success then
Result:=GetLastError
else
Str:=WideCharToString(PWideChar(@Packet.ConfigurationDescriptor[2]));
end;
end;
function GetConfigurationDescriptor(HubHandle: THandle; PortIndex: DWORD; var MaxPower: WORD; var ClassID: integer): Integer;
var
Packet: TDescriptorRequest;
BytesReturned: DWORD;
Success: boolean;
LowByte: Byte;
BufferPtr: Byte;
begin
Result:=0;
ClassID:=-1;
MaxPower:=0;
with Packet do begin
ConnectionIndex:=PortIndex;
SetupPacket.bmRequest:=$80;
SetupPacket.bRequest:=USB_REQUEST_GET_DESCRIPTOR;
SetupPacket.wValue[0]:=0;
SetupPacket.wValue[1]:=USB_CONFIGURATION_DESCRIPTOR_TYPE;
SetupPacket.wIndex[0]:=0;
SetupPacket.wIndex[1]:=0;
SetupPacket.wLength[0]:=18;
end;
Success:=DeviceIoControl(HubHandle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
@Packet,SizeOf(TDescriptorRequest),@Packet,SizeOf(TDescriptorRequest),BytesReturned,nil);
if not Success then begin
Result:=GetLastError;
Exit;
end;
with Packet do begin
ConnectionIndex:=PortIndex;
SetupPacket.bmRequest:=$80;
SetupPacket.bRequest:=USB_REQUEST_GET_DESCRIPTOR;
SetupPacket.wValue[0]:=0;
SetupPacket.wValue[1]:=USB_CONFIGURATION_DESCRIPTOR_TYPE;
SetupPacket.wIndex[0]:=0;
SetupPacket.wIndex[1]:=0;
SetupPacket.wLength[0]:=Packet.ConfigurationDescriptor[2];
SetupPacket.wLength[1]:=Packet.ConfigurationDescriptor[3];
end;
Success:=DeviceIoControl(HubHandle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
@Packet,SizeOf(TDescriptorRequest),@Packet,SizeOf(TDescriptorRequest),BytesReturned,nil);
if not Success then begin
Result:=GetLastError;
Exit;
end;
MaxPower:=Packet.ConfigurationDescriptor[8]*2;
BufferPtr:=9;
while (Packet.ConfigurationDescriptor[BufferPtr]<>0) do begin
if Packet.ConfigurationDescriptor[BufferPtr+1]=4 then begin
LowByte:=Packet.ConfigurationDescriptor[BufferPtr+5];
if ((LowByte>9) and (LowByte<255)) then
LowByte:=11;
if (LowByte=255) then
LowByte:=10;
ClassID:=LowByte;
Break;
end;
Inc(BufferPtr,9);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i, j, k: Integer;
hHCD, hRH: THandle;
Node: TNodeInformation;
HCDName, RootHubName: string;
SA: TSecurityAttributes;
NodeConnection: TNodeConnectionInformation;
LanguageID: Word;
KeyName, Product, Manufacturer, Serial: shortstring;
MaxPower: Word;
begin
Memo1.Clear;
SA.nLength := Sizeof(SECURITY_ATTRIBUTES);
SA.lpSecurityDescriptor := nil;
SA.bInheritHandle := False;
LanguageID := 0;
for i := 0 to 9 do
begin
HCDName := Format('HCD%d',[i]);
hHCD := CreateFile(PChar(Format('\\.\%s',[HCDName])),
GENERIC_WRITE,
FILE_SHARE_WRITE,
@SA,
OPEN_EXISTING,
0,
0);
if hHCD = INVALID_HANDLE_VALUE then continue;
Memo1.Lines.Add(Format('Host Controller %d',[i]));
KeyName := GetDeviceName1(hHCD,IOCTL_GET_HCD_DRIVERKEY_NAME);
RootHubName := GetDeviceName1(hHCD, IOCTL_USB_GET_NODE_INFORMATION);
hRH := CreateFile(PChar(Format('\\.\%s',[RootHubName])),
GENERIC_WRITE,
FILE_SHARE_WRITE,
@SA,
OPEN_EXISTING,
0,
0);
if hRH = INVALID_HANDLE_VALUE then
begin
CloseHandle(hHCD);
continue;
end;
if GetNodeInformation(hRH, Node) <> ERROR_SUCCESS then
begin
CloseHandle(hRH);
CloseHandle(hHCD);
continue;
end;
Memo1.Lines.Add(' Root Hub');
// 각 HID의 port 정보를 읽는다
for j := 1 to Node.NodeDescriptor.PortCount do
begin
if GetNodeConnection(hRH, j, NodeConnection) <> ERROR_SUCCESS then continue;
if NodeConnection.ThisConnectionStatus[0] <> 1 then
begin
Memo1.Lines.Add(Format(' Port[%d]: No device connected',[j])); // 사용하지 않음
continue;
end;
if Boolean(NodeConnection.DeviceIsHub) then continue;
KeyName := GetDeviceName2(hRH,j,IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME);
if GetStringDescriptor(hRH,j,LanguageID,NodeConnection.ThisDevice.ProductStringIndex,Product)=0 then
Memo1.Lines.Add(Format(' Port[%d]: %s',[j, Product])) // 제품 이름
else
Memo1.Lines.Add(Format(' Port[%d]: <unknown>',[j]));
Memo1.Lines.Add(Format(' Product ID: %.4x',[NodeConnection.ThisDevice.ProductID]));
Memo1.Lines.Add(Format(' Vendor ID: %.4x',[NodeConnection.ThisDevice.VendorID]));
Memo1.Lines.Add(Format(' Version: %d.%d',[NodeConnection.ThisDevice.USBSpec[1], NodeConnection.ThisDevice.USBSpec[0]]));
KeyName := GetDeviceName2(hRH,j,IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME);
if GetStringDescriptor(hRH,j,LanguageID,NodeConnection.ThisDevice.ManufacturerStringIndex,Manufacturer)=0 then
Memo1.Lines.Add(Format(' Manufacturer: %s',[Manufacturer]));
KeyName := GetDeviceName2(hRH,j,IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME);
if GetStringDescriptor(hRH,j,LanguageID,NodeConnection.ThisDevice.SerialNumberStringIndex,Serial)=0 then
Memo1.Lines.Add(Format(' Serial: %s',[Serial]));
k := -1;
GetConfigurationDescriptor(hRH,j,MaxPower,k);
Memo1.Lines.Add(Format(' Power Consumption: %d mA',[MaxPower]));
end;
CloseHandle(hRH);
CloseHandle(hHCD);
Memo1.Lines.Add('');
end;
end;
end.
카테고리 없음