bumble 0.0.214__py3-none-any.whl → 0.0.215__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.
Files changed (122) hide show
  1. bumble/_version.py +16 -3
  2. bumble/a2dp.py +15 -16
  3. bumble/apps/auracast.py +13 -38
  4. bumble/apps/bench.py +9 -10
  5. bumble/apps/ble_rpa_tool.py +1 -0
  6. bumble/apps/console.py +22 -25
  7. bumble/apps/controller_info.py +19 -19
  8. bumble/apps/controller_loopback.py +2 -2
  9. bumble/apps/controllers.py +1 -1
  10. bumble/apps/device_info.py +3 -3
  11. bumble/apps/gatt_dump.py +1 -1
  12. bumble/apps/gg_bridge.py +5 -6
  13. bumble/apps/hci_bridge.py +3 -3
  14. bumble/apps/l2cap_bridge.py +3 -3
  15. bumble/apps/lea_unicast/app.py +15 -25
  16. bumble/apps/pair.py +30 -43
  17. bumble/apps/pandora_server.py +5 -4
  18. bumble/apps/player/player.py +19 -22
  19. bumble/apps/rfcomm_bridge.py +3 -8
  20. bumble/apps/scan.py +16 -6
  21. bumble/apps/show.py +3 -4
  22. bumble/apps/speaker/speaker.py +22 -22
  23. bumble/apps/unbond.py +2 -1
  24. bumble/apps/usb_probe.py +1 -2
  25. bumble/att.py +241 -246
  26. bumble/audio/io.py +5 -9
  27. bumble/avc.py +2 -2
  28. bumble/avctp.py +6 -7
  29. bumble/avdtp.py +19 -22
  30. bumble/avrcp.py +1096 -588
  31. bumble/codecs.py +2 -0
  32. bumble/controller.py +52 -13
  33. bumble/core.py +567 -248
  34. bumble/crypto/__init__.py +2 -2
  35. bumble/crypto/builtin.py +1 -1
  36. bumble/crypto/cryptography.py +2 -4
  37. bumble/data_types.py +1025 -0
  38. bumble/device.py +280 -278
  39. bumble/drivers/__init__.py +3 -2
  40. bumble/drivers/intel.py +3 -4
  41. bumble/drivers/rtk.py +26 -9
  42. bumble/gap.py +4 -4
  43. bumble/gatt.py +3 -2
  44. bumble/gatt_adapters.py +3 -11
  45. bumble/gatt_client.py +69 -81
  46. bumble/gatt_server.py +124 -124
  47. bumble/hci.py +67 -18
  48. bumble/helpers.py +19 -26
  49. bumble/hfp.py +10 -21
  50. bumble/hid.py +22 -16
  51. bumble/host.py +181 -103
  52. bumble/keys.py +5 -3
  53. bumble/l2cap.py +121 -74
  54. bumble/link.py +8 -9
  55. bumble/pairing.py +7 -6
  56. bumble/pandora/__init__.py +8 -7
  57. bumble/pandora/config.py +3 -1
  58. bumble/pandora/device.py +3 -2
  59. bumble/pandora/host.py +38 -36
  60. bumble/pandora/l2cap.py +22 -21
  61. bumble/pandora/security.py +15 -15
  62. bumble/pandora/utils.py +5 -3
  63. bumble/profiles/aics.py +11 -11
  64. bumble/profiles/ams.py +7 -8
  65. bumble/profiles/ancs.py +6 -7
  66. bumble/profiles/ascs.py +4 -9
  67. bumble/profiles/asha.py +8 -12
  68. bumble/profiles/bap.py +11 -23
  69. bumble/profiles/bass.py +2 -7
  70. bumble/profiles/battery_service.py +3 -4
  71. bumble/profiles/cap.py +1 -2
  72. bumble/profiles/csip.py +2 -6
  73. bumble/profiles/device_information_service.py +2 -2
  74. bumble/profiles/gap.py +4 -4
  75. bumble/profiles/gatt_service.py +1 -4
  76. bumble/profiles/gmap.py +5 -5
  77. bumble/profiles/hap.py +62 -59
  78. bumble/profiles/heart_rate_service.py +5 -4
  79. bumble/profiles/le_audio.py +3 -1
  80. bumble/profiles/mcp.py +3 -7
  81. bumble/profiles/pacs.py +3 -6
  82. bumble/profiles/pbp.py +2 -0
  83. bumble/profiles/tmap.py +2 -3
  84. bumble/profiles/vcs.py +2 -8
  85. bumble/profiles/vocs.py +8 -8
  86. bumble/rfcomm.py +11 -14
  87. bumble/rtp.py +1 -0
  88. bumble/sdp.py +10 -8
  89. bumble/smp.py +142 -153
  90. bumble/snoop.py +5 -5
  91. bumble/tools/generate_company_id_list.py +1 -0
  92. bumble/tools/intel_fw_download.py +3 -3
  93. bumble/tools/intel_util.py +4 -4
  94. bumble/tools/rtk_fw_download.py +6 -3
  95. bumble/tools/rtk_util.py +24 -7
  96. bumble/transport/__init__.py +19 -15
  97. bumble/transport/android_emulator.py +8 -13
  98. bumble/transport/android_netsim.py +19 -18
  99. bumble/transport/common.py +12 -15
  100. bumble/transport/file.py +1 -1
  101. bumble/transport/hci_socket.py +4 -6
  102. bumble/transport/pty.py +5 -6
  103. bumble/transport/pyusb.py +7 -10
  104. bumble/transport/serial.py +2 -1
  105. bumble/transport/tcp_client.py +2 -2
  106. bumble/transport/tcp_server.py +11 -14
  107. bumble/transport/udp.py +3 -3
  108. bumble/transport/unix.py +67 -1
  109. bumble/transport/usb.py +6 -6
  110. bumble/transport/vhci.py +0 -1
  111. bumble/transport/ws_client.py +2 -1
  112. bumble/transport/ws_server.py +3 -2
  113. bumble/utils.py +20 -5
  114. bumble/vendor/android/hci.py +1 -2
  115. bumble/vendor/zephyr/hci.py +0 -1
  116. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/METADATA +2 -1
  117. bumble-0.0.215.dist-info/RECORD +183 -0
  118. bumble-0.0.214.dist-info/RECORD +0 -182
  119. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/WHEEL +0 -0
  120. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/entry_points.txt +0 -0
  121. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/licenses/LICENSE +0 -0
  122. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/top_level.txt +0 -0
