fix a few timescale adjustments
diff --git a/apps/bench.py b/apps/bench.py
index c306f19..0c74f72 100644
--- a/apps/bench.py
+++ b/apps/bench.py
@@ -121,9 +121,9 @@
 
         params.append(
             'Parameters='
-            f'{connection.parameters.connection_interval * 1.25:.2f}/'
+            f'{connection.parameters.connection_interval:.2f}/'
             f'{connection.parameters.peripheral_latency}/'
-            f'{connection.parameters.supervision_timeout * 10} '
+            f'{connection.parameters.supervision_timeout:.2f} '
         )
 
         params.append(f'MTU={connection.att_mtu}')
diff --git a/apps/console.py b/apps/console.py
index 606aadb..7ad313d 100644
--- a/apps/console.py
+++ b/apps/console.py
@@ -335,9 +335,9 @@
             elif self.connected_peer:
                 connection = self.connected_peer.connection
                 connection_parameters = (
-                    f'{connection.parameters.connection_interval}/'
+                    f'{connection.parameters.connection_interval:.2f}/'
                     f'{connection.parameters.peripheral_latency}/'
-                    f'{connection.parameters.supervision_timeout}'
+                    f'{connection.parameters.supervision_timeout:.2f}'
                 )
                 if self.connection_phy is not None:
                     phy_state = (
diff --git a/bumble/device.py b/bumble/device.py
index 4b0222d..f9c032b 100644
--- a/bumble/device.py
+++ b/bumble/device.py
@@ -61,7 +61,6 @@
     BaseBumbleError,
     ConnectionParameterUpdateError,
     CommandTimeoutError,
-    ConnectionParameters,
     ConnectionPHY,
     InvalidArgumentError,
     InvalidOperationError,
@@ -484,7 +483,7 @@
     sid: int
     num_bis: int
     nse: int
-    iso_interval: int
+    iso_interval: float
     bn: int
     pto: int
     irc: int
@@ -502,7 +501,7 @@
             sid,
             report.num_bis,
             report.nse,
-            report.iso_interval,
+            report.iso_interval * 1.25,
             report.bn,
             report.pto,
             report.irc,
@@ -529,8 +528,8 @@
     advertising_event_properties: AdvertisingEventProperties = field(
         default_factory=AdvertisingEventProperties
     )
-    primary_advertising_interval_min: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
-    primary_advertising_interval_max: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    primary_advertising_interval_min: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    primary_advertising_interval_max: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
     primary_advertising_channel_map: (
         hci.HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap
     ) = (
@@ -554,8 +553,8 @@
 # -----------------------------------------------------------------------------
 @dataclass
 class PeriodicAdvertisingParameters:
-    periodic_advertising_interval_min: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
-    periodic_advertising_interval_max: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    periodic_advertising_interval_min: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    periodic_advertising_interval_max: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
     periodic_advertising_properties: (
         hci.HCI_LE_Set_Periodic_Advertising_Parameters_Command.Properties
     ) = field(
@@ -685,8 +684,12 @@
         await self.device.send_command(
             hci.HCI_LE_Set_Periodic_Advertising_Parameters_Command(
                 advertising_handle=self.advertising_handle,
-                periodic_advertising_interval_min=advertising_parameters.periodic_advertising_interval_min,
-                periodic_advertising_interval_max=advertising_parameters.periodic_advertising_interval_max,
+                periodic_advertising_interval_min=int(
+                    advertising_parameters.periodic_advertising_interval_min / 1.25
+                ),
+                periodic_advertising_interval_max=int(
+                    advertising_parameters.periodic_advertising_interval_max / 1.25
+                ),
                 periodic_advertising_properties=advertising_parameters.periodic_advertising_properties,
             ),
             check_result=True,
@@ -826,7 +829,7 @@
     filter_duplicates: bool
     status: int
     advertiser_phy: int
-    periodic_advertising_interval: int
+    periodic_advertising_interval: float  # Advertising interval, in milliseconds
     advertiser_clock_accuracy: int
 
     EVENT_STATE_CHANGE = "state_change"
@@ -950,7 +953,7 @@
         if status == hci.HCI_SUCCESS:
             self.sync_handle = sync_handle
             self.advertiser_phy = advertiser_phy
-            self.periodic_advertising_interval = periodic_advertising_interval
+            self.periodic_advertising_interval = periodic_advertising_interval * 1.25
             self.advertiser_clock_accuracy = advertiser_clock_accuracy
             self.state = self.State.ESTABLISHED
             self.emit(self.EVENT_ESTABLISHMENT)
@@ -1055,7 +1058,7 @@
     pto: int = 0
     irc: int = 0
     max_pdu: int = 0
-    iso_interval: int = 0
+    iso_interval: float = 0.0
     bis_links: Sequence[BisLink] = ()
 
     def __post_init__(self) -> None:
@@ -1116,7 +1119,7 @@
     pto: int = 0
     irc: int = 0
     max_pdu: int = 0
-    iso_interval: int = 0
+    iso_interval: float = 0.0
     bis_links: Sequence[BisLink] = ()
 
     def __post_init__(self) -> None:
@@ -1197,11 +1200,11 @@
     selected_tx_power: int
     subevent_len: int
     subevents_per_event: int
-    subevent_interval: int
+    subevent_interval: float  # milliseconds.
     event_interval: int
     procedure_interval: int
     procedure_count: int
-    max_procedure_len: int
+    max_procedure_len: float  # milliseconds.
 
 
 # -----------------------------------------------------------------------------
@@ -1226,9 +1229,8 @@
     def __init__(self, connection: Connection) -> None:
         self.connection = connection
 
-        # Create a GATT client for the connection
-        self.gatt_client = gatt_client.Client(connection)
-        connection.gatt_client = self.gatt_client
+        # Shortcut to the connection's GATT client
+        self.gatt_client = connection.gatt_client
 
     @property
     def services(self) -> list[gatt_client.ServiceProxy]:
@@ -1586,7 +1588,7 @@
     encryption: int
     authenticated: bool
     sc: bool
-    link_key_type: int
+    link_key_type: Optional[int]
     gatt_client: gatt_client.Client
     pairing_peer_io_capability: Optional[int]
     pairing_peer_authentication_requirements: Optional[int]
@@ -1656,17 +1658,23 @@
         def on_connection_encryption_key_refresh(self):
             pass
 
+    @dataclass
+    class Parameters:
+        connection_interval: float  # Connection interval, in milliseconds. [LE only]
+        peripheral_latency: int  # Peripheral latency, in number of intervals. [LE only]
+        supervision_timeout: float  # Supervision timeout, in milliseconds.
+
     def __init__(
         self,
-        device,
-        handle,
-        transport,
-        self_address,
-        self_resolvable_address,
-        peer_address,
-        peer_resolvable_address,
-        role,
-        parameters,
+        device: Device,
+        handle: int,
+        transport: core.PhysicalTransport,
+        self_address: hci.Address,
+        self_resolvable_address: Optional[hci.Address],
+        peer_address: hci.Address,
+        peer_resolvable_address: Optional[hci.Address],
+        role: hci.Role,
+        parameters: Parameters,
     ):
         super().__init__()
         self.device = device
@@ -1685,7 +1693,7 @@
         self.link_key_type = None
         self.att_mtu = ATT_DEFAULT_MTU
         self.data_length = DEVICE_DEFAULT_DATA_LENGTH
-        self.gatt_client = None  # Per-connection client
+        self.gatt_client = gatt_client.Client(self)  # Per-connection client
         self.gatt_server = (
             device.gatt_server
         )  # By default, use the device's shared server
@@ -1812,12 +1820,22 @@
 
     async def update_parameters(
         self,
-        connection_interval_min,
-        connection_interval_max,
-        max_latency,
-        supervision_timeout,
+        connection_interval_min: float,
+        connection_interval_max: float,
+        max_latency: int,
+        supervision_timeout: float,
         use_l2cap=False,
-    ):
+    ) -> None:
+        """
+        Request an update of the connection parameters.
+
+        Args:
+          connection_interval_min: Minimum interval, in milliseconds.
+          connection_interval_max: Maximum interval, in milliseconds.
+          max_latency: Latency, in number of intervals.
+          supervision_timeout: Timeout, in milliseconds.
+          use_l2cap: Request the update via L2CAP.
+        """
         return await self.device.update_connection_parameters(
             self,
             connection_interval_min,
@@ -1904,8 +1922,8 @@
     address: hci.Address = hci.Address(DEVICE_DEFAULT_ADDRESS)
     class_of_device: int = DEVICE_DEFAULT_CLASS_OF_DEVICE
     scan_response_data: bytes = DEVICE_DEFAULT_SCAN_RESPONSE_DATA
-    advertising_interval_min: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
-    advertising_interval_max: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    advertising_interval_min: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
+    advertising_interval_max: float = DEVICE_DEFAULT_ADVERTISING_INTERVAL
     le_enabled: bool = True
     le_simultaneous_enabled: bool = False
     le_privacy_enabled: bool = False
@@ -2824,8 +2842,8 @@
         auto_restart: bool = False,
         advertising_data: Optional[bytes] = None,
         scan_response_data: Optional[bytes] = None,
-        advertising_interval_min: Optional[int] = None,
-        advertising_interval_max: Optional[int] = None,
+        advertising_interval_min: Optional[float] = None,
+        advertising_interval_max: Optional[float] = None,
     ) -> None:
         """Start legacy advertising.
 
@@ -3980,20 +3998,39 @@
 
     async def update_connection_parameters(
         self,
-        connection,
-        connection_interval_min,
-        connection_interval_max,
-        max_latency,
-        supervision_timeout,
-        min_ce_length=0,
-        max_ce_length=0,
-        use_l2cap=False,
+        connection: Connection,
+        connection_interval_min: float,
+        connection_interval_max: float,
+        max_latency: int,
+        supervision_timeout: float,
+        min_ce_length: float = 0.0,
+        max_ce_length: float = 0.0,
+        use_l2cap: bool = False,
     ) -> None:
         '''
+        Request an update of the connection parameters.
+
+        Args:
+          connection: The connection to update
+          connection_interval_min: Minimum interval, in milliseconds.
+          connection_interval_max: Maximum interval, in milliseconds.
+          max_latency: Latency, in number of intervals.
+          supervision_timeout: Timeout, in milliseconds.
+          min_ce_length: Minimum connection event length, in milliseconds.
+          max_ce_length: Maximum connection event length, in milliseconds.
+          use_l2cap: Request the update via L2CAP.
+
         NOTE: the name of the parameters may look odd, but it just follows the names
         used in the Bluetooth spec.
         '''
 
+        # Convert the input parameters
+        connection_interval_min = int(connection_interval_min / 1.25)
+        connection_interval_max = int(connection_interval_max / 1.25)
+        supervision_timeout = int(supervision_timeout / 10)
+        min_ce_length = int(min_ce_length / 0.625)
+        max_ce_length = int(max_ce_length / 0.625)
+
         if use_l2cap:
             if connection.role != hci.Role.PERIPHERAL:
                 raise InvalidStateError(
@@ -4011,6 +4048,8 @@
             if l2cap_result != l2cap.L2CAP_CONNECTION_PARAMETERS_ACCEPTED_RESULT:
                 raise ConnectionParameterUpdateError(l2cap_result)
 
+            return
+
         result = await self.send_command(
             hci.HCI_LE_Connection_Update_Command(
                 connection_handle=connection.handle,
@@ -5208,7 +5247,7 @@
         big.pto = pto
         big.irc = irc
         big.max_pdu = max_pdu
-        big.iso_interval = iso_interval
+        big.iso_interval = iso_interval * 1.25
         big.state = Big.State.ACTIVE
 
         for bis_link in big.bis_links:
@@ -5257,7 +5296,7 @@
         big_sync.pto = pto
         big_sync.irc = irc
         big_sync.max_pdu = max_pdu
-        big_sync.iso_interval = iso_interval
+        big_sync.iso_interval = iso_interval * 1.25
         big_sync.bis_links = [
             BisLink(handle=handle, big=big_sync) for handle in bis_handles
         ]
@@ -5314,7 +5353,7 @@
         self_resolvable_address: Optional[hci.Address],
         peer_resolvable_address: Optional[hci.Address],
         role: hci.Role,
-        connection_parameters: ConnectionParameters,
+        connection_parameters: Optional[core.ConnectionParameters],
     ) -> None:
         # Convert all-zeros addresses into None.
         if self_resolvable_address == hci.Address.ANY_RANDOM:
@@ -5345,6 +5384,8 @@
 
             return
 
+        assert connection_parameters is not None
+
         if peer_resolvable_address is None:
             # Resolve the peer address if we can
             if self.address_resolver:
@@ -5400,7 +5441,11 @@
             peer_address,
             peer_resolvable_address,
             role,
-            connection_parameters,
+            Connection.Parameters(
+                connection_parameters.connection_interval * 1.25,
+                connection_parameters.peripheral_latency,
+                connection_parameters.supervision_timeout * 10.0,
+            ),
         )
         self.connections[connection_handle] = connection
 
diff --git a/bumble/hci.py b/bumble/hci.py
index 4c9259f..2ab46e4 100644
--- a/bumble/hci.py
+++ b/bumble/hci.py
@@ -5976,6 +5976,33 @@
     [
         ('status', STATUS_SPEC),
         ('connection_handle', 2),
+        (
+            'role',
+            {'size': 1, 'mapper': lambda x: 'CENTRAL' if x == 0 else 'PERIPHERAL'},
+        ),
+        ('peer_address_type', Address.ADDRESS_TYPE_SPEC),
+        ('peer_address', Address.parse_address_preceded_by_type),
+        ('local_resolvable_private_address', Address.parse_random_address),
+        ('peer_resolvable_private_address', Address.parse_random_address),
+        ('connection_interval', 2),
+        ('peripheral_latency', 2),
+        ('supervision_timeout', 2),
+        ('central_clock_accuracy', 1),
+        ('advertising_handle', 1),
+        ('sync_handle', 2),
+    ]
+)
+class HCI_LE_Enhanced_Connection_Complete_V2_Event(HCI_LE_Meta_Event):
+    '''
+    See Bluetooth spec @ 7.7.65.10 LE Enhanced Connection Complete Event
+    '''
+
+
+# -----------------------------------------------------------------------------
+@HCI_LE_Meta_Event.event(
+    [
+        ('status', STATUS_SPEC),
+        ('connection_handle', 2),
         ('tx_phy', {'size': 1, 'mapper': HCI_Constant.le_phy_name}),
         ('rx_phy', {'size': 1, 'mapper': HCI_Constant.le_phy_name}),
     ]
diff --git a/bumble/host.py b/bumble/host.py
index 3b53b8a..183c5a7 100644
--- a/bumble/host.py
+++ b/bumble/host.py
@@ -456,6 +456,7 @@
                     hci.HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT,
                     hci.HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT,
                     hci.HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT,
+                    hci.HCI_LE_ENHANCED_CONNECTION_COMPLETE_V2_EVENT,
                     hci.HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT,
                     hci.HCI_LE_PHY_UPDATE_COMPLETE_EVENT,
                     hci.HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT,