Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
btl2capchannel.mm
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qbluetoothaddress.h"
5#include "btl2capchannel_p.h"
6#include "btdelegates_p.h"
7#include "btutility_p.h"
8
9#include <QtCore/qloggingcategory.h>
10#include <QtCore/qdebug.h>
11
13
14@implementation DarwinBTL2CAPChannel
15{
16 QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate;
17 IOBluetoothDevice *device;
18 IOBluetoothL2CAPChannel *channel;
20}
21
22- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate
23{
24 Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
25
26 if (self = [super init]) {
27 delegate = aDelegate;
28 device = nil;
29 channel = nil;
30 connected = false;
31 }
32
33 return self;
34}
35
36- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate
37 channel:(IOBluetoothL2CAPChannel *)aChannel
38{
39 // This type of channel does not require connect, it's created with
40 // already open channel.
41 Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)");
42 Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)");
43
44 if (self = [super init]) {
45 delegate = aDelegate;
46 channel = [aChannel retain];
47 [channel setDelegate:self];
48 device = [channel.device retain];
49 connected = true;
50 }
51
52 return self;
53}
54
55- (void)dealloc
56{
57 // TODO: test if this implementation works at all!
58 if (channel) {
59 [channel setDelegate:nil];
60 // From Apple's docs:
61 // "This method may only be called by the client that opened the channel
62 // in the first place. In the future asynchronous and synchronous versions
63 // will be provided that let the client know when the close process has been finished."
64 [channel closeChannel];
65 [channel release];
66 }
67
68 [device release];
69
70 [super dealloc];
71}
72
73- (IOReturn)connectAsyncToDevice:(const QBluetoothAddress &)address
74 withPSM:(BluetoothL2CAPChannelID)psm
75{
76 if (address.isNull()) {
77 qCCritical(QT_BT_DARWIN) << "invalid peer address";
78 return kIOReturnNoDevice;
79 }
80
81 // Can never be called twice.
82 if (connected || device || channel) {
83 qCCritical(QT_BT_DARWIN) << "connection is already active";
84 return kIOReturnStillOpen;
85 }
86
88
89 const BluetoothDeviceAddress iobtAddress = DarwinBluetooth::iobluetooth_address(address);
90 device = [IOBluetoothDevice deviceWithAddress:&iobtAddress];
91 if (!device) {
92 qCCritical(QT_BT_DARWIN) << "failed to create a device";
93 return kIOReturnNoDevice;
94 }
95
96 const IOReturn status = [device openL2CAPChannelAsync:&channel withPSM:psm delegate:self];
97 if (status != kIOReturnSuccess) {
98 qCCritical(QT_BT_DARWIN) << "failed to open L2CAP channel";
99 // device is still autoreleased.
100 device = nil;
101 return status;
102 }
103
104 [channel retain];// What if we're closed already?
105 [device retain];
106
107 return kIOReturnSuccess;
108}
109
110// IOBluetoothL2CAPChannelDelegate:
111
112- (void)l2capChannelData:(IOBluetoothL2CAPChannel*)l2capChannel
113 data:(void *)dataPointer length:(size_t)dataLength
114{
115 Q_UNUSED(l2capChannel);
116
117 Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
118
119 if (dataPointer && dataLength)
120 delegate->readChannelData(dataPointer, dataLength);
121}
122
123- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*)
124 l2capChannel status:(IOReturn)error
125{
126 Q_UNUSED(l2capChannel);
127
128 Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
129
130 if (error != kIOReturnSuccess) {
131 delegate->setChannelError(error);
132 } else {
133 connected = true;
134 delegate->channelOpenComplete();
135 }
136}
137
138- (void)l2capChannelClosed:(IOBluetoothL2CAPChannel*)l2capChannel
139{
140 Q_UNUSED(l2capChannel);
141
142 Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
143 delegate->channelClosed();
144 connected = false;
145}
146
147- (void)l2capChannelReconfigured:(IOBluetoothL2CAPChannel*)l2capChannel
148{
149 Q_UNUSED(l2capChannel);
150}
151
152- (void)l2capChannelWriteComplete:(IOBluetoothL2CAPChannel*)l2capChannel
153 refcon:(void*)refcon status:(IOReturn)error
154{
155 Q_UNUSED(l2capChannel);
156 Q_UNUSED(refcon);
157
158 Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
159
160 if (error != kIOReturnSuccess)
161 delegate->setChannelError(error);
162 else
163 delegate->writeComplete();
164}
165
166- (void)l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*)l2capChannel
167{
168 Q_UNUSED(l2capChannel);
169}
170
171// Aux. methods.
172- (BluetoothL2CAPPSM)getPSM
173{
174 if (channel)
175 return channel.PSM;
176
177 return 0;
178}
179
180- (BluetoothDeviceAddress)peerAddress
181{
182 const BluetoothDeviceAddress *const addr = device ? [device getAddress]
183 : nullptr;
184 if (addr)
185 return *addr;
186
187 return BluetoothDeviceAddress();
188}
189
190- (NSString *)peerName
191{
192 if (device)
193 return device.name;
194
195 return nil;
196}
197
198- (bool)isConnected
199{
200 return connected;
201}
202
203- (IOReturn) writeSync:(void*)data length:(UInt16)length
204{
205 Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
206 Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size");
207 Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel");
208
209 return [channel writeSync:data length:length];
210}
211
212- (IOReturn) writeAsync:(void*)data length:(UInt16)length
213{
214 Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
215 Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size");
216 Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel");
217
218 return [channel writeAsync:data length:length refcon:nullptr];
219}
220
221
222@end
IOBluetoothL2CAPChannel * channel
bool connected
IOBluetoothDevice * device
#define QT_BT_MAC_AUTORELEASEPOOL
Definition btutility_p.h:78
\inmodule QtBluetooth
BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &qAddress)
Definition btutility.mm:65
QString self
Definition language.cpp:58
#define Q_FUNC_INFO
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
#define qCCritical(category,...)
GLenum GLuint GLenum GLsizei length
GLenum GLuint id
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum const void * addr
GLuint GLuint64EXT address
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_UNUSED(x)