bumble/host.py CHANGED
@@ -16,33 +16,19 @@
16
16
  # Imports
17
17
  # -----------------------------------------------------------------------------
18
18
  from __future__ import annotations
19
+
19
20
  import asyncio
20
21
  import collections
21
22
  import dataclasses
22
23
  import logging
23
24
  import struct
25
+ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, Union, cast
24
26
 
25
- from typing import (
26
- Any,
27
- Awaitable,
28
- Callable,
29
- Optional,
30
- cast,
31
- TYPE_CHECKING,
32
- )
33
-
34
-
27
+ from bumble import drivers, hci, utils
35
28
  from bumble.colors import color
29
+ from bumble.core import ConnectionPHY, InvalidStateError, PhysicalTransport
36
30
  from bumble.l2cap import L2CAP_PDU
37
31
  from bumble.snoop import Snooper
38
- from bumble import drivers
39
- from bumble import hci
40
- from bumble.core import (
41
- PhysicalTransport,
42
- ConnectionPHY,
43
- ConnectionParameters,
44
- )
45
- from bumble import utils
46
32
  from bumble.transport.common import TransportLostError
47
33
 
48
34
  if TYPE_CHECKING:
@@ -707,11 +693,9 @@ class Host(utils.EventEmitter):
707
693
  raise hci.HCI_Error(status)
708
694
 
709
695
  return response
710
- except Exception as error:
711
- logger.exception(
712
- f'{color("!!! Exception while sending command:", "red")} {error}'
713
- )
714
- raise error
696
+ except Exception:
697
+ logger.exception(color("!!! Exception while sending command:", "red"))
698
+ raise
715
699
  finally:
716
700
  self.pending_command = None
717
701
  self.pending_response = None
@@ -918,10 +902,14 @@ class Host(utils.EventEmitter):
918
902
  def on_l2cap_pdu(self, connection: Connection, cid: int, pdu: bytes) -> None:
919
903
  self.emit('l2cap_pdu', connection.handle, cid, pdu)
920
904
 
921
- def on_command_processed(self, event):
905
+ def on_command_processed(
906
+ self, event: Union[hci.HCI_Command_Complete_Event, hci.HCI_Command_Status_Event]
907
+ ):
922
908
  if self.pending_response:
923
909
  # Check that it is what we were expecting
