bumble 0.0.160__py3-none-any.whl → 0.0.161__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.
- bumble/_version.py +2 -2
- bumble/controller.py +73 -55
- bumble/core.py +74 -3
- bumble/gatt.py +23 -22
- bumble/l2cap.py +210 -122
- bumble/smp.py +93 -66
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/METADATA +1 -1
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/RECORD +12 -12
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/WHEEL +1 -1
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/LICENSE +0 -0
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.160.dist-info → bumble-0.0.161.dist-info}/top_level.txt +0 -0
bumble/smp.py
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
import logging
|
|
27
27
|
import asyncio
|
|
28
|
+
import enum
|
|
28
29
|
import secrets
|
|
29
30
|
from typing import (
|
|
30
31
|
TYPE_CHECKING,
|
|
@@ -553,20 +554,16 @@ class AddressResolver:
|
|
|
553
554
|
|
|
554
555
|
|
|
555
556
|
# -----------------------------------------------------------------------------
|
|
556
|
-
class
|
|
557
|
-
# Pairing methods
|
|
557
|
+
class PairingMethod(enum.IntEnum):
|
|
558
558
|
JUST_WORKS = 0
|
|
559
559
|
NUMERIC_COMPARISON = 1
|
|
560
560
|
PASSKEY = 2
|
|
561
561
|
OOB = 3
|
|
562
|
+
CTKD_OVER_CLASSIC = 4
|
|
562
563
|
|
|
563
|
-
PAIRING_METHOD_NAMES = {
|
|
564
|
-
JUST_WORKS: 'JUST_WORKS',
|
|
565
|
-
NUMERIC_COMPARISON: 'NUMERIC_COMPARISON',
|
|
566
|
-
PASSKEY: 'PASSKEY',
|
|
567
|
-
OOB: 'OOB',
|
|
568
|
-
}
|
|
569
564
|
|
|
565
|
+
# -----------------------------------------------------------------------------
|
|
566
|
+
class Session:
|
|
570
567
|
# I/O Capability to pairing method decision matrix
|
|
571
568
|
#
|
|
572
569
|
# See Bluetooth spec @ Vol 3, part H - Table 2.8: Mapping of IO Capabilities to Key
|
|
@@ -581,47 +578,50 @@ class Session:
|
|
|
581
578
|
# (False).
|
|
582
579
|
PAIRING_METHODS = {
|
|
583
580
|
SMP_DISPLAY_ONLY_IO_CAPABILITY: {
|
|
584
|
-
SMP_DISPLAY_ONLY_IO_CAPABILITY: JUST_WORKS,
|
|
585
|
-
SMP_DISPLAY_YES_NO_IO_CAPABILITY: JUST_WORKS,
|
|
586
|
-
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PASSKEY, True, False),
|
|
587
|
-
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: JUST_WORKS,
|
|
588
|
-
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (PASSKEY, True, False),
|
|
581
|
+
SMP_DISPLAY_ONLY_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
582
|
+
SMP_DISPLAY_YES_NO_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
583
|
+
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, True, False),
|
|
584
|
+
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
585
|
+
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (PairingMethod.PASSKEY, True, False),
|
|
589
586
|
},
|
|
590
587
|
SMP_DISPLAY_YES_NO_IO_CAPABILITY: {
|
|
591
|
-
SMP_DISPLAY_ONLY_IO_CAPABILITY: JUST_WORKS,
|
|
592
|
-
SMP_DISPLAY_YES_NO_IO_CAPABILITY: (
|
|
593
|
-
|
|
594
|
-
|
|
588
|
+
SMP_DISPLAY_ONLY_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
589
|
+
SMP_DISPLAY_YES_NO_IO_CAPABILITY: (
|
|
590
|
+
PairingMethod.JUST_WORKS,
|
|
591
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
592
|
+
),
|
|
593
|
+
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, True, False),
|
|
594
|
+
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
595
595
|
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (
|
|
596
|
-
(PASSKEY, True, False),
|
|
597
|
-
NUMERIC_COMPARISON,
|
|
596
|
+
(PairingMethod.PASSKEY, True, False),
|
|
597
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
598
598
|
),
|
|
599
599
|
},
|
|
600
600
|
SMP_KEYBOARD_ONLY_IO_CAPABILITY: {
|
|
601
|
-
SMP_DISPLAY_ONLY_IO_CAPABILITY: (PASSKEY, False, True),
|
|
602
|
-
SMP_DISPLAY_YES_NO_IO_CAPABILITY: (PASSKEY, False, True),
|
|
603
|
-
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PASSKEY, False, False),
|
|
604
|
-
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: JUST_WORKS,
|
|
605
|
-
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (PASSKEY, False, True),
|
|
601
|
+
SMP_DISPLAY_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, False, True),
|
|
602
|
+
SMP_DISPLAY_YES_NO_IO_CAPABILITY: (PairingMethod.PASSKEY, False, True),
|
|
603
|
+
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, False, False),
|
|
604
|
+
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
605
|
+
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (PairingMethod.PASSKEY, False, True),
|
|
606
606
|
},
|
|
607
607
|
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: {
|
|
608
|
-
SMP_DISPLAY_ONLY_IO_CAPABILITY: JUST_WORKS,
|
|
609
|
-
SMP_DISPLAY_YES_NO_IO_CAPABILITY: JUST_WORKS,
|
|
610
|
-
SMP_KEYBOARD_ONLY_IO_CAPABILITY: JUST_WORKS,
|
|
611
|
-
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: JUST_WORKS,
|
|
612
|
-
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: JUST_WORKS,
|
|
608
|
+
SMP_DISPLAY_ONLY_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
609
|
+
SMP_DISPLAY_YES_NO_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
610
|
+
SMP_KEYBOARD_ONLY_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
611
|
+
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
612
|
+
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
613
613
|
},
|
|
614
614
|
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: {
|
|
615
|
-
SMP_DISPLAY_ONLY_IO_CAPABILITY: (PASSKEY, False, True),
|
|
615
|
+
SMP_DISPLAY_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, False, True),
|
|
616
616
|
SMP_DISPLAY_YES_NO_IO_CAPABILITY: (
|
|
617
|
-
(PASSKEY, False, True),
|
|
618
|
-
NUMERIC_COMPARISON,
|
|
617
|
+
(PairingMethod.PASSKEY, False, True),
|
|
618
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
619
619
|
),
|
|
620
|
-
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PASSKEY, True, False),
|
|
621
|
-
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: JUST_WORKS,
|
|
620
|
+
SMP_KEYBOARD_ONLY_IO_CAPABILITY: (PairingMethod.PASSKEY, True, False),
|
|
621
|
+
SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: PairingMethod.JUST_WORKS,
|
|
622
622
|
SMP_KEYBOARD_DISPLAY_IO_CAPABILITY: (
|
|
623
|
-
(PASSKEY, True, False),
|
|
624
|
-
NUMERIC_COMPARISON,
|
|
623
|
+
(PairingMethod.PASSKEY, True, False),
|
|
624
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
625
625
|
),
|
|
626
626
|
},
|
|
627
627
|
}
|
|
@@ -664,7 +664,7 @@ class Session:
|
|
|
664
664
|
self.passkey_ready = asyncio.Event()
|
|
665
665
|
self.passkey_step = 0
|
|
666
666
|
self.passkey_display = False
|
|
667
|
-
self.pairing_method =
|
|
667
|
+
self.pairing_method: PairingMethod = PairingMethod.JUST_WORKS
|
|
668
668
|
self.pairing_config = pairing_config
|
|
669
669
|
self.wait_before_continuing: Optional[asyncio.Future[None]] = None
|
|
670
670
|
self.completed = False
|
|
@@ -769,19 +769,23 @@ class Session:
|
|
|
769
769
|
def decide_pairing_method(
|
|
770
770
|
self, auth_req: int, initiator_io_capability: int, responder_io_capability: int
|
|
771
771
|
) -> None:
|
|
772
|
+
if self.connection.transport == BT_BR_EDR_TRANSPORT:
|
|
773
|
+
self.pairing_method = PairingMethod.CTKD_OVER_CLASSIC
|
|
774
|
+
return
|
|
772
775
|
if (not self.mitm) and (auth_req & SMP_MITM_AUTHREQ == 0):
|
|
773
|
-
self.pairing_method =
|
|
776
|
+
self.pairing_method = PairingMethod.JUST_WORKS
|
|
774
777
|
return
|
|
775
778
|
|
|
776
779
|
details = self.PAIRING_METHODS[initiator_io_capability][responder_io_capability] # type: ignore[index]
|
|
777
780
|
if isinstance(details, tuple) and len(details) == 2:
|
|
778
781
|
# One entry for legacy pairing and one for secure connections
|
|
779
782
|
details = details[1 if self.sc else 0]
|
|
780
|
-
if isinstance(details,
|
|
783
|
+
if isinstance(details, PairingMethod):
|
|
781
784
|
# Just a method ID
|
|
782
785
|
self.pairing_method = details
|
|
783
786
|
else:
|
|
784
787
|
# PASSKEY method, with a method ID and display/input flags
|
|
788
|
+
assert isinstance(details[0], PairingMethod)
|
|
785
789
|
self.pairing_method = details[0]
|
|
786
790
|
self.passkey_display = details[1 if self.is_initiator else 2]
|
|
787
791
|
|
|
@@ -932,9 +936,12 @@ class Session:
|
|
|
932
936
|
if self.sc:
|
|
933
937
|
|
|
934
938
|
async def next_steps() -> None:
|
|
935
|
-
if self.pairing_method in (
|
|
939
|
+
if self.pairing_method in (
|
|
940
|
+
PairingMethod.JUST_WORKS,
|
|
941
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
942
|
+
):
|
|
936
943
|
z = 0
|
|
937
|
-
elif self.pairing_method ==
|
|
944
|
+
elif self.pairing_method == PairingMethod.PASSKEY:
|
|
938
945
|
# We need a passkey
|
|
939
946
|
await self.passkey_ready.wait()
|
|
940
947
|
assert self.passkey
|
|
@@ -1227,7 +1234,7 @@ class Session:
|
|
|
1227
1234
|
# Create an object to hold the keys
|
|
1228
1235
|
keys = PairingKeys()
|
|
1229
1236
|
keys.address_type = peer_address.address_type
|
|
1230
|
-
authenticated = self.pairing_method !=
|
|
1237
|
+
authenticated = self.pairing_method != PairingMethod.JUST_WORKS
|
|
1231
1238
|
if self.sc or self.connection.transport == BT_BR_EDR_TRANSPORT:
|
|
1232
1239
|
keys.ltk = PairingKeys.Key(value=self.ltk, authenticated=authenticated)
|
|
1233
1240
|
else:
|
|
@@ -1330,9 +1337,7 @@ class Session:
|
|
|
1330
1337
|
self.decide_pairing_method(
|
|
1331
1338
|
command.auth_req, command.io_capability, self.io_capability
|
|
1332
1339
|
)
|
|
1333
|
-
logger.debug(
|
|
1334
|
-
f'pairing method: {self.PAIRING_METHOD_NAMES[self.pairing_method]}'
|
|
1335
|
-
)
|
|
1340
|
+
logger.debug(f'pairing method: {self.pairing_method.name}')
|
|
1336
1341
|
|
|
1337
1342
|
# Key distribution
|
|
1338
1343
|
(
|
|
@@ -1348,7 +1353,7 @@ class Session:
|
|
|
1348
1353
|
|
|
1349
1354
|
# Display a passkey if we need to
|
|
1350
1355
|
if not self.sc:
|
|
1351
|
-
if self.pairing_method ==
|
|
1356
|
+
if self.pairing_method == PairingMethod.PASSKEY and self.passkey_display:
|
|
1352
1357
|
self.display_passkey()
|
|
1353
1358
|
|
|
1354
1359
|
# Respond
|
|
@@ -1389,9 +1394,7 @@ class Session:
|
|
|
1389
1394
|
self.decide_pairing_method(
|
|
1390
1395
|
command.auth_req, self.io_capability, command.io_capability
|
|
1391
1396
|
)
|
|
1392
|
-
logger.debug(
|
|
1393
|
-
f'pairing method: {self.PAIRING_METHOD_NAMES[self.pairing_method]}'
|
|
1394
|
-
)
|
|
1397
|
+
logger.debug(f'pairing method: {self.pairing_method.name}')
|
|
1395
1398
|
|
|
1396
1399
|
# Key distribution
|
|
1397
1400
|
if (
|
|
@@ -1407,13 +1410,16 @@ class Session:
|
|
|
1407
1410
|
self.compute_peer_expected_distributions(self.responder_key_distribution)
|
|
1408
1411
|
|
|
1409
1412
|
# Start phase 2
|
|
1410
|
-
if self.
|
|
1411
|
-
|
|
1413
|
+
if self.pairing_method == PairingMethod.CTKD_OVER_CLASSIC:
|
|
1414
|
+
# Authentication is already done in SMP, so remote shall start keys distribution immediately
|
|
1415
|
+
return
|
|
1416
|
+
elif self.sc:
|
|
1417
|
+
if self.pairing_method == PairingMethod.PASSKEY:
|
|
1412
1418
|
self.display_or_input_passkey()
|
|
1413
1419
|
|
|
1414
1420
|
self.send_public_key_command()
|
|
1415
1421
|
else:
|
|
1416
|
-
if self.pairing_method ==
|
|
1422
|
+
if self.pairing_method == PairingMethod.PASSKEY:
|
|
1417
1423
|
self.display_or_input_passkey(self.send_pairing_confirm_command)
|
|
1418
1424
|
else:
|
|
1419
1425
|
self.send_pairing_confirm_command()
|
|
@@ -1425,7 +1431,10 @@ class Session:
|
|
|
1425
1431
|
self.send_pairing_random_command()
|
|
1426
1432
|
else:
|
|
1427
1433
|
# If the method is PASSKEY, now is the time to input the code
|
|
1428
|
-
if
|
|
1434
|
+
if (
|
|
1435
|
+
self.pairing_method == PairingMethod.PASSKEY
|
|
1436
|
+
and not self.passkey_display
|
|
1437
|
+
):
|
|
1429
1438
|
self.input_passkey(self.send_pairing_confirm_command)
|
|
1430
1439
|
else:
|
|
1431
1440
|
self.send_pairing_confirm_command()
|
|
@@ -1433,11 +1442,14 @@ class Session:
|
|
|
1433
1442
|
def on_smp_pairing_confirm_command_secure_connections(
|
|
1434
1443
|
self, _: SMP_Pairing_Confirm_Command
|
|
1435
1444
|
) -> None:
|
|
1436
|
-
if self.pairing_method in (
|
|
1445
|
+
if self.pairing_method in (
|
|
1446
|
+
PairingMethod.JUST_WORKS,
|
|
1447
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1448
|
+
):
|
|
1437
1449
|
if self.is_initiator:
|
|
1438
1450
|
self.r = crypto.r()
|
|
1439
1451
|
self.send_pairing_random_command()
|
|
1440
|
-
elif self.pairing_method ==
|
|
1452
|
+
elif self.pairing_method == PairingMethod.PASSKEY:
|
|
1441
1453
|
if self.is_initiator:
|
|
1442
1454
|
self.send_pairing_random_command()
|
|
1443
1455
|
else:
|
|
@@ -1493,13 +1505,16 @@ class Session:
|
|
|
1493
1505
|
def on_smp_pairing_random_command_secure_connections(
|
|
1494
1506
|
self, command: SMP_Pairing_Random_Command
|
|
1495
1507
|
) -> None:
|
|
1496
|
-
if self.pairing_method ==
|
|
1508
|
+
if self.pairing_method == PairingMethod.PASSKEY and self.passkey is None:
|
|
1497
1509
|
logger.warning('no passkey entered, ignoring command')
|
|
1498
1510
|
return
|
|
1499
1511
|
|
|
1500
1512
|
# pylint: disable=too-many-return-statements
|
|
1501
1513
|
if self.is_initiator:
|
|
1502
|
-
if self.pairing_method in (
|
|
1514
|
+
if self.pairing_method in (
|
|
1515
|
+
PairingMethod.JUST_WORKS,
|
|
1516
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1517
|
+
):
|
|
1503
1518
|
assert self.confirm_value
|
|
1504
1519
|
# Check that the random value matches what was committed to earlier
|
|
1505
1520
|
confirm_verifier = crypto.f4(
|
|
@@ -1509,7 +1524,7 @@ class Session:
|
|
|
1509
1524
|
self.confirm_value, confirm_verifier, SMP_CONFIRM_VALUE_FAILED_ERROR
|
|
1510
1525
|
):
|
|
1511
1526
|
return
|
|
1512
|
-
elif self.pairing_method ==
|
|
1527
|
+
elif self.pairing_method == PairingMethod.PASSKEY:
|
|
1513
1528
|
assert self.passkey and self.confirm_value
|
|
1514
1529
|
# Check that the random value matches what was committed to earlier
|
|
1515
1530
|
confirm_verifier = crypto.f4(
|
|
@@ -1532,9 +1547,12 @@ class Session:
|
|
|
1532
1547
|
else:
|
|
1533
1548
|
return
|
|
1534
1549
|
else:
|
|
1535
|
-
if self.pairing_method in (
|
|
1550
|
+
if self.pairing_method in (
|
|
1551
|
+
PairingMethod.JUST_WORKS,
|
|
1552
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1553
|
+
):
|
|
1536
1554
|
self.send_pairing_random_command()
|
|
1537
|
-
elif self.pairing_method ==
|
|
1555
|
+
elif self.pairing_method == PairingMethod.PASSKEY:
|
|
1538
1556
|
assert self.passkey and self.confirm_value
|
|
1539
1557
|
# Check that the random value matches what was committed to earlier
|
|
1540
1558
|
confirm_verifier = crypto.f4(
|
|
@@ -1565,10 +1583,13 @@ class Session:
|
|
|
1565
1583
|
(mac_key, self.ltk) = crypto.f5(self.dh_key, self.na, self.nb, a, b)
|
|
1566
1584
|
|
|
1567
1585
|
# Compute the DH Key checks
|
|
1568
|
-
if self.pairing_method in (
|
|
1586
|
+
if self.pairing_method in (
|
|
1587
|
+
PairingMethod.JUST_WORKS,
|
|
1588
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1589
|
+
):
|
|
1569
1590
|
ra = bytes(16)
|
|
1570
1591
|
rb = ra
|
|
1571
|
-
elif self.pairing_method ==
|
|
1592
|
+
elif self.pairing_method == PairingMethod.PASSKEY:
|
|
1572
1593
|
assert self.passkey
|
|
1573
1594
|
ra = self.passkey.to_bytes(16, byteorder='little')
|
|
1574
1595
|
rb = ra
|
|
@@ -1592,13 +1613,16 @@ class Session:
|
|
|
1592
1613
|
self.wait_before_continuing.set_result(None)
|
|
1593
1614
|
|
|
1594
1615
|
# Prompt the user for confirmation if needed
|
|
1595
|
-
if self.pairing_method in (
|
|
1616
|
+
if self.pairing_method in (
|
|
1617
|
+
PairingMethod.JUST_WORKS,
|
|
1618
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1619
|
+
):
|
|
1596
1620
|
# Compute the 6-digit code
|
|
1597
1621
|
code = crypto.g2(self.pka, self.pkb, self.na, self.nb) % 1000000
|
|
1598
1622
|
|
|
1599
1623
|
# Ask for user confirmation
|
|
1600
1624
|
self.wait_before_continuing = asyncio.get_running_loop().create_future()
|
|
1601
|
-
if self.pairing_method ==
|
|
1625
|
+
if self.pairing_method == PairingMethod.JUST_WORKS:
|
|
1602
1626
|
self.prompt_user_for_confirmation(next_steps)
|
|
1603
1627
|
else:
|
|
1604
1628
|
self.prompt_user_for_numeric_comparison(code, next_steps)
|
|
@@ -1635,13 +1659,16 @@ class Session:
|
|
|
1635
1659
|
if self.is_initiator:
|
|
1636
1660
|
self.send_pairing_confirm_command()
|
|
1637
1661
|
else:
|
|
1638
|
-
if self.pairing_method ==
|
|
1662
|
+
if self.pairing_method == PairingMethod.PASSKEY:
|
|
1639
1663
|
self.display_or_input_passkey()
|
|
1640
1664
|
|
|
1641
1665
|
# Send our public key back to the initiator
|
|
1642
1666
|
self.send_public_key_command()
|
|
1643
1667
|
|
|
1644
|
-
if self.pairing_method in (
|
|
1668
|
+
if self.pairing_method in (
|
|
1669
|
+
PairingMethod.JUST_WORKS,
|
|
1670
|
+
PairingMethod.NUMERIC_COMPARISON,
|
|
1671
|
+
):
|
|
1645
1672
|
# We can now send the confirmation value
|
|
1646
1673
|
self.send_pairing_confirm_command()
|
|
1647
1674
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
|
|
2
|
-
bumble/_version.py,sha256=
|
|
2
|
+
bumble/_version.py,sha256=z2uj4v0zOw20JF0drVkUjMouxtJipeDu3RBasPE26ks,164
|
|
3
3
|
bumble/a2dp.py,sha256=vwnKknvSKPR7IdTz8JHHNvHGObjepVy1kFRWm0kNWEI,21923
|
|
4
4
|
bumble/att.py,sha256=qXwC5gtC-4Bwjqul0sCm_bWA_BbK4NVf5xNlOCRE7LI,30231
|
|
5
5
|
bumble/avdtp.py,sha256=sT0mFeFvp9jTEP-dOp4_ibdtKX3mtw1Gyi-72tHfkiE,72268
|
|
@@ -7,13 +7,13 @@ bumble/bridge.py,sha256=T6es5oS1dy8QgkxQ8iOD-YcZ0SWOv8jaqC7TGxqodk4,3003
|
|
|
7
7
|
bumble/codecs.py,sha256=Vc7FOo6d-6VCgDI0ibnLmX8vCZ4-jtX_-0vEUM-yOrI,15343
|
|
8
8
|
bumble/colors.py,sha256=9H-qzGgMr-YoWdIFpcGPaiRvTvkCzz7FPIkpwqKyKug,3033
|
|
9
9
|
bumble/company_ids.py,sha256=mHmG9mk_0lkjiRm-IMggDnuXzY2QlZzH9jugy_ijhDc,95931
|
|
10
|
-
bumble/controller.py,sha256=
|
|
11
|
-
bumble/core.py,sha256=
|
|
10
|
+
bumble/controller.py,sha256=AaRNjz8-1UYH3HgSIVdBvLLwHOLNbxj5J9ScG518PE0,44940
|
|
11
|
+
bumble/core.py,sha256=5gvUyF8aJKg2T_8QPVGiv6wtP-zsWJZ6w89UTGKQHrQ,52293
|
|
12
12
|
bumble/crypto.py,sha256=JX3wg6kd-aFMxkxJz2FYFvyXHOukD-z0QcGH9jpEYvk,8679
|
|
13
13
|
bumble/decoder.py,sha256=N9nMvuVhuwpnfw7EDVuNe9uYY6B6c3RY2dh8RhRPC1U,9608
|
|
14
14
|
bumble/device.py,sha256=UPusLfD-sb3wpeDXTHMVS-MqoFRF39tKtCWLLfHfFOc,122493
|
|
15
15
|
bumble/gap.py,sha256=axlOZIv99357Ehq2vMokeioU85z81qdQvplGn0pF70Q,2137
|
|
16
|
-
bumble/gatt.py,sha256=
|
|
16
|
+
bumble/gatt.py,sha256=HwjxuFjuH0LvRyP4HUfslPd-qZ0P17e5Xx8E9usehz0,28295
|
|
17
17
|
bumble/gatt_client.py,sha256=0NrwW7Y3oy1HUWisIyBLwnBpYNnuI9jtbcNkS6CD__U,40297
|
|
18
18
|
bumble/gatt_server.py,sha256=vi_-sofp5NjPWDYX5K_hldsAaoFuNlt8GFA-eVzFkb8,35277
|
|
19
19
|
bumble/hci.py,sha256=7WleGG4Mp80qFGPGoRxUDP2qs6mpRRAWywkgTHJkPHM,217086
|
|
@@ -21,13 +21,13 @@ bumble/helpers.py,sha256=AgtOigAqQzzTEMMwHQJ2EO7dOTp77qhnyfHQ2LCDd-k,8896
|
|
|
21
21
|
bumble/hfp.py,sha256=BQEuh7A9WkP2V-YuuveuI5W-k1-O1Ovq2DvRao_2psk,3434
|
|
22
22
|
bumble/host.py,sha256=BzxDA4crNZrj0u0Gm_hW-uanXn6mFwjRVWKdfd4jrvw,34574
|
|
23
23
|
bumble/keys.py,sha256=_ibaJ4CxM5zyxnTp7wnihIQSsEAEkCiPxx9qHsGA04Q,12601
|
|
24
|
-
bumble/l2cap.py,sha256=
|
|
24
|
+
bumble/l2cap.py,sha256=lk8hNofT04uTiPZ169zgipHWxnq48bz3VcGs3t4CfWE,75417
|
|
25
25
|
bumble/link.py,sha256=dvb3fdmV8689A4rLhFVHHKMR3u4wQbUapFi-GeheK0M,20220
|
|
26
26
|
bumble/pairing.py,sha256=smMCrWdgtdLXKJ_Ix9e5x1SuvSs_49mKtwzJS94ygd4,7002
|
|
27
27
|
bumble/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
bumble/rfcomm.py,sha256=LgcHvRelcToJy3PiPedqkrj4CRZjCg2zFVba-hTkZCY,31632
|
|
29
29
|
bumble/sdp.py,sha256=h0DyXOYpQ5OLzwVZsE4b5YZq_jxxu7m_QSbFkaPy9mQ,42464
|
|
30
|
-
bumble/smp.py,sha256=
|
|
30
|
+
bumble/smp.py,sha256=kh8CA9wnyNT4kqz4Rt9_K6xqFeWDd7POdp4karCKsdU,70430
|
|
31
31
|
bumble/snoop.py,sha256=_QfF36eylBW6Snd-_KYOwKaGiM8i_Ed-B5XoFIPt3Dg,5631
|
|
32
32
|
bumble/utils.py,sha256=x7AKW6QD35Dl1OkROLJ6TX4dNN6ajwFjW8w_BZGGcA4,10195
|
|
33
33
|
bumble/apps/README.md,sha256=XTwjRAY-EJWDXpl1V8K3Mw8B7kIqzUIUizRjVBVhoIE,1769
|
|
@@ -119,9 +119,9 @@ bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py,sha256=k4RDFvE5Y4QgGL
|
|
|
119
119
|
bumble/transport/grpc_protobuf/startup_pb2.py,sha256=viPPlvFuRE1HoM3zg3Ayy5wfNnuSSAX80MNqtKVqv-o,1854
|
|
120
120
|
bumble/transport/grpc_protobuf/startup_pb2.pyi,sha256=8bDHVKJ_PIZuPvXRVK7tJCPOY8E8ZKW-5xzqbRLEJcw,2140
|
|
121
121
|
bumble/transport/grpc_protobuf/startup_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
122
|
-
bumble-0.0.
|
|
123
|
-
bumble-0.0.
|
|
124
|
-
bumble-0.0.
|
|
125
|
-
bumble-0.0.
|
|
126
|
-
bumble-0.0.
|
|
127
|
-
bumble-0.0.
|
|
122
|
+
bumble-0.0.161.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
|
|
123
|
+
bumble-0.0.161.dist-info/METADATA,sha256=Xy3VY03sptPDb03hJdGpFK6WqP476EPk6J63eAhvU0c,5221
|
|
124
|
+
bumble-0.0.161.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
|
125
|
+
bumble-0.0.161.dist-info/entry_points.txt,sha256=AjCwgm9SvZDOhV7T6jWwAhWdE728pd759LQCscMLjnM,765
|
|
126
|
+
bumble-0.0.161.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
|
|
127
|
+
bumble-0.0.161.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|