none
Determining Bluetooth COM port assignments in Windows 7

    Question

  • My company has developed a Bluetooth product that uses the serial port profile via a virtual COM port. In Windows XP (as well as Vista), the 'Bluetooth Devices' dialog box shows, after pairing, the COM port assignments for both 'incoming' and 'outgoing' COM ports. Our product uses the 'incoming' COM port, since it autonomously initiates a commuincation. This works fine in XP and Vista.

    However, in testing with Windows 7, we have discovered that the Bluetooth pairing utility is now different from the one used in XP... we can get it to work, but the process reports back only one virtual COM port number, which we have discovered empirically is actually the outgoing port, not the incoming port. Normally, Windows XP assigns the outgoing port first, and then assigns the next ordinal port number to the incoming port... although we know, from experience, that this isn't always the case. For example, when pairing with Windows 7, we see that COM port 7 is assigned. In testing, we find that COM port 8 is actually the incoming port... but we can't depend on that... sometimes, the two port numbers are not sequential

    What I am looking for is a way to determine, programmatically, what incoming port was assigned as a result of the pairing process. I am assuming that somewhere, there is an API which would permit us to determine what ports are assigned to what devices, by name. For example, our device uses a name like 'DF2D-A34F'... how can I determine, from knowing the name, what incoming and outgoing ports are assigned to it? Is there an API which will list the ports? Can it be determined from a registry key? (I haven't found one, by searching, yet...)

    Any help on this would be appreciated.

    Wednesday, December 15, 2010 2:15 PM

Answers

  • Looking to do the same thing here. What I did find was this registry entry - the "PnpInstance" entry indicates the port (in this case COM4).

    However, as you can see, the registry key contains a guid, which is probably specific to the device that I paired (a Motorola bluetooth scanner), so this isn't much use as the guid will change depending on the device that was paired.

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\BTHPORT\Parameters\LocalServices\{00001101-0000-1000-8000-00805f9b34fb}\0]
    "Enabled"=dword:00000001
    "ServiceName"="CS3070:10148522500354"
    "DeviceString"=""
    "AssocBdAddr"=hex:b7,6c,03,8b,0e,5c,00,00
    "PnpInstance"=dword:00000004

    So I think there must be some sort of Windows API call that would give us this information.

    Wednesday, March 02, 2011 9:30 PM
  • So, on the first point there are apparently various ways to use Bluetooth sockets from Delphi, from a component from http://www.btframework.com/ to the direct method at http://rix0r.nl/2005/07/bluetooth-between-phone-and-pc/ (Not a delphi user myself...)

    Secondly presumably the programming model for sockets is quite simple -- as simple if not simpler that for the COM port IO programming...

    To get the remote device's name is straightfoward via the Bluetooth APIs too.  Presumably that component provides a simple function to get it.  (Or one can do a native call to Win32 function BluetoothGetDeviceInfo for instance).

    Then, you do know that various manufacturers provide Bluetooth software stacks for Win32: MSFT, Widcomm/Broadcom, BlueSoleil, Toshiba...  Do you currently only support the MSFT stack -- as presumably the other stacks use different registry information?  Presumably that component supports all(?) of those stacks.  My .NET library for Bluetooth etc, 32feet.NET (http://32feet.codeplex.com) supports all but Toshiba.  (Presumably there's no way to use it from Delphi).

    I have no idea if any of that's possible throught the virtual COM port method by poking through the registry...  :-)


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Wednesday, March 09, 2011 8:11 PM

All replies

  • We also face the same problem. If you find any help on this do post the answer. I will do the same :)

    Wednesday, December 22, 2010 2:51 PM
  • Looking to do the same thing here. What I did find was this registry entry - the "PnpInstance" entry indicates the port (in this case COM4).

    However, as you can see, the registry key contains a guid, which is probably specific to the device that I paired (a Motorola bluetooth scanner), so this isn't much use as the guid will change depending on the device that was paired.

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\BTHPORT\Parameters\LocalServices\{00001101-0000-1000-8000-00805f9b34fb}\0]
    "Enabled"=dword:00000001
    "ServiceName"="CS3070:10148522500354"
    "DeviceString"=""
    "AssocBdAddr"=hex:b7,6c,03,8b,0e,5c,00,00
    "PnpInstance"=dword:00000004

    So I think there must be some sort of Windows API call that would give us this information.

    Wednesday, March 02, 2011 9:30 PM
  • First, that GUID is the Bluetooth Service Class Id for "Serial Port" so its the one your looking for.

    I know of no API for this. :-(  So one has to use that information, perhaps using WMI, see the code in my documentation http://32feet.codeplex.com/wikipage?title=Getting Virtual COM Port Names

    Ohh and I'm not a fan of virtual COM ports in general so it would be more robust to just create a Bluetooth winsock connection to the remote service. See http://msdn.microsoft.com/en-us/library/aa362901(VS.85).aspx

      SOCKADDR_BTH sa ... copy in UUID and remote address
      connect(sock, sa, ...);
      // Bingo a sockets connection, easy peasy.

     


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Thursday, March 03, 2011 12:19 PM
  • Thanks very much for the info. I checked out your example at http://32feet.codeplex.com/wikipage?title=Getting Virtual COM Port Names, but do you know if there is a way to inspect the windows registry directly to get the port name? The PnpInstance that I mentioned above is not the com port number as I first thought. I did find this information in the registry that gives me the actual port name for my bluetooth scanner, but how do I get from the registry key above to this key?

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\{00001101-0000-1000-8000-00805f9b34fb}_LOCALMFG&000f\8&1aae7cbc&0&002368674E4F_C00000000\Device Parameters]
    "PortName"="COM8"
    "PollingPeriod"=dword:00000000
    "Bluetooth_UniqueID"="{00001101-0000-1000-8000-00805f9b34fb}#002368674E4F_C00000000"
    "ForceFifoEnable"=dword:00000001
    "RxFIFO"=dword:0000000e
    "TxFIFO"=dword:00000010

    Thursday, March 03, 2011 3:57 PM
  • you can't the path under bthenum is the device's pnp path instance id, no other point in the registry will lead you to it.
    d -- This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, March 03, 2011 10:31 PM
    Owner
  • My code shows the port name and the remote device address...  For instance

    C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"
    DeviceID : COM66
    PNPDeviceID : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519 _C00000003

    So port COM66 , remote address 00803A686519 , and serial port UUID.

    Think that's for a outgoing port.  Can't remember what details are available for a outgoing port.


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Friday, March 04, 2011 4:20 PM
  • First, that GUID is the Bluetooth Service Class Id for "Serial Port" so its the one your looking for.

    I know of no API for this. :-(  So one has to use that information, perhaps using WMI, see the code in my documentation http://32feet.codeplex.com/wikipage?title=Getting Virtual COM Port Names

    Ohh and I'm not a fan of virtual COM ports in general so it would be more robust to just create a Bluetooth winsock connection to the remote service. See http://msdn.microsoft.com/en-us/library/aa362901(VS.85).aspx

      SOCKADDR_BTH sa ... copy in UUID and remote address
      connect(sock, sa, ...);
      // Bingo a sockets connection, easy peasy.

     

    Ufortunately, this does me no good. For one thing, I code using Delphi, so I need a solution which is accessible that way... and I use virtual COM ports because I don't know how to use sockets.

    Another problem: this doesn't show me the name of the device and it's corresponding port. For example, when my device is paired, the Bluetooth control panel shows me the device name (for example, 'DF3D-3F09') and the corresponding incoming port (COM  9). Searching the registry implies that this information is not actually in the Registry, at all... I can search on the device name, and it appears in a few places, but not with the corresponding incoming port (maybe it's there, just not in a recognizable form).

    Finally, the really BIG problem is that Windows 7 uses a different Bluetooth control panel that doesn't show both the incoming and outgoing port designations... it just shows a single port number, and empirically, I know it happens to be the outgoing port... I need the number of the incoming port. Usually, the incoming port is one number up... so, for example, if Windows 7 shows the port number as COM 11, the incoming port will usually be COM 12... but not always.

     

     

     


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered

    Sunday, March 06, 2011 5:29 PM
  • So, on the first point there are apparently various ways to use Bluetooth sockets from Delphi, from a component from http://www.btframework.com/ to the direct method at http://rix0r.nl/2005/07/bluetooth-between-phone-and-pc/ (Not a delphi user myself...)

    Secondly presumably the programming model for sockets is quite simple -- as simple if not simpler that for the COM port IO programming...

    To get the remote device's name is straightfoward via the Bluetooth APIs too.  Presumably that component provides a simple function to get it.  (Or one can do a native call to Win32 function BluetoothGetDeviceInfo for instance).

    Then, you do know that various manufacturers provide Bluetooth software stacks for Win32: MSFT, Widcomm/Broadcom, BlueSoleil, Toshiba...  Do you currently only support the MSFT stack -- as presumably the other stacks use different registry information?  Presumably that component supports all(?) of those stacks.  My .NET library for Bluetooth etc, 32feet.NET (http://32feet.codeplex.com) supports all but Toshiba.  (Presumably there's no way to use it from Delphi).

    I have no idea if any of that's possible throught the virtual COM port method by poking through the registry...  :-)


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Wednesday, March 09, 2011 8:11 PM
  • Hey there,

    I discovered something from searching through the APIs that might be of use to you: http://msdn.microsoft.com/en-us/library/bb870603%28v=VS.85%29.aspx

    This API allows you to advertise a service coming from a device, which leads me to believe that it creates an Incoming Port (I did some experimenting and it seemed to work that way). Additionally, it allows you to specify which Port you want to connect to in the BLUETOOTH_LOCAL_SERVICE_INFO struct, which means no more searching through the registry. :)

    Best of luck,

    Prodygy

    Thursday, July 21, 2011 6:24 PM
  • Interesting discovery!  I'd stayed away from that function due to the documentation text: "is used only by profile driver developers", (WDK http://msdn.microsoft.com/en-us/library/ff536580(VS.85).aspx )

    But I guess it makes sense that it works for COM ports in the way as you've found.  Good work. :-)


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Sunday, July 24, 2011 12:12 PM
  • I was able to determine the active Bluetooth COM port using Borland Delphi. It may not be elegant, but here is the code:

    function   GetBlutoothComPort: String;
    var        S, S1: String;
               Item: Integer;
               Reg: TRegistry;
               KeyList1, KeyList2: TStringList;
    
    begin
      Reg := TRegistry.Create;
      if Reg = nil then begin
        fmDebug.AddDebugItem( 'Error creating Reg ' );
        exit; end;
      KeyList1 := TStringList.Create;
      if KeyList1 = nil then begin
        fmDebug.AddDebugItem( 'Error creating KeyList1 ' );
        exit; end;
      KeyList2 := TStringList.Create;
      if KeyList2 = nil then begin
        fmDebug.AddDebugItem( 'Error creating KeyList2 ' );
        exit; end;
      try
        Reg.RootKey := HKEY_LOCAL_MACHINE;
        S := '\SYSTEM\CurrentControlSet\Enum\BTHENUM\';
        fmDebug.AddDebugItem( 'Key: ' + S );
        try
          Reg.OpenKeyReadOnly(S);
          Reg.GetKeyNames(KeyList1);
          For Item := 0 to KeyList1.Count-1 do begin
            S1 := KeyList1.Strings[Item];
            Reg.OpenKeyReadOnly(S + S1);
            Reg.GetKeyNames(KeyList2);
            S1 := S + KeyList1.Strings[Item] + '\' + KeyList2.Strings[0] + '\Device Parameters';
            Reg.OpenKeyReadOnly(S1);
            If Reg.ValueExists('RxFIFO') then begin
               S1 := Reg.ReadString('PortName');
               result := S1;
               break; end;
            end;
          fmDebug.AddDebugItem( 'Bluetooth Port detected: ' + S1 );
        except
            fmDebug.AddDebugItem( 'Error Bluetooth' );
        end;
      finally
        Reg.Free;
        KeyList1.Free;
        KeyList2.Free;
      end;
    end;
    

    Sunday, December 29, 2013 11:52 AM
  • you don't need to parse the ENUM key (the ENUM key is in fact private and should not be parsed). Rather you can use setupapi to enumerate the com port device interface and restrict the enumeration to the BTHENUM enumerator.  for each instance, setupapi can give you the HKEY that represents Device Parameters (without knowing the full parent path) key and you can query these values from there

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Sunday, December 29, 2013 4:29 PM
    Owner
  • I'm not sure exactly how to use the setupapi, although I found detailed information at:

    http://msdn.microsoft.com/en-us/library/windows/hardware/ff553567(v=vs.85).aspx

    Is there an example anywhere that shows what functions to use in order to get the Bluetooth COM port that can be opened and used to communicate with the device? I found that there are two ports, COM13 and COM14, associated with the USB Bluetooth adapter, but only COM14 can be used for communication. And the only way I know to identify it is by one of the additional parameters such as "RxFIFO" which I used. Otherwise, I would probably need to attempt to open each one and see where it was successful.

    Thanks.

    Sunday, December 29, 2013 10:15 PM
  • Look at the enum.exe project in the toaster sample to see how to use setupapi to enumerate a device interface. As for the usable com port heuristic, I don't know

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, December 30, 2013 12:08 AM
    Owner
  • http://code.msdn.microsoft.com/windowsdesktop/Toaster-7d256224

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, December 30, 2013 12:10 AM
    Owner
  • I appreciate your consideration and reply, but I was unable to find the real information I need for my purposes in the material for the "Toaster" project. It seems that it is directed toward software/hardware developers who want to introduce a new product and create a complete low-level driver to access its properties and methods. To do so, I would need to install and learn how to use the SDK and other applications, and go through the hoops of extensive testing, certification, and signing.

    My product is a highly specialized, low-volume data acquisition system which originally used the parallel port and then was redesigned to use a serial port, which then required the use of a USB-Serial adapter because of the lack of native serial ports on new laptop PCs. Because of the variation among commercially available adapters, I made my own using a Microchip USB PIC with their USB and CDC stack, and their drivers which I modified with my own VID and PID and descriptors. But the actual drivers are the standard usbser or the generic mchpusb which I also used for a custom USB device interface without the CDC layer.

    I have been able to use my application with some modification from its original development using WinME and WinXP, through Vista and Win7. With Win8 I had to instruct my customers to disable the driver signature requirement using the advanced start-up options. I tried to go through the steps to manually sign my driver (which is really just an INF file which loads usbser), but it seemed to be an arduous task.

    Now I am just trying to add Bluetooth functionality, which should be relatively transparent to the user and the application by appearing as a COM port, which is also the case with USB virtual ports. As a convenience to the user, and for less chance for error and confusion, I chose to determine the COM ports by accessing the registry, and in the case of USB ports the name was set to something identifiable and unique so it could be chosen without manual selection, polling, or guessing. The software further tests the port and will only be satisfied if it responds appropriately. I was advised against simply iterating through all possible COM ports and finding the correct one by opening and testing, because the customer could have another serial device connected which could malfunction if certain commands were sent to it. Unlikely, but my previous customer was paranoid.

    Anyway, I think I will just continue along the way I have found works, unless there is a serious hazard in so doing, or if there is a simpler and more effective way to do what I need.

    Finally, perhaps OT for this discussion, but I wish there were a way to submit a driver INF file to an outside agency for certification and signing, at a reasonable cost for small time software/hardware developers such as myself. The total market for this instrument is only a couple hundred units or so, and I have only sold about 30 of the new units in the past 3 years. I would be happy to have the INF file "blessed" for a reasonable cost of perhaps a couple hundred dollars, or perhaps $50 each. It seems like this would be a valuable service, and if you know of any such service, please let me know.

    Thank you.

    BTW, I found this information about signing an unsigned driver. As you can see, it is quite complex:

    http://www.itninja.com/question/guide-to-signing-unsigned-drivers

    http://pixcl.com/Signing_Windows_8_Drivers.htm

    • Edited by PStechPaul1 Monday, December 30, 2013 2:38 PM
    Monday, December 30, 2013 2:23 PM
  • For a couple hundred bucks you can buy your own cert and self sign

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, December 30, 2013 5:55 PM
    Owner
  • Adapting your application to properly use the API to locate the COM port is a bit involved, though definitely not a rocket science. So you may consider to hire a helper to do all these chores (come up with a "heuristic" to find the port, write some code, buy the certificate and sign the driver/INF for you ).

    Regards,

    -- pa

    (Btw, my car broke.  I cannot fix it myself and am going to visit a garage. It will cost me. This is ok.)

    Monday, December 30, 2013 7:44 PM
  • Figured out how to do it for both Windows 7 & Windows 8.
    See code on https://github.com/CarlosOnline/BluetoothDiscovery 

    The idea is to extract out the device id from the registry key path, then match it appropriately to join the name with the port.

    For Windows 7: The device id maps to the AssocBdAddr value under the LocalServices node.

    In the example below:
    646E6CC1CAB3 is the device id value that I map to "AssocBdAddr"=hex:b3,ca,c1,6c,6e,64,00,00 under LocalServices.

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\{00001101-0000-1000-8000-00805f9b34fb}_LOCALMFG&000f\7&5461823&0&646E6CC1CAB3_C00000001\Device Parameters]
    "PortName"="COM4"

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\BTHPORT\Parameters\LocalServices\{00001101-0000-1000-8000-00805f9b34fb}\0]
    "ServiceName"="MyBluetoothDeviceOnWindows7"
    "AssocBdAddr"=hex:b3,ca,c1,6c,6e,64,00,00

    For Windows 8: The device id maps to to a sub key Dev_XXXX where XXXX is your device id.

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\{00001101-0000-1000-8000-00805f9b34fb}_LOCALMFG&000f\7&22abdcbb&0&646E6CC16891_C00000000\Device Parameters]
    "PortName"="COM14"

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\Dev_646E6CC16891\7&13e7003a&0&BluetoothDevice_646E6CC16891]
    "FriendlyName"="MyBluetoothDeviceOnWindows8"

    Thursday, June 12, 2014 5:31 AM