summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/osx/osxbtcentralmanager.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/osx/osxbtcentralmanager.mm')
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm462
1 files changed, 223 insertions, 239 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index 73d9d5bc..2fc74e36 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -65,7 +65,7 @@ NSUInteger qt_countGATTEntries(CBService *service)
// No checks if NSUInteger is big enough :)
// Let's assume such number of entries is not possible :)
- Q_ASSERT_X(service, "qt_countGATTEntries", "invalid service (nil)");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -112,7 +112,7 @@ using namespace QT_NAMESPACE;
startingFrom:(CBDescriptor *)descriptor;
- (CBDescriptor *)descriptor:(const QBluetoothUuid &)dUuid
forCharacteristic:(CBCharacteristic *)ch;
-// TODO: check _what_ exactly I have to reset ...
+- (bool)cacheWriteValue:(const QByteArray &)value for:(NSObject *)obj;
- (void)reset;
@end
@@ -121,7 +121,7 @@ using namespace QT_NAMESPACE;
- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerDelegate *)aDelegate
{
- Q_ASSERT_X(aDelegate, "-initWithDelegate:", "invalid delegate (null)");
+ Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
if (self = [super init]) {
manager = nil;
@@ -159,8 +159,8 @@ using namespace QT_NAMESPACE;
- (QLowEnergyController::Error)connectToDevice:(const QBluetoothUuid &)aDeviceUuid
{
- Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle, "-connectToDevice",
- "invalid state"); // QLowEnergyController connects only if in UnconnectedState.
+ Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
+ Q_FUNC_INFO, "invalid state");
deviceUuid = aDeviceUuid;
@@ -169,7 +169,7 @@ using namespace QT_NAMESPACE;
manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
if (!manager) {
managerState = OSXBluetooth::CentralManagerIdle;
- qCWarning(QT_BT_OSX) << "-connectToDevice:, failed to allocate a "
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate a "
"central manager";
return QLowEnergyController::ConnectionError;
}
@@ -181,12 +181,12 @@ using namespace QT_NAMESPACE;
- (QLowEnergyController::Error)connectToDevice
{
- Q_ASSERT_X(manager, "-connectToDevice", "invalid central manager (nil)");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)");
Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
- "-connectToDevice", "invalid state");
+ Q_FUNC_INFO, "invalid state");
if ([self isConnected]) {
- qCDebug(QT_BT_OSX) << "-connectToDevice, already connected";
+ qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected";
delegate->connectSuccess();
return QLowEnergyController::NoError;
} else if (peripheral) {
@@ -201,7 +201,7 @@ using namespace QT_NAMESPACE;
// Retrieve a peripheral first ...
ObjCScopedPointer<NSMutableArray> uuids([[NSMutableArray alloc] init]);
if (!uuids) {
- qCWarning(QT_BT_OSX) << "-connectToDevice, failed to allocate identifiers";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate identifiers";
return QLowEnergyController::ConnectionError;
}
@@ -212,7 +212,7 @@ using namespace QT_NAMESPACE;
std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData);
const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]);
if (!nsUuid) {
- qCWarning(QT_BT_OSX) << "-connectToDevice, failed to allocate NSUUID identifier";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSUUID identifier";
return QLowEnergyController::ConnectionError;
}
@@ -222,7 +222,7 @@ using namespace QT_NAMESPACE;
QT_BT_MAC_AUTORELEASEPOOL;
NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids];
if (!peripherals || peripherals.count != 1) {
- qCWarning(QT_BT_OSX) << "-connectToDevice, failed to retrive a peripheral";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to retrive a peripheral";
return QLowEnergyController::UnknownRemoteDeviceError;
}
@@ -233,7 +233,7 @@ using namespace QT_NAMESPACE;
#else
OSXBluetooth::CFStrongReference<CFUUIDRef> cfUuid(OSXBluetooth::cf_uuid(deviceUuid));
if (!cfUuid) {
- qCWarning(QT_BT_OSX) << "-connectToDevice:, failed to create CFUUID object";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to create CFUUID object";
return QLowEnergyController::ConnectionError;
}
// TODO: With ARC this cast will be illegal:
@@ -248,17 +248,17 @@ using namespace QT_NAMESPACE;
- (void)connectToPeripheral
{
- Q_ASSERT_X(manager, "-connectToPeripheral", "invalid central manager (nil)");
- Q_ASSERT_X(peripheral, "-connectToPeripheral", "invalid peripheral (nil)");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
- "-connectToPeripheral", "invalid state");
+ Q_FUNC_INFO, "invalid state");
// The state is still the same - connecting.
if ([self isConnected]) {
- qCDebug(QT_BT_OSX) << "-connectToPeripheral, already connected";
+ qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected";
delegate->connectSuccess();
} else {
- qCDebug(QT_BT_OSX) << "-connectToPeripheral, trying to connect";
+ qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "trying to connect";
managerState = OSXBluetooth::CentralManagerConnecting;
[manager connectPeripheral:peripheral options:nil];
}
@@ -300,9 +300,9 @@ using namespace QT_NAMESPACE;
- (void)discoverServices
{
- Q_ASSERT_X(peripheral, "-discoverServices", "invalid peripheral (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
- "-discoverServices", "invalid state");
+ Q_FUNC_INFO, "invalid state");
// From Apple's docs:
//
@@ -321,17 +321,17 @@ using namespace QT_NAMESPACE;
{
using namespace OSXBluetooth;
- Q_ASSERT_X(managerState == CentralManagerIdle, "-discoverIncludedServices",
+ Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO,
"invalid state");
- Q_ASSERT_X(manager, "-discoverIncludedServices", "invalid manager (nil)");
- Q_ASSERT_X(peripheral, "-discoverIncludedServices", "invalid peripheral (nil)");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
QT_BT_MAC_AUTORELEASEPOOL;
NSArray *const services = peripheral.services;
if (!services || !services.count) { // Actually, !services.count works in both cases, but ...
// A peripheral without any services at all.
- Q_ASSERT_X(delegate, "-discoverIncludedServices",
+ Q_ASSERT_X(delegate, Q_FUNC_INFO,
"invalid delegate (null)");
delegate->serviceDiscoveryFinished(ObjCStrongReference<NSArray>());
} else {
@@ -356,16 +356,13 @@ using namespace QT_NAMESPACE;
using namespace OSXBluetooth;
- Q_ASSERT_X(managerState != CentralManagerUpdating, "-discoverServiceDetails:",
- "invalid state");
- Q_ASSERT_X(!serviceUuid.isNull(), "-discoverServiceDetails:",
- "invalid service UUID");
- Q_ASSERT_X(peripheral, "-discoverServiceDetailsl:",
- "invalid peripheral (nil)");
+ Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(!serviceUuid.isNull(), Q_FUNC_INFO, "invalid service UUID");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
if (servicesToDiscoverDetails.contains(serviceUuid)) {
- qCWarning(QT_BT_OSX) << "-discoverServiceDetails: "
- "already discovering for " << serviceUuid;
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO <<"already discovering for "
+ << serviceUuid;
return true;
}
@@ -377,8 +374,8 @@ using namespace QT_NAMESPACE;
return true;
}
- qCWarning(QT_BT_OSX) << "-discoverServiceDetails:, invalid service - "
- "unknown uuid " << serviceUuid;
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unknown service uuid "
+ << serviceUuid;
return false;
}
@@ -387,17 +384,17 @@ using namespace QT_NAMESPACE;
{
// This method does not change 'managerState', we can
// have several 'detail discoveries' active.
- Q_ASSERT_X(service, "-readCharacteristics:", "invalid service (nil)");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
using namespace OSXBluetooth;
QT_BT_MAC_AUTORELEASEPOOL;
- Q_ASSERT_X(managerState != CentralManagerUpdating, "-readCharacteristics:",
+ Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO,
"invalid state");
- Q_ASSERT_X(manager, "-readCharacteristics:", "invalid manager (nil)");
- Q_ASSERT_X(peripheral, "-readCharacteristics:", "invalid peripheral (nil)");
- Q_ASSERT_X(delegate, "-readCharacteristics:", "invalid delegate (null)");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
if (!service.characteristics || !service.characteristics.count)
return [self serviceDetailsDiscoveryFinished:service];
@@ -416,16 +413,16 @@ using namespace QT_NAMESPACE;
{
// This method does not change 'managerState', we can have
// several discoveries active.
- Q_ASSERT_X(service, "-discoverDescriptors:", "invalid service (nil)");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
using namespace OSXBluetooth;
QT_BT_MAC_AUTORELEASEPOOL;
- Q_ASSERT_X(managerState != CentralManagerUpdating, "-discoverDescriptors",
- "invalid state");
- Q_ASSERT_X(manager, "-discoverDescriptors:", "invalid manager (nil)");
- Q_ASSERT_X(peripheral, "-discoverDescriptors:", "invalid peripheral (nil)");
+ Q_ASSERT_X(managerState != CentralManagerUpdating,
+ Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
if (!service.characteristics || !service.characteristics.count) {
[self serviceDetailsDiscoveryFinished:service];
@@ -463,10 +460,8 @@ using namespace QT_NAMESPACE;
- (void)serviceDetailsDiscoveryFinished:(CBService *)service
{
//
- Q_ASSERT_X(service, "-serviceDetailsDiscoveryFinished:",
- "invalid service (nil)");
- Q_ASSERT_X(delegate, "-serviceDetailsDiscoveryFinished:",
- "invalid delegate (null)");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
using namespace OSXBluetooth;
@@ -476,16 +471,13 @@ using namespace QT_NAMESPACE;
servicesToDiscoverDetails.removeAll(serviceUuid);
const NSUInteger nHandles = qt_countGATTEntries(service);
- Q_ASSERT_X(nHandles, "-serviceDetailsDiscoveryFinished:",
- "unexpected number of GATT entires");
+ Q_ASSERT_X(nHandles, Q_FUNC_INFO, "unexpected number of GATT entires");
const QLowEnergyHandle maxHandle = std::numeric_limits<QLowEnergyHandle>::max();
if (nHandles >= maxHandle || lastValidHandle > maxHandle - nHandles) {
// Well, that's unlikely :) But we must be sure.
- qCWarning(QT_BT_OSX) << "-serviceDetailsDiscoveryFinished:",
- "can not allocate more handles";
- // TODO: add more 'error' functions not to use fake handles (0)?
- delegate->error(serviceUuid, 0, QLowEnergyService::OperationError);
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "can not allocate more handles";
+ delegate->error(serviceUuid, QLowEnergyService::OperationError);
return;
}
@@ -530,6 +522,11 @@ using namespace QT_NAMESPACE;
newDesc.uuid = qt_uuid(d.UUID);
newDesc.value = qt_bytearray(static_cast<NSObject *>(d.value));
descList[lastValidHandle] = newDesc;
+ // Check, if it's client characteristic configuration descriptor:
+ if (newDesc.uuid == QBluetoothUuid::ClientCharacteristicConfiguration) {
+ if (newDesc.value.size() && (newDesc.value[0] & 3))
+ [peripheral setNotifyValue:YES forCharacteristic:c];
+ }
}
newChar.descriptorList = descList;
@@ -551,8 +548,7 @@ using namespace QT_NAMESPACE;
{
using namespace OSXBluetooth;
- Q_ASSERT_X(peripheral, "-performNextWriteRequest",
- "invalid peripheral (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
if (writePending || !writeQueue.size())
return;
@@ -561,59 +557,67 @@ using namespace QT_NAMESPACE;
if (request.isDescriptor) {
if (!descMap.contains(request.handle)) {
- qCWarning(QT_BT_OSX) << "-performNextWriteRequest, descriptor with "
- "handle: " << request.handle << " not found";
- [self performNextWriteRequest];
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: "
+ << request.handle << " not found";
+ return [self performNextWriteRequest];
}
- CBDescriptor *const d = descMap[request.handle];
+ CBDescriptor *const descriptor = 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 "
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed "
"to allocate an NSData object";
- [self performNextWriteRequest];
+ return [self performNextWriteRequest];
}
+ if (![self cacheWriteValue:request.value for:descriptor])
+ return [self performNextWriteRequest];
+
writePending = true;
- return [peripheral writeValue:data.data() forDescriptor:d];
+ return [peripheral writeValue:data.data() forDescriptor:descriptor];
} else {
- CBCharacteristic *const ch = charMap[request.handle];
- Q_ASSERT_X(ch, "-performNextWriteRequest", "invalid characteristic (nil)");
+ if (!charMap.contains(request.handle)) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic with "
+ "handle: " << request.handle << " not found";
+ return [self performNextWriteRequest];
+ }
+
+ CBCharacteristic *const characteristic = charMap[request.handle];
if (request.isClientConfiguration) {
- if (valuesToWrite.remove(request.handle)) {
- // It can happen if something went wrong - we
- // tried to set notification value and never received
- // a callback.
- qCDebug(QT_BT_OSX) << "-performNextWriteRequest:, "
- "valuesToWrite already contains "
- "a value for a given client configuration "
- "descriptor, replacing it";
- }
- // We save the original value to report it later ...
- valuesToWrite[request.handle] = request.value;
- const bool enable = request.value[0] & 3;
+ const QBluetoothUuid qtUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
+ CBDescriptor *const descriptor = [self descriptor:qtUuid forCharacteristic:characteristic];
+ Q_ASSERT_X(descriptor, Q_FUNC_INFO, "no client characteristic "
+ "configuration descriptor found");
+
+ if (![self cacheWriteValue:request.value for:descriptor])
+ return [self performNextWriteRequest];
+
+ bool enable = false;
+ if (request.value.size())
+ enable = request.value[0] & 3;
+
writePending = true;
- [peripheral setNotifyValue:enable forCharacteristic:ch];
+ [peripheral setNotifyValue:enable forCharacteristic:characteristic];
} else {
ObjCStrongReference<NSData> data(data_from_bytearray(request.value));
if (!data) {
// Even if qtData.size() == 0, we still need NSData object.
- qCWarning(QT_BT_OSX) << "-performNextWriteRequest, "
- "failed to allocate NSData object";
- [self performNextWriteRequest];
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSData object";
+ return [self performNextWriteRequest];
}
// TODO: check what happens if I'm using NSData with length 0.
if (request.withResponse) {
- NSLog(@"trying to write %@", data.data());
- NSLog(@"initial value: %@", ch.value);
+ if (![self cacheWriteValue:request.value for:characteristic])
+ return [self performNextWriteRequest];
+
writePending = true;
- [peripheral writeValue:data.data() forCharacteristic:ch
+ [peripheral writeValue:data.data() forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
} else {
- [peripheral writeValue:data.data() forCharacteristic:ch
+ [peripheral writeValue:data.data() forCharacteristic:characteristic
type:CBCharacteristicWriteWithoutResponse];
[self performNextWriteRequest];
}
@@ -624,12 +628,22 @@ using namespace QT_NAMESPACE;
- (bool)setNotifyValue:(const QByteArray &)value
forCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle
{
- Q_ASSERT_X(charHandle, "-setNotifyValue:forCharacteristic:",
- "invalid characteristic handle (0)");
+ Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
if (!charMap.contains(charHandle)) {
- qCWarning(QT_BT_OSX) << "-setNotifyValue:forCharacteristic:, "
- "unknown characteristic handle " << charHandle;
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO
+ << "unknown characteristic handle " << charHandle;
+ return false;
+ }
+
+ // At the moment we call setNotifyValue _only_ from 'writeDescriptor';
+ // from Qt's API POV it's a descriptor write oprtation and we must report
+ // it back, so check _now_ that we really have this descriptor.
+ const QBluetoothUuid qtUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
+ if (![self descriptor:qtUuid forCharacteristic:charMap[charHandle]]) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO
+ << "no client characteristic configuration found";
return false;
}
@@ -653,13 +667,12 @@ using namespace QT_NAMESPACE;
{
using namespace OSXBluetooth;
- Q_ASSERT_X(charHandle, "-write:charHandle:withResponse:", "invalid characteristic handle (0)");
+ Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)");
QT_BT_MAC_AUTORELEASEPOOL;
if (!charMap.contains(charHandle)) {
- qCWarning(QT_BT_OSX) << "-write:charHandle:withResponse:, "
- "characteristic: " << charHandle << " not found";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " << charHandle << " not found";
return false;
}
@@ -675,39 +688,17 @@ using namespace QT_NAMESPACE;
// write actually. If I have any problems with the order later,
// I'll use performSelector afterDelay with some delay.
return true;
-/*
- // Write without responce is not serialized - no way I can
- // know about the write operation success/failure - and
- // I will never perform the next write.
- 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)");
-
- ObjCStrongReference<NSData> data(data_from_bytearray(value));
- if (!data) {
- // Even if qtData.size() == 0, we still need NSData object.
- qCWarning(QT_BT_OSX) << "-write:charHandle:withResponse:, "
- "failed to allocate NSData object";
- return false;
- }
-
- // TODO: check what happens if I'm using NSData with length 0.
- [peripheral writeValue:data.data() forCharacteristic:ch
- type:CBCharacteristicWriteWithoutResponse];
-
- return true;*/
}
- (bool)write:(const QByteArray &)value descHandle:(QLowEnergyHandle)descHandle
{
using namespace OSXBluetooth;
- Q_ASSERT_X(descHandle, "-write:descHandle:",
- "invalid descriptor handle (0)");
+ Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
if (!descMap.contains(descHandle)) {
- qCWarning(QT_BT_OSX) << "-write:descHandle:, descriptor with "
- "handle: " << descHandle << " not found";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: "
+ << descHandle << " not found";
return false;
}
@@ -730,10 +721,8 @@ using namespace QT_NAMESPACE;
{
using namespace OSXBluetooth;
- Q_ASSERT_X(!qtUuid.isNull(), "-serviceForUUID:",
- "invalid uuid");
- Q_ASSERT_X(peripheral, "-serviceForUUID:",
- "invalid peripherla (nil)");
+ Q_ASSERT_X(!qtUuid.isNull(), Q_FUNC_INFO, "invalid uuid");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
ObjCStrongReference<NSMutableArray> toVisit([NSMutableArray arrayWithArray:peripheral.services], true);
ObjCStrongReference<NSMutableArray> toVisitNext([[NSMutableArray alloc] init], false);
@@ -763,14 +752,10 @@ using namespace QT_NAMESPACE;
- (CBCharacteristic *)nextCharacteristicForService:(CBService*)service
startingFrom:(CBCharacteristic *)characteristic
{
- Q_ASSERT_X(service, "-nextCharacteristicForService:startingFrom:",
- "invalid service (nil)");
- Q_ASSERT_X(characteristic, "-nextCharacteristicForService:startingFrom:",
- "invalid characteristic (nil)");
- Q_ASSERT_X(service.characteristics, "-nextCharacteristicForService:startingFrom:",
- "invalid service");
- Q_ASSERT_X(service.characteristics.count, "-nextCharacteristicForService:startingFrom:",
- "invalid service");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
+ Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)");
+ Q_ASSERT_X(service.characteristics, Q_FUNC_INFO, "invalid service");
+ Q_ASSERT_X(service.characteristics.count, Q_FUNC_INFO, "invalid service");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -790,8 +775,7 @@ using namespace QT_NAMESPACE;
}
}
- Q_ASSERT_X([cs objectAtIndex:0] == characteristic,
- "-nextCharacteristicForService:startingFrom:",
+ Q_ASSERT_X([cs objectAtIndex:0] == characteristic, Q_FUNC_INFO,
"characteristic was not found in service.characteristics");
return [cs objectAtIndex:1];
@@ -801,14 +785,10 @@ using namespace QT_NAMESPACE;
startingFrom:(CBCharacteristic *)characteristic
properties:(CBCharacteristicProperties)properties
{
- Q_ASSERT_X(service, "-nextCharacteristicForService:startingFrom:properties:",
- "invalid service (nil)");
- Q_ASSERT_X(characteristic, "-nextCharacteristicForService:startingFrom:properties:",
- "invalid characteristic (nil)");
- Q_ASSERT_X(service.characteristics, "-nextCharacteristicForService:startingFrom:properties:",
- "invalid service");
- Q_ASSERT_X(service.characteristics.count, "-nextCharacteristicForService:startingFrom:properties:",
- "invalid service");
+ Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
+ Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)");
+ Q_ASSERT_X(service.characteristics, Q_FUNC_INFO, "invalid service");
+ Q_ASSERT_X(service.characteristics.count, Q_FUNC_INFO, "invalid service");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -832,8 +812,7 @@ using namespace QT_NAMESPACE;
}
if (!index) {
- Q_ASSERT_X([cs objectAtIndex:0] == characteristic,
- "-nextCharacteristicForService:startingFrom:properties:",
+ Q_ASSERT_X([cs objectAtIndex:0] == characteristic, Q_FUNC_INFO,
"characteristic not found in service.characteristics");
index = 1;
}
@@ -850,16 +829,10 @@ using namespace QT_NAMESPACE;
- (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic
startingFrom:(CBDescriptor *)descriptor
{
- Q_ASSERT_X(characteristic, "-nextDescriptorForCharacteristic:startingFrom:",
- "invalid characteristic (nil)");
- Q_ASSERT_X(descriptor, "-nextDescriptorForCharacteristic:startingFrom:",
- "invalid descriptor (nil)");
- Q_ASSERT_X(characteristic.descriptors,
- "-nextDescriptorForCharacteristic:startingFrom:",
- "invalid characteristic");
- Q_ASSERT_X(characteristic.descriptors.count,
- "-nextDescriptorForCharacteristic:startingFrom:",
- "invalid characteristic");
+ Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)");
+ Q_ASSERT_X(descriptor, Q_FUNC_INFO, "invalid descriptor (nil)");
+ Q_ASSERT_X(characteristic.descriptors, Q_FUNC_INFO, "invalid characteristic");
+ Q_ASSERT_X(characteristic.descriptors.count, Q_FUNC_INFO, "invalid characteristic");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -876,8 +849,7 @@ using namespace QT_NAMESPACE;
}
}
- Q_ASSERT_X([ds objectAtIndex:0] == descriptor,
- "-nextDescriptorForCharacteristic:startingFrom:",
+ Q_ASSERT_X([ds objectAtIndex:0] == descriptor, Q_FUNC_INFO,
"descriptor was not found in characteristic.descriptors");
return [ds objectAtIndex:1];
@@ -905,6 +877,41 @@ using namespace QT_NAMESPACE;
return descriptor;
}
+- (bool)cacheWriteValue:(const QByteArray &)value for:(NSObject *)obj
+{
+ Q_ASSERT_X(obj, Q_FUNC_INFO, "invalid object (nil)");
+
+ if ([obj isKindOfClass:[CBCharacteristic class]]) {
+ CBCharacteristic *const ch = static_cast<CBCharacteristic *>(obj);
+ if (!charMap.key(ch)) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected "
+ "characteristic, no handle found";
+ return false;
+ }
+ } else if ([obj isKindOfClass:[CBDescriptor class]]) {
+ CBDescriptor *const d = static_cast<CBDescriptor *>(obj);
+ if (!descMap.key(d)) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected "
+ "descriptor, no handle found";
+ return false;
+ }
+ } else {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "invalid object, "
+ "characteristic or descriptor required";
+ return false;
+ }
+
+ if (valuesToWrite.contains(obj)) {
+ // It can be a result of some previous errors - for example,
+ // we never got a callback from a previous write.
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "already has a cached value for this "
+ "object, the value will be replaced";
+ }
+
+ valuesToWrite[obj] = value;
+ return true;
+}
+
- (void)reset
{
writePending = false;
@@ -923,7 +930,7 @@ using namespace QT_NAMESPACE;
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
- Q_ASSERT_X(delegate, "-centralManagerDidUpdateState:", "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
using namespace OSXBluetooth;
@@ -983,7 +990,7 @@ using namespace QT_NAMESPACE;
}
} else {
// We actually handled all known states, but .. Core Bluetooth can change?
- Q_ASSERT_X(0, "-centralManagerDidUpdateState:", "invalid centra's state");
+ Q_ASSERT_X(0, Q_FUNC_INFO, "invalid centra's state");
}
}
@@ -992,7 +999,7 @@ using namespace QT_NAMESPACE;
Q_UNUSED(central)
// This method is required for iOS before 7.0 and OS X below 10.9.
- Q_ASSERT_X(manager, "-centralManager:didRetrivePeripherals:", "invalid central manager (nil)");
+ Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)");
if (managerState != OSXBluetooth::CentralManagerConnecting) {
// Canceled by calling -disconnectFromDevice method.
@@ -1002,11 +1009,10 @@ using namespace QT_NAMESPACE;
managerState = OSXBluetooth::CentralManagerIdle;
if (!peripherals || peripherals.count != 1) {
- Q_ASSERT_X(delegate, "-centralManager:didRetrievePeripherals:",
+ Q_ASSERT_X(delegate, Q_FUNC_INFO,
"invalid delegate (null)");
- qCDebug(QT_BT_OSX) << "-centralManager:didRetrievePeripherals:, "
- "unexpected number of peripherals (!= 1)";
+ qCDebug(QT_BT_OSX) << Q_FUNC_INFO <<"unexpected number of peripherals (!= 1)";
delegate->error(QLowEnergyController::UnknownRemoteDeviceError);
} else {
@@ -1020,8 +1026,7 @@ using namespace QT_NAMESPACE;
Q_UNUSED(central)
Q_UNUSED(aPeripheral)
- Q_ASSERT_X(delegate, "-centralManager:didConnectPeripheral:",
- "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
if (managerState != OSXBluetooth::CentralManagerConnecting) {
// We called cancel but before disconnected, managed to connect?
@@ -1039,8 +1044,7 @@ using namespace QT_NAMESPACE;
Q_UNUSED(aPeripheral)
Q_UNUSED(error)
- Q_ASSERT_X(delegate, "-centralManager:didFailToConnectPeripheral:",
- "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
if (managerState != OSXBluetooth::CentralManagerConnecting) {
// Canceled already.
@@ -1058,16 +1062,14 @@ using namespace QT_NAMESPACE;
Q_UNUSED(central)
Q_UNUSED(aPeripheral)
- Q_ASSERT_X(delegate, "-centralManager:didDisconnectPeripheral:error:",
- "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
// Clear internal caches/data.
[self reset];
if (error && managerState == OSXBluetooth::CentralManagerDisconnecting) {
managerState = OSXBluetooth::CentralManagerIdle;
- qCWarning(QT_BT_OSX) << "-centralManager:didDisconnectPeripheral:, "
- "failed to disconnect";
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to disconnect";
// TODO: instead of 'unknown' - .. ?
delegate->error(QLowEnergyController::UnknownRemoteDeviceError);
} else {
@@ -1091,7 +1093,7 @@ using namespace QT_NAMESPACE;
if (error) {
// NSLog, not qCDebug/Warning - to print the error.
- NSLog(@"-peripheral:didDiscoverServices:, failed with error %@", error);
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
// TODO: better error mapping required.
delegate->error(QLowEnergyController::UnknownError);
} else {
@@ -1114,18 +1116,16 @@ using namespace QT_NAMESPACE;
QT_BT_MAC_AUTORELEASEPOOL;
- Q_ASSERT_X(delegate, "-peripheral:didDiscoverIncludedServicesForService:",
- "invalid delegate (null)");
- Q_ASSERT_X(peripheral, "-peripheral:didDiscoverIncludedServicesForService:",
- "invalid peripheral (nil)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
// TODO: asserts on other "pointers" ...
managerState = CentralManagerIdle;
if (error) {
// NSLog, not qCWarning/Critical - to log the actual NSError and service UUID.
- NSLog(@"-peripheral:didDiscoverIncludedServicesForService:, finished with error %@ for service %@",
- error, service.UUID);
+ NSLog(@"%s: finished with error %@ for service %@",
+ Q_FUNC_INFO, error, service.UUID);
} else if (service.includedServices && service.includedServices.count) {
// Now we have even more services to do included services discovery ...
if (!servicesToVisitNext)
@@ -1186,15 +1186,13 @@ using namespace QT_NAMESPACE;
using namespace OSXBluetooth;
Q_ASSERT_X(managerState != CentralManagerUpdating,
- "-peripheral:didDiscoverCharacteristicsForService:",
- "invalid state");
- Q_ASSERT_X(delegate, "-peripheral:didDiscoverCharacteristicsForService:",
+ Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO,
"invalid delegate (null)");
if (error) {
// NSLog to show the actual NSError (can contain something interesting).
- NSLog(@"-peripheral:didDiscoverCharacteristicsForService:error, failed with error: %@",
- error);
+ NSLog(@"%s failed with error: %@", Q_FUNC_INFO, error);
// We did not discover any characteristics and can not discover descriptors,
// inform our delegate (it will set a service state also).
delegate->error(qt_uuid(service.UUID), QLowEnergyController::UnknownError);
@@ -1210,11 +1208,8 @@ using namespace QT_NAMESPACE;
using namespace OSXBluetooth;
- Q_ASSERT_X(managerState != CentralManagerUpdating,
- "-peripheral:didUpdateValueForCharacteristic:error:",
- "invalid state");
- Q_ASSERT_X(peripheral, "-peripheral:didUpdateValueForCharacteristic:error:",
- "invalid peripheral (nil)");
+ Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
QT_BT_MAC_AUTORELEASEPOOL;
// First, let's check if we're discovering a service details now.
@@ -1224,9 +1219,7 @@ using namespace QT_NAMESPACE;
if (error) {
// Use NSLog, not qCDebug/qCWarning to log the actual error.
- NSLog(@"-peripheral:didUpdateValueForCharacteristic:error:, failed with error %@",
- error);
-
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
if (!isDetailsDiscovery) {
// TODO: this can be something else in a future (if needed at all).
return;
@@ -1250,13 +1243,12 @@ using namespace QT_NAMESPACE;
// updated values ...
// TODO: this must be properly tested.
if (!chHandle) {
- qCCritical(QT_BT_OSX) << "-peripheral:didUpdateValueForCharacteristic:error:, "
- "unexpected update notification, no characteristic handle found";
+ qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "unexpected update notification, "
+ "no characteristic handle found";
return;
}
- Q_ASSERT_X(delegate, "-peripheral:didUpdateValueForCharacteristic:error:",
- "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
delegate->characteristicUpdateNotification(chHandle,
qt_bytearray(characteristic.value));
}
@@ -1276,8 +1268,7 @@ using namespace QT_NAMESPACE;
if (error) {
// Log the error using NSLog:
- NSLog(@"-peripheral:didDiscoverDescriptorsForCharacteristic:error:, failed with error %@",
- error);
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
// Probably, we can continue though ...
}
@@ -1296,8 +1287,7 @@ using namespace QT_NAMESPACE;
{
Q_UNUSED(aPeripheral)
- Q_ASSERT_X(peripheral, "-peripheral:didUpdateValueForDescriptor:error:",
- "invalid peripheral (nil)");
+ Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -1309,8 +1299,7 @@ using namespace QT_NAMESPACE;
if (error) {
// NSLog to log the actual error ...
- NSLog(@"-peripheral:didUpdateValueForDescriptor:error:, failed with error %@",
- error);
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
if (!isDetailsDiscovery) {
// TODO: probably will be required in a future.
return;
@@ -1365,24 +1354,26 @@ using namespace QT_NAMESPACE;
writePending = false;
- Q_ASSERT_X(delegate, "-peripheral:didWriteValueForCharacteristic:error",
- "invalid delegate (null)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
+
+
+ // Error or not, but the cached value has to be deleted ...
+ const QByteArray valueToReport(valuesToWrite.value(characteristic, QByteArray()));
+ if (!valuesToWrite.remove(characteristic)) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no updated value found"
+ " for characteristic";
+ }
if (error) {
// Use NSLog to log the actual error:
- NSLog(@"-peripheral:didWriteValueForCharacteristic:error:, failed with error: %@",
- error);
- // TODO: no char handle at the moment, have to change to char index instead
- // and calculate the right handle in the LE controller.
- delegate->error(qt_uuid(characteristic.service.UUID), 0,
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
+ delegate->error(qt_uuid(characteristic.service.UUID),
QLowEnergyService::CharacteristicWriteError);
} else {
// Keys are unique.
const QLowEnergyHandle cHandle = charMap.key(characteristic);
- Q_ASSERT_X(cHandle, "-peripheral:didWriteValueForCharacteristic:error",
- "invalid handle, not found in the characteristics map");
- NSLog(@"characteristic written, the value is %@", characteristic.value);
- delegate->characteristicWriteNotification(cHandle, qt_bytearray(characteristic.value));
+ Q_ASSERT_X(cHandle, Q_FUNC_INFO, "invalid handle, not found in the characteristics map");
+ delegate->characteristicWriteNotification(cHandle, valueToReport);
}
[self performNextWriteRequest];
@@ -1394,6 +1385,8 @@ using namespace QT_NAMESPACE;
{
Q_UNUSED(aPeripheral)
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
+
using namespace OSXBluetooth;
QT_BT_MAC_AUTORELEASEPOOL;
@@ -1402,21 +1395,21 @@ using namespace QT_NAMESPACE;
using namespace OSXBluetooth;
+ // Error or not, a value (if any) must be removed.
+ const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray()));
+ if (!valuesToWrite.remove(descriptor))
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no updated value found";
+
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,
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
+ delegate->error(qt_uuid(descriptor.characteristic.service.UUID),
QLowEnergyService::DescriptorWriteError);
} else {
- // We know that keys are unique, so we 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 the descriptors map");
- delegate->descriptorWriteNotification(dHandle, qt_bytearray(static_cast<NSObject *>(descriptor.value)));
+ Q_ASSERT_X(dHandle, Q_FUNC_INFO,
+ "descriptor not found in the descriptors map");
+ delegate->descriptorWriteNotification(dHandle, valueToReport);
}
[self performNextWriteRequest];
@@ -1434,39 +1427,30 @@ using namespace QT_NAMESPACE;
writePending = false;
- Q_ASSERT_X(delegate, "-peripheral:didUpdateNotificationStateForCharacteristic:",
- "invalid delegate (nil)");
+ Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (nil)");
const QBluetoothUuid qtUuid(QBluetoothUuid::ClientCharacteristicConfiguration);
CBDescriptor *const descriptor = [self descriptor:qtUuid forCharacteristic:characteristic];
- const QLowEnergyHandle dHandle = descMap.key(descriptor);// 0 if descriptor is nil or unknown.
- const QByteArray valueToReport(valuesToWrite.value(dHandle, QByteArray()));
-
- if (!valuesToWrite.remove(dHandle)) {
- // In future it can be a special case: we can, in principle,
- // set notify value on a characteristic without 'writeDescriptor'.
- // It can also be some error. Right now we report it as error, can change.
- qCWarning(QT_BT_OSX) << "-peripheral:didUpdateNotificationStateForCharacteristic:, "
- "setNotifyValue called, but no client characteristic descriptor "
- "found or no writeDescriptor call";
- }
+ const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray()));
+ const int nRemoved = valuesToWrite.remove(descriptor);
if (error) {
// NSLog to log the actual NSError:
- NSLog(@"-peripheral:didUpdateNotificationStateForCharacteristic:, failed with error %@",
- error);
- delegate->error(qt_uuid(characteristic.service.UUID), 0,
+ NSLog(@"%s failed with error %@", Q_FUNC_INFO, error);
+ delegate->error(qt_uuid(characteristic.service.UUID),
// In Qt's API it's a descriptor write actually.
QLowEnergyService::DescriptorWriteError);
} else {
- if (!valueToReport.isNull()) {
+ if (nRemoved) {
+ const QLowEnergyHandle dHandle = descMap.key(descriptor);
delegate->descriptorWriteNotification(dHandle, valueToReport);
} else {
- // TODO: can we in future have another way to set notify value without writeDescriptor?
- qCWarning(QT_BT_OSX) << "-peripheral:didUpdateNotificationStateForCharacteristic:, "
- "notification value set to " << int(characteristic.isNotifying)
+ /*
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << ": notification value set to "
+ << int(characteristic.isNotifying)
<< " but no client characteristic configuration descriptor found"
- "or no previous writeDescriptor request found";
+ " or no previous writeDescriptor request found";
+ */
}
}