924
- if self.pending_command.op_code != event.command_opcode:
910
+ if self.pending_command is None:
911
+ logger.warning('!!! pending_command is None ')
912
+ elif self.pending_command.op_code != event.command_opcode:
925
913
  logger.warning(
926
914
  '!!! command result mismatch, expected '
927
915
  f'0x{self.pending_command.op_code:X} but got '
@@ -935,10 +923,10 @@ class Host(utils.EventEmitter):
935
923
  ############################################################
936
924
  # HCI handlers
937
925
  ############################################################
938
- def on_hci_event(self, event):
926
+ def on_hci_event(self, event: hci.HCI_Event):
939
927
  logger.warning(f'{color(f"--- Ignoring event {event}", "red")}')
940
928
 
941
- def on_hci_command_complete_event(self, event):
929
+ def on_hci_command_complete_event(self, event: hci.HCI_Command_Complete_Event):
942
930
  if event.command_opcode == 0:
943
931
  # This is used just for the Num_HCI_Command_Packets field, not related to
944
932
  # an actual command
@@ -947,7 +935,7 @@ class Host(utils.EventEmitter):
947
935
 
948
936
  return self.on_command_processed(event)
949
937
 
950
- def on_hci_command_status_event(self, event):
938
+ def on_hci_command_status_event(self, event: hci.HCI_Command_Status_Event):
951
939
  return self.on_command_processed(event)
952
940
 
953
941
  def on_hci_number_of_completed_packets_event(
@@ -967,7 +955,7 @@ class Host(utils.EventEmitter):
967
955
  )
968
956
 
969
957
  # Classic only
970
- def on_hci_connection_request_event(self, event):
958
+ def on_hci_connection_request_event(self, event: hci.HCI_Connection_Request_Event):
971
959
  # Notify the listeners
972
960
  self.emit(
973
961
  'connection_request',
@@ -976,7 +964,14 @@ class Host(utils.EventEmitter):
976
964
  event.link_type,
977
965
  )
978
966
 
979
- def on_hci_le_connection_complete_event(self, event):
967
+ def on_hci_le_connection_complete_event(
968
+ self,
969
+ event: Union[
970
+ hci.HCI_LE_Connection_Complete_Event,
971
+ hci.HCI_LE_Enhanced_Connection_Complete_Event,
972
+ hci.HCI_LE_Enhanced_Connection_Complete_V2_Event,
973
+ ],
974
+ ):
980
975
  # Check if this is a cancellation
981
976
  if event.status == hci.HCI_SUCCESS:
982
977
  # Create/update the connection
@@ -996,20 +991,16 @@ class Host(utils.EventEmitter):
996
991
  self.connections[event.connection_handle] = connection
997
992
 
998
993
  # Notify the client
999
- connection_parameters = ConnectionParameters(
1000
- event.connection_interval,
1001
- event.peripheral_latency,
1002
- event.supervision_timeout,
1003
- )
1004
994
  self.emit(
1005
- 'connection',
995
+ 'le_connection',
1006
996
  event.connection_handle,
1007
- PhysicalTransport.LE,
1008
997
  event.peer_address,
1009
998
  getattr(event, 'local_resolvable_private_address', None),
1010
999
  getattr(event, 'peer_resolvable_private_address', None),
1011
1000
  hci.Role(event.role),
1012
- connection_parameters,
1001
+ event.connection_interval,
1002
+ event.peripheral_latency,
1003
+ event.supervision_timeout,
1013
1004
  )
1014
1005
  else:
1015
1006
  logger.debug(f'### CONNECTION FAILED: {event.status}')
@@ -1022,15 +1013,25 @@ class Host(utils.EventEmitter):
1022
1013
  event.status,
1023
1014
  )
1024
1015
 
1025
- def on_hci_le_enhanced_connection_complete_event(self, event):
1016
+ def on_hci_le_enhanced_connection_complete_event(
1017
+ self,
1018
+ event: Union[
1019
+ hci.HCI_LE_Enhanced_Connection_Complete_Event,
1020
+ hci.HCI_LE_Enhanced_Connection_Complete_V2_Event,
1021
+ ],
1022
+ ):
1026
1023
  # Just use the same implementation as for the non-enhanced event for now
1027
1024
  self.on_hci_le_connection_complete_event(event)
1028
1025
 
1029
- def on_hci_le_enhanced_connection_complete_v2_event(self, event):
1026
+ def on_hci_le_enhanced_connection_complete_v2_event(
1027
+ self, event: hci.HCI_LE_Enhanced_Connection_Complete_V2_Event
1028
+ ):
1030
1029
  # Just use the same implementation as for the v1 event for now
1031
1030
  self.on_hci_le_enhanced_connection_complete_event(event)
1032
1031
 
1033
- def on_hci_connection_complete_event(self, event):
1032
+ def on_hci_connection_complete_event(
1033
+ self, event: hci.HCI_Connection_Complete_Event
1034
+ ):
1034
1035
  if event.status == hci.HCI_SUCCESS:
1035
1036
  # Create/update the connection
1036
1037
  logger.debug(
@@ -1050,14 +1051,9 @@ class Host(utils.EventEmitter):
1050
1051
 
1051
1052
  # Notify the client
1052
1053
  self.emit(
1053
- 'connection',
1054
+ 'classic_connection',
1054
1055
  event.connection_handle,
1055
- PhysicalTransport.BR_EDR,
1056
1056
  event.bd_addr,
1057
- None,
1058
- None,
1059
- None,
1060
- None,
1061
1057
  )
1062
1058
  else:
1063
1059
  logger.debug(f'### BR/EDR CONNECTION FAILED: {event.status}')
@@ -1070,7 +1066,9 @@ class Host(utils.EventEmitter):
1070
1066
  event.status,
1071
1067
  )
1072
1068
 
1073
- def on_hci_disconnection_complete_event(self, event):
1069
+ def on_hci_disconnection_complete_event(
1070
+ self, event: hci.HCI_Disconnection_Complete_Event
1071
+ ):
1074
1072
  # Find the connection
1075
1073
  handle = event.connection_handle
