How can I change data length in BLE?

Hello there.
I want to increase the data length in BLE communication, but I couldn’t find any api function to change the data packet length. Is there any configuration parameter should I add to mbed_app.json?

Not exactly sure what you need exactly. Are you asking about MTU size? If so, search within the forum as similar questions haves been asked before. Here is an old forum post on the topic, by way of example. There are more recent posts. Max Size Allowed for a GATT Characteristic in MBED CORDIO API? - Question | Mbed

Otherwise, if you are looking to create a characteristic that allows the user or central client device to send multiple bytes of data, have a look within GattCharacteristic.h. Here you will find a number of premade templates (you can also create your own) which help define your characteristics. For example, the WriteOnlyArrayGattCharacteristic template is one that allows multiple bytes to be sent. The data length within this template is defined as NUM_ELEMENTS.

1 Like

Thank you for your help Gerriko.
As mentioned in this documentation page, there are tow different concepts that affect the data throughput, ATT_MTU and Data Length Extension. I can easily change the ATT_MTU by changing default configuration parameter “cordio.desired-att-mtu” and there is no problem about ATT_MTU.

But, I want to change the Data Length to 240 octets which it’s default value is 23 octets and the maximum value is 251 octets. In fact I want to deliver more data (i.e. 240 octets) in one transmission. how can I do this?

my client and server devices are both powered by the STM32WB series micro controller which supports the Data Length Extension feature.

Best regards.

From my experience, this is not for you to choose. It depends on BLE version of the sender and the receiver. For full support, you’ll need at leaser BLE 4.2 on both sides.

I recommend those three articles which explain really well:

Another thing, things are a little different if your device is connected to a phone. For example, on iOS, you do not choose the size, iOS does that for you and will use the maximum size possible.

See bluetooth lowenergy - Change iOS BLE MTU size to 512 (SWIFT) - Stack Overflow

On Android, it can’t say, I’ve never programmed for that platform.

1 Like

Ah right. Now I get you. Unfortunately I haven’t tested this myself yet and is on my todo list, hence the interest in your post.

So, other than changing the configuration parameter “cordio.desired-att-mtu” I am curious to learn if you tried the central client command negotiateAttMtu(ble::connection_handle_t connection); which is found in GattClient.h. According to documentation this triggers MTU negotiation.

I assume then that this triggers this event within peripheral (as indicated in the mbed website documentation page):

If both controllers support data length extension and a higher value is negotiated, the BLE stack will call onDataLengthChange in the Gap::EventHandler registered by the user. The supported length is set in the link layer with a maximum of 251. For Cordio Link Layer it is derived from the config option cordio_ll.max-acl-size .

Now upon further searching I see there is also a BLE folder labeled “pal”. I have no idea what this “pal” stands for but there is a further function of interest found within PalGattClient.h called get_mtu_size , which may help too.

Not sure if that helps.

1 Like

Thanks for your great explanation Gerriko.

I have been trying various parameters and situations. I think there is a lack of well explained documentation about Cordio stack and how to configure parameters. So the only thing we can do is try and error and I will share my observations about different situations and parameters soon.

Sincerely Yours

I’ve been playing around with this. Have a look for the build file mbed_config.h
This will confirm what settings you have used.

I discovered that the desired-att-mtu setting I had changed was within the wrong mbed_lib.json (found in folder was under the header “cordio-ll-nrf52840”) and thus it had no effect.

I then changed the default cordio desired-att-mtu settings (found in folder connectivity/FEATURE_BLE/source/cordio) and this worked.

I used the nRFconnect Android utility app to check that my requested MTU change was accepted by my peripheral device.

I now know that I can override the default settings. So going forward I need to just make sure my override settings are under the group “name”: “cordio” rather than the device name.

Hope that makes sense.

I’m busy developing a simple demo, using a modified version of ble_app.h (found on github: GitHub - ARMmbed/mbed-os-ble-utils: mbed os BLE utilities used by ble examples).

I thought to include a handler for AttMtu changes on the Gatt Server side (for peripheral device).

The ble_app.h relies heavily on “chainable events” for the GAP and so I included ChainableGattServerEventHandler.h as well in my ble_app (mod).

Now I can set up some callbacks to capture Att Mtu changes inside the ble_app class. Such as
mbed::Callback<void(ble::connection_handle_t connectionHandle, uint16_t attMtuSize)> _post_mtuchange_cb;

and created a new protected function

void onAttMtuChange(ble::connection_handle_t connectionHandle, uint16_t attMtuSize) override
        if (_post_mtuchange_cb) {
            _post_mtuchange_cb(connectionHandle, attMtuSize);


and a new public function

void on_AttMtuChange(mbed::Callback<void(ble::connection_handle_t connectionHandle, uint16_t attMtuSize)> cb)
        _post_mtuchange_cb = cb;

Now I’ve got access to this event in my application code.

Did a quick test and it appears to work.

Changing MTU from my phone:

Event captured on serial monitor from peripheral device:

I was curious to see how an MbedOS BLE central client device would do it so I created some test code.

It is interesting to observe that MTU negotiation is automatically done once the device connects, if you have “cordio.desired-att-mtu” defined in your mbed_app.json file.

I had a MTU callback in my code to capture the change being done.