ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 ноября
530443 Топик полностью
бомж (14.07.2014 17:15, просмотров: 253) ответил fk0 на Как в виндовсе можно просмотреть состояние USB-шины. Интересует среди подключенных хабов найти с определённым PID и VID, и найти подключенные к ним компорты в итоге (комп может иметь больше компортов и в них лезть не нужно). И ещё знать для
Давно писал, не помню уже, что и зачем, но до сих пор работает безупречно под всеми виндами. 

unit CP2101;

interface
uses Windows, SysUtils, Classes, Registry;

const
  //Masks for the serial number and description
  CP210x_RETURN_SERIAL_NUMBER = $0;
  CP210x_RETURN_DESCRIPTION = $1;
  CP210x_RETURN_FULL_PATH = $2;

  //Masks for return values from the device
  CP210x_SUCCESS = $0;
  CP210x_DEVICE_NOT_FOUND = $FF;
  CP210x_INVALID_HANDLE = $1;
  CP210x_INVALID_PARAMETER = $2;
  CP210x_DEVICE_IO_FAILED = $3;

  //Maximum Length of Strings
  CP210x_MAX_DEVICE_STRLEN = 256;
  CP210x_MAX_PRODUCT_STRLEN = 126;
  CP210x_MAX_SERIAL_STRLEN = 63;
  CP210x_MAX_MAXPOWER = 250;

  INVALID_HANDLE_VALUE = $1;
  
  // GetDeviceVersion() return codes
	CP210x_CP2101_VERSION	=	$1;
	CP210x_CP2102_VERSION	=	$2;
	CP210x_CP2103_VERSION	=	$3;

  CP2102DLL = 'CP210x.DLL';
  //CP2102RUNTIME = 'CP210xRuntime.dll';

type
  CP210x_STATUS = integer;

  TCP2102 = record
    SerNr : string[CP210x_MAX_SERIAL_STRLEN];
    PortNr : integer;
  end;

TCP210X = class
  private
    FList: TList;
    procedure EnumDevices;
    procedure GetDeviceData;
    function ConvertToString(const ConvertArray: array of Byte; ConvertLength: integer):string;
    function GetPortNumXP2000(Vid,Pid: WORD; serNum: String): Integer;
    function GetCount: Integer;
    function GetItems(Index: Integer): TCP2102;
    function Add(const SerNr: string; PortNr: Integer): Integer; overload;
    function Add(ACP2102: TCP2102): Integer; overload;
  public
    devNum : integer;     //global variable to hold number of devices connected
    hUSBDevice : integer; //global handle that is set when connected with the CP210x device
    Status : integer;     //status, value to set when communicating with the board to determine success
    property Count: Integer read GetCount;
    property Items[Index: Integer]: TCP2102 read GetItems; default;
    constructor Create();
    destructor Destroy; override;
    procedure Clear;
    procedure FillDeviceList;
end;

function CP210x_GetNumDevices (var lpwdNumDevices:integer):Integer; stdcall; external CP2102DLL;
function CP210x_GetProductString(dwDeviceNum:integer; var lpvDeviceString:integer; dwFlags:integer):Integer; stdcall; external CP2102DLL;
function CP210x_Open(dwDevice:integer; var cyHandle:integer):Integer; stdcall; external CP2102DLL;
function CP210x_Close(cyHandle:integer):Integer; stdcall; external CP2102DLL;
function CP210x_Reset(cyHandle:integer):Integer; stdcall; external CP2102DLL;

function CP210x_SetVid(cyHandle:integer; wVid:WORD):Integer; stdcall; external CP2102DLL;
function CP210x_SetPid(cyHandle:integer;	wPid:WORD):Integer; stdcall; external CP2102DLL;
function CP210x_SetProductString(cyHandle:integer; var lpvProduct:integer; bLength:BYTE; bConvertToUnicode : BOOL = TRUE):Integer; stdcall; external CP2102DLL;
function CP210x_SetSerialNumber( cyHandle:integer; var	lpvSerialNumber:byte; bLength:WORD;	bConvertToUnicode :BOOL = TRUE):Integer; stdcall; external CP2102DLL;
function CP210x_SetSelfPower(cyHandle:integer;  bSelfPower:BOOL):Integer; stdcall; external CP2102DLL;
function CP210x_SetMaxPower(cyHandle:integer; bMaxPower:BYTE):Integer; stdcall; external CP2102DLL;
function CP210x_SetDeviceVersion(cyHandle:integer; wVersion:integer):Integer; stdcall; external CP2102DLL;

