(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 

Конференция "Embarcadero"

Обсуждение вопросов, связанных с компанией Embarcadero, ее продуктами RAD Studio, C++Builder, Delphi и другими.

 
 
Добавить сообщение »

Тема: VID и PID из виртуального COM-порта

Автор:  Юра Дата: 15.10.2013 15:47
Спасибо за ответ.
Только это стандартное решение: перелапатить весь Enum реестра и выбрать COM-порты для нужного VID/PID. Потом прочитать DeviceMap. Сравнивая списки, получаем открытые COM-порты для нужного VID/PID.
Проблема в том, что некоторые производители помещают свои VCOM-порты не в ...Enum\USB, а в другие ключи реестра, например, для сканеров Symbol информация лежит в Enum\WIP.
Поэтому искался путь от обратного: получили список открытых VCOM-портов, потом посредством некого IOCTL_xxxx-вызова получить для него VID/PID, и выбрали нужный VCOM-порт.
К сожалению найти не смог, поэтому пока реализовано, по типу, как Вы предлагаете. Возможно это единственный и правильный путь.
Юра.
Ответить на сообщение »
 
Автор:  graf Дата: 15.10.2013 13:16
unit Unit1;

interface

uses
windows,
sysutils,
classes,
setupAPI,Forms,
Registry, Controls, StdCtrls;

type
TForm2 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

// Name_company='FTDIBUS'; VID:='6001'; PID:='0403';('FTDIBUS\VID_0403+PID_6001+A501XYRYA\0000')
// Com_enabled - только доступные для работы порты (которым можно подключиться сейчас и их не кто уже не использует);
function SetupEnumAvailableComPorts(Name_company,VID, PID:string; Com_enabled:boolean):TstringList;
// Enumerates all serial communications ports that are available and ready to
// be used.

// For the setupapi unit see
// [открыть ссылку]

function LowerCase(s: string): string;// малым регистром
const
arr_lat:string='abcdefghijklmnopqrstuvwxyz'+
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
arr_rus:string='абвгдеёжзийклмнопрстуфхцчшщъыьэюя'+
'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
var
res: string;
c,i: integer;
p:boolean;
begin
try
res:=s;
for i := 1 to length(res) do
begin
p:=false;
for c:=1 to 26 do
if res[i] = arr_lat[26+c] then
begin
p:=true;
res[i]:=arr_lat[c]
end;
if not p then
for c:=1 to 33 do
if res[i] = arr_rus[33+c] then
begin
res[i]:=arr_rus[c]
end;
end;
result:=res
except
result := s;
end;
end;
var
RequiredSize: Cardinal;
GUIDSize: DWORD;
Guid: TGUID;
DevInfoHandle: HDEVINFO;
DeviceInfoData: TSPDevInfoData;
MemberIndex: Cardinal;
PropertyRegDataType: DWord;
RegProperty: Cardinal;
RegTyp: Cardinal;
Key: Hkey;
Info: TRegKeyInfo;
S1,S2: string;
hc: THandle;
Name: string;
Err,i: Integer;
Name_company_,VID_, PID_:string;
Com_enabled_:boolean;
begin
try
Result:=Nil;
//If we cannot access the setupapi.dll then we return a nil pointer.
if not LoadsetupAPI then exit;
try
// get 'Ports' class guid from name
GUIDSize := 1; // missing from original code - need to tell function that the Guid structure contains a single GUID
if SetupDiClassGuidsFromName('Ports',@Guid,GUIDSize,RequiredSize) then
begin
//get object handle of 'Ports' class to interate all devices
DevInfoHandle:=SetupDiGetClassDevs(@Guid,Nil,0,DIGCF_PRESENT);
if Cardinal(DevInfoHandle)<>Invalid_Handle_Value then
begin
try
MemberIndex:=0;
result:=TStringList.Create;
//iterate device list
repeat
FillChar(DeviceInfoData,SizeOf(DeviceInfoData),0);
DeviceInfoData.cbSize:=SizeOf(DeviceInfoData);
//get device info that corresponds to the next memberindex
if Not SetupDiEnumDeviceInfo(DevInfoHandle,MemberIndex,DeviceInfoData) then
break;
//query friendly device name LIKE 'BlueTooth Communication Port (COM8)' etc
RegProperty:=SPDRP_FriendlyName;{SPDRP_Driver, SPDRP_SERVICE, SPDRP_ENUMERATOR_NAME,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,SPDRP_FRIENDLYNAME,}
SetupDiGetDeviceRegistryProperty(DevInfoHandle,
DeviceInfoData,
RegProperty,
PropertyRegDataType,
NIL,0,RequiredSize);
SetLength(S1,RequiredSize);
if SetupDiGetDeviceRegistryProperty(DevInfoHandle,DeviceInfoData,
RegProperty,
PropertyRegDataType,
@S1[1],RequiredSize,RequiredSize) then
begin
KEY:=SetupDiOpenDevRegKey(DevInfoHandle,DeviceInfoData,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ);
if key<>INValid_Handle_Value then
begin
FillChar(Info, SizeOf(Info), 0);
//query the real port name from the registry value 'PortName'
if RegQueryInfoKey(Key, nil, nil, nil, @Info.NumSubKeys,@Info.MaxSubKeyLen, nil, @Info.NumValues, @Info.MaxValueLen,
@Info.MaxDataLen, nil, @Info.FileTime) = ERROR_SUCCESS then
begin
RequiredSize:= Info.MaxValueLen + 1;
SetLength(S2,RequiredSize);
if RegQueryValueEx(KEY,'PortName',Nil,@Regtyp,@s2[1],@RequiredSize)=Error_Success then
begin
If (Pos('COM',S2)=1) then
begin
Name:='';
//получаем размер строчки HardwareID
SetupDiGetDeviceRegistryProperty(DevInfoHandle, DeviceInfoData,
SPDRP_HARDWAREID, PropertyRegDataType, nil, 0, RequiredSize);
Err := GetLastError;
if Err = ERROR_INSUFFICIENT_BUFFER then
// только эта ошибка должна возникнуть - все другое - что-то не так
begin
if Length(Name) < RequiredSize div SizeOf(Char) then
// если буфер маленький, то
SetLength(Name, RequiredSize div SizeOf(Char));
// устанавливаем размер буфера
SetupDiGetDeviceRegistryProperty(DevInfoHandle, DeviceInfoData,
SPDRP_HARDWAREID, PropertyRegDataType, @Name[1], RequiredSize, RequiredSize);
Err:=GetLastError;
if Err=0 then // получаем HardwareID
begin
Name_company_:='';
VID_:='';
PID_:='';
if Name<>'' then
begin
i:=pos('\',Name);
if i>0 then
Name_company_:=copy(Name,1,i-1);
i:=pos('VID_',Name);
if i>0 then
if length(name)>=i+7 then
VID_:=copy(Name,i+4,4);
i:=pos('PID_',Name);
if i>0 then
if length(name)>=i+7 then
PID_:=copy(Name,i+4,4);
end;
end;
end
else
Continue;
//Test if the device can be used
Com_enabled_:=false;
try
hc:=CreateFile(pchar('\\.\'+S2+#0),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hc<> INVALID_HANDLE_VALUE then
begin
Com_enabled_:=true;
CloseHandle(hc);
end;
except
Com_enabled_:=false;
end;
if ((LowerCase(Name_company)=LowerCase(Name_company_)) or (Name_company='')) and
((LowerCase(VID)=LowerCase(VID_)) or (VID='')) and
((LowerCase(PID)=LowerCase(PID_)) or (PID='')) and
((Com_enabled_) or (not Com_enabled)) then
Result.Add(Strpas(PChar(S2))+': = '+StrPas(PChar(S1)));
end;
end;
end;
RegCloseKey(key);
end;
end;
Inc(MemberIndex);
until False;
//If we did not found any free com. port we return a NIL pointer.
if Result.Count=0 then
begin
Result.Free;
Result:=NIL;
end
finally
SetupDiDestroyDeviceInfoList(DevInfoHandle);
end;
end;
end;
finally
UnloadSetupApi;
end;
except
end;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
index : integer;
Name_company,VID,PID:string;
Com_enabled:boolean;
ComPortStringList : TStringList;
begin
ListBox1.Clear;
Name_company:=Edit1.Text;
VID:=Edit2.Text;
PID:=Edit3.Text;
Com_enabled:=CheckBox1.Checked;

ComPortStringList := SetupEnumAvailableComPorts(Name_company,VID,PID,Com_enabled);
if (ComPortStringList <> nil) and (ComPortStringList.Count > 0) then
for Index := 0 to ComPortStringList.Count - 1 do
ListBox1.Items.Add(ComPortStringList[Index]);
end;

end.
Ответить на сообщение »
 
Автор:  Юрий Дата: 16.04.2012 15:57
Добрый день.

USB-устройство устанавливается как виртуальный COM-порт.
Открываю его HDL=CreateFile("\\\\.\\COMn",...),
Вызываю DeviceIoControl(HDL,IOCTL_GET_DEVICE_DESCRIPTOR,...); и
DeviceIoControl(HDL,IOCTL_GET_USB_DESCRIPTOR,...);
в обоих случаях возвращает TRUE, но структуры с данными не заполняет, и счетчик байт=0.
Вызовов IOCTL_SERIAL_... и IOCTL_SERENUM_..., возвращающих VID и PID не нашел.
Работаю в Borland C++.
Может кто-нибудь подсказать, можно получить VID и PID для виртуального COM-порта, и если да, то как.

Юрий.
Ответить на сообщение »
 

Добавить сообщение »

 Распечатать »
 Правила публикации »
   
 Рекомендовать »  
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Купить WinRAR : 5 : Академическая лицензия 1 лицензия
Quest Software. Toad for Oracle Development Suite
ESET NOD32 Smart Security - лицензия на 1 год на 3ПК или продление на 20 месяцев, Ключ
VMware Workstation 14 Player for Linux and Windows, ESD
DeviceLock Endpoint DLP Suite - от 1 ПК до 24 ПК
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Мир OLAP и Business Intelligence: новости, статьи, обзоры
3D и виртуальная реальность. Все о Macromedia Flash MX.
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Написание оптимального кода под Delphi (1)
Delphi выполняет все почти именно так, как должен. Это как раз переизбыток "оптимизации" в...
 
Скачиваем файлы из интернета при помощи Delphi (1)
Почему то не скачивает, хотя прогресс показывает...
 
получение информации об устройстве. (3)
Добрый день. Программа должна обслуживать любые устройства от любого производителя типа:...
 
Легализация программы написанной на нелицензионной платформе Delphi7 (4)
Была написана программа используя нелегальный продукт Delphi 7. Потом эту программу продали...
 
Direct Show и Delphi (1)
Здравствуйте. Как получить в DirectShow9 (DirectSound) функцию похожую на...
 
 
 



    
rambler's top100 Rambler's Top100