Skip to content

Commit

Permalink
Add connection parameter update from peripheral
Browse files Browse the repository at this point in the history
  • Loading branch information
wescande committed Sep 12, 2023
1 parent 1e00c8f commit 12968b0
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
19 changes: 18 additions & 1 deletion bumble/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -2110,11 +2110,27 @@ async def update_connection_parameters(
supervision_timeout,
min_ce_length=0,
max_ce_length=0,
):
use_l2cap=False,
) -> bool:
'''
NOTE: the name of the parameters may look odd, but it just follows the names
used in the Bluetooth spec.
'''

if use_l2cap:
if connection.role != BT_PERIPHERAL_ROLE:
raise InvalidStateError(
'only peripheral can update connection parameters with l2cap'
)
result = await self.l2cap_channel_manager.update_connection_parameters(
connection,
connection_interval_min,
connection_interval_max,
max_latency,
supervision_timeout,
)
return result == 0

result = await self.send_command(
HCI_LE_Connection_Update_Command(
connection_handle=connection.handle,
Expand All @@ -2128,6 +2144,7 @@ async def update_connection_parameters(
)
if result.status != HCI_Command_Status_Event.PENDING:
raise HCI_StatusError(result)
return True

async def get_connection_rssi(self, connection):
result = await self.send_command(
Expand Down
40 changes: 38 additions & 2 deletions bumble/l2cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,7 @@ class ChannelManager:
le_coc_requests: Dict[int, L2CAP_LE_Credit_Based_Connection_Request]
fixed_channels: Dict[int, Optional[Callable[[int, bytes], Any]]]
_host: Optional[Host]
connection_parameters_update_response: Optional[asyncio.Future[int]]

def __init__(
self,
Expand All @@ -1408,6 +1409,7 @@ def __init__(
self.le_coc_requests = {} # LE CoC connection requests, by identifier
self.extended_features = extended_features
self.connectionless_mtu = connectionless_mtu
self.connection_parameters_update_response = None

@property
def host(self) -> Host:
Expand Down Expand Up @@ -1865,11 +1867,45 @@ def on_l2cap_connection_parameter_update_request(
),
)

async def update_connection_parameters(
self,
connection: Connection,
interval_min: int,
interval_max: int,
latency: int,
timeout: int,
) -> int:
# Check that there isn't already a request pending
if self.connection_parameters_update_response:
raise InvalidStateError('request already pending')
self.connection_parameters_update_response = (
asyncio.get_running_loop().create_future()
)
self.send_control_frame(
connection,
L2CAP_LE_SIGNALING_CID,
L2CAP_Connection_Parameter_Update_Request(
interval_min=interval_min,
interval_max=interval_max,
latency=latency,
timeout=timeout,
),
)
return await self.connection_parameters_update_response

def on_l2cap_connection_parameter_update_response(
self, connection: Connection, cid: int, response
) -> None:
# TODO: check response
pass
if self.connection_parameters_update_response:
self.connection_parameters_update_response.set_result(response.result)
self.connection_parameters_update_response = None
else:
logger.warning(
color(
'received l2cap_connection_parameter_update_response without a pending request',
'red',
)
)

def on_l2cap_le_credit_based_connection_request(
self, connection: Connection, cid: int, request
Expand Down

0 comments on commit 12968b0

Please sign in to comment.