function CP210x_GetDeviceVid(cyHandle:integer; var	lpwVid:WORD):Integer; stdcall; external CP2102DLL;
function CP210x_GetDevicePid(cyHandle:integer; var	lpwPid:WORD):Integer; stdcall; external CP2102DLL;
function CP210x_GetDeviceProductString(cyHandle:integer; var	lpProduct:Byte; var	lpbLength:integer;	bConvertToASCII:BOOL = TRUE):Integer; stdcall; external CP2102DLL;
//function CP210x_GetDeviceSerialNumber(cyHandle:integer; var	lpSerialNumber:byte; var lpbLength:Byte;	bConvertToASCII:BOOL = TRUE):Integer; stdcall; external CP2102DLL;
function CP210x_GetDeviceSerialNumber(cyHandle:integer;var lpSerialNumber: Byte; var lpbLength:Byte;	bConvertToASCII:BOOL = TRUE):Integer; stdcall; external CP2102DLL;

function CP210x_GetSelfPower(cyHandle:integer; var	lpbSelfPower:integer):Integer; stdcall; external CP2102DLL;
function CP210x_GetMaxPower(cyHandle:integer; var	lpbPower:integer):Integer; stdcall; external CP2102DLL;
function CP210x_GetDeviceVersion(cyHandle:integer; var	lpwVersion:integer):Integer; stdcall; external CP2102DLL;


//function CP210xRT_GetPartNumber(cyHandle:integer; var lpbPartNum:Word):Integer; stdcall; external 'CP210xRuntime.dll';
//function CP210x_GetDeviceProductString(cyHandle:integer; var	lpProduct:integer; var	lpbLength:WORD;	bConvertToASCII:BOOL = TRUE)
//function CP210x_GetDeviceSerialNumber(cyHandle:integer; var	lpSerialNumber:byte; var	lpbLength:WORD;	bConvertToASCII:BOOL = TRUE)
//function CP210xRT_GetDeviceProductString(cyHandle:integer;var lpProduct: Byte; var lpbLength: Byte; bConvertToASCII:BOOL = TRUE):Integer; stdcall; external CP2102RUNTIME;

//function CP210xRT_GetDeviceSerialNumber(cyHandle:integer;
//							   var lpSerialNumber:byte;
//							   var lpbLength:Word;
//							   bConvertToASCII:BOOL = TRUE
//							   ):Integer; stdcall; external 'CP210xRuntime.dll';



implementation

type PCP2102 = ^TCP2102;
//function CP210xRT_GetDeviceProductString; external CP2102Runtime name 'CP210xRT_GetDeviceProductString';

procedure SilabsComPorts(out Port: TStringList);
var
  Reg: TRegistry;
  List: TStringList;
  i: Integer;
  w: String;
begin
  Reg := TRegistry.Create;
  List:= TStringList.Create;
  try
    Reg.RootKey:= HKEY_LOCAL_MACHINE;
    Reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM', false);
    Reg.GetValueNames(List);
    for i := 0 to List.Count - 1 do begin
      w:= copy(List.strings[i],9,7);
      if w = 'slabser' then begin             //device vom Silicon Labs
//        cmbComPort.Items.Add(Reg.ReadString(List.Strings[i]));
        Port.Add(Reg.ReadString(List.Strings[i]));
      end;
    end;
    Reg.CloseKey;
  finally
    Reg.Free;
    List.Free;
  end;
end;

constructor TCP210X.Create;
begin
  inherited;
  FList := TList.Create;
  hUSBDevice := INVALID_HANDLE_VALUE;
  FillDeviceList;
end;

destructor TCP210X.Destroy;
begin
  Clear;
  FList.Free;
  inherited;
end;

function TCP210X.Add(const SerNr: string; PortNr: Integer): Integer;
var
  AddPort: TCP2102;
begin
  AddPort.SerNr := SerNr;
  AddPort.PortNr := PortNr;
  Result := Add (AddPort)
end;

function TCP210X.Add(ACP2102: TCP2102): Integer;
var
  NewPt: PCP2102;
begin
  GetMem (NewPt,SizeOf(TCP2102));
  NewPt^ := ACP2102;
  Result := FList.Add(NewPt)
end;

procedure TCP210X.Clear;
var
  I: Integer;
begin
  for I := Count - 1 downto 0 do
    FreeMem (FList[I]);
  FList.Clear;
end;

function TCP210X.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TCP210X.GetItems(Index: Integer): TCP2102;
begin
  Result := PCP2102(FList[Index])^
end;

procedure TCP210X.GetDeviceData;
var
  Vid, Pid : WORD;       //Variables for the Vid, Pid and Serial Number (SN is a String of chars of length SerialLength)
  SerialString : array[0..CP210x_MAX_SERIAL_STRLEN] of Byte;
  SerialLength : Byte;
  i : integer;
  Port : integer;
  SerNr : string;
