bumble 0.0.222__py3-none-any.whl → 0.0.224__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 (43) hide show
  1. bumble/_version.py +2 -2
  2. bumble/apps/controller_info.py +90 -114
  3. bumble/apps/controller_loopback.py +11 -9
  4. bumble/apps/gg_bridge.py +1 -1
  5. bumble/apps/hci_bridge.py +3 -1
  6. bumble/apps/l2cap_bridge.py +1 -1
  7. bumble/apps/rfcomm_bridge.py +1 -1
  8. bumble/apps/scan.py +10 -4
  9. bumble/apps/speaker/speaker.py +1 -1
  10. bumble/apps/usb_probe.py +15 -2
  11. bumble/att.py +97 -32
  12. bumble/avctp.py +1 -1
  13. bumble/avdtp.py +3 -3
  14. bumble/avrcp.py +366 -190
  15. bumble/bridge.py +10 -2
  16. bumble/controller.py +14 -1
  17. bumble/core.py +1 -1
  18. bumble/device.py +999 -577
  19. bumble/drivers/intel.py +45 -39
  20. bumble/drivers/rtk.py +102 -43
  21. bumble/gatt.py +2 -2
  22. bumble/gatt_client.py +5 -4
  23. bumble/gatt_server.py +100 -1
  24. bumble/hci.py +1367 -844
  25. bumble/hid.py +2 -2
  26. bumble/host.py +339 -157
  27. bumble/l2cap.py +13 -6
  28. bumble/pandora/l2cap.py +1 -1
  29. bumble/profiles/battery_service.py +25 -34
  30. bumble/profiles/heart_rate_service.py +130 -121
  31. bumble/rfcomm.py +1 -1
  32. bumble/sdp.py +2 -2
  33. bumble/smp.py +8 -3
  34. bumble/snoop.py +111 -1
  35. bumble/transport/android_netsim.py +1 -1
  36. bumble/vendor/android/hci.py +108 -86
  37. bumble/vendor/zephyr/hci.py +24 -18
  38. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/METADATA +4 -3
  39. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/RECORD +43 -43
  40. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/WHEEL +1 -1
  41. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/entry_points.txt +0 -0
  42. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/licenses/LICENSE +0 -0
  43. {bumble-0.0.222.dist-info → bumble-0.0.224.dist-info}/top_level.txt +0 -0
bumble/snoop.py CHANGED
@@ -110,6 +110,53 @@ class BtSnooper(Snooper):
110
110
  )
111
111
 
112
112
 
113
+ # -----------------------------------------------------------------------------
114
+ class PcapSnooper(Snooper):
115
+ """
116
+ Snooper that saves or streames HCI packets using the PCAP format.
117
+ """
118
+
119
+ PCAP_MAGIC = 0xA1B2C3D4
120
+ DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 201
121
+
122
+ def __init__(self, output: BinaryIO):
123
+ self.output = output
124
+
125
+ # Write the header
126
+ self.output.write(
127
+ struct.pack(
128
+ "<IHHIIII",
129
+ self.PCAP_MAGIC,
130
+ 2, # Major PCAP Version
131
+ 4, # Minor PCAP Version
132
+ 0, # Reserved 1
133
+ 0, # Reserved 2
134
+ 65535, # SnapLen
135
+ # FCS and f are set to 0 implicitly by the next line
136
+ self.DLT_BLUETOOTH_HCI_H4_WITH_PHDR, # The DLT in this PCAP
137
+ )
138
+ )
139
+
140
+ def snoop(self, hci_packet: bytes, direction: Snooper.Direction):
141
+ now = datetime.datetime.now(datetime.timezone.utc)
142
+ sec = int(now.timestamp())
143
+ usec = now.microsecond
144
+
145
+ # Emit the record
146
+ self.output.write(
147
+ struct.pack(
148
+ "<IIII",
149
+ sec, # Timestamp (Seconds)
150
+ usec, # Timestamp (Microseconds)
151
+ len(hci_packet) + 4,
152
+ len(hci_packet) + 4, # +4 because of the addtional direction info...
153
+ )
154
+ + struct.pack(">I", int(direction)) # ...thats being added here
155
+ + hci_packet
156
+ )
157
+ self.output.flush() # flush after every packet for live logging
158
+
159
+
113
160
  # -----------------------------------------------------------------------------
114
161
  _SNOOPER_INSTANCE_COUNT = 0
115
162
 
@@ -140,9 +187,38 @@ def create_snooper(spec: str) -> Generator[Snooper, None, None]:
140
187
  pid: the current process ID.
141
188
  instance: the instance ID in the current process.
142
189
 
190
+ pcapsnoop
191
+ The syntax for the type-specific arguments for this type is:
192
+ <io-type>:<io-type-specific-arguments>
193
+
194
+ Supported I/O types are:
195
+
196
+ file
197
+ The type-specific arguments for this I/O type is a string that is converted
198
+ to a file path using the python `str.format()` string formatting. The log
199
+ records will be written to that file if it can be opened/created.
200
+ The keyword args that may be referenced by the string pattern are:
201
+ now: the value of `datetime.now()`
202
+ utcnow: the value of `datetime.now(tz=datetime.timezone.utc)`
203
+ pid: the current process ID.
204
+ instance: the instance ID in the current process.
205
+
206
+ pipe
207
+ The type-specific arguments for this I/O type is a string that is converted
208
+ to a path using the python `str.format()` string formatting. The log
209
+ records will be written to the named pipe referenced by this path
210
+ if it can be opened. The keyword args that may be referenced by the
211
+ string pattern are:
212
+ now: the value of `datetime.now()`
213
+ utcnow: the value of `datetime.now(tz=datetime.timezone.utc)`
214
+ pid: the current process ID.
215
+ instance: the instance ID in the current process.
216
+
143
217
  Examples:
144
218
  btsnoop:file:my_btsnoop.log
145
219
  btsnoop:file:/tmp/bumble_{now:%Y-%m-%d-%H:%M:%S}_{pid}.log
220
+ pcapsnoop:pipe:/tmp/bumble-extcap
221
+
146
222
 