1076
1074
  if (
@@ -1109,27 +1107,30 @@ class Host(utils.EventEmitter):
1109
1107
  # Notify the listeners
1110
1108
  self.emit('disconnection_failure', handle, event.status)
1111
1109
 
1112
- def on_hci_le_connection_update_complete_event(self, event):
1110
+ def on_hci_le_connection_update_complete_event(
1111
+ self, event: hci.HCI_LE_Connection_Update_Complete_Event
1112
+ ):
1113
1113
  if (connection := self.connections.get(event.connection_handle)) is None:
1114
1114
  logger.warning('!!! CONNECTION PARAMETERS UPDATE COMPLETE: unknown handle')
1115
1115
  return
1116
1116
 
1117
1117
  # Notify the client
1118
1118
  if event.status == hci.HCI_SUCCESS:
1119
- connection_parameters = ConnectionParameters(
1119
+ self.emit(
1120
+ 'connection_parameters_update',
1121
+ connection.handle,
1120
1122
  event.connection_interval,
1121
1123
  event.peripheral_latency,
1122
1124
  event.supervision_timeout,
1123
1125
  )
1124
- self.emit(
1125
- 'connection_parameters_update', connection.handle, connection_parameters
1126
- )
1127
1126
  else:
1128
1127
  self.emit(
1129
1128
  'connection_parameters_update_failure', connection.handle, event.status
1130
1129
  )
1131
1130
 
1132
- def on_hci_le_phy_update_complete_event(self, event):
1131
+ def on_hci_le_phy_update_complete_event(
1132
+ self, event: hci.HCI_LE_PHY_Update_Complete_Event
1133
+ ):
1133
1134
  if (connection := self.connections.get(event.connection_handle)) is None:
1134
1135
  logger.warning('!!! CONNECTION PHY UPDATE COMPLETE: unknown handle')
1135
1136
  return
@@ -1159,7 +1160,9 @@ class Host(utils.EventEmitter):
1159
1160
  ):
1160
1161
  self.on_hci_le_advertising_report_event(event)
1161
1162
 
1162
- def on_hci_le_advertising_set_terminated_event(self, event):
1163
+ def on_hci_le_advertising_set_terminated_event(
1164
+ self, event: hci.HCI_LE_Advertising_Set_Terminated_Event
1165
+ ):
1163
1166
  self.emit(
1164
1167
  'advertising_set_termination',
1165
1168
  event.status,
@@ -1168,7 +1171,9 @@ class Host(utils.EventEmitter):
1168
1171
  event.num_completed_extended_advertising_events,
1169
1172
  )
1170
1173
 
1171
- def on_hci_le_periodic_advertising_sync_established_event(self, event):
1174
+ def on_hci_le_periodic_advertising_sync_established_event(
1175
+ self, event: hci.HCI_LE_Periodic_Advertising_Sync_Established_Event
1176
+ ):
1172
1177
  self.emit(
1173
1178
  'periodic_advertising_sync_establishment',
1174
1179
  event.status,
@@ -1180,16 +1185,22 @@ class Host(utils.EventEmitter):
1180
1185
  event.advertiser_clock_accuracy,
1181
1186
  )
1182
1187
 
1183
- def on_hci_le_periodic_advertising_sync_lost_event(self, event):
1188
+ def on_hci_le_periodic_advertising_sync_lost_event(
1189
+ self, event: hci.HCI_LE_Periodic_Advertising_Sync_Lost_Event
1190
+ ):
1184
1191
  self.emit('periodic_advertising_sync_loss', event.sync_handle)
1185
1192
 
1186
- def on_hci_le_periodic_advertising_report_event(self, event):
1193
+ def on_hci_le_periodic_advertising_report_event(
1194
+ self, event: hci.HCI_LE_Periodic_Advertising_Report_Event
1195
+ ):
1187
1196
  self.emit('periodic_advertising_report', event.sync_handle, event)
1188
1197
 
1189
- def on_hci_le_biginfo_advertising_report_event(self, event):
1198
+ def on_hci_le_biginfo_advertising_report_event(
1199
+ self, event: hci.HCI_LE_BIGInfo_Advertising_Report_Event
1200
+ ):
1190
1201
  self.emit('biginfo_advertising_report', event.sync_handle, event)
1191
1202
 
1192
- def on_hci_le_cis_request_event(self, event):
1203
+ def on_hci_le_cis_request_event(self, event: hci.HCI_LE_CIS_Request_Event):
1193
1204
  self.emit(
1194
1205
  'cis_request',
1195
1206
  event.acl_connection_handle,
@@ -1198,10 +1209,12 @@ class Host(utils.EventEmitter):
1198
1209
  event.cis_id,
1199
1210
  )
1200
1211
 
1201
- def on_hci_le_create_big_complete_event(self, event):
1212
+ def on_hci_le_create_big_complete_event(
1213
+ self, event: hci.HCI_LE_Create_BIG_Complete_Event
1214
+ ):
1202
1215
  self.bigs[event.big_handle] = set(event.connection_handle)
1203
1216
  if self.iso_packet_queue is None:
1204
- logger.warning("BIS established but ISO packets not supported")
1217
+ raise InvalidStateError("BIS established but ISO packets not supported")
1205
1218
 
1206
1219
  for connection_handle in event.connection_handle:
1207
1220
  self.bis_links[connection_handle] = IsoLink(
@@ -1224,8 +1237,13 @@ class Host(utils.EventEmitter):
1224
1237
  event.iso_interval,
1225
1238
  )
1226
1239
 
1227
- def on_hci_le_big_sync_established_event(self, event):
1240
+ def on_hci_le_big_sync_established_event(
1241
+ self, event: hci.HCI_LE_BIG_Sync_Established_Event
1242
+ ):
1228
1243
  self.bigs[event.big_handle] = set(event.connection_handle)
1244
+ if self.iso_packet_queue is None:
1245
+ raise InvalidStateError("BIS established but ISO packets not supported")
1246
+
1229
1247
  for connection_handle in event.connection_handle:
1230
1248
  self.bis_links[connection_handle] = IsoLink(
1231
1249
  connection_handle, self.iso_packet_queue
@@ -1245,15 +1263,19 @@ class Host(utils.EventEmitter):
1245
1263
  event.connection_handle,
1246
1264
  )
1247
1265
 
1248
- def on_hci_le_big_sync_lost_event(self, event):
1266
+ def on_hci_le_big_sync_lost_event(self, event: hci.HCI_LE_BIG_Sync_Lost_Event):
1249
1267
  self.remove_big(event.big_handle)
1250
1268
  self.emit('big_sync_lost', event.big_handle, event.reason)
1251
1269
 
1252
- def on_hci_le_terminate_big_complete_event(self, event):
1270
+ def on_hci_le_terminate_big_complete_event(
1271
+ self, event: hci.HCI_LE_Terminate_BIG_Complete_Event
1272
+ ):
1253
1273
  self.remove_big(event.big_handle)
1254
1274
  self.emit('big_termination', event.reason, event.big_handle)
1255
1275
 
1256
- def on_hci_le_periodic_advertising_sync_transfer_received_event(self, event):
1276
+ def on_hci_le_periodic_advertising_sync_transfer_received_event(
1277
+ self, event: hci.HCI_LE_Periodic_Advertising_Sync_Transfer_Received_Event
1278
+ ):
1257
1279
  self.emit(
1258
1280
  'periodic_advertising_sync_transfer',
1259
1281
  event.status,
@@ -1266,7 +1288,9 @@ class Host(utils.EventEmitter):
1266
1288
  event.advertiser_clock_accuracy,
1267
1289
  )
1268
1290
 
1269
- def on_hci_le_periodic_advertising_sync_transfer_received_v2_event(self, event):
1291
+ def on_hci_le_periodic_advertising_sync_transfer_received_v2_event(
1292
+ self, event: hci.HCI_LE_Periodic_Advertising_Sync_Transfer_Received_V2_Event
1293
+ ):
1270
1294
  self.emit(
1271
1295
  'periodic_advertising_sync_transfer',
1272
1296
  event.status,
@@ -1279,11 +1303,11 @@ class Host(utils.EventEmitter):
1279
1303
  event.advertiser_clock_accuracy,
1280
1304
  )
1281
1305
 
1282
- def on_hci_le_cis_established_event(self, event):
1306
+ def on_hci_le_cis_established_event(self, event: hci.HCI_LE_CIS_Established_Event):
1283
1307
  # The remaining parameters are unused for now.
1284
1308
  if event.status == hci.HCI_SUCCESS:
1285
1309
  if self.iso_packet_queue is None:
1286
- logger.warning("CIS established but ISO packets not supported")
1310
+ raise InvalidStateError("CIS established but ISO packets not supported")
1287
1311
  self.cis_links[event.connection_handle] = IsoLink(
1288
1312
  handle=event.connection_handle, packet_queue=self.iso_packet_queue
1289
1313
  )
@@ -1310,7 +1334,9 @@ class Host(utils.EventEmitter):
1310
1334
  'cis_establishment_failure', event.connection_handle, event.status
1311
1335
  )
