Давно писал, не помню уже, что и зачем, но до сих пор работает безупречно под всеми виндами.
memento mori
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.