This project has moved. For the latest updates, please go here.

Widcomm -- Library classes support

BluetoothClient

BluetoothDeviceInfo[] DiscoverDevices(…) Y:
TimeSpan InquiryLength { get; set; } Y: [1]
void Connect(…); Y: [4] [5] [6]
void Begin-/EndConnect(…); Y: [4] [5] [6]
bool Connected { get; } Y:
NetworkStream GetStream(); Y:
Stream GetStream2(); historic
Socket Client { get; set; } NotSupportedEx - As Widcomm doesn't use Sockets.
int Available { get; } Y:
void Dispose(); Y:
bool Authenticate { get; set; } NotImplementedEx [2]
bool Encrypt { get; set; } NotImplementedEx [2]
void SetPin(string pin); [3]
void SetPin(BluetoothAddress device, string pin); NotImplementedEx
Guid LinkKey { get; } NotImplementedEx
LinkPolicy LinkPolicy { get; } NotImplementedEx
string GetRemoteMachineName(BluetoothAddress) Y: [8]
string RemoteMachineName { get; } Y: [8]
BluetoothEndPoint RemoteEndPoint { get; } Y: [9]

Notes/ToDo:
  1. ToDo InquiryLength - Implemented in v3.
  2. ToDo Authenticate/Encrypt - Do we just need to call SetSecurityLevel on the new CRfcommIf with the corresponding bit-flags value? Or do we need to aggregate all the Authenticate/Encrypt settings for all the active connections and when we call SetSecurityLevel (currently in WidcommRfcommStream.BeginConnect), set it to the union of the settings? And on every connection close, call it then if the current connection was the only one with Authenticate/Encrypt set?
  3. Note SetPin - Widcomm doesn't have an "Bonding-requested" handler /event feature (MSFT WinCE has both a socket option to set a PIN to use and a 'bonding-required' event, and MSFT Win32 has a similar event which we expose with class BluetoothRegisterForAuthentication). So it's not simple to handle the case where the server might want bonding. Our best attempt is to try connecting, and if it fails, try to Bond, and then retry the connection. This is what SetPin does now. Let me have feedback on whether this works or not for you...
  4. Note Widcomm Service Discovery returns ALL the records it has ever read from the peer (see BluetoothDeviceInfo. GetServiceRecords). This means that a service that has stopped and started many times will have many records. If it has started more that ten (currently) times we won't read the last record(s) and connect will fail it the service's current channel number is not the same as in the last record we read.
  5. Note Currently we don't support more than one concurrent connect attempt, this is due to Widcomm service-lookup not allowing more that one concurrent query. See BluetoothDeviceInfo.GetServiceRecords note number 10 for more information.
  6. ToDo Currently we don't fully support cancelling a connect by calling Close/Dispose whilst the connect is in progress. The actual connect part of the connect will be terminated early, but the service lookup part is not terminated. There is no API to cancel the service-lookup, but we could at least stop waiting for the result and thus have connect return early. (We'd have to ensure that when the lookup does complete that we handle it without error).
  7. ToDo Since service-lookup is slow when the remote device isn't present, and there can only be one outstanding, it is a major contention point which block other connect attempts. We should investigate whether we can use CBtIf::IsRemoteDeviceConnected/CBtIf::IsRemoteDevicePresent to detect if a remote device is not in range and thus we need not call do service-lookup, and thus allow other connects to proceed promptly.
  8. Note RemoteMachineName et al did not work in 2.4 beta. They were fixed subsequently, see bug 25362.
  9. Note RemoteEndPoint in 2.4 beta and earlier has only the DeviceAddress set; the Port/Channel is blank (the UUID is obviously blank). Since repository r62238 we provide the Port in the client case (we look it up manually in order to connect) (bug 25658). The Port is not known in the server case.

BluetoothDeviceInfo

bool Authenticated {get; } Y: [9]
ClassOfDevice ClassOfDevice { get; } Y:
bool Connected { get; } Y: [2]
BluetoothAddress DeviceAddress { get; } Y:
string DeviceName { get; … Y:
…. set; } Y: [3]
byte[][] GetServiceRecordsUnparsed(Guid service); NotSupportedEx. No way to get the raw bytes of the record from Widcomm.
ServiceRecord[] GetServiceRecords(Guid service); Y: [5] [6] [7].
Guid[] InstalledServices { get; } NotImplementedEx
DateTime LastSeen { get; } If device in range and discovered then returns the actual time, else DateTime.MinValue
DateTime LastUsed { get; } DateTime.MinValue
void Refresh(); No effect [8]
bool Remembered { get; } Y:
int Rssi { get; } Y: Needs a connection to the remote device to work.
void SetServiceState(Guid service, bool state, bool throwOnError); NotImplementedEx
void SetServiceState(Guid service, bool state); NotImplementedEx
void ShowDialog(); Displays a simple WinForms MessageBox, like CE version
void Update(); NotImplementedEx [3]