begin
  SerNr := '';
  Clear;
  for i := 0 to devNum - 1 do begin
    Status := CP210x_Open(i, hUSBDevice);
    If Status = CP210x_SUCCESS Then begin
      Status := CP210x_GetDeviceVid(hUSBDevice, Vid);
      If Status = CP210x_SUCCESS Then begin
        Status := CP210x_GetDevicePid(hUSBDevice, Pid);
        If Status = CP210x_SUCCESS Then begin
          Status := CP210x_GetDeviceSerialNumber(hUSBDevice, SerialString[0], &SerialLength, True);
          If Status = CP210x_SUCCESS Then begin
            SerNr := ConvertToString(SerialString[0], SerialLength);
          end;
        end;
      end;
    end;
    if(Pid = $34A5) then begin     //Нужный нам Pid = 34A5 ?
      Port := GetPortNumXP2000(Vid, Pid, SerNr);
      if Port <> -1 then
        Add(SerNr, Port)
      else
        Beep();
    end;
    CP210x_Close (hUSBDevice);
  end;
end;

procedure TCP210X.FillDeviceList;
begin
  EnumDevices;
  if devNum > 0 then
    GetDeviceData;
end;

procedure TCP210X.EnumDevices;
begin
  Status := CP210x_GetNumDevices(devNum);
end;

function TCP210X.ConvertToString(const ConvertArray: array of Byte; ConvertLength: integer):string;
var
  ConvertString : string;
  i : integer;
  PByte : ^Byte;
begin
  ConvertString := '';
  PByte := @ConvertArray;
  For i := 0 to ConvertLength - 1 do begin
    if Chr(PByte^)=#0 then  break;
    if PByte^ = 32 then
      ConvertString := ConvertString + Chr(95)
    else
      ConvertString := ConvertString + Chr(PByte^);
    inc(PByte);
  end;
    result := ConvertString;
end;

function TCP210X.GetPortNumXP2000(Vid,Pid: WORD; serNum: String): Integer;
var
  HKLMKey, EnumKey, PortKey, VidPidKey :HKEY;
  VidPidString, prmStr : PChar;
  valtype : DWORD;
  p : pointer;
  portNum : integer;
  length_of : Cardinal;
  i: integer;
begin
  for i := 0 to 1 do begin
    portNum := -1;
    GetMem(p, 100);
    if(ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\', 0, KEY_READ, HKLMKey)) then begin  // KEY_ALL_ACCESS
      if(ERROR_SUCCESS = RegOpenKey(HKLMKey, 'Enum\\USB\\', EnumKey)) then begin
        VidPidString := pChar('Vid_' + LowerCase(IntToHex(vid, 2)) + '&Pid_' + LowerCase(IntToHex(pid, 2)) + '&Mi_00\\' + serNum + '_00\\');
        if(ERROR_SUCCESS = RegOpenKey(EnumKey, VidPidString, VidPidKey)) then begin
          if(ERROR_SUCCESS = RegOpenKey(VidPidKey, pChar('Device Parameters\\'), PortKey)) then begin
            if(ERROR_SUCCESS = RegQueryValueEx(PortKey, pChar('PortName'), nil, @valtype, p, @length_of)) then begin
              prmStr := p;
              prmStr[0] := '0';
              prmStr[1] := '0';
              prmStr[2] := '0';
              portNum := StrToInt(string(prmStr));
            end;
            RegCloseKey(PortKey);
          end;
          RegCloseKey(VidPidKey);
        end else begin
          VidPidString := pChar('Vid_' + LowerCase(IntToHex(vid, 2)) + '&Pid_' + LowerCase(IntToHex(pid, 2)) + '\\' + serNum);  //  '\\' + serNum
          if(ERROR_SUCCESS = RegOpenKey(EnumKey, VidPidString, VidPidKey)) then begin
            if(ERROR_SUCCESS = RegOpenKey(VidPidKey, pChar('Device Parameters'), PortKey)) then begin
              if(ERROR_SUCCESS = RegQueryValueEx(PortKey, pChar('PortName'), nil, @valtype, p, @length_of)) then begin
                prmStr := p;
                prmStr[0] := '0';
                prmStr[1] := '0';
                prmStr[2] := '0';
                portNum := StrToInt(string(prmStr));
              end;
              RegCloseKey(PortKey);
            end;
            RegCloseKey (VidPidKey);
          end;
        end;
        RegCloseKey(EnumKey);
      end;
      RegCloseKey(HKLMKey);
    end;
    RegCloseKey(HKEY_LOCAL_MACHINE);
    FreeMem(p);
  end;
  Result := portNum;
end;

end.


memento mori