1312
1336
 
1313
- def on_hci_le_remote_connection_parameter_request_event(self, event):
1337
+ def on_hci_le_remote_connection_parameter_request_event(
1338
+ self, event: hci.HCI_LE_Remote_Connection_Parameter_Request_Event
1339
+ ):
1314
1340
  if event.connection_handle not in self.connections:
1315
1341
  logger.warning('!!! REMOTE CONNECTION PARAMETER REQUEST: unknown handle')
1316
1342
  return
@@ -1329,7 +1355,9 @@ class Host(utils.EventEmitter):
1329
1355
  )
1330
1356
  )
1331
1357
 
1332
- def on_hci_le_long_term_key_request_event(self, event):
1358
+ def on_hci_le_long_term_key_request_event(
1359
+ self, event: hci.HCI_LE_Long_Term_Key_Request_Event
1360
+ ):
1333
1361
  if (connection := self.connections.get(event.connection_handle)) is None:
1334
1362
  logger.warning('!!! LE LONG TERM KEY REQUEST: unknown handle')
1335
1363
  return
@@ -1363,7 +1391,9 @@ class Host(utils.EventEmitter):
1363
1391
 
1364
1392
  asyncio.create_task(send_long_term_key())
1365
1393
 
1366
- def on_hci_synchronous_connection_complete_event(self, event):
1394
+ def on_hci_synchronous_connection_complete_event(
1395
+ self, event: hci.HCI_Synchronous_Connection_Complete_Event
1396
+ ):
1367
1397
  if event.status == hci.HCI_SUCCESS:
