delphi usb serial port

chrislock
chrislock used Ask the Experts™
on

Delphi 7 XP prof.

Hi -

I'm using the free Tcomport component for Delphi. Although I do not usually have problems, there is one bugbear that I cant seem to solve.
If you have a couple of USB serial converters connected to the PC, sometimes there is a problem with port initialisation.
Is there a simple way to find out which Comport belongs to which external USB-serial device?
How does the allocation of these devices occur?
What exactly is the meaning of Purgecomm function failed?

Thanks,
Chris





Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
The function below returns a list of available COM-ports
(not open by this or an other process), with friendly names. The list is formatted as follows:

COM1: = Communications Port (COM1)
COM5: = NI Serial Port (Com5)
COM6: = NI Serial Port (Com6)
COM7: = USB Serial Port (COM7)
COM8: = Bluetooth Communications Port (COM8)
COM9: = Bluetooth Communications Port (COM9)



The function uses the setupapi (setup api) unit that is available from
ftp://ftp.delphi-jedi.org/api/SetupAPI.zip 

I have verified the code and it worked  for W2000, WXP, W98. It does not work for W95, and NT 4.0. I did not check WME but I guess it will work with WME too.




function SetupEnumAvailableComPorts:TstringList; 
// Enumerates all serial communications ports that are available and ready to 
// be used. 
 
// For the setupapi unit see 
// http://homepages.borland.com/jedi/cms/modules/apilib/visit.php?cid=4&lid=3 
 
var 
  RequiredSize:             Cardinal; 
  Guid:                     TGUID; 
  DevInfoHandle:            HDEVINFO; 
  DeviceInfoData:           TSPDevInfoData; 
  MemberIndex:              Cardinal; 
  PropertyRegDataType:      DWord; 
  RegProperty:              Cardinal; 
  RegTyp:                   Cardinal; 
  Key:                      Hkey; 
  Info:                     TRegKeyInfo; 
  S1,S2:                    string; 
  hc:                       THandle; 
begin 
  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 
    if SetupDiClassGuidsFromName('Ports',@Guid,RequiredSize,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 
//Test if the device can be used 
                       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 
                         Result.Add(Strpas(PChar(S2))+': = '+StrPas(PChar(S1))); 
                         CloseHandle(hc); 
                       end; 
                     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; 
end; 

Open in new window

Top Expert 2010

Commented:
com ports are dead and buried.In prehistoric times used by DOS and some antiquated software (mainly modems).
What you got hooked can be seen with System Information.
Allocation is an automatic process done by Windows.
 

Author

Commented:
Actually, standard serial comports are still being used by vast quantities of newly manufactured items such as weighing machines, bar code scanners, modems, satellite boxes, GPS, test equipment, medical systems, scientific instruments etc. etc, some of which use RS485/Rs232.
Other serial port systems such as USB are very complicated in their operation and extremely fragile in an industrial environment.
I can understand a serial port down to the register level inside the chip. I would have to spend a lot of time to get that acquainted with USB!!!

Chris
Acronis in Gartner 2019 MQ for datacenter backup

It is an honor to be featured in Gartner 2019 Magic Quadrant for Datacenter Backup and Recovery Solutions. Gartner’s MQ sets a high standard and earning a place on their grid is a great affirmation that Acronis is delivering on our mission to protect all data, apps, and systems.

MerijnBSr. Software Engineer

Commented:
@senad: you could not be more wrong...

@chris: figuring out what physical connector is what comport is hard. Why do you want to achieve this?

Are you using the open source TComport?

Author

Commented:
MerijnB
Because the system has a serial printer and a serial weigher running from a laptop (which unfortunately does not have any internal standard RS232 ports) The problem is that the user may connect the USB converters in any configuration and be presented with a choice of maybe 4 ports (e.g. internal modem
etc). I will probably look for a serial stream of data (another problem!!!) to identify the weigher.

Yes I'm using Tcomport.

Chris
MerijnBSr. Software Engineer
Commented:
I've tackled this problem by detection a couple of times before. USB to serial convertors almost always get a 'high' comport number allocated (> 4). So enumerate the comports (TComport can do this) and start with the highest port going down.
You will need (like you mentioned) do detect whether either device (scale or printer) is attached to a comport, my gut feeling is that the scale is easy, but the printer might pose a problem. Do you have full documentation on the protocol used for both devices?

Author

Commented:
Thanks all for the advice - I am going to try thiagoblimeira's suggestion. I also have another problem with the USB ports (see          usb serial port buffer problem    ), which is rather more serious!

Oh for the days when you could understand the workings of a computer! Now you have to have a Phd in USBology to understand just one small facet!


Chris
MerijnBSr. Software Engineer

Commented:
Chris, keep in mind that a 'USB to serial port' port does not have the word USB in it always!

Author

Commented:
Thanks All

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial