SimpleBLE icon indicating copy to clipboard operation
SimpleBLE copied to clipboard

Change or get mtu size

Open Yohannfra opened this issue 2 years ago • 3 comments

Hi,

Would it be possible to request or change the MTU size ?

On OSX it should be set to 185 bytes by default but you can check it with maximumWriteValueLength(for:)

I don't know for windows and linux but it would be useful (for my application at least) to be able to retrieve it or change it.

Thanks again for this lib

Yohannfra avatar Jul 26 '22 13:07 Yohannfra

Great suggestion! I'll add it to the list to investigate.

kdewald avatar Jul 27 '22 16:07 kdewald

I would also love to have the library report the negotiated MTU as my tool works with multiple os, devices, and chipsets, and I'd prefer to chunk the data based on this value. Currently I default it to the known peripheral, but that could be potentially problematic if the central has a maximum less than the peripheral. My understanding is that the MTU size is negotiated between the devices for the maximum value that both support, so while a stack may support requesting a size, it may not be the size that one gets. Thanks Kevin for this great library!

I'm aware this is a big request, I would also benefit from this a lot.

The main difficulty here is that the negotiated values are not very transparent to outside users, so I'm not exactly sure how to implement this in a cross platform manner. If you have time to research a bit and add a few pointers to how this could be done, it would help speed up this process a lot.

Thanks for the help and the encouraging feedback!

kdewald avatar Sep 05 '22 18:09 kdewald

A user very gently discovered that this seems to be available in newer versions of Bluez:

Since BlueZ 5.62 there is a new property in the org.bluez.GattCharacteristic1 that holds the negotiated MTU per-characteristic. It is related to Bluetooth 5.2 Enhanced Attribute Protocol (EATT) but generally this number is the same for all Characteristics.

https://github.com/bluez/bluez/blob/master/doc/gatt-api.txt

A small example from the device I am using here:

[NINA-B1-AE7ABC]# attribute-info /org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017/char0018 Characteristic - Vendor specific UUID: 2456e1b9-26e2-8f83-e744-f34f01e9d703 Service: /org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017 Notifying: yes Flags: read Flags: write-without-response Flags: write Flags: notify MTU: 0x00f7 [NINA-B1-AE7ABC]#

Service org.bluez: └─/org └─/org/bluez └─/org/bluez/hci0 ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000a │ │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000a/char000b │ │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000a/char000b/desc000d │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000e │ │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000e/char000f │ │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000e/char0011 │ │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000e/char0013 │ │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service000e/char0015 │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017 │ ├─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017/char0018 │ │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017/char0018/desc001a │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017/char001b │ └─/org/bluez/hci0/dev_6C_1D_EB_AE_7A_BC/service0017/char001b/desc001d

https://github.com/bluez/bluez/commit/1abf1400fa18e70a9085be7864f68f7c054fca14

kdewald avatar Nov 07 '22 02:11 kdewald

Implemented in https://github.com/OpenBluetoothToolbox/SimpleBLE/pull/130

kdewald avatar Nov 14 '22 02:11 kdewald

Looking at your linked update, @kdewald, I'm I right in thinking this only works on Win/Mac at the moment and 'only' reports the mtu, it doesn't allow setting it?

I'm currently working on a module to control Instax instant photo printers over bluetooth and at the moment I'm implementing two different approaches for Linux / Mac / Windows because on Linux no mtu gets negotiated, meaning you're stuck on a very, VERY slow value (which is no good when you try to send an image over to the printer) but Mac / Windows can't work with the bluetooth socket that does work on Linux. So I'd love to be able to use the same approach on Linux and just bump the mtu manually, but I think this means bluez needs to support this, which it doesn't?

javl avatar Jan 25 '23 23:01 javl

Hey @javl, thanks for reaching out!

If you're talking about the GATT MTU size (which is the one reported by SimpleBLE) this one gets negotiated by both parties based on their capabilities. One thing that could cause a low speed is if the adapter is not using data length extension (https://punchthrough.com/ble-throughput-part-4/).

A few questions on my part to help you solve this:

  • What physical adapter are you using?
  • What version of Bluez do you use? (bluetoothd -v)
  • Can you provide the output of btmon while running your program? It should tell you exactly what is being negotiated.