1368
1398
  # Create/update the connection
1369
1399
  logger.debug(
@@ -1389,7 +1419,9 @@ class Host(utils.EventEmitter):
1389
1419
  # Notify the client
1390
1420
  self.emit('sco_connection_failure', event.bd_addr, event.status)
1391
1421
 
1392
- def on_hci_synchronous_connection_changed_event(self, event):
1422
+ def on_hci_synchronous_connection_changed_event(
1423
+ self, event: hci.HCI_Synchronous_Connection_Changed_Event
1424
+ ):
1393
1425
  pass
1394
1426
 
1395
1427
  def on_hci_mode_change_event(self, event: hci.HCI_Mode_Change_Event):
@@ -1401,7 +1433,7 @@ class Host(utils.EventEmitter):
1401
1433
  event.interval,
1402
1434
  )
1403
1435
 
1404
- def on_hci_role_change_event(self, event):
1436
+ def on_hci_role_change_event(self, event: hci.HCI_Role_Change_Event):
1405
1437
  if event.status == hci.HCI_SUCCESS:
1406
1438
  logger.debug(
1407
1439
  f'role change for {event.bd_addr}: '
@@ -1415,7 +1447,9 @@ class Host(utils.EventEmitter):
1415
1447
  )
1416
1448
  self.emit('role_change_failure', event.bd_addr, event.status)
1417
1449
 
1418
- def on_hci_le_data_length_change_event(self, event):
1450
+ def on_hci_le_data_length_change_event(
1451
+ self, event: hci.HCI_LE_Data_Length_Change_Event
1452
+ ):
1419
1453
  if (connection := self.connections.get(event.connection_handle)) is None:
1420
1454
  logger.warning('!!! DATA LENGTH CHANGE: unknown handle')
1421
1455
  return
@@ -1429,7 +1463,9 @@ class Host(utils.EventEmitter):
1429
1463
  event.max_rx_time,
1430
1464
  )
1431
1465
 
1432
- def on_hci_authentication_complete_event(self, event):
1466
+ def on_hci_authentication_complete_event(
1467
+ self, event: hci.HCI_Authentication_Complete_Event
1468
+ ):
1433
1469
  # Notify the client
1434
1470
  if event.status == hci.HCI_SUCCESS:
1435
1471
  self.emit('connection_authentication', event.connection_handle)
@@ -1470,7 +1506,9 @@ class Host(utils.EventEmitter):
1470
1506
  'connection_encryption_failure', event.connection_handle, event.status
1471
1507
  )
1472
1508
 
1473
- def on_hci_encryption_key_refresh_complete_event(self, event):
1509
+ def on_hci_encryption_key_refresh_complete_event(
1510
+ self, event: hci.HCI_Encryption_Key_Refresh_Complete_Event
1511
+ ):
1474
1512
  # Notify the client
1475
1513
  if event.status == hci.HCI_SUCCESS:
1476
1514
  self.emit('connection_encryption_key_refresh', event.connection_handle)
@@ -1481,7 +1519,7 @@ class Host(utils.EventEmitter):
1481
1519
  event.status,
1482
1520
  )
1483
1521
 
1484
- def on_hci_qos_setup_complete_event(self, event):
1522
+ def on_hci_qos_setup_complete_event(self, event: hci.HCI_QOS_Setup_Complete_Event):
1485
1523
  if event.status == hci.HCI_SUCCESS:
1486
1524
  self.emit(
1487
1525
  'connection_qos_setup', event.connection_handle, event.service_type
@@ -1493,23 +1531,31 @@ class Host(utils.EventEmitter):
1493
1531
  event.status,
1494
1532
  )
1495
1533
 
1496
- def on_hci_link_supervision_timeout_changed_event(self, event):
1534
+ def on_hci_link_supervision_timeout_changed_event(
1535
+ self, event: hci.HCI_Link_Supervision_Timeout_Changed_Event
1536
+ ):
1497
1537
  pass
1498
1538
 
1499
- def on_hci_max_slots_change_event(self, event):
1539
+ def on_hci_max_slots_change_event(self, event: hci.HCI_Max_Slots_Change_Event):
1500
1540
  pass
1501
1541
 
1502
- def on_hci_page_scan_repetition_mode_change_event(self, event):
1542
+ def on_hci_page_scan_repetition_mode_change_event(
1543
+ self, event: hci.HCI_Page_Scan_Repetition_Mode_Change_Event
1544
+ ):
1503
1545
  pass
1504
1546
 