147
223
  """
148
224
  if ':' not in spec:
@@ -150,6 +226,8 @@ def create_snooper(spec: str) -> Generator[Snooper, None, None]:
150
226
 
151
227
  snooper_type, snooper_args = spec.split(':', maxsplit=1)
152
228
 
229
+ global _SNOOPER_INSTANCE_COUNT
230
+
153
231
  if snooper_type == 'btsnoop':
154
232
  if ':' not in snooper_args:
155
233
  raise core.InvalidArgumentError('I/O type for btsnoop snooper type missing')
@@ -157,7 +235,6 @@ def create_snooper(spec: str) -> Generator[Snooper, None, None]:
157
235
  io_type, io_name = snooper_args.split(':', maxsplit=1)
158
236
  if io_type == 'file':
159
237
  # Process the file name string pattern.
160
- global _SNOOPER_INSTANCE_COUNT
161
238
  file_path = io_name.format(
162
239
  now=datetime.datetime.now(),
163
240
  utcnow=datetime.datetime.now(tz=datetime.timezone.utc),
@@ -173,6 +250,39 @@ def create_snooper(spec: str) -> Generator[Snooper, None, None]:
173
250
  _SNOOPER_INSTANCE_COUNT -= 1
174
251
  return
175
252
 
253
+ elif snooper_type == 'pcapsnoop':
254
+ if ':' not in snooper_args:
255
+ raise core.InvalidArgumentError(
256
+ 'I/O type for pcapsnoop snooper type missing'
257
+ )
258
+
259
+ io_type, io_name = snooper_args.split(':', maxsplit=1)
260
+ if io_type in {'pipe', 'file'}:
261
+ # Process the file name string pattern.
262
+ file_path = io_name.format(
263
+ now=datetime.datetime.now(),
264
+ utcnow=datetime.datetime.now(tz=datetime.timezone.utc),
265
+ pid=os.getpid(),
266
+ instance=_SNOOPER_INSTANCE_COUNT,
267
+ )
268
+
269
+ # Open a file or pipe
270
+ logger.debug(f'PCAP file: {file_path}')
271
+
272
+ # Pipes we have to open with unbuffered binary I/O
273
+ # so we pass ``buffering`` for pipes but not for files
274
+ pcap_file: BinaryIO
275
+ if io_type == 'pipe':
276
+ pcap_file = open(file_path, 'wb', buffering=0)
277
+ else:
278
+ pcap_file = open(file_path, 'wb')
279
+
280
+ with pcap_file:
281
+ _SNOOPER_INSTANCE_COUNT += 1
282
+ yield PcapSnooper(pcap_file)
283
+ _SNOOPER_INSTANCE_COUNT -= 1
284
+ return
285
+
176
286
  raise core.InvalidArgumentError(f'I/O type {io_type} not supported')
177
287
 
178
288
  raise core.InvalidArgumentError(f'snooper type {snooper_type} not found')
@@ -194,7 +194,7 @@ async def open_android_netsim_controller_transport(
194
194
 
195
195
  # We only accept BLUETOOTH
196
196
  if request.initial_info.chip.kind != ChipKind.BLUETOOTH:
197
- logger.warning('Unsupported chip type')
197
+ logger.debug('Request for unsupported chip type')
198
198
  error = PacketResponse(error='Unsupported chip type')
199
199
  await self.context.write(error)
200
200
  # return
@@ -43,44 +43,53 @@ hci.HCI_Command.register_commands(globals())
43
43
 
44
44
 
45
45
  # -----------------------------------------------------------------------------
46
- @hci.HCI_Command.command
47
46
  @dataclasses.dataclass
48
- class HCI_LE_Get_Vendor_Capabilities_Command(hci.HCI_Command):
47
+ class HCI_LE_Get_Vendor_Capabilities_ReturnParameters(hci.HCI_StatusReturnParameters):
48
+ max_advt_instances: int = field(metadata=hci.metadata(1), default=0)
49
+ offloaded_resolution_of_private_address: int = field(
50
+ metadata=hci.metadata(1), default=0
51
+ )
52
+ total_scan_results_storage: int = field(metadata=hci.metadata(2), default=0)
53
+ max_irk_list_sz: int = field(metadata=hci.metadata(1), default=0)
54
+ filtering_support: int = field(metadata=hci.metadata(1), default=0)
55
+ max_filter: int = field(metadata=hci.metadata(1), default=0)
56
+ activity_energy_info_support: int = field(metadata=hci.metadata(1), default=0)
57
+ version_supported: int = field(metadata=hci.metadata(2), default=0)
58
+ total_num_of_advt_tracked: int = field(metadata=hci.metadata(2), default=0)
59
+ extended_scan_support: int = field(metadata=hci.metadata(1), default=0)
60
+ debug_logging_supported: int = field(metadata=hci.metadata(1), default=0)
61
+ le_address_generation_offloading_support: int = field(
62
+ metadata=hci.metadata(1), default=0
63
+ )
64
+ a2dp_source_offload_capability_mask: int = field(
65
+ metadata=hci.metadata(4), default=0
66
+ )
67
+ bluetooth_quality_report_support: int = field(metadata=hci.metadata(1), default=0)
68
+ dynamic_audio_buffer_support: int = field(metadata=hci.metadata(4), default=0)
69
+
70
+
71
+ @hci.HCI_SyncCommand.sync_command(HCI_LE_Get_Vendor_Capabilities_ReturnParameters)
72
+ @dataclasses.dataclass
73
+ class HCI_LE_Get_Vendor_Capabilities_Command(
74
+ hci.HCI_SyncCommand[HCI_LE_Get_Vendor_Capabilities_ReturnParameters]
75
+ ):
49
76
  # pylint: disable=line-too-long
50
77
  '''
51
78
  See https://source.android.com/docs/core/connect/bluetooth/hci_requirements#vendor-specific-capabilities
52
79
  '''
53
80
 
54
- return_parameters_fields = [
55
- ('status', hci.STATUS_SPEC),
56
- ('max_advt_instances', 1),
57
- ('offloaded_resolution_of_private_address', 1),
58
- ('total_scan_results_storage', 2),
59
- ('max_irk_list_sz', 1),
60
- ('filtering_support', 1),
61
- ('max_filter', 1),
62
- ('activity_energy_info_support', 1),
63
- ('version_supported', 2),
64
- ('total_num_of_advt_tracked', 2),
65
- ('extended_scan_support', 1),
66
- ('debug_logging_supported', 1),
67
- ('le_address_generation_offloading_support', 1),
68
- ('a2dp_source_offload_capability_mask', 4),
69
- ('bluetooth_quality_report_support', 1),
70
- ('dynamic_audio_buffer_support', 4),
71
- ]
72
-
73
81
  @classmethod
74
82
  def parse_return_parameters(cls, parameters):
75
83
  # There are many versions of this data structure, so we need to parse until
76
- # there are no more bytes to parse, and leave un-signal parameters set to
77
- # None (older versions)
78
- nones = {field: None for field, _ in cls.return_parameters_fields}
79
- return_parameters = hci.HCI_Object(cls.return_parameters_fields, **nones)
84
+ # there are no more bytes to parse, and leave un-signaled parameters set to
85
+ # 0
86
+ return_parameters = HCI_LE_Get_Vendor_Capabilities_ReturnParameters(
87
+ hci.HCI_ErrorCode.SUCCESS
88
+ )
80
89
 
81
90
  try:
82
91
  offset = 0
83
- for field in cls.return_parameters_fields:
92
+ for field in cls.return_parameters_class.fields:
84
93
  field_name, field_type = field
85
94
  field_value, field_size = hci.HCI_Object.parse_field(
86
95
  parameters, offset, field_type
@@ -94,9 +103,30 @@ class HCI_LE_Get_Vendor_Capabilities_Command(hci.HCI_Command):
94
103
 
95
104
 
96
105
  # -----------------------------------------------------------------------------
97
- @hci.HCI_Command.command
106
+ # APCF Subcommands
107
+ class LeApcfOpcode(hci.SpecableEnum):
108
+ ENABLE = 0x00
109
+ SET_FILTERING_PARAMETERS = 0x01
110
+ BROADCASTER_ADDRESS = 0x02
111
+ SERVICE_UUID = 0x03
112
+ SERVICE_SOLICITATION_UUID = 0x04
113
+ LOCAL_NAME = 0x05
114
+ MANUFACTURER_DATA = 0x06
115
+ SERVICE_DATA = 0x07
116
+ TRANSPORT_DISCOVERY_SERVICE = 0x08
117
+ AD_TYPE_FILTER = 0x09
118
+ READ_EXTENDED_FEATURES = 0xFF
119
+
120
+
121
+ @dataclasses.dataclass
122
+ class HCI_LE_APCF_ReturnParameters(hci.HCI_StatusReturnParameters):
123
+ opcode: int = field(metadata=LeApcfOpcode.type_metadata(1))
124
+ payload: bytes = field(metadata=hci.metadata('*'))
125
+
126
+
127
+ @hci.HCI_SyncCommand.sync_command(HCI_LE_APCF_ReturnParameters)
98
128
  @dataclasses.dataclass
99
- class HCI_LE_APCF_Command(hci.HCI_Command):
129
+ class HCI_LE_APCF_Command(hci.HCI_SyncCommand[HCI_LE_APCF_ReturnParameters]):
100
130
  # pylint: disable=line-too-long
101
131
  '''
102
132
  See https://source.android.com/docs/core/connect/bluetooth/hci_requirements#le_apcf_command
@@ -105,52 +135,52 @@ class HCI_LE_APCF_Command(hci.HCI_Command):
105
135
  implementation. A future enhancement may define subcommand-specific data structures.
106
136
  '''
107
137
 
108
- # APCF Subcommands
109
- class Opcode(hci.SpecableEnum):
110
- ENABLE = 0x00
111
- SET_FILTERING_PARAMETERS = 0x01
112
- BROADCASTER_ADDRESS = 0x02
113
- SERVICE_UUID = 0x03
114
- SERVICE_SOLICITATION_UUID = 0x04
115
- LOCAL_NAME = 0x05
116
- MANUFACTURER_DATA = 0x06
117
- SERVICE_DATA = 0x07
118
- TRANSPORT_DISCOVERY_SERVICE = 0x08
119
- AD_TYPE_FILTER = 0x09
120
- READ_EXTENDED_FEATURES = 0xFF
121
-
122
- opcode: int = dataclasses.field(metadata=Opcode.type_metadata(1))
138
+ opcode: int = dataclasses.field(metadata=LeApcfOpcode.type_metadata(1))
123
139
  payload: bytes = dataclasses.field(metadata=hci.metadata("*"))
124
140
 
125
- return_parameters_fields = [
126
- ('status', hci.STATUS_SPEC),
127
- ('opcode', Opcode.type_spec(1)),
128
- ('payload', '*'),
129
- ]
130
-
131
141
 
132
142
  # -----------------------------------------------------------------------------
133
- @hci.HCI_Command.command
134
143
  @dataclasses.dataclass
135
- class HCI_Get_Controller_Activity_Energy_Info_Command(hci.HCI_Command):
144
+ class HCI_Get_Controller_Activity_Energy_Info_ReturnParameters(
145
+ hci.HCI_StatusReturnParameters
146
+ ):
147
+ total_tx_time_ms: int = field(metadata=hci.metadata(4))
148
+ total_rx_time_ms: int = field(metadata=hci.metadata(4))
149
+ total_idle_time_ms: int = field(metadata=hci.metadata(4))
150
+ total_energy_used: int = field(metadata=hci.metadata(4))
151
+
152
+
153
+ @hci.HCI_SyncCommand.sync_command(
154
+ HCI_Get_Controller_Activity_Energy_Info_ReturnParameters
155
+ )
156
+ @dataclasses.dataclass
157
+ class HCI_Get_Controller_Activity_Energy_Info_Command(
158
+ hci.HCI_SyncCommand[HCI_Get_Controller_Activity_Energy_Info_ReturnParameters]
159
+ ):
136
160
  # pylint: disable=line-too-long
137
161
  '''
138
162
  See https://source.android.com/docs/core/connect/bluetooth/hci_requirements#le_get_controller_activity_energy_info
139
163
  '''
140
164
 
141
- return_parameters_fields = [
142
- ('status', hci.STATUS_SPEC),
143
- ('total_tx_time_ms', 4),
144
- ('total_rx_time_ms', 4),
145
- ('total_idle_time_ms', 4),
146
- ('total_energy_used', 4),
147
- ]
148
-
149
165
 
150
166
  # -----------------------------------------------------------------------------
151
- @hci.HCI_Command.command
167
+ # A2DP Hardware Offload Subcommands
168
+ class A2dpHardwareOffloadOpcode(hci.SpecableEnum):
169
+ START_A2DP_OFFLOAD = 0x01
170
+ STOP_A2DP_OFFLOAD = 0x02
171
+
172
+
173
+ @dataclasses.dataclass
174
+ class HCI_A2DP_Hardware_Offload_ReturnParameters(hci.HCI_StatusReturnParameters):
175
+ opcode: int = dataclasses.field(metadata=A2dpHardwareOffloadOpcode.type_metadata(1))
176
+ payload: bytes = dataclasses.field(metadata=hci.metadata("*"))
177
+
178
+
179
+ @hci.HCI_SyncCommand.sync_command(HCI_A2DP_Hardware_Offload_ReturnParameters)
152
180
  @dataclasses.dataclass
153
- class HCI_A2DP_Hardware_Offload_Command(hci.HCI_Command):
181
+ class HCI_A2DP_Hardware_Offload_Command(
182
+ hci.HCI_SyncCommand[HCI_A2DP_Hardware_Offload_ReturnParameters]
183
+ ):
154
184
  # pylint: disable=line-too-long
155
185
  '''
156
186
  See https://source.android.com/docs/core/connect/bluetooth/hci_requirements#a2dp-hardware-offload-support
@@ -159,25 +189,27 @@ class HCI_A2DP_Hardware_Offload_Command(hci.HCI_Command):
159
189
  implementation. A future enhancement may define subcommand-specific data structures.
160
190
  '''
161
191
 
162
- # A2DP Hardware Offload Subcommands
163
- class Opcode(hci.SpecableEnum):
164
- START_A2DP_OFFLOAD = 0x01
165
- STOP_A2DP_OFFLOAD = 0x02
166
-
167
- opcode: int = dataclasses.field(metadata=Opcode.type_metadata(1))
192
+ opcode: int = dataclasses.field(metadata=A2dpHardwareOffloadOpcode.type_metadata(1))
168
193
  payload: bytes = dataclasses.field(metadata=hci.metadata("*"))
169
194
 
170
- return_parameters_fields = [
171
- ('status', hci.STATUS_SPEC),
172
- ('opcode', Opcode.type_spec(1)),
173
- ('payload', '*'),
174
- ]
175
-
176
195
 
177
196
  # -----------------------------------------------------------------------------
178
- @hci.HCI_Command.command
197
+ # Dynamic Audio Buffer Subcommands
198
+ class DynamicAudioBufferOpcode(hci.SpecableEnum):
199
+ GET_AUDIO_BUFFER_TIME_CAPABILITY = 0x01
200
+
201
+
179
202
  @dataclasses.dataclass
180
- class HCI_Dynamic_Audio_Buffer_Command(hci.HCI_Command):
203
+ class HCI_Dynamic_Audio_Buffer_ReturnParameters(hci.HCI_StatusReturnParameters):
204
+ opcode: int = dataclasses.field(metadata=DynamicAudioBufferOpcode.type_metadata(1))
205
+ payload: bytes = dataclasses.field(metadata=hci.metadata("*"))
206
+
207
+
208
+ @hci.HCI_SyncCommand.sync_command(HCI_Dynamic_Audio_Buffer_ReturnParameters)
209
+ @dataclasses.dataclass
210
+ class HCI_Dynamic_Audio_Buffer_Command(
211
+ hci.HCI_SyncCommand[HCI_Dynamic_Audio_Buffer_ReturnParameters]
212
+ ):
181
213
  # pylint: disable=line-too-long
182
214
  '''
183
215
  See https://source.android.com/docs/core/connect/bluetooth/hci_requirements#dynamic-audio-buffer-command
@@ -186,19 +218,9 @@ class HCI_Dynamic_Audio_Buffer_Command(hci.HCI_Command):
186
218
  implementation. A future enhancement may define subcommand-specific data structures.
187
219
  '''
188
220
 
189
- # Dynamic Audio Buffer Subcommands
190
- class Opcode(hci.SpecableEnum):
191
- GET_AUDIO_BUFFER_TIME_CAPABILITY = 0x01
192
-
193
- opcode: int = dataclasses.field(metadata=Opcode.type_metadata(1))
221
+ opcode: int = dataclasses.field(metadata=DynamicAudioBufferOpcode.type_metadata(1))
194
222
  payload: bytes = dataclasses.field(metadata=hci.metadata("*"))
195
223
 
196
- return_parameters_fields = [
197
- ('status', hci.STATUS_SPEC),
198
- ('opcode', Opcode.type_spec(1)),
199
- ('payload', '*'),
200
- ]
201
-
202
224
 
203
225
  # -----------------------------------------------------------------------------
204
226
  class HCI_Android_Vendor_Event(hci.HCI_Extended_Event):
@@ -46,9 +46,19 @@ class TX_Power_Level_Command:
46
46
 
47
47
 
48
48
  # -----------------------------------------------------------------------------
49
- @hci.HCI_Command.command
50
49
  @dataclasses.dataclass
51
- class HCI_Write_Tx_Power_Level_Command(hci.HCI_Command, TX_Power_Level_Command):
50
+ class HCI_Write_Tx_Power_Level_ReturnParameters(hci.HCI_StatusReturnParameters):
51
+ handle_type: int = hci.field(metadata=hci.metadata(1))
52
+ connection_handle: int = hci.field(metadata=hci.metadata(2))
53
+ selected_tx_power_level: int = hci.field(metadata=hci.metadata(-1))
54
+
55
+
56
+ @hci.HCI_SyncCommand.sync_command(HCI_Write_Tx_Power_Level_ReturnParameters)
57
+ @dataclasses.dataclass
58
+ class HCI_Write_Tx_Power_Level_Command(
59
+ hci.HCI_SyncCommand[HCI_Write_Tx_Power_Level_ReturnParameters],
60
+ TX_Power_Level_Command,
61
+ ):
52
62
  '''
53
63
  Write TX power level. See BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL in
54
64
  https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/bluetooth/hci_vs.h
@@ -61,18 +71,21 @@ class HCI_Write_Tx_Power_Level_Command(hci.HCI_Command, TX_Power_Level_Command):
61
71
  connection_handle: int = dataclasses.field(metadata=hci.metadata(2))
62
72
  tx_power_level: int = dataclasses.field(metadata=hci.metadata(-1))
63
73
 
64
- return_parameters_fields = [
65
- ('status', hci.STATUS_SPEC),
66
- ('handle_type', 1),
67
- ('connection_handle', 2),
68
- ('selected_tx_power_level', -1),
69
- ]
70
-
71
74
 
72
75
  # -----------------------------------------------------------------------------
73
- @hci.HCI_Command.command
74
76
  @dataclasses.dataclass
75
- class HCI_Read_Tx_Power_Level_Command(hci.HCI_Command, TX_Power_Level_Command):
77
+ class HCI_Read_Tx_Power_Level_ReturnParameters(hci.HCI_StatusReturnParameters):
78
+ handle_type: int = hci.field(metadata=hci.metadata(1))
79
+ connection_handle: int = hci.field(metadata=hci.metadata(2))
80
+ tx_power_level: int = hci.field(metadata=hci.metadata(-1))
81
+
82
+
83
+ @hci.HCI_SyncCommand.sync_command(HCI_Read_Tx_Power_Level_ReturnParameters)
84
+ @dataclasses.dataclass
85
+ class HCI_Read_Tx_Power_Level_Command(
86
+ hci.HCI_SyncCommand[HCI_Read_Tx_Power_Level_ReturnParameters],
87
+ TX_Power_Level_Command,
88
+ ):
76
89
  '''
77
90
  Read TX power level. See BT_HCI_OP_VS_READ_TX_POWER_LEVEL in
78
91
  https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/bluetooth/hci_vs.h
@@ -83,10 +96,3 @@ class HCI_Read_Tx_Power_Level_Command(hci.HCI_Command, TX_Power_Level_Command):
83
96
 
84
97
  handle_type: int = dataclasses.field(metadata=hci.metadata(1))
85
98
  connection_handle: int = dataclasses.field(metadata=hci.metadata(2))
86
-
87
- return_parameters_fields = [
88
- ('status', hci.STATUS_SPEC),
89
- ('handle_type', 1),
90
- ('connection_handle', 2),
91
- ('tx_power_level', -1),
92
- ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bumble
3
- Version: 0.0.222
3
+ Version: 0.0.224
4
4
  Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
5
5
  Author-email: Google <bumble-dev@google.com>
6
6
  License-Expression: Apache-2.0
@@ -11,12 +11,13 @@ License-File: LICENSE
11
11
  Requires-Dist: aiohttp~=3.8; platform_system != "Emscripten"
12
12
  Requires-Dist: appdirs>=1.4; platform_system != "Emscripten"
13
13
  Requires-Dist: click>=8.1.3; platform_system != "Emscripten"
14
- Requires-Dist: cryptography>=44.0.3; platform_system != "Emscripten"
14
+ Requires-Dist: cryptography>=44.0.3; platform_system != "Emscripten" and platform_system != "Android"
15
15
  Requires-Dist: cryptography>=44.0.3; platform_system == "Emscripten"
16
+ Requires-Dist: cryptography>=42.0.8; platform_system == "Android"
16
17
  Requires-Dist: grpcio>=1.62.1; platform_system != "Emscripten"
17
18
  Requires-Dist: humanize>=4.6.0; platform_system != "Emscripten"
18
19
  Requires-Dist: libusb1>=2.0.1; platform_system != "Emscripten"
19
- Requires-Dist: libusb-package==1.0.26.1; platform_system != "Emscripten"
20
+ Requires-Dist: libusb-package==1.0.26.1; platform_system != "Emscripten" and platform_system != "Android"
20
21
  Requires-Dist: platformdirs>=3.10.0; platform_system != "Emscripten"
21
22
  Requires-Dist: prompt_toolkit>=3.0.16; platform_system != "Emscripten"
22
23
  Requires-Dist: prettytable>=3.6.0; platform_system != "Emscripten"