My best take here is that it's probably an issue with the adapter, drivers for these are very finicky.

kdewald avatar Jan 26 '23 05:01 kdewald

Sorry for the delay in getting back to you, @kdewald. Still setting up my studio after a move.

When looking for ways to change the MTU through other software I found reports of people saying this can't be done on Linux, but I'll look at it again as soon as I can and try to get a btmon report. I'm using Bluez 5.64 by the way. I'll get back to you.

javl avatar Jan 30 '23 20:01 javl

On my Ubuntu desktop it seems to negotiate a valid mtu (at 224) but my Raspberry Pi 3 Model B+ keeps returning this invalid 65533 value. For the most part data transfer does work, it's just WAY slower than on Ubuntu / macOS (which suggests it's using something like the default mtu of 20).

  • Using simplepyble==0.6.2.dev1
  • Broadcom BCM43438 (wireless chip used in Raspberry Pi 3 Model B+)
  • Bluez 5.55
  • below are the parts of the log I think show the mtu negotiation:

I wasn't able find the right datasheet myself but according to chatgpt the datasheet for this chipset mentions: "Data packets exchanged between the Host and the Controller shall not exceed the size of MTU - 4 octets. The minimum and default MTU is 23 octets. The maximum MTU is 185 octets." This is less than the 224 I get on other systems you'd still expect it to negotiate a speed higher than 20.

So again, I can have my code cross platform, but slow on Rpi, or I need separate code-bases per platform and have it work fast. I need to try and get some proper bluetooth USB device I guess, to see if that works. But maybe my best bet is to add different modes, so use simplepyble for Macos/windows and allow using sockets with Linux / Rpi.

Bluetooth monitor ver 5.55
= Note: Linux version 6.1.19-v8+ (aarch64)                                                                                         
= Note: Bluetooth subsystem version 2.22                                                                                         
= New Index: B8:27:EB:08:69:1A (Primary,UART,hci0)                                                                       
= Open Index: B8:27:EB:08:69:1A                                                                                          
= Index Info: B8:27:EB:08:69:1A (Cypress Semiconductor)                                               
@ MGMT Open: bluetoothd (privileged) version 1.22    
...
@ MGMT Event: Device Connected (0x000b) plen 43
        LE Address: FA:AB:BC:4E:20:CE (Static)
        Flags: 0x00000008
          Unknown device flag (0x00000008)
        Data length: 30
        Flags: 0x05
          LE Limited Discoverable Mode
          BR/EDR Not Supported
        128-bit Service UUIDs (complete): 1 entry
          Vendor specific (70954782-2d83-473d-9e5f-81e1d02d5273)
        TX power: 0 dBm
        Company: FUJIFILM Corporation (1240)
          Data: 0100
< HCI Command: LE Read Remote Used Features (0x08|0x0016) plen 2
        Handle: 64
> ACL Data RX: Handle 64 flags 0x02 dlen 7
      ATT: Exchange MTU Request (0x02) len 2
        Client RX MTU: 247
< ACL Data TX: Handle 64 flags 0x00 dlen 7
      ATT: Exchange MTU Response (0x03) len 2
        Server RX MTU: 517
< ACL Data TX: Handle 64 flags 0x00 dlen 7
      ATT: Exchange MTU Request (0x02) len 2
        Client RX MTU: 517
> HCI Event: Command Complete (0x0e) plen 6
      Write Authenticated Payload Timeout (0x03|0x007c) ncmd 1
        Status: Success (0x00)
        Handle: 64
> HCI Event: Number of Completed Packets (0x13) plen 5
        Num handles: 1
        Handle: 64
        Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 7
      ATT: Exchange MTU Response (0x03) len 2
        Server RX MTU: 247
< ACL Data TX: Handle 64 flags 0x00 dlen 7
      ATT: Read Request (0x0a) len 2
        Handle: 0x0007
> ACL Data RX: Handle 64 flags 0x02 dlen 26
      ATT: Read Response (0x0b) len 21
        Value: 494e535441582d313532343337353428494f532900
< ACL Data TX: Handle 64 flags 0x00 dlen 7
      ATT: Read Request (0x0a) len 2
        Handle: 0x0009

javl avatar Mar 26 '23 19:03 javl