1505
- def on_hci_link_key_notification_event(self, event):
1547
+ def on_hci_link_key_notification_event(
1548
+ self, event: hci.HCI_Link_Key_Notification_Event
1549
+ ):
1506
1550
  logger.debug(
1507
1551
  f'link key for {event.bd_addr}: {event.link_key.hex()}, '
1508
1552
  f'type={hci.HCI_Constant.link_key_type_name(event.key_type)}'
1509
1553
  )
1510
1554
  self.emit('link_key', event.bd_addr, event.link_key, event.key_type)
1511
1555
 
1512
- def on_hci_simple_pairing_complete_event(self, event):
1556
+ def on_hci_simple_pairing_complete_event(
1557
+ self, event: hci.HCI_Simple_Pairing_Complete_Event
1558
+ ):
1513
1559
  logger.debug(
1514
1560
  f'simple pairing complete for {event.bd_addr}: '
1515
1561
  f'status={hci.HCI_Constant.status_name(event.status)}'
@@ -1519,10 +1565,10 @@ class Host(utils.EventEmitter):
1519
1565
  else:
1520
1566
  self.emit('classic_pairing_failure', event.bd_addr, event.status)
1521
1567
 
1522
- def on_hci_pin_code_request_event(self, event):
1568
+ def on_hci_pin_code_request_event(self, event: hci.HCI_PIN_Code_Request_Event):
1523
1569
  self.emit('pin_code_request', event.bd_addr)
1524
1570
 
1525
- def on_hci_link_key_request_event(self, event):
1571
+ def on_hci_link_key_request_event(self, event: hci.HCI_Link_Key_Request_Event):
1526
1572
  async def send_link_key():
1527
1573
  if self.link_key_provider is None:
1528
1574
  logger.debug('no link key provider')
@@ -1547,10 +1593,14 @@ class Host(utils.EventEmitter):
1547
1593
 
1548
1594
  asyncio.create_task(send_link_key())
1549
1595
 
1550
- def on_hci_io_capability_request_event(self, event):
1596
+ def on_hci_io_capability_request_event(
1597
+ self, event: hci.HCI_IO_Capability_Request_Event
1598
+ ):
1551
1599
  self.emit('authentication_io_capability_request', event.bd_addr)
1552
1600
 
1553
- def on_hci_io_capability_response_event(self, event):
1601
+ def on_hci_io_capability_response_event(
1602
+ self, event: hci.HCI_IO_Capability_Response_Event
1603
+ ):
1554
1604
  self.emit(
1555
1605
  'authentication_io_capability_response',
1556
1606
  event.bd_addr,
@@ -1558,25 +1608,33 @@ class Host(utils.EventEmitter):
1558
1608
  event.authentication_requirements,
1559
1609
  )
1560
1610
 
1561
- def on_hci_user_confirmation_request_event(self, event):
1611
+ def on_hci_user_confirmation_request_event(
1612
+ self, event: hci.HCI_User_Confirmation_Request_Event
1613
+ ):
1562
1614
  self.emit(
1563
1615
  'authentication_user_confirmation_request',
1564
1616
  event.bd_addr,
1565
1617
  event.numeric_value,
1566
1618
  )
1567
1619
 
1568
- def on_hci_user_passkey_request_event(self, event):
1620
+ def on_hci_user_passkey_request_event(
1621
+ self, event: hci.HCI_User_Passkey_Request_Event
1622
+ ):
1569
1623
  self.emit('authentication_user_passkey_request', event.bd_addr)
1570
1624
 
1571
- def on_hci_user_passkey_notification_event(self, event):
1625
+ def on_hci_user_passkey_notification_event(
1626
+ self, event: hci.HCI_User_Passkey_Notification_Event
1627
+ ):
1572
1628
  self.emit(
1573
1629
  'authentication_user_passkey_notification', event.bd_addr, event.passkey
1574
1630
  )
1575
1631
 
1576
- def on_hci_inquiry_complete_event(self, _event):
1632
+ def on_hci_inquiry_complete_event(self, _event: hci.HCI_Inquiry_Complete_Event):
1577
1633
  self.emit('inquiry_complete')
1578
1634
 
1579
- def on_hci_inquiry_result_with_rssi_event(self, event):
1635
+ def on_hci_inquiry_result_with_rssi_event(
1636
+ self, event: hci.HCI_Inquiry_Result_With_RSSI_Event
1637
+ ):
1580
1638
  for bd_addr, class_of_device, rssi in zip(
1581
1639
  event.bd_addr, event.class_of_device, event.rssi
1582
1640
  ):
@@ -1588,7 +1646,9 @@ class Host(utils.EventEmitter):
1588
1646
  rssi,
1589
1647
  )
1590
1648
 
1591
- def on_hci_extended_inquiry_result_event(self, event):
1649
+ def on_hci_extended_inquiry_result_event(
1650
+ self, event: hci.HCI_Extended_Inquiry_Result_Event
1651
+ ):
1592
1652
  self.emit(
1593
1653
  'inquiry_result',
1594
1654
  event.bd_addr,
@@ -1597,7 +1657,9 @@ class Host(utils.EventEmitter):
1597
1657
  event.rssi,
1598
1658
  )
