Use unconfirmed BLE ACK writes and notifications on Android
This commit is contained in:
1 parent
452ab50f9e
commit
09e045a45d
2 files changed
+16
-11
No files matched your search
@@ -2,6 +2,7 @@
|
||||
* Каждая отправка адресована link/subscribedClient; одна незавершённая операция на link.
|
||||
* Слабые ссылки в WinRT handlers и отменяемый posted_task исключают обращения к уничтоженному core. */
|
||||
#include "ble_backend.h"
|
||||
#include "ble_identity.h"
|
||||
#include "../u_async.h"
|
||||
#include "../mem.h"
|
||||
#include "../debug_config.h"
|
||||
|
||||
@@ -176,8 +176,8 @@ object BleRadio {
|
||||
}
|
||||
override fun onDescriptorWriteRequest(device: BluetoothDevice, requestId: Int, descriptor: BluetoothGattDescriptor,
|
||||
preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray) = post {
|
||||
val expected = if (descriptor.characteristic.uuid == txUuid) BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
else BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
||||
val expected = if (descriptor.characteristic.uuid == inviteUuid) BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
||||
else BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
val valid = incoming && descriptor.uuid == cccUuid && descriptor.characteristic.uuid in listOf(txUuid, inviteUuid, ackUuid) &&
|
||||
!preparedWrite && offset == 0 && value.contentEquals(expected)
|
||||
var link = links.values.find { !it.outgoing && it.device.address == device.address }
|
||||
@@ -207,7 +207,7 @@ object BleRadio {
|
||||
preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray) = post {
|
||||
val link = links.values.find { !it.outgoing && it.device.address == device.address }
|
||||
val valid = link != null && link.opened && characteristic.uuid in listOf(rxUuid, inviteUuid, ackUuid) &&
|
||||
!preparedWrite && responseNeeded == (characteristic.uuid != rxUuid) && offset == 0
|
||||
!preparedWrite && responseNeeded == (characteristic.uuid == inviteUuid) && offset == 0
|
||||
if (valid) emit(3, link!!.token, arg = wireChannel(characteristic.uuid), data = value.copyOf())
|
||||
if (responseNeeded) respond(device, requestId, if (valid) 0 else BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED)
|
||||
if (!valid) log("WARN", "Write rejected address=${device.address} characteristic=${characteristic.uuid} " +
|
||||
@@ -253,7 +253,7 @@ object BleRadio {
|
||||
}
|
||||
service.addCharacteristic(invite)
|
||||
ack = BluetoothGattCharacteristic(ackUuid,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_INDICATE,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
|
||||
BluetoothGattCharacteristic.PERMISSION_WRITE).apply {
|
||||
addDescriptor(BluetoothGattDescriptor(cccUuid, BluetoothGattDescriptor.PERMISSION_WRITE))
|
||||
}
|
||||
@@ -405,8 +405,10 @@ object BleRadio {
|
||||
if (characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY == 0) {
|
||||
close(link, "TX lacks Notification properties=${characteristic.properties}"); return@dispatch
|
||||
}
|
||||
val controlProperties = BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_INDICATE
|
||||
for (control in listOf(checkNotNull(link.invite), checkNotNull(link.ack))) {
|
||||
val controlProperties = if (control.uuid == inviteUuid)
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_INDICATE
|
||||
else BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or BluetoothGattCharacteristic.PROPERTY_NOTIFY
|
||||
if (control.properties and controlProperties != controlProperties || control.getDescriptor(cccUuid) == null) {
|
||||
close(link, "Control characteristic invalid uuid=${control.uuid} properties=${control.properties}"); return@dispatch
|
||||
}
|
||||
@@ -414,7 +416,7 @@ object BleRadio {
|
||||
if (!gatt.setCharacteristicNotification(characteristic, true)) {
|
||||
close(link, "DATA local subscription refused characteristic=${characteristic.uuid}"); return@dispatch
|
||||
}
|
||||
log("INFO", "Client DATA configured link=$token write=without_response receive=notification mtu=${link.mtu}")
|
||||
log("INFO", "Client DATA/ACK configured link=$token write=without_response receive=notification mtu=${link.mtu}")
|
||||
val result = if (Build.VERSION.SDK_INT >= 33) gatt.writeDescriptor(ccc, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
|
||||
else { ccc.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; if (gatt.writeDescriptor(ccc)) 0 else -1 }
|
||||
if (result != 0) close(link, "DATA CCC write refused status=$result")
|
||||
@@ -427,8 +429,10 @@ object BleRadio {
|
||||
if (ccc == null || !gatt.setCharacteristicNotification(characteristic, true)) {
|
||||
close(link, "control subscription unavailable after=${descriptor.characteristic.uuid}"); return@dispatch
|
||||
}
|
||||
val result = if (Build.VERSION.SDK_INT >= 33) gatt.writeDescriptor(ccc, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)
|
||||
else { ccc.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE; if (gatt.writeDescriptor(ccc)) 0 else -1 }
|
||||
val value = if (characteristic?.uuid == inviteUuid) BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
||||
else BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
val result = if (Build.VERSION.SDK_INT >= 33) gatt.writeDescriptor(ccc, value)
|
||||
else { ccc.value = value; if (gatt.writeDescriptor(ccc)) 0 else -1 }
|
||||
if (result != 0) close(link, "Control CCC write refused uuid=${characteristic?.uuid} status=$result")
|
||||
} else if (descriptor.characteristic.uuid == ackUuid) { link.opened = true; emit(2, token, link.mtu, address) }
|
||||
else close(link, "unexpected CCC completion")
|
||||
@@ -458,7 +462,7 @@ object BleRadio {
|
||||
val bytes = checkNotNull(link.pending)
|
||||
val status = if (link.outgoing) {
|
||||
val characteristic = checkNotNull(when (link.channel) { 0 -> link.rx; 1 -> link.invite; else -> link.ack })
|
||||
val type = if (link.channel != 0) BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
val type = if (link.channel == 1) BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
else BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
|
||||
if (Build.VERSION.SDK_INT >= 33) link.gatt!!.writeCharacteristic(characteristic, bytes, type)
|
||||
else {
|
||||
@@ -467,10 +471,10 @@ object BleRadio {
|
||||
}
|
||||
} else {
|
||||
val characteristic = checkNotNull(when (link.channel) { 0 -> tx; 1 -> invite; else -> ack })
|
||||
if (Build.VERSION.SDK_INT >= 33) server!!.notifyCharacteristicChanged(link.device, characteristic, link.channel != 0, bytes)
|
||||
if (Build.VERSION.SDK_INT >= 33) server!!.notifyCharacteristicChanged(link.device, characteristic, link.channel == 1, bytes)
|
||||
else {
|
||||
characteristic.value = bytes
|
||||
if (server!!.notifyCharacteristicChanged(link.device, characteristic, link.channel != 0)) 0 else -1
|
||||
if (server!!.notifyCharacteristicChanged(link.device, characteristic, link.channel == 1)) 0 else -1
|
||||
}
|
||||
}
|
||||
if (status == 0) {
|
||||
|
||||
Reference in new issue
Block a user