Notes/ToDo:
  1. Done ToDo getRssi — Need to call CBtIf::GetConnectionStats and return the tBTCONN_STATS.Rssi value, or the invalid value if the call fails.
  2. ToDo getConnected — Note on the MSFT stack this property returns constant false on WCE/WM platform, and on Win32 is updated only after Refresh has been called. On Widcomm after Refresh can call IsRemoteDeviceConnected. (Or could call GetConnectionStats like for [1] and check whether it succeeds. Apparently its tBTCONN_STATS.bConnected field is not set).
  3. ToDo Update()/set_DeviceName — A change of DeviceName is stored on the object, but not persisted to the system. Could do like on the WCE/WM platform and persist the updated DeviceName to the stack’s Registry keys.
  4. Done ToDo get_ LastSeen — Why don’t we set LastSeen=DateTime.UtcNow when we learn the devices from discovery (inquiry)? We could do that on all three platforms…
  5. ToDo/Note GetServiceRecords — Widcomm provides access only to particular Attributes and not to the whole raw record. The current support is reading the Service Class and Name, and RFCOMM Channel Number attributes only. We need to read the other well-known attributes, and also use the CSdpDiscoveryRec::FindAttribute function to get any non-standard ones. // Note, it will not be possible to read any general attributes that has a data element sequence/alternative value, the Widcomm CSdpDiscoveryRec::FindAttribute function won’t return them.
  6. Note Widcomm returns ALL the records it has ever read from the peer! We filter the records by the class id in the query.
  7. Note Widcomm does not support lookup to the local machine
  8. ToDo Refresh() — Should we re-read the DeviceName from the Registry?
  9. Note Originally we just used getAuthenticated=getRemembered; as of r47830 we now report the correct Authenticated value — using CBtIf::BondQuery.
  10. Note The Widcomm API supports only one concurrent Discovery (SDP query). Thus if a second discovery is initiated we fail it (XXXX). This affects both GetServiceRecords but also BluetoothClient.Connect/BeginConnect. // We could store the requests in a queue and carry them out one at a time, but most people will only ever do one at a time, and those whose want to do many connects/discovers will likely not want to wait for the delay this causes. // Actually the WCE (CE/WM) version on the Widcomm stack supports one query per individual remote device. We don’t make use of that feature as likely applications on CE/WM will be less commonly want to do multiple concurrent operations.

BluetoothRadio

ClassOfDevice ClassOfDevice { get; } Returns zero. No API to read it.
IntPtr Handle { get; } NotSupportedEx
HardwareStatus HardwareStatus { get; } Y After “3.0 Beta” (at/after repository revision 78547)
int LmpSubversion { get; } Y [4]
BluetoothAddress LocalAddress { get; } Y
Manufacturer Manufacturer { get; } Y
RadioMode Mode { get; … Y WCE/WM [7]; N Win32 — Returns constant ‘Discoverable’ [2]
....set; } Y WCE/WM [3]; N Win32 — NotSupportedEx
string Name { get; … Y
....set; } NotImplementedEx [5]
Manufacturer SoftwareManufacturer { get; } ‘Broadcom’ [1]


