12#include <QtCore/qstring.h>
13#include <QtCore/qdebug.h>
14#include <QtCore/qlist.h>
28 return CBCharacteristicProperties(
int(
data.properties()));
36 CBAttributePermissions cbFlags = {};
38 if ((
props & QLEC::Write) || (
props & QLEC::WriteNoResponse)
39 || (
props & QLEC::WriteSigned)) {
40 cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteable);
43 if (
props & QLEC::Read)
44 cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadable);
47 cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteEncryptionRequired);
50 cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadEncryptionRequired);
60 permissions:cb_permissions(
data)],
77 qCWarning(QT_BT_DARWIN) <<
"unsupported descriptor" <<
data.uuid();
88 value.reset(asQString.toNSString(), RetainPolicy::doInitialRetain);
91 value.reset(nsData.data(), RetainPolicy::doInitialRetain);
102 const auto maxu32 = std::numeric_limits<quint32>::max();
105 for (
const auto &
ch :
data.characteristics()) {
106 if (maxu32 - 2 < nEntries)
109 if (maxu32 -
ch.descriptors().size() < nEntries)
111 nEntries +=
ch.descriptors().size();
119 if (
data.minimumValueLength() >
data.maximumValueLength()
120 ||
data.minimumValueLength() < 0) {
124 return data.value().size() <=
data.maximumValueLength();
129@interface DarwinBTPeripheralManager (PrivateAPI)
131- (
void)addConnectedCentral:(CBCentral *)central;
135 to:(CBMutableService *)cbService
139 to:(CBMutableService *)cbService
142- (CBATTError)validateWriteRequest:(CBATTRequest *)request;
155 std::vector<ObjCStrongReference<CBMutableService>>
services;
199 if (!nEntries || nEntries > std::numeric_limits<QLowEnergyHandle>::max() -
lastHandle) {
200 qCCritical(QT_BT_DARWIN) <<
"addService: not enough handles";
210 newCBService([[CBMutableService alloc] initWithType:cbUUID primary:primary],
214 qCCritical(QT_BT_DARWIN) <<
"addService: failed to create CBMutableService";
220 newQtService->uuid =
data.uuid();
221 newQtService->type = primary ? QLES::PrimaryService : QLES::IncludedService;
225 [
self addIncludedServices:data to:newCBService qtService:newQtService.data()];
226 [
self addCharacteristicsAndDescriptors:data to:newCBService qtService:newQtService.data()];
263 qCWarning(QT_BT_DARWIN) <<
"setParameters: failed to allocate "
264 "NSMutableDictonary (advertisementData)";
268 auto localName = scanResponse.
localName();
269 if (!localName.size())
270 localName =
data.localName();
272 if (localName.size()) {
273 [advertisementData setObject:localName.toNSString()
274 forKey:CBAdvertisementDataLocalNameKey];
283 qCWarning(QT_BT_DARWIN) <<
"setParameters: failed to allocate "
284 "NSMutableArray (services uuids)";
290 const auto cbUUID =
cb_uuid(qtUUID);
292 [uuids addObject:cbUUID];
295 for (
const auto &qtUUID : scanResponse.
services()) {
296 const auto cbUUID =
cb_uuid(qtUUID);
298 [uuids addObject:cbUUID];
302 [advertisementData setObject:uuids
303 forKey:CBAdvertisementDataServiceUUIDsKey];
307- (
void)startAdvertising
311 [manager setDelegate:nil];
312 manager.reset([[CBPeripheralManager alloc] initWithDelegate:
self
317- (
void)stopAdvertising
319 [manager stopAdvertising];
332 [manager stopAdvertising];
333 [manager setDelegate:nil];
360 qCWarning(QT_BT_DARWIN) <<
"ignoring value of invalid length" <<
value.size();
373 [
self sendUpdateRequests];
376- (
void) addServicesToPeripheral
381 [manager addService:services[nextServiceToAdd++]];
386- (
void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
388#pragma clang diagnostic push
389#pragma clang diagnostic ignored "-Wunguarded-availability-new"
394 if (
peripheral.state == CBManagerStatePoweredOn) {
397 [manager removeAllServices];
401 [
self addServicesToPeripheral];
426 if (
peripheral.state == CBManagerStateUnsupported) {
429 }
else if (
peripheral.state == CBManagerStateUnauthorized) {
434#pragma clang diagnostic pop
437- (
void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
438 error:(NSError *)error
444 NSLog(
@"failed to start advertising, error: %@",
error);
450- (
void)peripheralManager:(CBPeripheralManager *)peripheral
451 didAddService:(CBService *)service error:(NSError *)error
459 NSLog(
@"failed to add a service, error: %@",
error);
469 [manager startAdvertising:[advertisementData count] ? advertisementData.get() : nil];
471 [
self addServicesToPeripheral];
475- (
void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central
476 didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
483 [
self addConnectedCentral:central];
489- (
void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central
490 didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
498 if (![
static_cast<CBMutableCharacteristic*
>(characteristic).subscribedCentrals
count]
503- (
void)peripheralManager:(CBPeripheralManager *)peripheral
504 didReceiveReadRequest:(CBATTRequest *)request
513 qCWarning(QT_BT_DARWIN) <<
"invalid read request, unknown characteristic";
514 [manager respondToRequest:request withResult:CBATTErrorInvalidHandle];
520 qCWarning(QT_BT_DARWIN) <<
"invalid offset in a read request";
521 [manager respondToRequest:request withResult:CBATTErrorInvalidOffset];
525 [
self addConnectedCentral:request.central];
527 NSData *dataToSend = nil;
531 dataToSend = [value subdataWithRange:
532 NSMakeRange(request.offset, [value
length] - request.offset)];
536 [manager respondToRequest:request withResult:CBATTErrorSuccess];
541 withWriteRequest:(CBATTRequest *)request
554 [value increaseLengthBy:request.offset + request.value.length - value.length];
556 [value replaceBytesInRange:NSMakeRange(request.offset, request.value.length)
557 withBytes:request.value.bytes];
560- (
void)peripheralManager:(CBPeripheralManager *)peripheral
561 didReceiveWriteRequests:(NSArray *)requests
576 const auto status = [
self validateWriteRequest:request];
577 if (status != CBATTErrorSuccess) {
578 [manager respondToRequest:[requests objectAtIndex:0]
584 std::map<QLowEnergyHandle, NSUInteger> updated;
588 [
self addConnectedCentral:request.central];
590 const auto prevLen = updated[charHandle];
591 updated[charHandle] = std::max(
request.offset +
request.value.length,
593 [
self writeValueForCharacteristic:charHandle withWriteRequest:request];
596 for (
const auto &pair : updated) {
597 const auto handle = pair.first;
599 value.length = pair.second;
607 [manager respondToRequest:[requests objectAtIndex:0]
608 withResult:CBATTErrorSuccess];
611 [
self sendUpdateRequests];
614- (
void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
621 [
self sendUpdateRequests];
624- (
void)sendUpdateRequests
632 qCWarning(QT_BT_DARWIN) <<
"value of length" << [request.value length]
633 <<
"will possibly be truncated to"
636 const BOOL
res = [manager updateValue:request.value
637 forCharacteristic:static_cast<CBMutableCharacteristic *>(charMap[request.charHandle])
638 onSubscribedCentrals:nil];
651- (
void)addConnectedCentral:(CBCentral *)central
662 central.maximumUpdateValueLength);
682 to:(CBMutableService *)cbService
693 qCWarning(QT_BT_DARWIN) <<
"addIncludedSerivces: failed "
694 "to allocate NSMutableArray";
698 for (
auto includedService :
data.includedServices()) {
699 if (CBService *cbs = [self findIncludedService:includedService->serviceUuid()]) {
700 [included addObject:cbs];
704 qCWarning(QT_BT_DARWIN) <<
"can not use" << includedService->serviceUuid()
705 <<
"as included, it has to be added first";
709 if ([included
count])
710 cbService.includedServices = included;
714 to:(CBMutableService *)cbService
725 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
726 "failed to allocate NSMutableArray "
731 for (
const auto &
ch :
data.characteristics()) {
732 if (!qt_validate_value_range(
ch)) {
733 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
734 "invalid value size/min-max length";
740 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
741 "value exceeds the maximal permitted "
744 <<
"octets) on the platform";
749 const auto cbChar(create_characteristic(
ch));
751 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
752 "failed to allocate a characteristic";
758 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
759 "addService: failed to allocate NSData (char value)";
763 [newCBChars addObject:cbChar];
773 charData.
uuid =
ch.uuid();
780 qCWarning(QT_BT_DARWIN) <<
"addCharacteristicsAndDescritptors: "
781 "failed to allocate NSMutableArray "
786 for (
const auto &
desc :
ch.descriptors()) {
788 const auto cbDesc(create_descriptor(
desc));
793 [newCBDescs addObject:cbDesc];
802 if ([newCBDescs
count])
803 cbChar.data().descriptors = newCBDescs.get();
808 if ([newCBChars
count])
809 cbService.characteristics = newCBChars.get();
812- (CBATTError)validateWriteRequest:(CBATTRequest *)request
820 return CBATTErrorInvalidHandle;
826 return CBATTErrorInvalidOffset;
829 return CBATTErrorInvalidAttributeValueLength;
831 return CBATTErrorSuccess;
DarwinBluetooth::CharHash charMap
CBPeripheral * peripheral
DarwinBluetooth::RequestQueue requests
DarwinBluetooth::LECBManagerNotifier * notifier
std::map< QBluetoothUuid, CBService * > serviceIndex
decltype(services.size()) nOfFailedAds
QMap< QLowEnergyHandle, ValueRange > valueRanges
ObjCScopedPointer< NSMutableDictionary > advertisementData
NSUInteger maxNotificationValueLength
GenericLEMap< CBCharacteristic * > charMap
GenericLEMap< ObjCStrongReference< NSMutableData > > charValues
QLowEnergyHandle lastHandle
decltype(services.size()) nextServiceToAdd
std::deque< UpdateRequest > updateQueue
LECBManagerNotifier * notifier
std::vector< ObjCStrongReference< CBMutableService > > services
QPair< NSUInteger, NSUInteger > ValueRange
#define QT_BT_MAC_AUTORELEASEPOOL
void characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value)
void characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value)
void notificationEnabled(QLowEnergyHandle charHandle, bool enabled)
void CBManagerError(QBluetoothDeviceDiscoveryAgent::Error error)
@ CharacteristicPresentationFormat
@ CharacteristicUserDescription
qsizetype length() const noexcept
Same as size().
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Key key(const T &value) const noexcept
bool isEmpty() const noexcept
qsizetype count() const noexcept
The QLowEnergyAdvertisingData class represents the data to be broadcast during Bluetooth Low Energy a...
QString localName() const
Returns the name of the local device that is to be advertised.
QList< QBluetoothUuid > services() const
Returns the list of service UUIDs to be advertised.
The QLowEnergyAdvertisingParameters class represents the parameters used for Bluetooth Low Energy adv...
The QLowEnergyCharacteristicData class is used to set up GATT service data. \inmodule QtBluetooth.
QLowEnergyCharacteristic::PropertyTypes properties() const
Returns the properties of the characteristic.
@ MissingPermissionsError
The QLowEnergyDescriptorData class is used to create GATT service data. \inmodule QtBluetooth.
The QLowEnergyServiceData class is used to set up GATT service data. \inmodule QtBluetooth.
QList< QBluetoothUuid > includedServices
QHash< QLowEnergyHandle, CharData > characteristicList
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void deleteLater()
\threadsafe
static QSharedPointer create(Args &&...arguments)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QSet< QString >::iterator it
ObjCStrongReference< CBUUID > cb_uuid(const QBluetoothUuid &qtUuid)
ObjCStrongReference< NSMutableData > mutable_data_from_bytearray(const QByteArray &qtData)
QByteArray qt_bytearray(NSData *data)
NSUInteger qt_countGATTEntries(CBService *service)
ObjCStrongReference< NSData > data_from_bytearray(const QByteArray &qtData)
dispatch_queue_t qt_LE_queue()
static jboolean copy(JNIEnv *, jobject)
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCCritical(category,...)
#define qCWarning(category,...)
GLuint64 GLenum void * handle
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLuint GLsizei const GLenum * props
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
gzip write("uncompressed data")
QNetworkAccessManager manager
QNetworkRequest request(url)
QHash< QLowEnergyHandle, DescData > descriptorList
QLowEnergyHandle valueHandle
QLowEnergyCharacteristic::PropertyTypes properties