swbt-python 0.5.2__py3-none-any.whl → 0.5.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swbt/transport/_bumble_acl.py +9 -25
- swbt/transport/_bumble_key_store.py +2 -28
- swbt/transport/_bumble_lifecycle.py +28 -54
- swbt/transport/_pairing_profile.py +7 -11
- swbt/transport/bumble.py +8 -7
- {swbt_python-0.5.2.dist-info → swbt_python-0.5.3.dist-info}/METADATA +2 -2
- {swbt_python-0.5.2.dist-info → swbt_python-0.5.3.dist-info}/RECORD +10 -10
- {swbt_python-0.5.2.dist-info → swbt_python-0.5.3.dist-info}/WHEEL +0 -0
- {swbt_python-0.5.2.dist-info → swbt_python-0.5.3.dist-info}/entry_points.txt +0 -0
- {swbt_python-0.5.2.dist-info → swbt_python-0.5.3.dist-info}/licenses/LICENSE +0 -0
swbt/transport/_bumble_acl.py
CHANGED
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
"""ACL queue drain helper for Bumble HID transport."""
|
|
1
|
+
"""ACL queue drain helper for the pinned Bumble HID transport."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from typing import Any, cast
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
async def drain_bumble_acl_queue(l2cap_channel: object) -> None:
|
|
7
|
-
"""Wait
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
acl_packet_queue =
|
|
11
|
-
if acl_packet_queue is None
|
|
12
|
-
device = getattr(connection, "device", None)
|
|
13
|
-
host = getattr(device, "host", None)
|
|
14
|
-
get_data_packet_queue = getattr(host, "get_data_packet_queue", None)
|
|
15
|
-
if callable(get_data_packet_queue):
|
|
16
|
-
acl_packet_queue = get_data_packet_queue(connection_handle)
|
|
17
|
-
drain = getattr(acl_packet_queue, "drain", None)
|
|
18
|
-
if not isinstance(connection_handle, int) or not callable(drain):
|
|
7
|
+
"""Wait for the pinned Bumble connection's pending ACL packets to complete."""
|
|
8
|
+
channel = cast("Any", l2cap_channel)
|
|
9
|
+
connection = channel.connection
|
|
10
|
+
acl_packet_queue = connection.device.host.get_data_packet_queue(connection.handle)
|
|
11
|
+
if acl_packet_queue is None:
|
|
19
12
|
return
|
|
20
13
|
try:
|
|
21
|
-
|
|
22
|
-
while True:
|
|
23
|
-
pending = getattr(acl_packet_queue, "pending", 0)
|
|
24
|
-
if not isinstance(pending, int) or pending <= 0 or pending == last_pending:
|
|
25
|
-
return
|
|
26
|
-
last_pending = pending
|
|
27
|
-
drain_result = drain(connection_handle)
|
|
28
|
-
if isinstance(drain_result, Awaitable):
|
|
29
|
-
await drain_result
|
|
30
|
-
continue
|
|
31
|
-
return
|
|
14
|
+
await acl_packet_queue.drain(connection.handle)
|
|
32
15
|
except ValueError:
|
|
16
|
+
# Bumble raises when the queue has no state for a channel that was already drained.
|
|
33
17
|
return
|
|
@@ -9,11 +9,9 @@ from swbt.diagnostics import DiagnosticsRecorder
|
|
|
9
9
|
from swbt.errors import InvalidKeyStoreError
|
|
10
10
|
from swbt.transport._pairing_profile import KeyStoreNamespaces, PairingProfile
|
|
11
11
|
|
|
12
|
-
PREVIOUS_NAMESPACE_PREFIX = "swbt.previous::"
|
|
13
|
-
|
|
14
12
|
|
|
15
13
|
class _PairingProfileKeyStore:
|
|
16
|
-
"""Bumble-compatible profile key store
|
|
14
|
+
"""Bumble-compatible profile key store for the current namespace."""
|
|
17
15
|
|
|
18
16
|
def __init__(
|
|
19
17
|
self,
|
|
@@ -24,7 +22,6 @@ class _PairingProfileKeyStore:
|
|
|
24
22
|
self._profile_path = Path(profile_path)
|
|
25
23
|
self._namespace = namespace if isinstance(namespace, str) else None
|
|
26
24
|
self._namespace_resolver = None if isinstance(namespace, str) else namespace
|
|
27
|
-
self.last_update_previous_saved = False
|
|
28
25
|
|
|
29
26
|
def _resolve_namespace(self) -> str:
|
|
30
27
|
namespace = (
|
|
@@ -36,16 +33,9 @@ class _PairingProfileKeyStore:
|
|
|
36
33
|
return namespace
|
|
37
34
|
|
|
38
35
|
async def update(self, name: str, keys: object) -> None:
|
|
39
|
-
"""
|
|
36
|
+
"""Replace the current namespace with one peer's keys."""
|
|
40
37
|
current_store = self._current_store()
|
|
41
38
|
db, current_key_map = await current_store.load()
|
|
42
|
-
previous_namespace = self._previous_namespace(current_store)
|
|
43
|
-
previous_key_map = copy.deepcopy(current_key_map)
|
|
44
|
-
self.last_update_previous_saved = bool(previous_key_map)
|
|
45
|
-
if previous_key_map:
|
|
46
|
-
db[previous_namespace] = previous_key_map
|
|
47
|
-
else:
|
|
48
|
-
db.pop(previous_namespace, None)
|
|
49
39
|
current_key_map.clear()
|
|
50
40
|
current_key_map[name] = cast("Any", keys).to_dict()
|
|
51
41
|
await current_store.save(db)
|
|
@@ -84,10 +74,6 @@ class _PairingProfileKeyStore:
|
|
|
84
74
|
adapter_default=self._namespace_resolver is not None,
|
|
85
75
|
)
|
|
86
76
|
|
|
87
|
-
@staticmethod
|
|
88
|
-
def _previous_namespace(current_store: "_PairingProfileNamespaceStore") -> str:
|
|
89
|
-
return f"{PREVIOUS_NAMESPACE_PREFIX}{current_store.namespace}"
|
|
90
|
-
|
|
91
77
|
|
|
92
78
|
class _PairingProfileNamespaceStore:
|
|
93
79
|
"""JsonKeyStore-compatible view over one profile namespace map."""
|
|
@@ -169,20 +155,16 @@ class _DiagnosticKeyStore:
|
|
|
169
155
|
try:
|
|
170
156
|
await cast("Any", self._key_store).update(name, keys)
|
|
171
157
|
except Exception as error:
|
|
172
|
-
fields = self._generation_fields()
|
|
173
158
|
self._diagnostics.record_event(
|
|
174
159
|
"key_store_update",
|
|
175
|
-
**fields,
|
|
176
160
|
error_type=type(error).__name__,
|
|
177
161
|
message=str(error),
|
|
178
162
|
peer_address=name,
|
|
179
163
|
status="failed",
|
|
180
164
|
)
|
|
181
165
|
raise
|
|
182
|
-
fields = self._generation_fields()
|
|
183
166
|
self._diagnostics.record_event(
|
|
184
167
|
"key_store_update",
|
|
185
|
-
**fields,
|
|
186
168
|
peer_address=name,
|
|
187
169
|
status="succeeded",
|
|
188
170
|
)
|
|
@@ -209,11 +191,3 @@ class _DiagnosticKeyStore:
|
|
|
209
191
|
|
|
210
192
|
def __getattr__(self, name: str) -> object:
|
|
211
193
|
return getattr(self._key_store, name)
|
|
212
|
-
|
|
213
|
-
def _generation_fields(self) -> dict[str, object]:
|
|
214
|
-
if not isinstance(self._key_store, _PairingProfileKeyStore):
|
|
215
|
-
return {}
|
|
216
|
-
return {
|
|
217
|
-
"generation": "current",
|
|
218
|
-
"previous_saved": self._key_store.last_update_previous_saved,
|
|
219
|
-
}
|
|
@@ -25,20 +25,19 @@ class ConnectionDiagnostics:
|
|
|
25
25
|
self._record_event = record_event
|
|
26
26
|
|
|
27
27
|
def register(self, connection: object) -> None:
|
|
28
|
-
"""Register all
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
28
|
+
"""Register all diagnostics callbacks provided by Bumble 0.0.233."""
|
|
29
|
+
connection_with_attrs = cast("Any", connection)
|
|
30
|
+
on_event = connection_with_attrs.on
|
|
32
31
|
on_event(
|
|
33
|
-
|
|
32
|
+
connection_with_attrs.EVENT_DISCONNECTION,
|
|
34
33
|
self._handle_disconnection,
|
|
35
34
|
)
|
|
36
35
|
on_event(
|
|
37
|
-
|
|
36
|
+
connection_with_attrs.EVENT_CLASSIC_PAIRING,
|
|
38
37
|
lambda *_args: self._record_event("classic_pairing", adapter=self._adapter),
|
|
39
38
|
)
|
|
40
39
|
on_event(
|
|
41
|
-
|
|
40
|
+
connection_with_attrs.EVENT_CLASSIC_PAIRING_FAILURE,
|
|
42
41
|
lambda reason=None, *_args: self._record_event(
|
|
43
42
|
"classic_pairing_failure",
|
|
44
43
|
adapter=self._adapter,
|
|
@@ -46,15 +45,15 @@ class ConnectionDiagnostics:
|
|
|
46
45
|
),
|
|
47
46
|
)
|
|
48
47
|
on_event(
|
|
49
|
-
|
|
48
|
+
connection_with_attrs.EVENT_PAIRING_START,
|
|
50
49
|
lambda *_args: self._record_event("pairing_start", adapter=self._adapter),
|
|
51
50
|
)
|
|
52
51
|
on_event(
|
|
53
|
-
|
|
52
|
+
connection_with_attrs.EVENT_PAIRING,
|
|
54
53
|
lambda keys=None, *_args: self._record_pairing_complete(connection, keys),
|
|
55
54
|
)
|
|
56
55
|
on_event(
|
|
57
|
-
|
|
56
|
+
connection_with_attrs.EVENT_PAIRING_FAILURE,
|
|
58
57
|
lambda reason=None, *_args: self._record_event(
|
|
59
58
|
"pairing_failure",
|
|
60
59
|
adapter=self._adapter,
|
|
@@ -62,15 +61,11 @@ class ConnectionDiagnostics:
|
|
|
62
61
|
),
|
|
63
62
|
)
|
|
64
63
|
on_event(
|
|
65
|
-
|
|
64
|
+
connection_with_attrs.EVENT_CONNECTION_AUTHENTICATION,
|
|
66
65
|
lambda *_args: self._record_connection_authentication(connection),
|
|
67
66
|
)
|
|
68
67
|
on_event(
|
|
69
|
-
|
|
70
|
-
connection,
|
|
71
|
-
"EVENT_CONNECTION_AUTHENTICATION_FAILURE",
|
|
72
|
-
"connection_authentication_failure",
|
|
73
|
-
),
|
|
68
|
+
connection_with_attrs.EVENT_CONNECTION_AUTHENTICATION_FAILURE,
|
|
74
69
|
lambda error=None, *_args: self._record_event(
|
|
75
70
|
"connection_authentication_failure",
|
|
76
71
|
adapter=self._adapter,
|
|
@@ -78,19 +73,11 @@ class ConnectionDiagnostics:
|
|
|
78
73
|
),
|
|
79
74
|
)
|
|
80
75
|
on_event(
|
|
81
|
-
|
|
82
|
-
connection,
|
|
83
|
-
"EVENT_CONNECTION_ENCRYPTION_CHANGE",
|
|
84
|
-
"connection_encryption_change",
|
|
85
|
-
),
|
|
76
|
+
connection_with_attrs.EVENT_CONNECTION_ENCRYPTION_CHANGE,
|
|
86
77
|
lambda *_args: self._record_connection_encryption_change(connection),
|
|
87
78
|
)
|
|
88
79
|
on_event(
|
|
89
|
-
|
|
90
|
-
connection,
|
|
91
|
-
"EVENT_CONNECTION_ENCRYPTION_FAILURE",
|
|
92
|
-
"connection_encryption_failure",
|
|
93
|
-
),
|
|
80
|
+
connection_with_attrs.EVENT_CONNECTION_ENCRYPTION_FAILURE,
|
|
94
81
|
lambda error=None, *_args: self._record_event(
|
|
95
82
|
"connection_encryption_failure",
|
|
96
83
|
adapter=self._adapter,
|
|
@@ -98,23 +85,19 @@ class ConnectionDiagnostics:
|
|
|
98
85
|
),
|
|
99
86
|
)
|
|
100
87
|
on_event(
|
|
101
|
-
|
|
102
|
-
connection,
|
|
103
|
-
"EVENT_CONNECTION_ENCRYPTION_KEY_REFRESH",
|
|
104
|
-
"connection_encryption_key_refresh",
|
|
105
|
-
),
|
|
88
|
+
connection_with_attrs.EVENT_CONNECTION_ENCRYPTION_KEY_REFRESH,
|
|
106
89
|
lambda *_args: self._record_connection_encryption_refresh(connection),
|
|
107
90
|
)
|
|
108
91
|
on_event(
|
|
109
|
-
|
|
92
|
+
connection_with_attrs.EVENT_LINK_KEY,
|
|
110
93
|
lambda *_args: self._record_event("link_key_available", adapter=self._adapter),
|
|
111
94
|
)
|
|
112
95
|
on_event(
|
|
113
|
-
|
|
96
|
+
connection_with_attrs.EVENT_MODE_CHANGE,
|
|
114
97
|
lambda *_args: self._record_classic_mode_change(connection),
|
|
115
98
|
)
|
|
116
99
|
on_event(
|
|
117
|
-
|
|
100
|
+
connection_with_attrs.EVENT_MODE_CHANGE_FAILURE,
|
|
118
101
|
lambda status=None, *_args: self._record_event(
|
|
119
102
|
"classic_mode_change_failure",
|
|
120
103
|
adapter=self._adapter,
|
|
@@ -179,7 +162,8 @@ def register_connection_request_bridge(
|
|
|
179
162
|
record_event: EventRecorder,
|
|
180
163
|
) -> None:
|
|
181
164
|
"""Wrap Bumble's connection request callback while avoiding deprecated sync APIs."""
|
|
182
|
-
|
|
165
|
+
device_with_attrs = cast("Any", device)
|
|
166
|
+
original_connection_request = device_with_attrs.on_connection_request
|
|
183
167
|
|
|
184
168
|
def on_connection_request(
|
|
185
169
|
bd_addr: object,
|
|
@@ -201,7 +185,6 @@ def register_connection_request_bridge(
|
|
|
201
185
|
link_type,
|
|
202
186
|
)
|
|
203
187
|
|
|
204
|
-
device_with_attrs = cast("Any", device)
|
|
205
188
|
device_with_attrs.on_connection_request = on_connection_request
|
|
206
189
|
replace_host_connection_request_listener(
|
|
207
190
|
device,
|
|
@@ -267,24 +250,18 @@ def call_connection_request_without_deprecated_sync_command(
|
|
|
267
250
|
link_type: int,
|
|
268
251
|
) -> None:
|
|
269
252
|
"""Run Bumble's connection request handler without its deprecated sync helper."""
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if host is None or not callable(send_async_command):
|
|
273
|
-
connection_request(bd_addr, class_of_device, link_type)
|
|
274
|
-
return
|
|
253
|
+
device_with_attrs = cast("Any", device)
|
|
254
|
+
host = device_with_attrs.host
|
|
275
255
|
|
|
276
256
|
from bumble import utils # noqa: PLC0415
|
|
277
257
|
|
|
278
258
|
missing = object()
|
|
279
|
-
|
|
280
|
-
previous_instance_attr = (
|
|
281
|
-
host_dict.get("send_command_sync", missing) if isinstance(host_dict, dict) else missing
|
|
282
|
-
)
|
|
259
|
+
previous_instance_attr = host.__dict__.get("send_command_sync", missing)
|
|
283
260
|
|
|
284
261
|
def send_command_sync(command: object) -> None:
|
|
285
|
-
utils.AsyncRunner.spawn(send_async_command(command))
|
|
262
|
+
utils.AsyncRunner.spawn(host.send_async_command(command))
|
|
286
263
|
|
|
287
|
-
host_with_attrs =
|
|
264
|
+
host_with_attrs = host
|
|
288
265
|
host_with_attrs.send_command_sync = send_command_sync
|
|
289
266
|
try:
|
|
290
267
|
connection_request(bd_addr, class_of_device, link_type)
|
|
@@ -300,12 +277,9 @@ def replace_host_connection_request_listener(
|
|
|
300
277
|
original_connection_request: Callable[[object, int, int], None],
|
|
301
278
|
replacement_connection_request: Callable[[object, int, int], None],
|
|
302
279
|
) -> None:
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
on = getattr(host, "on", None)
|
|
306
|
-
if not callable(remove_listener) or not callable(on):
|
|
307
|
-
return
|
|
280
|
+
device_with_attrs = cast("Any", device)
|
|
281
|
+
host = device_with_attrs.host
|
|
308
282
|
|
|
309
283
|
with suppress(KeyError, ValueError):
|
|
310
|
-
remove_listener("connection_request", original_connection_request)
|
|
311
|
-
on("connection_request", replacement_connection_request)
|
|
284
|
+
host.remove_listener("connection_request", original_connection_request)
|
|
285
|
+
host.on("connection_request", replacement_connection_request)
|
|
@@ -16,7 +16,7 @@ _ADDRESS_PATTERN = re.compile(r"(?:[0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}")
|
|
|
16
16
|
_RESERVED_INQUIRY_LAP_MIN = 0x9E8B00
|
|
17
17
|
_RESERVED_INQUIRY_LAP_MAX = 0x9E8B3F
|
|
18
18
|
_PROFILE_FORMAT = "swbt.profile"
|
|
19
|
-
_PROFILE_SCHEMA_VERSION =
|
|
19
|
+
_PROFILE_SCHEMA_VERSION = 2
|
|
20
20
|
_PROFILE_LOCAL_ADDRESS_IDENTITY_KIND = "exp-local-address"
|
|
21
21
|
_PROFILE_ADAPTER_DEFAULT_IDENTITY_KIND = "adapter-default"
|
|
22
22
|
_CONTROLLER_KINDS_BY_PROFILE_VALUE: dict[str, ControllerKind] = {
|
|
@@ -79,7 +79,7 @@ class LocalAddress:
|
|
|
79
79
|
|
|
80
80
|
@dataclass(frozen=True)
|
|
81
81
|
class PairingProfile:
|
|
82
|
-
"""Validated version
|
|
82
|
+
"""Validated version 2 envelope for one controller shape and its pairing data."""
|
|
83
83
|
|
|
84
84
|
local_address: LocalAddress | None
|
|
85
85
|
key_store_namespaces: KeyStoreNamespaces
|
|
@@ -97,14 +97,7 @@ class PairingProfile:
|
|
|
97
97
|
address = None if local_address is None else str(local_address)
|
|
98
98
|
profile = cls(
|
|
99
99
|
local_address=local_address,
|
|
100
|
-
key_store_namespaces=(
|
|
101
|
-
{}
|
|
102
|
-
if address is None
|
|
103
|
-
else {
|
|
104
|
-
address: {},
|
|
105
|
-
f"swbt.previous::{address}": {},
|
|
106
|
-
}
|
|
107
|
-
),
|
|
100
|
+
key_store_namespaces=({} if address is None else {address: {}}),
|
|
108
101
|
controller_kind=controller_kind,
|
|
109
102
|
)
|
|
110
103
|
target = Path(path)
|
|
@@ -200,7 +193,10 @@ class PairingProfile:
|
|
|
200
193
|
if payload.get("format") != _PROFILE_FORMAT:
|
|
201
194
|
_invalid_profile("profile format is unsupported")
|
|
202
195
|
if payload.get("schema_version") != _PROFILE_SCHEMA_VERSION:
|
|
203
|
-
_invalid_profile(
|
|
196
|
+
_invalid_profile(
|
|
197
|
+
"profile schema_version is unsupported; create a new schema v2 profile "
|
|
198
|
+
"and pair again"
|
|
199
|
+
)
|
|
204
200
|
controller_kind_value = payload.get("controller_kind")
|
|
205
201
|
if not isinstance(controller_kind_value, str):
|
|
206
202
|
_invalid_profile("profile controller_kind is unsupported")
|
swbt/transport/bumble.py
CHANGED
|
@@ -132,6 +132,12 @@ class _BumbleHidRuntime(Protocol):
|
|
|
132
132
|
def send_data(self, data: bytes) -> None:
|
|
133
133
|
"""Send an interrupt-channel HID data message."""
|
|
134
134
|
|
|
135
|
+
def register_set_report_cb(
|
|
136
|
+
self,
|
|
137
|
+
callback: Callable[[int, int, int, bytes], _BumbleGetSetStatus],
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Register a HID SET_REPORT callback."""
|
|
140
|
+
|
|
135
141
|
async def connect_control_channel(self) -> None:
|
|
136
142
|
"""Request control-channel L2CAP connection."""
|
|
137
143
|
|
|
@@ -455,10 +461,6 @@ class BumbleHidTransport:
|
|
|
455
461
|
self._register_set_report_callback(hid_device)
|
|
456
462
|
|
|
457
463
|
def _register_set_report_callback(self, hid_device: _BumbleHidRuntime) -> None:
|
|
458
|
-
register_set_report = getattr(hid_device, "register_set_report_cb", None)
|
|
459
|
-
if not callable(register_set_report):
|
|
460
|
-
return
|
|
461
|
-
|
|
462
464
|
def on_set_report(
|
|
463
465
|
report_id: int,
|
|
464
466
|
report_type: int,
|
|
@@ -475,7 +477,7 @@ class BumbleHidTransport:
|
|
|
475
477
|
return _BumbleGetSetStatus(status=HID_GET_SET_UNSUPPORTED_REQUEST)
|
|
476
478
|
return _BumbleGetSetStatus(status=HID_GET_SET_SUCCESS)
|
|
477
479
|
|
|
478
|
-
|
|
480
|
+
hid_device.register_set_report_cb(on_set_report)
|
|
479
481
|
|
|
480
482
|
def _register_device_callbacks(self, device: _BumbleDeviceRuntime) -> None:
|
|
481
483
|
device.on(device.EVENT_CONNECTION, self._handle_device_connection)
|
|
@@ -840,8 +842,7 @@ def _device_info_bluetooth_address_from_bumble_address(address: object) -> bytes
|
|
|
840
842
|
"""Return Device Info address bytes from a Bumble address object."""
|
|
841
843
|
if address is None:
|
|
842
844
|
return None
|
|
843
|
-
|
|
844
|
-
address_text = str(to_string(False)) if callable(to_string) else str(address)
|
|
845
|
+
address_text = str(cast("Any", address).to_string(False))
|
|
845
846
|
address_text = address_text.split("/", 1)[0]
|
|
846
847
|
parts = address_text.split(":")
|
|
847
848
|
if len(parts) != 6 or any(len(part) != 2 for part in parts):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swbt-python
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: Python library for presenting an NX-compatible virtual Bluetooth HID input device.
|
|
5
5
|
Keywords: bluetooth,bluetooth-hid,controller,gamepad,hid,nx
|
|
6
6
|
Author: niart120
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
|
-
Requires-Dist: bumble
|
|
21
|
+
Requires-Dist: bumble==0.0.233
|
|
22
22
|
Maintainer: niart120
|
|
23
23
|
Maintainer-email: niart120 <38847256+niart120@users.noreply.github.com>
|
|
24
24
|
Requires-Python: >=3.12
|
|
@@ -34,20 +34,20 @@ swbt/report_loop.py,sha256=jEnwlxdWQgPwbIXvJfyhgMaJdrGYLNYzlZNotOMKiKw,7853
|
|
|
34
34
|
swbt/state_store.py,sha256=jE1TeNpqynbVpxFp0Xt3m1Dfl1LUKR-uqV4f14qntuM,1402
|
|
35
35
|
swbt/transport/__init__.py,sha256=b_Vqsg0k_g7XclN9XHQrcJxqCwGIklxG5NqzISal4_I,68
|
|
36
36
|
swbt/transport/_adapter_identity.py,sha256=xOECQBlGAZJoyKrfxrIPt88kXoksHWmWzzVo1-x5XmA,6621
|
|
37
|
-
swbt/transport/_bumble_acl.py,sha256=
|
|
37
|
+
swbt/transport/_bumble_acl.py,sha256=tZalNxNSKEsTB6WD4wEOyqEY-Td6s5wg2s_3Ve5UOqI,653
|
|
38
38
|
swbt/transport/_bumble_hidp.py,sha256=mL_eT-otopHzg5G0p7uhqTYsqSuDwdXAiAwakQiHbCY,835
|
|
39
|
-
swbt/transport/_bumble_key_store.py,sha256=
|
|
40
|
-
swbt/transport/_bumble_lifecycle.py,sha256=
|
|
39
|
+
swbt/transport/_bumble_key_store.py,sha256=d7IJ9537QRruvy4aOyVtK7RsOOnjuJ7hKmiYTt7gC_I,6938
|
|
40
|
+
swbt/transport/_bumble_lifecycle.py,sha256=9NgXzyW3g2s91gPcsDuyzS9-rAp64ahDKk9fb3VJLDg,10174
|
|
41
41
|
swbt/transport/_bumble_sdp.py,sha256=RtVgNI3EFi0-cIbiNqrLUi0A2Ju513kF-JWmFlkuvi4,9254
|
|
42
42
|
swbt/transport/_bumble_usb_devices.py,sha256=soAKiHTzeeTYdb7M357yaac-RxG2c_BiKWH9NK9zJFY,894
|
|
43
43
|
swbt/transport/_csr_bd_addr.py,sha256=FNc7y9SvEXhHyChZ8I4zgC-LyduiddLqt-HM_Ux2QXA,7949
|
|
44
44
|
swbt/transport/_csr_bd_addr_harness.py,sha256=aSuFCVbneRENveN_b3CuamD7R9Wqf3CKRNU6Zcdxvpc,10297
|
|
45
|
-
swbt/transport/_pairing_profile.py,sha256=
|
|
45
|
+
swbt/transport/_pairing_profile.py,sha256=95tISeYHnllHfFpNs0oBsaYb5uAffXfi9eFkjb-EeFQ,9342
|
|
46
46
|
swbt/transport/base.py,sha256=eI0hs1wTwJf2ppzqda4ok-tUXF1hE9dwpb0p-lpvwmo,5163
|
|
47
|
-
swbt/transport/bumble.py,sha256=
|
|
47
|
+
swbt/transport/bumble.py,sha256=VufUEo4aUeVebSFvZPJaVe_G7nNz5fKQMCbjgqmBbRs,33414
|
|
48
48
|
swbt/transport/fake.py,sha256=4O5zlsg1TO61Ai54FGCn_xM8TEA9yi938Fso-XHdh1w,12891
|
|
49
|
-
swbt_python-0.5.
|
|
50
|
-
swbt_python-0.5.
|
|
51
|
-
swbt_python-0.5.
|
|
52
|
-
swbt_python-0.5.
|
|
53
|
-
swbt_python-0.5.
|
|
49
|
+
swbt_python-0.5.3.dist-info/licenses/LICENSE,sha256=FzzUoYjuIh5DzpeaujIbDUTylYnyzcHRVU-_ZMyowyk,1065
|
|
50
|
+
swbt_python-0.5.3.dist-info/WHEEL,sha256=uOqnPWqgFlbov4NeTCercq7cBQ2UN7xh5fiW55lOnAg,81
|
|
51
|
+
swbt_python-0.5.3.dist-info/entry_points.txt,sha256=YYQc7VgoSy74iZ6s8Qr6iJpnvFoDpp8G4-v0KJH5TGo,48
|
|
52
|
+
swbt_python-0.5.3.dist-info/METADATA,sha256=W59IobyxaCz0_nIchUTIqNv24T9XjR9d7CuarGeItW0,5902
|
|
53
|
+
swbt_python-0.5.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|