arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
306 stars 205 forks source link

XBox One controller - current firmware (BLE) - (peripheral.discoverAttributes fails #276

Open KurtE opened 1 year ago

KurtE commented 1 year ago

If you update an XBox One controller to the latest firmware, the update will convert the controller to running using BLE. Microsoft shows a few different ways to do the update, including I believe simply plug it into USB to XBox One that is running the latest stuff. I updated one of mine using the Windows XBox Accessories App.

Side note: trying to add BLE support to our Teensy USBHost_t36 code base. We already have some bluetooth support, and for example we can connect and use an XBox one controller, with the original firmware, but not after they are updated.

So I thought I would experiment using the ArduinoBLE library, and first tried on Arduino Nano 33 IOT as well as BLE and this call fails. Note: I now also have a fork/branch of this library that runs on Teensy boards (T3.6 and 4.x) and right now doing most of my stuff I am using a bluetooth dongle plugged into an USBHost connector on either a 4.1 or a Micromod.

In order for BLE to see this you need to put the controller into pairing mode. Hopefully after I figure out this part will then figure out how to do an actual BLE pairing (Again sort of outside of this issue).

When in pairing mode I found a windows App, that can talk to the device. image

Note: I posted Some of these details up on both a PJRC forum thread as well as an Arduino one: https://forum.arduino.cc/t/arduinoble-trying-to-connect-to-xbox-one-controller-and-other-ble-devices/1054844/3 https://forum.pjrc.com/threads/71503-USBHost-Bluetooth-gt-BLE-gt-ArduinoBLE

As the title mentioned, the discoverAttributes call fails. I have added a lot of debug outputs and the like to code including into my TeensyTransport code. This includes doing some decoding of the data that is sent back and forth with the ATT messages.

It looks like the code is properly enumerating the Services and the Characteristics and then fails after that:

From my debug output: first enumerating the Services: Pardon some of my cryptic outputs:

>>(ACLDATA, 0):40 00 07 00 03 00 04 00 02 12 00 
    ** MTU_REQ **: MTU: 12
<<(ACLDATA, 5183):40 20 07 00 03 00 04 00 03 12 00 
    ** MTU_RESP **: MTU: 12
>>(ACLDATA, 42):40 00 0B 00 07 00 04 00 10 01 00 FF FF 00 28 
    ** READ_BY_GROUP_REQ **: Starting handle:0001 ending handle:ffff Group Type:2800
<<(ACLDATA, 45):40 20 12 00 0E 00 04 00 11 06 01 00 07 00 00 18 08 00 08 00 01 18 
    ** READ_MULTI_RESP **: len per:06
        Atr Handle:0001 End Group Handle:0012 Data: 00 18
        Atr Handle:0008 End Group Handle:0012 Data: 01 18
>>(ACLDATA, 29):40 00 0B 00 07 00 04 00 10 09 00 FF FF 00 28 
    ** READ_BY_GROUP_REQ **: Starting handle:0009 ending handle:ffff Group Type:2800
<<(ACLDATA, 30):40 20 12 00 0E 00 04 00 11 06 09 00 11 00 0A 18 12 00 15 00 0F 18 
    ** READ_MULTI_RESP **: len per:06
        Atr Handle:0009 End Group Handle:0012 Data: 0a 18
        Atr Handle:0012 End Group Handle:0012 Data: 0f 18
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 10 16 00 FF FF 00 28 
    ** READ_BY_GROUP_REQ **: Starting handle:0016 ending handle:ffff Group Type:2800
<<(ACLDATA, 30):40 20 0C 00 08 00 04 00 11 06 16 00 23 00 12 18 
    ** READ_MULTI_RESP **: len per:06
        Atr Handle:0016 End Group Handle:000c Data: 12 18
>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 10 24 00 FF FF 00 28 
    ** READ_BY_GROUP_REQ **: Starting handle:0024 ending handle:ffff Group Type:2800
<<(ACLDATA, 45):40 20 09 00 05 00 04 00 01 10 24 00 80 
    ** ATT_ERROR **: OP:10 handle:24 error:80 

    After discoverServices

But it looks here like it found: Handle:0001 ID: 1800 0008 ID: 1801 0009 180a 0012 180f 0016 1812

Which map to:

      case 0x1800: return "Generic Access service";
      case 0x1801: return "Generic Attribute service";
      case 0x180A: return "Device Information service";
      case 0x1812: return "Human Interface Device service";

It then goes through all 5 of these Services looking for Characteristics:

>>(ACLDATA, 45):40 00 0B 00 07 00 04 00 08 01 00 07 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0001 ending handle:0007 Attribute Type:2803
<<(ACLDATA, 30):40 20 14 00 10 00 04 00 09 07 02 00 02 03 00 00 2A 04 00 02 05 00 01 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0002 Data: 02 03 00 00 2a
        Atr Handle:0004 Data: 02 05 00 01 2a
>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 08 06 00 07 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0006 ending handle:0007 Attribute Type:2803
<<(ACLDATA, 30):40 20 0D 00 09 00 04 00 09 07 06 00 02 07 00 04 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0006 Data: 02 07 00 04 2a
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 08 00 07 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0008 ending handle:0007 Attribute Type:2803
<<(ACLDATA, 45):40 20 09 00 05 00 04 00 01 08 08 00 01 
    ** ATT_ERROR **: OP:8 handle:8 error:01 - INVALID_HANDLE

>>(ACLDATA, 29):40 00 0B 00 07 00 04 00 08 08 00 08 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0008 ending handle:0008 Attribute Type:2803
<<(ACLDATA, 30):40 20 09 00 05 00 04 00 01 08 08 00 0A 
    ** ATT_ERROR **: OP:8 handle:8 error:0a - ATTR_NOT_FOUND

>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 09 00 11 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0009 ending handle:0011 Attribute Type:2803
<<(ACLDATA, 30):40 20 14 00 10 00 04 00 09 07 0A 00 02 0B 00 29 2A 0C 00 02 0D 00 50 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:000a Data: 02 0b 00 29 2a
        Atr Handle:000c Data: 02 0d 00 50 2a
>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 08 0E 00 11 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:000e ending handle:0011 Attribute Type:2803
<<(ACLDATA, 30):40 20 14 00 10 00 04 00 09 07 0E 00 02 0F 00 26 2A 10 00 02 11 00 25 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:000e Data: 02 0f 00 26 2a
        Atr Handle:0010 Data: 02 11 00 25 2a
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 12 00 11 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0012 ending handle:0011 Attribute Type:2803
<<(ACLDATA, 30):40 20 09 00 05 00 04 00 01 08 12 00 01 
    ** ATT_ERROR **: OP:8 handle:12 error:01 - INVALID_HANDLE

>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 08 12 00 15 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0012 ending handle:0015 Attribute Type:2803
<<(ACLDATA, 30):40 20 0D 00 09 00 04 00 09 07 13 00 12 14 00 19 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0013 Data: 12 14 00 19 2a
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 15 00 15 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0015 ending handle:0015 Attribute Type:2803
<<(ACLDATA, 30):40 20 09 00 05 00 04 00 01 08 15 00 0A 
    ** ATT_ERROR **: OP:8 handle:15 error:0a - ATTR_NOT_FOUND

>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 08 16 00 23 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0016 ending handle:0023 Attribute Type:2803
<<(ACLDATA, 30):40 20 14 00 10 00 04 00 09 07 17 00 02 18 00 4A 2A 19 00 04 1A 00 4C 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0017 Data: 02 18 00 4a 2a
        Atr Handle:0019 Data: 04 1a 00 4c 2a
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 1B 00 23 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:001b ending handle:0023 Attribute Type:2803
<<(ACLDATA, 30):40 20 14 00 10 00 04 00 09 07 1B 00 02 1C 00 4B 2A 1D 00 12 1E 00 4D 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:001b Data: 02 1c 00 4b 2a
        Atr Handle:001d Data: 12 1e 00 4d 2a
>>(ACLDATA, 14):40 00 0B 00 07 00 04 00 08 1F 00 23 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:001f ending handle:0023 Attribute Type:2803
<<(ACLDATA, 30):40 20 0D 00 09 00 04 00 09 07 21 00 0E 22 00 4D 2A 
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0021 Data: 0e 22 00 4d 2a
>>(ACLDATA, 30):40 00 0B 00 07 00 04 00 08 23 00 23 00 03 28 
    ** READ_BY_TYPE_REQ **: Starting handle:0023 ending handle:0023 Attribute Type:2803
<<(ACLDATA, 30):40 20 09 00 05 00 04 00 01 08 23 00 0A 
    ** ATT_ERROR **: OP:8 handle:23 error:0a - ATTR_NOT_FOUND

    After discoverCharacteristics

I won't go through all 5 groups here to decode. But looking at the first we see:

    ** READ_BY_TYPE_REQ **: Starting handle:0001 ending handle:0007 Attribute Type:2803
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0002 Data: 02 03 00 00 2a
        Atr Handle:0004 Data: 02 05 00 01 2a
    ** READ_BY_TYPE_REQ **: Starting handle:0006 ending handle:0007 Attribute Type:2803
    ** READ_BY_TYPE_RESP **: len per:07
        Atr Handle:0006 Data: 02 07 00 04 2a
    ** READ_BY_TYPE_REQ **: Starting handle:0008 ending handle:0007 Attribute Type:2803
    ** ATT_ERROR **: OP:8 handle:8 error:01 - INVALID_HANDLE

So as I read this, the first group should have 3 handles 2, 4 and 6 I have not fully decoded the 5 bytes, but it looks like 2 goes to UUID 0x2A00 and likewise and 04->0x2A01 Which maps to: case 0x2A00: return "Device Name"; case 0x2A01: return "Appearance"; Which again matches the data I see with the Windows app.

Again the call discoverCharacteristics works, but then the call to: bool ATTClass::discoverDescriptors(uint16_t connectionHandle, BLERemoteDevice* device) Fails on the first items. That is i=0 and j=0;

If fails in the while(1) { loop. Some debug from that part:

`ATTClass::discoverDescriptors(64, 0x20203338)
    Service Count:5
    0 Service: 1800 #characteristic:3
    **(0, 0) characteristic: 2a00 0x20203590, range: 4 5**
ATTClass::findInfoReq(64, 4, 5, 0x20067e80)

>>(ACLDATA, 14):40 00 09 00 05 00 04 00 04 04 00 05 00 
    ** FIND_INFO_REQ **: Starting handle:0004 ending handle:0005
<<(ACLDATA, 30):40 20 0A 00 06 00 04 00 05 01 04 00 03 28 
    ** FIND_INFO_RESP **: Format:1
        **Handle:04 UUID:280a**
>>(ACLDATA, 30):40 00 09 00 05 00 04 00 04 05 00 05 00 
    **** FIND_INFO_REQ **: Starting handle:0005 ending handle:0005**
tx_data callback (bluetooth):40 00 09 00 05 00 04 00 04 05 00 05 00 
<<(EVT, 16, H:163 T:163)13 05 01 40 00 02 00 

HCI event: 13
Outstanding packets: 0
Data[0]: 0x64
Data[1]: 0x2
    0 0 respLength:0
Attribute discovery failed!
Command tx ->  0x1 0x6 0x4 0x3 0x40 0x0 0x13
>>(CMD, 4984):06 04 03 40 00 13 
    Control callback (bluetooth): 0 : 06 04 03 40 00 13 
<<(EVT, 2, H:171 T:171)0F 04 00 01 06 04 
HCI event: F
F n cmd:  0x1
F status: 0x0
F opcode: 0x406
<<(EVT, 1899, H:178 T:178)05 04 00 40 00 22 
HCI event: 5
Command tx ->  0x1 0xA 0x20 0x1 0x1
>>(CMD, 0):0A 20 01 01 
    Control callback (bluetooth): 0 : 0a 20 01 01 
<<(EVT, 2, H:185 T:185)0E 04 01 0A 20 00 
HCI event: E
E ncmd:   0x1
E opcode: 0x200A
E status: 0x0
`

Something that does not feel right here is: As I mentioned earlier is it looks like the first one has handle 2 but it is searching for it with the range 4,5? It finds the 2nd one with ID 4, It then tries a search on 5-5 which then bails with an error and I don't see any response on the ACLDATA for it.

Still investigating

KurtE commented 1 year ago

To follow up on the first post, I am still trying to figure out what the bool ATTClass::discoverDescriptors(uint16_t connectionHandle, BLERemoteDevice* device) code is doing when it is tries to enumerate the services/Characteristics to discover the attributes:

I added some debug code at the start of this, that enumerates some of the stuff we know when we get here: Serial.printf("\tService Count:%u\n", serviceCount);

  #if 1
  // Lets print out the information we know:
  Serial.println("****************** Service characteristic list ******************");
  for (int i = 0; i < serviceCount; i++) {
    BLERemoteService* service = device->service(i);
    Serial.printf("Service(%u): UUID: %s Handle Range: %u %u\n", i, service->uuid(), 
          service->startHandle(), service->endHandle());
    int characteristicCount = service->characteristicCount();

    for (int j = 0; j < characteristicCount; j++) {
      BLERemoteCharacteristic* characteristic = service->characteristic(j);
      Serial.printf("\tcharacteristic(%u): UUID: %s Handle Range: %u %u\n", j, characteristic->uuid(), 
            characteristic->startHandle(), characteristic->valueHandle());
    }
  }
  Serial.println("****************** end ******************");

And for example if I run the PeripheralExplorer with the Microsoft "Surface Arc Mouse"; running in pairing mode, I see:

    Service Count:5
****************** Service characteristic list ******************
Service(0): UUID: 1800 Handle Range: 1 7
    characteristic(0): UUID: 2a00 Handle Range: 2 3
    characteristic(1): UUID: 2a01 Handle Range: 4 5
    characteristic(2): UUID: 2a04 Handle Range: 6 7
Service(1): UUID: 1801 Handle Range: 8 8
Service(2): UUID: 180a Handle Range: 9 13
    characteristic(0): UUID: 2a29 Handle Range: 10 11
    characteristic(1): UUID: 2a50 Handle Range: 12 13
Service(3): UUID: 180f Handle Range: 14 17
    characteristic(0): UUID: 2a19 Handle Range: 15 16
Service(4): UUID: 1812 Handle Range: 18 65535
    characteristic(0): UUID: 2a4e Handle Range: 19 20
    characteristic(1): UUID: 2a4d Handle Range: 21 22
    characteristic(2): UUID: 2a4d Handle Range: 25 26
    characteristic(3): UUID: 2a4d Handle Range: 29 30
    characteristic(4): UUID: 2a4d Handle Range: 33 34
    characteristic(5): UUID: 2a4d Handle Range: 37 38
    characteristic(6): UUID: 2a4d Handle Range: 41 42
    characteristic(7): UUID: 2a4d Handle Range: 45 46
    characteristic(8): UUID: 2a4d Handle Range: 49 50
    characteristic(9): UUID: 2a4d Handle Range: 53 54
    characteristic(10): UUID: 2a4d Handle Range: 57 58
    characteristic(11): UUID: 2a4d Handle Range: 61 62
    characteristic(12): UUID: 2a4d Handle Range: 64 65
    characteristic(13): UUID: 2a4d Handle Range: 67 68
    characteristic(14): UUID: 2a4d Handle Range: 70 71
    characteristic(15): UUID: 2a4d Handle Range: 73 74
    characteristic(16): UUID: 2a4d Handle Range: 76 77
    characteristic(17): UUID: 2a4b Handle Range: 79 80
    characteristic(18): UUID: 2a33 Handle Range: 81 82
    characteristic(19): UUID: 2a4a Handle Range: 84 85
    characteristic(20): UUID: 2a4c Handle Range: 86 87
****************** end ******************

Then when the current main code is trying to enumerate let's say the first Service with 3 characteristics: I have some additional debug output, condensed here:

    0 Service: 1800 #characteristic:3
    (0, 0) characteristic: 2a00 0x20203590, range: 4 5
        Handle:04 UUID:280e
        Handle:05 UUID:2a0e
    (0, 1) characteristic: 2a01 0x202035f0, range: 6 7
        Handle:06 UUID:280e
        Handle:07 UUID:2a0e
    (0, 2) characteristic: 2a04 0x0, range: 8 7
    1 Service: 1801 #characteristic:0
    2 Service: 180a #characteristic:2

So the first characteristic it looks like it is passing in the range for the 2nd one. Second one, the third, and the third one invalid range so it returns nothing for it.

I know I am probably missing something obvious here, My Gut (read that as my Naive and very little understanding of BLE) wonders if this code Could simply call the while (1) loop with the range maybe incremented by 1? like: Service(0): UUID: 1800 Handle Range: 1 7 And guessing if the handle returned matches one of the start handle, value handle of a characteristic add the object to that one?

EDIT: Or maybe if >= start handle of one and less then then next one then add it...

But again, I more or less am throwing darts here.

Thoughts?

KurtE commented 1 year ago

I know I am probably simply talking to myself (not too unusual) ;)

I now have my extended version of the Peripheral Explorer getting information from an XBox One Controller with the updated firmware that uses BLE on a Teensy 4.1... Example Output:

HCIClass::readLeBufferSize called
Bluetooth® Low Energy Central - Peripheral Explorer
Found c8:3f:26:b3:ac:16 'Xbox Wireless Controller' 
Connecting ...
Connected
Discovering attributes ...
Attributes discovered

Device name: Xbox Wireless Controll
Appearance: 0x0

Service 1800    //Generic Access service
    Characteristic 2a00, properties 0x2, value 0x58626F7820576972656C65737320436F6E74726F6C6C   //Device Name
        Descriptor 2803, value 0x020300002A //Characteristic
        Descriptor 00002a00-0000-0000-0000-000000000000, value 0x58626F7820576972656C65737320436F6E74726F6C6C
    Characteristic 2a01, properties 0x2, value 0xC403   //Appearance
        Descriptor 2803, value 0x020500012A //Characteristic
        Descriptor 00002a01-0000-0000-0000-000000000000, value 0xC403
    Characteristic 2a04, properties 0x2, value 0x0600060000002C01   //Peripheral Preferred Connection Parameters
        Descriptor 2803, value 0x020700042A //Characteristic
        Descriptor 00002a04-0000-0000-0000-000000000000, value 0x0600060000002C01
Service 1801    //Generic Attribute service
Service 180a    //Device Information service
    Characteristic 2a29, properties 0x2, value 0x4D6963726F736F6674 //Manufacturer Name String
        Descriptor 2803, value 0x020B00292A //Characteristic
        Descriptor 00002a29-0000-0000-0000-000000000000, value 0x4D6963726F736F6674
    Characteristic 2a50, properties 0x2, value 0x025E04200B1505 //PnP ID
        Descriptor 2803, value 0x020D00502A //Characteristic
        Descriptor 00002a50-0000-0000-0000-000000000000, value 0x025E04200B1505
    Characteristic 2a26, properties 0x2, value 0x352E31352E333136382E30 //Firmware Revision String
        Descriptor 2803, value 0x020F00262A //Characteristic
        Descriptor 00002a26-0000-0000-0000-000000000000, value 0x352E31352E333136382E30
    Characteristic 2a25, properties 0x2, value 0x3033363030303332393035363234   //Serial Number String
        Descriptor 2803, value 0x021100252A //Characteristic
        Descriptor 00002a25-0000-0000-0000-000000000000, value 0x3033363030303332393035363234
Service 180f    //Battery service
    Characteristic 2a19, properties 0x12, value 0x32    //Battery Level
        Descriptor 2803, value 0x121400192A //Characteristic
        Descriptor 00002a19-0000-0000-0000-000000000000, value 0x32
        Descriptor 2902, value 0x0000   //Client Characteristic Configuration
Service 1812    //Human Interface Device service
    Characteristic 2a4a, properties 0x2 //HID Information
        Descriptor 2803, value 0x0218004A2A //Characteristic
        Descriptor 00002a4a-0000-0000-0000-000000000000, value 0x
    Characteristic 2a4c, properties 0x4 //HID Control Point
        Descriptor 2803, value 0x041A004C2A //Characteristic
        Descriptor 00002a4c-0000-0000-0000-000000000000, value 0x
    Characteristic 2a4b, properties 0x2 //Report Map
        Descriptor 2803, value 0x021C004B2A //Characteristic
        Descriptor 00002a4b-0000-0000-0000-000000000000, value 0x
    Characteristic 2a4d, properties 0x12    //Report
        Descriptor 2803, value 0x121E004D2A //Characteristic
        Descriptor 00002a4d-0000-0000-0000-000000000000, value 0x
        Descriptor 2902, value 0x0000   //Client Characteristic Configuration
        Descriptor 2908, value 0x0101   //Report Reference
    Characteristic 2a4d, properties 0xE //Report
        Descriptor 2803, value 0x0E22004D2A //Characteristic
        Descriptor 00002a4d-0000-0000-0000-000000000000, value 0x
        Descriptor 2908, value 0x0302   //Report Reference
Service 00000001-5f60-4c4f-9c83-a7953298d40d
    Characteristic 00000002-5f60-4c4f-9c83-a7953298d40d, properties 0x2
        Descriptor 2803, value 0x0226000DD4983295A7839C4F4C605F02000000 //Characteristic
        Descriptor 00000002-5f60-4c4f-9c83-a7953298d40d, value 0x
    Characteristic 00000003-5f60-4c4f-9c83-a7953298d40d, properties 0x2
        Descriptor 2803, value 0x0228000DD4983295A7839C4F4C605F03000000 //Characteristic
        Descriptor 00000003-5f60-4c4f-9c83-a7953298d40d, value 0x
    Characteristic 00000004-5f60-4c4f-9c83-a7953298d40d, properties 0x8
        Descriptor 2803, value 0x082A000DD4983295A7839C4F4C605F04000000 //Characteristic
        Descriptor 00000004-5f60-4c4f-9c83-a7953298d40d, value 0x

Disconnecting ...
Disconnected

My Fork/Branch is updated with the code. Still has some debug stuff turned on.

KurtE commented 1 year ago

Note: The main Issue that was causing this to not work, was in the function:

int HCIClass::readLeBufferSize(uint16_t& pktLen, uint8_t& maxPkt)
{
  int result = sendCommand(OGF_LE_CTL << 10 | OCF_LE_READ_BUFFER_SIZE);

  //Serial.println("HCIClass::readLeBufferSize called");
  if (result == 0) {
    struct __attribute__ ((packed)) HCILeBufferSize {
      uint16_t pktLen;
      uint8_t maxPkt;
    } *leBufferSize = (HCILeBufferSize*)_cmdResponse;

    pktLen = leBufferSize->pktLen;
    _maxPkt = maxPkt = leBufferSize->maxPkt;

#ifdef _BLE_TRACE_
  Serial.print("\tpktlen: ");
  Serial.print(pktLen, DEC);
  Serial.print(" maxPkt: ");
  Serial.println(maxPkt, DEC);
#endif

#if (defined(TEENSYDUINO) && (__IMXRT1062__) || (ARDUINO_TEENSY36)) || !defined(__AVR__)
    ATT.setMaxMtu(pktLen/* - 9*/); // max pkt len - ACL header size
#endif
  }

  return result;
}

The Bluetooth 4.0 dongle returned 27 and the code was subtracting 9 from it for the ACL data size...

From the Bluetooth 5.3 manual it says:

Total_Num_ISO_Data_Packets return parameter contains the total number of isochronous data packets that can be stored in the data buffers of the Controller. The Host determines how to divide the buffers between different connection handle(s). Note: The LE_ACL_Data_Packet_Length and ISO_Data_Packet_Length return parameters do not include the length of the HCI ACL Data packet header or the HCI ISO Data packet header respectively.

Removing that -9 caused everything to appear to work now.

bediver commented 1 year ago

Hello, I've run into same issue when attempting discoverAttributes on XBox controller (BLE). I've been testing your changes and what made this work are your changes for descriptor UUID (16/128 bit format). -9 on setMaxMtu has no effect in my case. My HW: Arduino Nano RB2040 Connect

Stoutscientist commented 1 year ago

^

fstrugar commented 7 months ago

Hi! Just run into the same issue with Arduino Uno R4 - stuck in infinite loop in discoverAttributes. Can confirm what @bediver said, your changes in discoverDescriptors from https://github.com/KurtE/ArduinoBLE/tree/uno_r4_wifi_teensy branch fix it.

Thank you kindly for putting it up here, I would've never figured it out myself! Hope ArduinoBLE devs will pick it up eventually?