summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/osx/osxbtcentralmanager.mm
diff options
context:
space:
mode:
authorTimur Pocheptsov <Timur.Pocheptsov@digia.com>2014-11-25 16:11:48 +0100
committerTimur Pocheptsov <Timur.Pocheptsov@digia.com>2014-12-01 12:10:36 +0100
commit63a158b2d53a4f18f118a95796c0386911e1e5fa (patch)
tree0c39dafd71c760fd4fdc6a1fbfc4063aeb000553 /src/bluetooth/osx/osxbtcentralmanager.mm
parentae3d26661aeaa2917ed35e5892648dea4caced04 (diff)
QLowEnergyController - writeDescriptor (OS X/iOS)
Core Bluetooth - based implementation. Change-Id: Ie642a13ae9a4d75401dd10648fac6eeee4123a3b Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/osx/osxbtcentralmanager.mm')
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm117
1 files changed, 109 insertions, 8 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index da4e6c34..35a284c2 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -99,6 +99,7 @@ using namespace QT_NAMESPACE;
- (void)discoverIncludedServices;
- (void)readCharacteristics:(CBService *)service;
- (void)serviceDetailsDiscoveryFinished:(CBService *)service;
+- (void)performNextWriteRequest;
// Aux. functions.
- (CBService *)serviceForUUID:(const QBluetoothUuid &)qtUuid;
@@ -110,6 +111,9 @@ using namespace QT_NAMESPACE;
- (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic
startingFrom:(CBDescriptor *)descriptor;
+// TODO: check _what_ exactly I have to reset ...
+- (void)reset;
+
@end
@implementation QT_MANGLE_NAMESPACE(OSXBTCentralManager)
@@ -126,6 +130,7 @@ using namespace QT_NAMESPACE;
delegate = aDelegate;
currentService = 0;
lastValidHandle = 0;
+ writePending = false;
}
return self;
@@ -272,7 +277,7 @@ using namespace QT_NAMESPACE;
- (void)disconnectFromDevice
{
- servicesToDiscoverDetails.clear();
+ [self reset];
if (managerState == OSXBluetooth::CentralManagerUpdating) {
disconnectPending = true;
@@ -306,11 +311,6 @@ using namespace QT_NAMESPACE;
//
// ... but we'd like to have them all:
- lastValidHandle = 0;
- serviceMap.clear();
- charMap.clear();
- descMap.clear();
-
[peripheral setDelegate:self];
managerState = OSXBluetooth::CentralManagerDiscovering;
[peripheral discoverServices:nil];
@@ -546,6 +546,41 @@ using namespace QT_NAMESPACE;
delegate->serviceDetailsDiscoveryFinished(qtService);
}
+- (void)performNextWriteRequest
+{
+ using namespace OSXBluetooth;
+
+ Q_ASSERT_X(peripheral, "-performNextWriteRequest",
+ "invalid peripheral (nil)");
+
+ if (writePending || !writeQueue.size())
+ return;
+
+ LEWriteRequest request(writeQueue.dequeue());
+
+ if (request.isDescriptor) {
+ if (!descMap.contains(request.handle)) {
+ qCWarning(QT_BT_OSX) << "-performNextWriteRequest, descriptor with "
+ "handle: " << request.handle << " not found";
+ [self performNextWriteRequest];
+ }
+
+ CBDescriptor *const d = descMap[request.handle];
+ ObjCStrongReference<NSData> data(data_from_bytearray(request.value));
+ if (!data) {
+ // Even if qtData.size() == 0, we still need NSData object.
+ qCWarning(QT_BT_OSX) << "-write:descHandle:, failed "
+ "to allocate an NSData object";
+ [self performNextWriteRequest];
+ }
+
+ writePending = true;
+ return [peripheral writeValue:data.data() forDescriptor:d];
+ } else {
+ // TODO: characteristics write requests.
+ }
+}
+
- (bool)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value
charHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle
withResponse:(bool)withResponse
@@ -562,7 +597,7 @@ using namespace QT_NAMESPACE;
return false;
}
- CBCharacteristic *const ch = charMap.value(charHandle);
+ CBCharacteristic *const ch = charMap[charHandle];
Q_ASSERT_X(ch, "-write:charHandle:withResponse:", "invalid characteristic (nil) for a give handle");
Q_ASSERT_X(peripheral, "-write:charHandle:withResponse:", "invalid peripheral (nil)");
@@ -581,6 +616,32 @@ using namespace QT_NAMESPACE;
return true;
}
+- (bool)write:(const QByteArray &)value descHandle:(QLowEnergyHandle)descHandle
+{
+ using namespace OSXBluetooth;
+
+ Q_ASSERT_X(descHandle, "-write:descHandle:",
+ "invalid descriptor handle (0)");
+
+ if (!descMap.contains(descHandle)) {
+ qCWarning(QT_BT_OSX) << "-write:descHandle:, descriptor with "
+ "handle: " << descHandle << " not found";
+ return false;
+ }
+
+ LEWriteRequest request;
+ request.isDescriptor = true;
+ request.handle = descHandle;
+ request.value = value;
+
+ writeQueue.enqueue(request);
+ [self performNextWriteRequest];
+ // TODO: this is quite ugly: true value can be returned after
+ // write actually. If I have any problems with the order later,
+ // I'll use performSelector afterDelay with some delay.
+ return true;
+}
+
// Aux. methods:
- (CBService *)serviceForUUID:(const QBluetoothUuid &)qtUuid
@@ -740,6 +801,17 @@ using namespace QT_NAMESPACE;
return [ds objectAtIndex:1];
}
+- (void)reset
+{
+ writePending = false;
+ writeQueue.clear();
+ servicesToDiscoverDetails.clear();
+ lastValidHandle = 0;
+ serviceMap.clear();
+ charMap.clear();
+ descMap.clear();
+}
+
// CBCentralManagerDelegate (the real one).
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
@@ -1162,7 +1234,6 @@ using namespace QT_NAMESPACE;
Q_UNUSED(aPeripheral)
Q_UNUSED(characteristic)
- Q_UNUSED(error)
Q_ASSERT_X(delegate, "-peripheral:didWriteValueForCharacteristic:error",
"invalid delegate (null)");
@@ -1181,4 +1252,34 @@ using namespace QT_NAMESPACE;
}
}
+- (void)peripheral:(CBPeripheral *)aPeripheral
+ didWriteValueForDescriptor:(CBDescriptor *)descriptor
+ error:(NSError *)error
+{
+ Q_UNUSED(aPeripheral)
+
+ using namespace OSXBluetooth;
+
+ writePending = false;
+
+ if (error) {
+ // NSLog to log the actual NSError:
+ NSLog(@"-peripheral:didWriteValueForDescriptor:error:, failed with error %@",
+ error);
+ // TODO: this error function is not good at all - it takes charHandle,
+ // which is noop at the moment and ... we actually work with a descriptor handle
+ // here.
+ delegate->error(qt_uuid(descriptor.characteristic.service.UUID), 0,
+ QLowEnergyService::DescriptorWriteError);
+ } else {
+ // We know that keys are unique, so can find a key for a given descriptor.
+ const QLowEnergyHandle dHandle = descMap.key(descriptor);
+ Q_ASSERT_X(dHandle, "-peripheral:didWriteValueForDescriptor:error:",
+ "invalid descriptor, not found in a descMap");
+ delegate->descriptorWriteNotification(dHandle, qt_bytearray(descriptor.value));
+ }
+
+ [self performNextWriteRequest];
+}
+
@end