1599
1659
 
1600
- def on_hci_remote_name_request_complete_event(self, event):
1660
+ def on_hci_remote_name_request_complete_event(
1661
+ self, event: hci.HCI_Remote_Name_Request_Complete_Event
1662
+ ):
1601
1663
  if event.status != hci.HCI_SUCCESS:
1602
1664
  self.emit('remote_name_failure', event.bd_addr, event.status)
1603
1665
  else:
@@ -1608,14 +1670,18 @@ class Host(utils.EventEmitter):
1608
1670
 
1609
1671
  self.emit('remote_name', event.bd_addr, utf8_name)
1610
1672
 
1611
- def on_hci_remote_host_supported_features_notification_event(self, event):
1673
+ def on_hci_remote_host_supported_features_notification_event(
1674
+ self, event: hci.HCI_Remote_Host_Supported_Features_Notification_Event
1675
+ ):
1612
1676
  self.emit(
1613
1677
  'remote_host_supported_features',
1614
1678
  event.bd_addr,
1615
1679
  event.host_supported_features,
1616
1680
  )
1617
1681
 
1618
- def on_hci_le_read_remote_features_complete_event(self, event):
1682
+ def on_hci_le_read_remote_features_complete_event(
1683
+ self, event: hci.HCI_LE_Read_Remote_Features_Complete_Event
1684
+ ):
1619
1685
  if event.status != hci.HCI_SUCCESS:
1620
1686
  self.emit(
1621
1687
  'le_remote_features_failure', event.connection_handle, event.status
@@ -1627,22 +1693,34 @@ class Host(utils.EventEmitter):
1627
1693
  int.from_bytes(event.le_features, 'little'),
1628
1694
  )
1629
1695
 
1630
- def on_hci_le_cs_read_remote_supported_capabilities_complete_event(self, event):
1696
+ def on_hci_le_cs_read_remote_supported_capabilities_complete_event(
1697
+ self, event: hci.HCI_LE_CS_Read_Remote_Supported_Capabilities_Complete_Event
1698
+ ):
1631
1699
  self.emit('cs_remote_supported_capabilities', event)
1632
1700
 
1633
- def on_hci_le_cs_security_enable_complete_event(self, event):
1701
+ def on_hci_le_cs_security_enable_complete_event(
1702
+ self, event: hci.HCI_LE_CS_Security_Enable_Complete_Event
1703
+ ):
1634
1704
  self.emit('cs_security', event)
1635
1705
 
1636
- def on_hci_le_cs_config_complete_event(self, event):
1706
+ def on_hci_le_cs_config_complete_event(
1707
+ self, event: hci.HCI_LE_CS_Config_Complete_Event
1708
+ ):
1637
1709
  self.emit('cs_config', event)
1638
1710
 
1639
- def on_hci_le_cs_procedure_enable_complete_event(self, event):
1711
+ def on_hci_le_cs_procedure_enable_complete_event(
1712
+ self, event: hci.HCI_LE_CS_Procedure_Enable_Complete_Event
1713
+ ):
1640
1714
  self.emit('cs_procedure', event)
1641
1715
 
1642
- def on_hci_le_cs_subevent_result_event(self, event):
1716
+ def on_hci_le_cs_subevent_result_event(
1717
+ self, event: hci.HCI_LE_CS_Subevent_Result_Event
1718
+ ):
1643
1719
  self.emit('cs_subevent_result', event)
1644
1720
 
1645
- def on_hci_le_cs_subevent_result_continue_event(self, event):
1721
+ def on_hci_le_cs_subevent_result_continue_event(
1722
+ self, event: hci.HCI_LE_CS_Subevent_Result_Continue_Event
1723
+ ):
1646
1724
  self.emit('cs_subevent_result_continue', event)
1647
1725
 
1648
1726
  def on_hci_le_subrate_change_event(self, event: hci.HCI_LE_Subrate_Change_Event):
@@ -1655,5 +1733,5 @@ class Host(utils.EventEmitter):
1655
1733
  event.supervision_timeout,
1656
1734
  )
1657
1735
 
1658
- def on_hci_vendor_event(self, event):
1736
+ def on_hci_vendor_event(self, event: hci.HCI_Vendor_Event):
1659
1737
  self.emit('vendor_event', event)
bumble/keys.py CHANGED
@@ -21,16 +21,18 @@
21
21
  # Imports
22
22
  # -----------------------------------------------------------------------------
23
23
  from __future__ import annotations
24
+
24
25
  import asyncio
25
26
  import dataclasses
27
+ import json
26
28
  import logging
27
29
  import os
28
- import json
29
- from typing import TYPE_CHECKING, Optional, Any
30
+ from typing import TYPE_CHECKING, Any, Optional
31
+
30
32
  from typing_extensions import Self
31
33
 
32
- from bumble.colors import color
33
34
  from bumble import hci
35
+ from bumble.colors import color
34
36
 
35
37
  if TYPE_CHECKING:
36
38
  from bumble.device import Device