Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion micropython/bluetooth/aioble/aioble/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def timeout(self, timeout_ms):

async def exchange_mtu(self, mtu=None, timeout_ms=1000):
if not self.is_connected():
raise ValueError("Not connected")
raise DeviceDisconnectedError

if mtu:
ble.config(mtu=mtu)
Expand Down
44 changes: 32 additions & 12 deletions micropython/bluetooth/aioble/aioble/l2cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from micropython import const

import asyncio
import errno

from .core import ble, log_error, register_irq_handler
from .device import DeviceConnection
from .device import DeviceConnection, DeviceDisconnectedError


_IRQ_L2CAP_ACCEPT = const(22)
Expand Down Expand Up @@ -63,7 +64,7 @@


# The channel was disconnected during a send/recvinto/flush.
class L2CAPDisconnectedError(Exception):
class L2CAPDisconnectedError(DeviceDisconnectedError):
pass


Expand All @@ -75,7 +76,7 @@
class L2CAPChannel:
def __init__(self, connection):
if not connection.is_connected():
raise ValueError("Not connected")
raise L2CAPDisconnectedError

if connection._l2cap_channel:
raise ValueError("Already has channel")
Expand Down Expand Up @@ -118,10 +119,17 @@
self._assert_connected()

# Extract up to len(buf) bytes from the channel buffer.
n = ble.l2cap_recvinto(self._connection._conn_handle, self._cid, buf)
try:
n = ble.l2cap_recvinto(self._connection._conn_handle, self._cid, buf)

# Check if there's still remaining data in the channel buffers.
self._data_ready = ble.l2cap_recvinto(self._connection._conn_handle, self._cid, None) > 0
# Check if there's still remaining data in the channel buffers.
self._data_ready = (
ble.l2cap_recvinto(self._connection._conn_handle, self._cid, None) > 0
)
except OSError as e:
if e.errno == errno.EINVAL:
raise L2CAPDisconnectedError()

Check failure on line 131 in micropython/bluetooth/aioble/aioble/l2cap.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (RSE102)

micropython/bluetooth/aioble/aioble/l2cap.py:131:45: RSE102 Unnecessary parentheses on raised exception
raise

return n

Expand All @@ -141,11 +149,16 @@
await self.flush(timeout_ms)
# l2cap_send returns True if you can send immediately.
self._assert_connected()
self._stalled = not ble.l2cap_send(
self._connection._conn_handle,
self._cid,
mv[offset : offset + chunk_size],
)
try:
self._stalled = not ble.l2cap_send(
self._connection._conn_handle,
self._cid,
mv[offset : offset + chunk_size],
)
except OSError as e:
if e.errno == errno.EINVAL:
raise L2CAPDisconnectedError()

Check failure on line 160 in micropython/bluetooth/aioble/aioble/l2cap.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (RSE102)

micropython/bluetooth/aioble/aioble/l2cap.py:160:49: RSE102 Unnecessary parentheses on raised exception
raise
offset += chunk_size

async def flush(self, timeout_ms=None):
Expand All @@ -161,7 +174,14 @@
return

# Wait for the cid to be cleared by the disconnect IRQ.
ble.l2cap_disconnect(self._connection._conn_handle, self._cid)
try:
ble.l2cap_disconnect(self._connection._conn_handle, self._cid)
except OSError as e:
if e.errno == errno.EINVAL:
# Channel already closed by peer — treat as disconnected.
self._cid = None
return
raise
await self.disconnected(timeout_ms)

async def disconnected(self, timeout_ms=1000):
Expand Down
4 changes: 2 additions & 2 deletions micropython/bluetooth/aioble/aioble/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
register_irq_handler,
GattError,
)
from .device import DeviceConnection, DeviceTimeout
from .device import DeviceConnection, DeviceDisconnectedError, DeviceTimeout

_registered_characteristics = {}

Expand Down Expand Up @@ -263,7 +263,7 @@ async def indicate(self, connection, data=None, timeout_ms=1000):
if self._indicate_connection is not None:
raise ValueError("In progress")
if not connection.is_connected():
raise ValueError("Not connected")
raise DeviceDisconnectedError

self._indicate_connection = connection
self._indicate_status = None
Expand Down
Loading