Reputation: 1293
Issue: After setting MTU>23 on Samsung Device (S10e) running Android 10 and writing data to a characteristic the connection times-out and is closed.
Root cause: The reason for the timeout is the phone hardware is not actually sending anything...so the end device does not respond(ack).
How do I know it’s not an end device issue: This problem does not occur with other devices (pixel) and is also doesn’t occur on the S10 if it’s running Android 9.
Details: We are using requestMtu in BluetoothGatt to change the MTU to 185, and then onMtuChanged return mtu value is 185 and status Is GATT_SUCCESS. When we send the longer message which is about 40 bytes, the return value of writeCharacteristic of BluetoothGatt is true, but the onCharacteristicWrite callback will give us a 133 status code, which is not GATT_SUCCESS. Then the devices will disconnect.
Why do I need a larger MTU: What we expect is to be able to use a bigger MTU so that we can send data to end-device to provision Wi-Fi credentials. The end device was built to only accept the credentials all at one time(assumes MTU>23 wouldn’t be an issue. So we have field devices that customers can’t use.
Question: Is there any ideas or workaround that we can try?
Phone info: Samsung s10e Os: Android 10 Android security patch: March 1, 2020
End-Device info: ESP32
Upvotes: 12
Views: 3541
Reputation: 6068
I'm not using a Samsung device, but I had the same issue with a Sunmi device and apparently the problem is attempting to send the full MTU or any value close to that. If I negotiate 512 and attempt to send 512 I get a 133 status followed by a disconnection, but if I negotiate 512 and send 500 bytes the whole thing runs fine. Right now I'm using this formula, but I have only tested it for an MTU negotiated value of 512:
private int getMtu() {
return Math.max(GattClient.DEFAULT_MTU, (int)(this.mtu * .99));
}
The idea is that you'll always send at least 20 bytes, since that works fine even if the MTU is not negotiated. Other than that, I send only 99% of the MTU. I'm not getting the 133 status anymore.
Upvotes: 2
Reputation: 21
This is not an issue with your code, but rather an issue with Samsung's BLE stack. Essentially Samsung improperly does nothing when calling the setMTU method. The way to allow writes to work correctly is to wait for the 133 status code, wait some time for the device to disconnect, then call the BLE connect method and try the write again. Calling other BLE methods may cause the failure again. The logic should look as follows:
Write to characteristic. If status is 133 in the onCharacteristicWrite, wait for the device to disconnect. Call the connect method. When connected, retry the write (perhaps with some exponential backoff of the process).
Upvotes: 2