bumble 0.0.204__py3-none-any.whl → 0.0.207__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/apps/bench.py CHANGED
@@ -16,6 +16,7 @@
16
16
  # Imports
17
17
  # -----------------------------------------------------------------------------
18
18
  import asyncio
19
+ import dataclasses
19
20
  import enum
20
21
  import logging
21
22
  import os
@@ -97,34 +98,6 @@ DEFAULT_RFCOMM_MTU = 2048
97
98
  # -----------------------------------------------------------------------------
98
99
  # Utils
99
100
  # -----------------------------------------------------------------------------
100
- def parse_packet(packet):
101
- if len(packet) < 1:
102
- logging.info(
103
- color(f'!!! Packet too short (got {len(packet)} bytes, need >= 1)', 'red')
104
- )
105
- raise ValueError('packet too short')
106
-
107
- try:
108
- packet_type = PacketType(packet[0])
109
- except ValueError:
110
- logging.info(color(f'!!! Invalid packet type 0x{packet[0]:02X}', 'red'))
111
- raise
112
-
113
- return (packet_type, packet[1:])
114
-
115
-
116
- def parse_packet_sequence(packet_data):
117
- if len(packet_data) < 5:
118
- logging.info(
119
- color(
120
- f'!!!Packet too short (got {len(packet_data)} bytes, need >= 5)',
121
- 'red',
122
- )
123
- )
124
- raise ValueError('packet too short')
125
- return struct.unpack_from('>bI', packet_data, 0)
126
-
127
-
128
101
  def le_phy_name(phy_id):
