Ticket Created
over 4 years ago

WERETECH-9123

Connect-IQ Ble advertising layer parsing bug, prevent many devices to function properly. (paired or not paired) Toybox::BluetoothLowEnergy::ScanResult:getRawData(), getServiceData , getServiceUuids are broken

Connect-IQ Ble advertising layer parsing bug, prevent many devices to function properly.
Reproduced on simulator, fenix 6x (9.0), fenix 6s.

Used bluetooth sniffer to confirm that the advertising bytes were correct, and different than what connect IQ returns.

When not paired :

Toybox::BluetoothLowEnergy::ScanResult:getRawData(), getServiceData , getServiceUuids
 are not receiving the proper data bytes from the network layer when **to be confirmed !!**the last advertising data type are :
 Complete List of 16-bit Service Class UUIDs

which is very common !
if the order is changed, and something else is set at the end, there is no problem at all.

In order to demonstrate this, I'm parsing the content of getRaw, using 2 stryd devices (ble indeed), one hardware v4 (last advertising data, is Shortened local name), which is working perfectly.

The parser, read all data, and decode them, now problem on this trace, it is complete, and perfectly good and valid.

devicename:Stryd kl
raw Adverting Data:[2, 1, 6, 7, 3, 24, 24, 20, 24, 10, 24, 9, 255, 170, 170, 210, 91, 0, 81, 82, 41, 9, 8, 83, 116, 114, 121, 100, 32, 107, 108]
--[AD Dump:
----[Record Dump:
    AD Len:2
    AD Type:Flags
    AD Type Integer:1
    AD Data Integer:[6]
    AD Data Hex:06
----[Record Dump:
    AD Len:7
    AD Type:Complete List of 16-bit Service Class UUIDs
    AD Type Integer:3
    AD Data Integer:[24, 24, 20, 24, 10, 24]
    AD Data Hex:181814180a18
    AD Data 16bits Service Class UUIDs:
        UUID: 0x1818
        UUID: 0x1418
        UUID: 0x0A18
----[Record Dump:
    AD Len:9
    AD Type:Manufacturer Specific Data
    AD Type Integer:255
    AD Data Integer:[170, 170, 210, 91, 0, 81, 82, 41]
    AD Data Hex:aaaad25b00515229
    AD Data String:ªªÒ[QR)
----[Record Dump:
    AD Len:9
    AD Type:Shortened Local Name
    AD Type Integer:8
    AD Data Integer:[83, 116, 114, 121, 100, 32, 107, 108]
    AD Data Hex:5374727964206b6c
    AD Data String:Stryd kl
--end of AD Dump]


Now, another generation of stryd (v3), where by lack of lack, advertising data last bytes are ...Complete List of 16-bit Service Class UUIDs

In this case, you can see that the raw data, is not correct, and stop before those advertising data.

If it was only the raw data, it won't be a problem, but getServiceUuids looks to use those bytes... so return none of those services.

devicename:Stryd
raw Adverting Data:[2, 1, 6, 9, 255, 170, 170, 115, 84, 0, 80, 82, 166, 6, 9, 83, 116, 114, 121, 100]
--[AD Dump:
----[Record Dump:
    AD Len:2
    AD Type:Flags
    AD Type Integer:1
    AD Data Integer:[6]
    AD Data Hex:06
----[Record Dump:
    AD Len:9
    AD Type:Manufacturer Specific Data
    AD Type Integer:255
    AD Data Integer:[170, 170, 115, 84, 0, 80, 82, 166]
    AD Data Hex:aaaa7354005052a6
    AD Data String:ªªsTPR¦
----[Record Dump:
    AD Len:6
    AD Type:Complete Local Name
    AD Type Integer:9
    AD Data Integer:[83, 116, 114, 121, 100]
    AD Data Hex:5374727964
    AD Data String:Stryd
--end of AD Dump]


When paired :

Class: Toybox::BluetoothLowEnergy::Device getService() and getServices()

are also affected !

This was confirmed with :
- nrf connect on android
- nrf connect desktop, with the nrf52 dongle I'm using for the simulator (confirmed into the simulator indeed)

Now, if it was only stryd, it would be okay, but my elliptical bike(FTMS profile), also adverstise services at the end... so they are not visible to the watch.

It is the same for many devices I checked, all that was availlable to me.

Is reporting to this forum enough to get it tracked by garmin ? anything else to do ?

Kind Regards.

Klick

Parents Comment Children
  • Displaying stuff like this on the screen can be a bit easier as you don't have to create a log file, and then connect to a pc to see the log file.  As I said in one case, the raw data actually changes over time, so on the screen, that's easy to see.

    In the screen shot I posted, you can easily see the name ("thing17"), and right before that is the UUID, starting with EF, then 68 then 01 and so on.  It's in reverse byte order. 

    here's the function I use for the display.

    y is where you want to start on the screen, font is the font to use, fontH is the high of the font, and the 3 lines comment out are calculated elsewhere (they only need to be done once, and not each time the function is called)

        function hexDump(dc,y,bytes,size) {
        	//hexPerLine=8;
            //twoHex=dc.getTextWidthInPixels("88 ", font);
        	//hexStart=centerW-(twoHex*hexPerLine/2);
        	var i=0;
    		while(i<size) {
    			var j=0;
    			var x=hexStart;
    			while(j<hexPerLine && i<size) {
    				dc.drawText(x,y,font,bytes[i].format("%02x")+" ",Gfx.TEXT_JUSTIFY_LEFT);
    				dc.drawText(x,y+fontH,font,bytes[i].toChar().toString(),Gfx.TEXT_JUSTIFY_LEFT);
    				j++;
    				i++;
    				x+=twoHex;
    			}
    			y+=fontH*2;
    		}
        }

  • I admit that the char is good, but I don't know all the codes from the top of my head, and on some devices, have to count for lenght Slight smile

    that's why I love lazy text decoding :)