Notes:
  1. ToDo get_SoftwareManufacturer — Should it return Broadcom or Widcomm?
  2. ToDo get_RadioMode —CBtIf::IsDeviceConnectable/-Discoverable are only supported on WCE. Any substitutes on Win32?
  3. ToDo set_RadioMode — Supported on WCE/WM. Calls CBtIf::AllowToConnect/SetDiscoverable on. There is no Widcomm API on Win32.
  4. ToDo LOW There are many other HCI/LMP version numbers that could be exposed. Also on MSFT/CE, don’t know about MSFT/Win32.
  5. ToDo/Note set_Name on MSFT, is not supported on Win32 and just updates the Registry on WCE/WM. Widcomm on Win32 had SetLocalDeviceName but it “has been disabled” according to the docs. Could just update the Registry.
  6. ToDo As noted in the stack checking section, if we get errors when checking the radio status we continue to load. This was due to my middle-aged iPAQ frequently giving errors there. This should probably be changed, as on a PC with the stack installed but with its dongle unplugged, the stack loads when it shouldn’t. We might then need a configuration setting to allow the old behaviour to be reenabled however.
  7. Note Prior to version 2.6 if that Widcomm stack is disabled/turned-off then Mode still reports Connectable/Discoverable. From that version onward we detect that case (using Widcomm methods IsStackServerUp and IsDeviceReady). Note, setting Mode at the time to Connectable/etc appear not to switch the radio back on. :-(

temp

BluetoothListener

void Start(int backlog); Y: The 'backlog' param is ignored currently
void Start(); Y:
void Stop(); Y:
bool Pending(); Y:
BluetoothEndPoint LocalEndPoint { get; } Y: Port is set, address (and service) are not
Socket Server { get; } NotSupportedEx - As Widcomm doesn't use Sockets.
BluetoothClient AcceptBluetoothClient(); Y:
BluetoothClient Begin-/EndAcceptBluetoothClient(…); Y:
Socket AcceptSocket(); NotSupportedEx - As Widcomm doesn't use Sockets.
Socket Begin-/EndAcceptSocket(…); NotSupportedEx - As Widcomm doesn't use Sockets.
ServiceClass ServiceClass { get; NotImplementedEx
…. set; } Ignores value - no API on Widcomm.
string ServiceName { get; set; } Y:
ServiceRecord ServiceRecord { get; } Y:
bool Authenticate { get; set; } Y: [2]
bool Encrypt { get; set; } Y: [2]
void SetPin(BluetoothAddress device, string pin); NotImplementedEx
void Construct(Guid service); Y:
void Construct(BluetoothAddress localAddress, Guid service); Y: Ignores address
void Construct(BluetoothEndPoint localEP); Y: Ignores address
void Construct(Guid service, byte[] sdpRecord, int channelOffset); Y: [3]
void Construct(BluetoothAddress localAddress, Guid service, byte[] sdpRecord, int channelOffset); Y: Ignores address [3]
void Construct(BluetoothEndPoint localEP, byte[] sdpRecord, int channelOffset); Y: Ignores address [3]
void Construct(Guid service, ServiceRecord sdpRecord); Y:
void Construct(BluetoothAddress localAddress, Guid service, ServiceRecord sdpRecord); Y: Ignores address
void Construct(BluetoothEndPoint localEP, ServiceRecord sdpRecord); Y: Ignores address

Notes
  1. Seems that if the application isn't shutdown cleanly (such that Finalizers aren't run, then the Service Record stays in place. That misleads remote client applications that the service is still running. Also when the application next restarts the server can get the same port (SCN) assigned and thus adds the same record, but any incoming connections don't get passed through! Seen on WM at least.
  2. 'Authenticate' sets security level BTM_IN_AUTHENTICATE. 'Encrypt' sets (BTM_IN_ENCRYPT | BTM_IN_AUTHENTICATE). Seems to be correct, certainly causes prompt for passphrase.
  3. Parses the raw record into a ServiceRecord to pass to the Widcomm stack.
  4. Note/ToDo Property LocalEndPoint reports only the port in use, and not the address bound to - we could just fill in the address from the (sole) local radio. It's safe to assume that's the address used - well except in the case where Widcomm had wrapped the MSFT stack…

BluetoothSecurity

PairRequest(BluetoothAddress device, string pin) Y: [1]
RemoveDevice(BluetoothAddress device) Y: [1] [5]
SetPin(BluetoothAddress device, string pin) NotImplementedEx [4]
RevokePin(BluetoothAddress device) NotImplementedEx [4]
BluetoothAddress GetPinRequest() NotImplementedEx [2]
RefusePinRequest(BluetoothAddress device) NotImplementedEx [2]
SetLinkKey(BluetoothAddress a, Guid linkkey) NotImplementedEx [3]

Notes:
  1. Note Tested and working on WM. I can't get them work on my Win32 box however. Testers on Win32 are welcomed.
  2. Note There's no support in Widcomm for getting authentication requests.
  3. Note There's no support in Widcomm for setting the link key.
  4. ToDo It's possible that we may be able to implement the behaviour of SetPin for certain scenarios… For instance connecting with BluetoothClient, if the connection fails, try a Bond operation, and retry the connect if it succeeds. We can use the SetPin on BluetoothClient as an information source, but could also use this one. Note it's quite unlikely that we'll be able to support other scenarios, e.g. BluetoothListener incoming connection needing auth, or another application connection than requires authentication.
  5. Note After "3.0 Beta" (at/after repository revision r78484) we changed this to fully delete the specified device and not just un-pair it. bug 29188.

Last edited Apr 25, 2012 at 8:36 AM by alanjmcf, version 1

Comments

No comments yet.