129
102
  return {HCI_LE_1M_PHY: '1M', HCI_LE_2M_PHY: '2M', HCI_LE_CODED_PHY: 'CODED'}.get(
130
103
  phy_id, HCI_Constant.le_phy_name(phy_id)
@@ -225,13 +198,135 @@ async def switch_roles(connection, role):
225
198
  logging.info(f'{color("### Role switch failed:", "red")} {error}')
226
199
 
227
200
 
228
- class PacketType(enum.IntEnum):
229
- RESET = 0
230
- SEQUENCE = 1
231
- ACK = 2
201
+ # -----------------------------------------------------------------------------
202
+ # Packet
203
+ # -----------------------------------------------------------------------------
204
+ @dataclasses.dataclass
205
+ class Packet:
206
+ class PacketType(enum.IntEnum):
207
+ RESET = 0
208
+ SEQUENCE = 1
209
+ ACK = 2
210
+
211
+ class PacketFlags(enum.IntFlag):
212
+ LAST = 1
213
+
214
+ packet_type: PacketType
215
+ flags: PacketFlags = PacketFlags(0)
216
+ sequence: int = 0
217
+ timestamp: int = 0
218
+ payload: bytes = b""
219
+
220
+ @classmethod
221
+ def from_bytes(cls, data: bytes):
222
+ if len(data) < 1:
223
+ logging.warning(
224
+ color(f'!!! Packet too short (got {len(data)} bytes, need >= 1)', 'red')
225
+ )
226
+ raise ValueError('packet too short')
227
+
228
+ try:
229
+ packet_type = cls.PacketType(data[0])
230
+ except ValueError:
231
+ logging.warning(color(f'!!! Invalid packet type 0x{data[0]:02X}', 'red'))
232
+ raise
233
+
234
+ if packet_type == cls.PacketType.RESET:
235
+ return cls(packet_type)
236
+
237
+ flags = cls.PacketFlags(data[1])
238
+ (sequence,) = struct.unpack_from("<I", data, 2)
239
+
240
+ if packet_type == cls.PacketType.ACK:
241
+ if len(data) < 6:
242
+ logging.warning(
243
+ color(
244
+ f'!!! Packet too short (got {len(data)} bytes, need >= 6)',
245
+ 'red',
246
+ )
247
+ )
248
+ return cls(packet_type, flags, sequence)
249
+
250
+ if len(data) < 10:
251
+ logging.warning(
252
+ color(
253
+ f'!!! Packet too short (got {len(data)} bytes, need >= 10)', 'red'
254
+ )
255
+ )
256
+ raise ValueError('packet too short')
257
+
258
+ (timestamp,) = struct.unpack_from("<I", data, 6)
259
+ return cls(packet_type, flags, sequence, timestamp, data[10:])
260
+
261
+ def __bytes__(self):
262
+ if self.packet_type == self.PacketType.RESET:
263
+ return bytes([self.packet_type])
264
+
265
+ if self.packet_type == self.PacketType.ACK:
266
+ return struct.pack("<BBI", self.packet_type, self.flags, self.sequence)
267
+
268
+ return (
269
+ struct.pack(
270
+ "<BBII", self.packet_type, self.flags, self.sequence, self.timestamp
271
+ )
272
+ + self.payload
273
+ )
274
+
275
+
276
+ # -----------------------------------------------------------------------------
277
+ # Jitter Stats
278
+ # -----------------------------------------------------------------------------
279
+ class JitterStats:
280
+ def __init__(self):
281
+ self.reset()
282
+
283
+ def reset(self):
284
+ self.packets = []
285
+ self.receive_times = []
286
+ self.jitter = []
287
+
288
+ def on_packet_received(self, packet):
289
+ now = time.time()
290
+ self.packets.append(packet)
291
+ self.receive_times.append(now)
292
+
293
+ if packet.timestamp and len(self.packets) > 1:
294
+ expected_time = (
295
+ self.receive_times[0]
296
+ + (packet.timestamp - self.packets[0].timestamp) / 1000000
297
+ )
298
+ jitter = now - expected_time
299
+ else:
300
+ jitter = 0.0
232
301
 
302
+ self.jitter.append(jitter)
303
+ return jitter
233
304
 
234
- PACKET_FLAG_LAST = 1
305
+ def show_stats(self):
306
+ if len(self.jitter) < 3:
307
+ return
308
+ average = sum(self.jitter) / len(self.jitter)
309
+ adjusted = [jitter - average for jitter in self.jitter]
310
+
311
+ log_stats('Jitter (signed)', adjusted, 3)
312
+ log_stats('Jitter (absolute)', [abs(jitter) for jitter in adjusted], 3)
313
+
314
+ # Show a histogram
315
+ bin_count = 20
316
+ bins = [0] * bin_count
317
+ interval_min = min(adjusted)
318
+ interval_max = max(adjusted)
319
+ interval_range = interval_max - interval_min
320
+ bin_thresholds = [
321
+ interval_min + i * (interval_range / bin_count) for i in range(bin_count)
322
+ ]
323
+ for jitter in adjusted:
324
+ for i in reversed(range(bin_count)):
325
+ if jitter >= bin_thresholds[i]:
326
+ bins[i] += 1
327
+ break
328
+ for i in range(bin_count):
329
+ logging.info(f'@@@ >= {bin_thresholds[i]:.4f}: {bins[i]}')
235
330
 
236
331
 
237
332
  # -----------------------------------------------------------------------------
@@ -281,19 +376,37 @@ class Sender:
281
376
  await asyncio.sleep(self.tx_start_delay)
282
377
 
283
378
  logging.info(color('=== Sending RESET', 'magenta'))
284
- await self.packet_io.send_packet(bytes([PacketType.RESET]))
379
+ await self.packet_io.send_packet(
380
+ bytes(Packet(packet_type=Packet.PacketType.RESET))
381
+ )
382
+
285
383
  self.start_time = time.time()
286
384
  self.bytes_sent = 0
287
385
  for tx_i in range(self.tx_packet_count):
288
- packet_flags = (
289
- PACKET_FLAG_LAST if tx_i == self.tx_packet_count - 1 else 0
386
+ if self.pace > 0:
387
+ # Wait until it is time to send the next packet
388
+ target_time = self.start_time + (tx_i * self.pace / 1000)
389
+ now = time.time()
390
+ if now < target_time:
391
+ await asyncio.sleep(target_time - now)
392
+ else:
393
+ await self.packet_io.drain()
394
+
395
+ packet = bytes(
396
+ Packet(
397
+ packet_type=Packet.PacketType.SEQUENCE,
398
+ flags=(
399
+ Packet.PacketFlags.LAST
400
+ if tx_i == self.tx_packet_count - 1
401
+ else 0
402
+ ),
403
+ sequence=tx_i,
404
+ timestamp=int((time.time() - self.start_time) * 1000000),
405
+ payload=bytes(
406
+ self.tx_packet_size - 10 - self.packet_io.overhead_size
407
+ ),
408
+ )
290
409
  )
291
- packet = struct.pack(
292
- '>bbI',
293
- PacketType.SEQUENCE,
294
- packet_flags,
295
- tx_i,
296
- ) + bytes(self.tx_packet_size - 6 - self.packet_io.overhead_size)
297
410
  logging.info(
298
411
  color(
299
412
  f'Sending packet {tx_i}: {self.tx_packet_size} bytes', 'yellow'
@@ -302,14 +415,6 @@ class Sender:
302
415
  self.bytes_sent += len(packet)
303
416
  await self.packet_io.send_packet(packet)
304
417
 
305
- if self.pace is None:
306
- continue
307
-
308
- if self.pace > 0:
309
- await asyncio.sleep(self.pace / 1000)
310
- else:
311
- await self.packet_io.drain()
312
-
313
418
  await self.done.wait()
314
419
 
315
420
  run_counter = f'[{run + 1} of {self.repeat + 1}]' if self.repeat else ''
@@ -321,13 +426,13 @@ class Sender:
321
426
  if self.repeat:
322
427
  logging.info(color('--- End of runs', 'blue'))
323
428
 
324
- def on_packet_received(self, packet):
429
+ def on_packet_received(self, data):
325
430
  try:
326
- packet_type, _ = parse_packet(packet)
431
+ packet = Packet.from_bytes(data)
327
432
  except ValueError:
328
433
  return
329
434
 
330
- if packet_type == PacketType.ACK:
435
+ if packet.packet_type == Packet.PacketType.ACK:
331
436
  elapsed = time.time() - self.start_time
332
437
  average_tx_speed = self.bytes_sent / elapsed
333
438
  self.stats.append(average_tx_speed)
@@ -350,52 +455,53 @@ class Receiver:
350
455
  last_timestamp: float
351
456
 
352
457
  def __init__(self, packet_io, linger):
353
- self.reset()
458
+ self.jitter_stats = JitterStats()
354
459
  self.packet_io = packet_io
355
460
  self.packet_io.packet_listener = self
356
461
  self.linger = linger
357
462
  self.done = asyncio.Event()
463
+ self.reset()
358
464
 
359
465
  def reset(self):
360
466
  self.expected_packet_index = 0
361
467
  self.measurements = [(time.time(), 0)]
362
468
  self.total_bytes_received = 0
469
+ self.jitter_stats.reset()
363
470
 
364
- def on_packet_received(self, packet):
471
+ def on_packet_received(self, data):
365
472
  try:
366
- packet_type, packet_data = parse_packet(packet)
473
+ packet = Packet.from_bytes(data)
367
474
  except ValueError:
475
+ logging.exception("invalid packet")
368
476
  return
369
477
 
370
- if packet_type == PacketType.RESET:
478
+ if packet.packet_type == Packet.PacketType.RESET:
371
479
  logging.info(color('=== Received RESET', 'magenta'))
372
480
  self.reset()
373
481
  return
374
482
 
375
- try:
376
- packet_flags, packet_index = parse_packet_sequence(packet_data)
377
- except ValueError:
378
- return
483
+ jitter = self.jitter_stats.on_packet_received(packet)
379
484
  logging.info(
380
- f'<<< Received packet {packet_index}: '
381
- f'flags=0x{packet_flags:02X}, '
382
- f'{len(packet) + self.packet_io.overhead_size} bytes'
485
+ f'<<< Received packet {packet.sequence}: '
486
+ f'flags={packet.flags}, '
487
+ f'jitter={jitter:.4f}, '
488
+ f'{len(data) + self.packet_io.overhead_size} bytes',
383
489
  )
384
490
 
385
- if packet_index != self.expected_packet_index:
491
+ if packet.sequence != self.expected_packet_index:
386
492
  logging.info(
387
493
  color(
388
494
  f'!!! Unexpected packet, expected {self.expected_packet_index} '
389
- f'but received {packet_index}'
495
+ f'but received {packet.sequence}'
390
496
  )
391
497
  )
392
498
 
393
499
  now = time.time()
394
500
  elapsed_since_start = now - self.measurements[0][0]
395
501
  elapsed_since_last = now - self.measurements[-1][0]
396
- self.measurements.append((now, len(packet)))
397
- self.total_bytes_received += len(packet)
398
- instant_rx_speed = len(packet) / elapsed_since_last
502
+ self.measurements.append((now, len(data)))
503
+ self.total_bytes_received += len(data)
504
+ instant_rx_speed = len(data) / elapsed_since_last
399
505
  average_rx_speed = self.total_bytes_received / elapsed_since_start
400
506
  window = self.measurements[-64:]
401
507
  windowed_rx_speed = sum(measurement[1] for measurement in window[1:]) / (
@@ -411,15 +517,17 @@ class Receiver:
411
517
  )
412
518
  )
413
519
 
414
- self.expected_packet_index = packet_index + 1
520
+ self.expected_packet_index = packet.sequence + 1
415
521
 
416
- if packet_flags & PACKET_FLAG_LAST:
522
+ if packet.flags & Packet.PacketFlags.LAST:
417
523
  AsyncRunner.spawn(
418
524
  self.packet_io.send_packet(
419
- struct.pack('>bbI', PacketType.ACK, packet_flags, packet_index)
525
+ bytes(Packet(Packet.PacketType.ACK, packet.flags, packet.sequence))
420
526
  )
421
527
  )
422
528
  logging.info(color('@@@ Received last packet', 'green'))
529
+ self.jitter_stats.show_stats()
530
+
423
531
  if not self.linger:
424
532
  self.done.set()
425
533
 
@@ -479,25 +587,32 @@ class Ping:
479
587
  await asyncio.sleep(self.tx_start_delay)
480
588
 
481
589
  logging.info(color('=== Sending RESET', 'magenta'))
482
- await self.packet_io.send_packet(bytes([PacketType.RESET]))
590
+ await self.packet_io.send_packet(bytes(Packet(Packet.PacketType.RESET)))
483
591
 
484
- packet_interval = self.pace / 1000
485
592
  start_time = time.time()
486
593
  self.next_expected_packet_index = 0
487
594
  for i in range(self.tx_packet_count):
488
- target_time = start_time + (i * packet_interval)
595
+ target_time = start_time + (i * self.pace / 1000)
489
596
  now = time.time()
490
597
  if now < target_time:
491
598
  await asyncio.sleep(target_time - now)
492
-
493
- packet = struct.pack(
494
- '>bbI',
495
- PacketType.SEQUENCE,
496
- (PACKET_FLAG_LAST if i == self.tx_packet_count - 1 else 0),
497
- i,
498
- ) + bytes(self.tx_packet_size - 6)
599
+ now = time.time()
600
+
601
+ packet = bytes(
602
+ Packet(
603
+ packet_type=Packet.PacketType.SEQUENCE,
604
+ flags=(
605
+ Packet.PacketFlags.LAST
606
+ if i == self.tx_packet_count - 1
607
+ else 0
608
+ ),
609
+ sequence=i,
610
+ timestamp=int((now - start_time) * 1000000),
611
+ payload=bytes(self.tx_packet_size - 10),
612
+ )
613
+ )
499
614
  logging.info(color(f'Sending packet {i}', 'yellow'))
500
- self.ping_times.append(time.time())
615
+ self.ping_times.append(now)
501
616
  await self.packet_io.send_packet(packet)
502
617
 
503
618
  await self.done.wait()
@@ -531,40 +646,35 @@ class Ping:
531
646
  if self.repeat:
532
647
  logging.info(color('--- End of runs', 'blue'))
533
648
 
534
- def on_packet_received(self, packet):
649
+ def on_packet_received(self, data):
535
650
  try:
536
- packet_type, packet_data = parse_packet(packet)
651
+ packet = Packet.from_bytes(data)
537
652
  except ValueError:
538
653
  return
539
654
 
540
- try:
541
- packet_flags, packet_index = parse_packet_sequence(packet_data)
542
- except ValueError:
543
- return
544
-
545
- if packet_type == PacketType.ACK:
546
- elapsed = time.time() - self.ping_times[packet_index]
655
+ if packet.packet_type == Packet.PacketType.ACK:
656
+ elapsed = time.time() - self.ping_times[packet.sequence]
547
657
  rtt = elapsed * 1000
548
658
  self.rtts.append(rtt)
549
659
  logging.info(
550
660
  color(
551
- f'<<< Received ACK [{packet_index}], RTT={rtt:.2f}ms',
661
+ f'<<< Received ACK [{packet.sequence}], RTT={rtt:.2f}ms',
552
662
  'green',
553
663
  )
554
664
  )
555
665
 
556
- if packet_index == self.next_expected_packet_index:
666
+ if packet.sequence == self.next_expected_packet_index:
557
667
  self.next_expected_packet_index += 1
558
668
  else:
559
669
  logging.info(
560
670
  color(
561
671
  f'!!! Unexpected packet, '
562
672
  f'expected {self.next_expected_packet_index} '
563
- f'but received {packet_index}'
673
+ f'but received {packet.sequence}'
564
674
  )
565
675
  )
566
676
 
567
- if packet_flags & PACKET_FLAG_LAST:
677
+ if packet.flags & Packet.PacketFlags.LAST:
568
678
  self.done.set()
569
679
  return
570
680
 
@@ -576,89 +686,56 @@ class Pong:
576
686
  expected_packet_index: int
577
687
 
578
688
  def __init__(self, packet_io, linger):
579
- self.reset()
689
+ self.jitter_stats = JitterStats()
580
690
  self.packet_io = packet_io
581
691
  self.packet_io.packet_listener = self
582
692
  self.linger = linger
583
693
  self.done = asyncio.Event()
694
+ self.reset()
584
695
 
585
696
  def reset(self):
586
697
  self.expected_packet_index = 0
587
- self.receive_times = []
588
-
589
- def on_packet_received(self, packet):
590
- self.receive_times.append(time.time())
698
+ self.jitter_stats.reset()
591
699
 
700
+ def on_packet_received(self, data):
592
701
  try:
593
- packet_type, packet_data = parse_packet(packet)
702
+ packet = Packet.from_bytes(data)
594
703
  except ValueError:
595
704
  return
596
705
 
597
- if packet_type == PacketType.RESET:
706
+ if packet.packet_type == Packet.PacketType.RESET:
598
707
  logging.info(color('=== Received RESET', 'magenta'))
599
708
  self.reset()
600
709
  return
601
710
 
602
- try:
603
- packet_flags, packet_index = parse_packet_sequence(packet_data)
604
- except ValueError:
605
- return
606
- interval = (
607
- self.receive_times[-1] - self.receive_times[-2]
608
- if len(self.receive_times) >= 2
609
- else 0
610
- )
711
+ jitter = self.jitter_stats.on_packet_received(packet)
611
712
  logging.info(
612
713
  color(
613
- f'<<< Received packet {packet_index}: '
614
- f'flags=0x{packet_flags:02X}, {len(packet)} bytes, '
615
- f'interval={interval:.4f}',
714
+ f'<<< Received packet {packet.sequence}: '
715
+ f'flags={packet.flags}, {len(data)} bytes, '
716
+ f'jitter={jitter:.4f}',
616
717
  'green',
617
718
  )
618
719
  )
619
720
 
620
- if packet_index != self.expected_packet_index:
721
+ if packet.sequence != self.expected_packet_index:
621
722
  logging.info(
622
723
  color(
623
724
  f'!!! Unexpected packet, expected {self.expected_packet_index} '
624
- f'but received {packet_index}'
725
+ f'but received {packet.sequence}'
625
726
  )
626
727
  )
627
728
 
628
- self.expected_packet_index = packet_index + 1
729
+ self.expected_packet_index = packet.sequence + 1
629
730
 
630
731
  AsyncRunner.spawn(
631
732
  self.packet_io.send_packet(
632
- struct.pack('>bbI', PacketType.ACK, packet_flags, packet_index)
733
+ bytes(Packet(Packet.PacketType.ACK, packet.flags, packet.sequence))
633
734
  )
634
735
  )
635
736
 
636
- if packet_flags & PACKET_FLAG_LAST:
637
- if len(self.receive_times) >= 3:
638
- # Show basic stats
639
- intervals = [
640
- self.receive_times[i + 1] - self.receive_times[i]
641
- for i in range(len(self.receive_times) - 1)
642
- ]
643
- log_stats('Packet intervals', intervals, 3)
644
-
645
- # Show a histogram
646
- bin_count = 20
647
- bins = [0] * bin_count
648
- interval_min = min(intervals)
649
- interval_max = max(intervals)
650
- interval_range = interval_max - interval_min
651
- bin_thresholds = [
652
- interval_min + i * (interval_range / bin_count)
653
- for i in range(bin_count)
654
- ]
655
- for interval in intervals:
656
- for i in reversed(range(bin_count)):
657
- if interval >= bin_thresholds[i]:
658
- bins[i] += 1
659
- break
660
- for i in range(bin_count):
661
- logging.info(f'@@@ >= {bin_thresholds[i]:.4f}: {bins[i]}')
737
+ if packet.flags & Packet.PacketFlags.LAST:
738
+ self.jitter_stats.show_stats()
662
739
 
663
740
  if not self.linger:
664
741
  self.done.set()
@@ -1471,7 +1548,7 @@ def create_mode_factory(ctx, default_mode):
1471
1548
  def create_scenario_factory(ctx, default_scenario):
1472
1549
  scenario = ctx.obj['scenario']
1473
1550
  if scenario is None:
1474
- scenarion = default_scenario
1551
+ scenario = default_scenario
1475
1552
 
1476
1553
  def create_scenario(packet_io):
1477
1554
  if scenario == 'send':
@@ -1530,6 +1607,7 @@ def create_scenario_factory(ctx, default_scenario):
1530
1607
  '--att-mtu',
1531
1608
  metavar='MTU',
1532
1609
  type=click.IntRange(23, 517),
1610
+ default=517,
1533
1611
  help='GATT MTU (gatt-client mode)',
1534
1612
  )
1535
1613
  @click.option(
@@ -1605,7 +1683,7 @@ def create_scenario_factory(ctx, default_scenario):
1605
1683
  '--packet-size',
1606
1684
  '-s',
1607
1685
  metavar='SIZE',
1608
- type=click.IntRange(8, 8192),
1686
+ type=click.IntRange(10, 8192),
1609
1687
  default=500,
1610
1688
  help='Packet size (send or ping scenario)',
1611
1689
  )
@@ -37,6 +37,8 @@ from bumble.hci import (
37
37
  HCI_Command_Status_Event,
38
38
  HCI_READ_BUFFER_SIZE_COMMAND,
39
39
  HCI_Read_Buffer_Size_Command,
40
+ HCI_LE_READ_BUFFER_SIZE_V2_COMMAND,
41
+ HCI_LE_Read_Buffer_Size_V2_Command,
40
42
  HCI_READ_BD_ADDR_COMMAND,
41
43
  HCI_Read_BD_ADDR_Command,
42
44
  HCI_READ_LOCAL_NAME_COMMAND,
@@ -75,7 +77,7 @@ async def get_classic_info(host: Host) -> None:
75
77
  if command_succeeded(response):
76
78
  print()
77
79
  print(
78
- color('Classic Address:', 'yellow'),
80
+ color('Public Address:', 'yellow'),
79
81
  response.return_parameters.bd_addr.to_string(False),
80
82
  )
81
83
 
@@ -147,7 +149,7 @@ async def get_le_info(host: Host) -> None:
147
149
 
148
150
 
149
151
  # -----------------------------------------------------------------------------
150
- async def get_acl_flow_control_info(host: Host) -> None:
152
+ async def get_flow_control_info(host: Host) -> None:
151
153
  print()
152
154
 
153
155
  if host.supports_command(HCI_READ_BUFFER_SIZE_COMMAND):
@@ -160,14 +162,28 @@ async def get_acl_flow_control_info(host: Host) -> None:
160
162
  f'packets of size {response.return_parameters.hc_acl_data_packet_length}',
161
163
  )
162
164
 
163
- if host.supports_command(HCI_LE_READ_BUFFER_SIZE_COMMAND):
165
+ if host.supports_command(HCI_LE_READ_BUFFER_SIZE_V2_COMMAND):
166
+ response = await host.send_command(
167
+ HCI_LE_Read_Buffer_Size_V2_Command(), check_result=True
168
+ )
169
+ print(
170
+ color('LE ACL Flow Control:', 'yellow'),
171
+ f'{response.return_parameters.total_num_le_acl_data_packets} '
172
+ f'packets of size {response.return_parameters.le_acl_data_packet_length}',
173
+ )
174
+ print(
175
+ color('LE ISO Flow Control:', 'yellow'),
176
+ f'{response.return_parameters.total_num_iso_data_packets} '
177
+ f'packets of size {response.return_parameters.iso_data_packet_length}',
178
+ )
179
+ elif host.supports_command(HCI_LE_READ_BUFFER_SIZE_COMMAND):
164
180
  response = await host.send_command(
165
181
  HCI_LE_Read_Buffer_Size_Command(), check_result=True
166
182
  )
167
183
  print(
168
184
  color('LE ACL Flow Control:', 'yellow'),
169
- f'{response.return_parameters.hc_total_num_le_acl_data_packets} '
170
- f'packets of size {response.return_parameters.hc_le_acl_data_packet_length}',
185
+ f'{response.return_parameters.total_num_le_acl_data_packets} '
186
+ f'packets of size {response.return_parameters.le_acl_data_packet_length}',
171
187
  )
172
188
 
173
189
 
@@ -274,8 +290,8 @@ async def async_main(latency_probes, transport):
274
290
  # Get the LE info
275
291
  await get_le_info(host)
276
292
 
277
- # Print the ACL flow control info
278
- await get_acl_flow_control_info(host)
293
+ # Print the flow control info
294
+ await get_flow_control_info(host)
279
295
 
280
296
  # Get codec info
281
297
  await get_codecs_info(host)