mirror of
https://github.com/google/bumble.git
synced 2026-07-14 14:10:50 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b2bd06393 | |||
| ab0e5801a2 | |||
| 1d26b99865 | |||
| c75402d29a | |||
| c8360b7a06 | |||
| 13c6090f8c | |||
| 6fd08b709a | |||
| 55d8171ad8 | |||
| 2111c49a2c | |||
| adef270195 | |||
| 8015e528f2 | |||
| 9f2fdf5309 | |||
| 7d816b0c6c |
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
// Use 'postCreateCommand' to run commands after the container is created.
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
"postCreateCommand":
|
"postCreateCommand":
|
||||||
"python -m pip install '.[build,test,development,documentation]'",
|
"python -m pip install '.[all]' --group dev",
|
||||||
|
|
||||||
// Configure tool-specific properties.
|
// Configure tool-specific properties.
|
||||||
"customizations": {
|
"customizations": {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install ".[build,test,development]"
|
python -m pip install ".[all]" --group dev
|
||||||
- name: Check
|
- name: Check
|
||||||
run: |
|
run: |
|
||||||
invoke project.pre-commit
|
invoke project.pre-commit
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install .[avatar]
|
python -m pip install .[all,avatar]
|
||||||
- name: Rootcanal
|
- name: Rootcanal
|
||||||
run: nohup python -m rootcanal > rootcanal.log &
|
run: nohup python -m rootcanal > rootcanal.log &
|
||||||
- name: Test
|
- name: Test
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install ".[build,test,development,documentation]"
|
python -m pip install ".[all]" --group dev
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
invoke test
|
invoke test
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install ".[build,test,development,documentation]"
|
python -m pip install ".[all]" --group dev
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ To install package dependencies needed to run the bumble examples, execute the f
|
|||||||
|
|
||||||
```
|
```
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install ".[test,development,documentation]"
|
python -m pip install ".[all]" --group dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|||||||
+1
-3
@@ -40,9 +40,7 @@ else:
|
|||||||
try:
|
try:
|
||||||
import lc3 # type: ignore # pylint: disable=E0401
|
import lc3 # type: ignore # pylint: disable=E0401
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(
|
raise ImportError("Try `python -m pip install '.[auracast]'`.") from e
|
||||||
"Try `python -m pip install \"git+https://github.com/google/liblc3.git\"`."
|
|
||||||
) from e
|
|
||||||
|
|
||||||
import bumble.device
|
import bumble.device
|
||||||
import bumble.logging
|
import bumble.logging
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from importlib import resources
|
|||||||
try:
|
try:
|
||||||
import lc3 # type: ignore # pylint: disable=E0401
|
import lc3 # type: ignore # pylint: disable=E0401
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError("Try `python -m pip install \".[lc3]\"`.") from e
|
raise ImportError("Try `python -m pip install \".[auracast]\"`.") from e
|
||||||
|
|
||||||
import aiohttp.web
|
import aiohttp.web
|
||||||
import click
|
import click
|
||||||
|
|||||||
+12
-2
@@ -913,7 +913,8 @@ class PeriodicAdvertisingSync(utils.EventEmitter):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.state = self.State.PENDING
|
if self.state == self.State.INIT:
|
||||||
|
self.state = self.State.PENDING
|
||||||
|
|
||||||
async def terminate(self) -> None:
|
async def terminate(self) -> None:
|
||||||
if self.state in (self.State.INIT, self.State.CANCELLED, self.State.TERMINATED):
|
if self.state in (self.State.INIT, self.State.CANCELLED, self.State.TERMINATED):
|
||||||
@@ -1575,6 +1576,15 @@ class CigParameters:
|
|||||||
rtn_c_to_p: int = DEVICE_DEFAULT_ISO_CIS_RTN # Number of C->P retransmissions
|
rtn_c_to_p: int = DEVICE_DEFAULT_ISO_CIS_RTN # Number of C->P retransmissions
|
||||||
rtn_p_to_c: int = DEVICE_DEFAULT_ISO_CIS_RTN # Number of P->C retransmissions
|
rtn_p_to_c: int = DEVICE_DEFAULT_ISO_CIS_RTN # Number of P->C retransmissions
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
# For unidirectional CIS (e.g., Central-to-Peripheral only), the unused direction's
|
||||||
|
# SDU size is 0. If SDU size is 0, we set RTN to 0 as well for maintaining
|
||||||
|
# compatibility with older firmware that has error 0x30 bug.
|
||||||
|
if self.max_sdu_c_to_p == 0:
|
||||||
|
self.rtn_c_to_p = 0
|
||||||
|
if self.max_sdu_p_to_c == 0:
|
||||||
|
self.rtn_p_to_c = 0
|
||||||
|
|
||||||
cig_id: int
|
cig_id: int
|
||||||
cis_parameters: list[CisParameters]
|
cis_parameters: list[CisParameters]
|
||||||
sdu_interval_c_to_p: int # C->P SDU interval, in microseconds
|
sdu_interval_c_to_p: int # C->P SDU interval, in microseconds
|
||||||
@@ -5430,7 +5440,7 @@ class Device(utils.CompositeEventEmitter):
|
|||||||
role: int = hci.CsRole.INITIATOR,
|
role: int = hci.CsRole.INITIATOR,
|
||||||
rtt_type: int = hci.RttType.AA_ONLY,
|
rtt_type: int = hci.RttType.AA_ONLY,
|
||||||
cs_sync_phy: int = hci.CsSyncPhy.LE_1M,
|
cs_sync_phy: int = hci.CsSyncPhy.LE_1M,
|
||||||
channel_map: bytes = b'\x54\x55\x55\x54\x55\x55\x55\x55\x55\x15',
|
channel_map: bytes = b'\x54\x55\x55\x54\x55\x55\x55\x55\x55\x05',
|
||||||
channel_map_repetition: int = 0x01,
|
channel_map_repetition: int = 0x01,
|
||||||
channel_selection_type: int = hci.HCI_LE_CS_Create_Config_Command.ChannelSelectionType.ALGO_3B,
|
channel_selection_type: int = hci.HCI_LE_CS_Create_Config_Command.ChannelSelectionType.ALGO_3B,
|
||||||
ch3c_shape: int = hci.HCI_LE_CS_Create_Config_Command.Ch3cShape.HAT,
|
ch3c_shape: int = hci.HCI_LE_CS_Create_Config_Command.Ch3cShape.HAT,
|
||||||
|
|||||||
@@ -28,13 +28,18 @@ from bumble.transport.common import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# pylint: disable=no-name-in-module
|
# pylint: disable=no-name-in-module
|
||||||
from bumble.transport.grpc_protobuf.emulated_bluetooth_packets_pb2 import HCIPacket
|
try:
|
||||||
from bumble.transport.grpc_protobuf.emulated_bluetooth_pb2_grpc import (
|
from bumble.transport.grpc_protobuf.emulated_bluetooth_packets_pb2 import HCIPacket
|
||||||
EmulatedBluetoothServiceStub,
|
from bumble.transport.grpc_protobuf.emulated_bluetooth_pb2_grpc import (
|
||||||
)
|
EmulatedBluetoothServiceStub,
|
||||||
from bumble.transport.grpc_protobuf.emulated_bluetooth_vhci_pb2_grpc import (
|
)
|
||||||
VhciForwardingServiceStub,
|
from bumble.transport.grpc_protobuf.emulated_bluetooth_vhci_pb2_grpc import (
|
||||||
)
|
VhciForwardingServiceStub,
|
||||||
|
)
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(
|
||||||
|
'The bumble[android] extra is required to use the Android emulator transport'
|
||||||
|
) from e
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Logging
|
# Logging
|
||||||
|
|||||||
@@ -37,18 +37,27 @@ from bumble.transport.common import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# pylint: disable=no-name-in-module
|
# pylint: disable=no-name-in-module
|
||||||
from bumble.transport.grpc_protobuf.netsim.common_pb2 import ChipKind
|
try:
|
||||||
from bumble.transport.grpc_protobuf.netsim.hci_packet_pb2 import HCIPacket
|
from bumble.transport.grpc_protobuf.netsim.common_pb2 import ChipKind
|
||||||
from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2 import (
|
from bumble.transport.grpc_protobuf.netsim.hci_packet_pb2 import HCIPacket
|
||||||
PacketRequest,
|
from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2 import (
|
||||||
PacketResponse,
|
PacketRequest,
|
||||||
)
|
PacketResponse,
|
||||||
from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2_grpc import (
|
)
|
||||||
PacketStreamerServicer,
|
from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2_grpc import (
|
||||||
PacketStreamerStub,
|
PacketStreamerServicer,
|
||||||
add_PacketStreamerServicer_to_server,
|
PacketStreamerStub,
|
||||||
)
|
add_PacketStreamerServicer_to_server,
|
||||||
from bumble.transport.grpc_protobuf.netsim.startup_pb2 import Chip, ChipInfo, DeviceInfo
|
)
|
||||||
|
from bumble.transport.grpc_protobuf.netsim.startup_pb2 import (
|
||||||
|
Chip,
|
||||||
|
ChipInfo,
|
||||||
|
DeviceInfo,
|
||||||
|
)
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(
|
||||||
|
'The bumble[android] extra is required to use the Android netsim transport'
|
||||||
|
) from e
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Logging
|
# Logging
|
||||||
|
|||||||
@@ -729,7 +729,10 @@ class UsbTransport(Transport):
|
|||||||
# We no longer need the event loop to run
|
# We no longer need the event loop to run
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.event_loop_should_exit = True
|
self.event_loop_should_exit = True
|
||||||
self.context.interruptEventHandler()
|
try:
|
||||||
|
self.context.interruptEventHandler()
|
||||||
|
except (AttributeError, usb1.USBError) as error:
|
||||||
|
logger.warning(f"Failed to interrupt event handler: {error}")
|
||||||
|
|
||||||
self.device.releaseInterface(self.acl_interface.getNumber())
|
self.device.releaseInterface(self.acl_interface.getNumber())
|
||||||
if self.sco_interface:
|
if self.sco_interface:
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ Try installing the optional `[auracast]` dependencies:
|
|||||||
|
|
||||||
## LC3
|
## LC3
|
||||||
The `auracast` app depends on the `lc3` python module, which is available
|
The `auracast` app depends on the `lc3` python module, which is available
|
||||||
either as PyPI module (currently only available for Linux x86_64).
|
as a PyPI module `lc3py` (currently available for Linux x86_64 and macOS arm64).
|
||||||
When installing Bumble with the optional `auracast` dependency, the `lc3`
|
When installing Bumble with the optional `auracast` dependency, the `lc3`
|
||||||
module will be installed from the `lc3py` PyPI package if available.
|
module will be installed automatically if your platform is supported.
|
||||||
If not, you will need to install it separately. This can be done with:
|
If not, you will need to install it separately. This can be done by building it from source:
|
||||||
```bash
|
```bash
|
||||||
$ python3 -m pip install "git+https://github.com/google/liblc3.git"
|
$ python3 -m pip install "git+https://github.com/google/liblc3.git"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ $ python3 -m pip install git+https://github.com/google/bumble.git@27c0551
|
|||||||
When you work on the Bumble code itself, and run some of the tests or example apps, or import the
|
When you work on the Bumble code itself, and run some of the tests or example apps, or import the
|
||||||
module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase.
|
module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase.
|
||||||
|
|
||||||
|
!!! tip "Installing Development Dependencies"
|
||||||
|
To install all optional dependencies and development tools (like `pytest`, `black`, `invoke`, etc.), run:
|
||||||
|
```bash
|
||||||
|
python3 -m pip install -e ".[all]" --group dev
|
||||||
|
```
|
||||||
|
|
||||||
If you plan on contributing to the project, please read the [contributing](development/contributing.md) section.
|
If you plan on contributing to the project, please read the [contributing](development/contributing.md) section.
|
||||||
|
|
||||||
## Without Installing
|
## Without Installing
|
||||||
|
|||||||
@@ -24,6 +24,20 @@ stack via a virtual HCI interface.
|
|||||||
Both ways are controlled via gRPC requests to the Android emulator controller and/or
|
Both ways are controlled via gRPC requests to the Android emulator controller and/or
|
||||||
from the Android emulator.
|
from the Android emulator.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Using the Android Emulator or Netsim transports requires the `android` optional dependencies (which include `grpcio` and `protobuf`).
|
||||||
|
|
||||||
|
If you installed Bumble from PyPI:
|
||||||
|
```bash
|
||||||
|
python3 -m pip install "bumble[android]"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are running from source:
|
||||||
|
```bash
|
||||||
|
python3 -m pip install ".[android]"
|
||||||
|
```
|
||||||
|
|
||||||
## Launching the Emulator
|
## Launching the Emulator
|
||||||
|
|
||||||
If the version of the emulator you are running does not yet support enabling
|
If the version of the emulator you are running does not yet support enabling
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ ANDROID EMULATOR TRANSPORT
|
|||||||
Use the `android-netsim` transport name instead.
|
Use the `android-netsim` transport name instead.
|
||||||
|
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
This transport requires the `android` extra. See the [Android Platform](../platforms/android.md) page for installation instructions.
|
||||||
|
|
||||||
The Android "netsim" transport either connects, as a host, to a **Netsim** virtual controller
|
The Android "netsim" transport either connects, as a host, to a **Netsim** virtual controller
|
||||||
("host" mode), or acts as a virtual controller itself ("controller" mode) accepting host
|
("host" mode), or acts as a virtual controller itself ("controller" mode) accepting host
|
||||||
connections.
|
connections.
|
||||||
|
|||||||
+35
-22
@@ -24,23 +24,42 @@ dependencies = [
|
|||||||
# updated. Relax the version requirement since it's better than being completely unable
|
# updated. Relax the version requirement since it's better than being completely unable
|
||||||
# to import the package in case of version mismatch.
|
# to import the package in case of version mismatch.
|
||||||
"cryptography >= 42.0.8; platform_system=='Android'",
|
"cryptography >= 42.0.8; platform_system=='Android'",
|
||||||
"grpcio >= 1.62.1; platform_system!='Emscripten'",
|
|
||||||
"humanize >= 4.6.0; platform_system!='Emscripten'",
|
"humanize >= 4.6.0; platform_system!='Emscripten'",
|
||||||
"libusb1 >= 2.0.1; platform_system!='Emscripten'",
|
|
||||||
"libusb-package == 1.0.26.4; platform_system!='Emscripten' and platform_system!='Android'",
|
|
||||||
"platformdirs >= 3.10.0; platform_system!='Emscripten'",
|
"platformdirs >= 3.10.0; platform_system!='Emscripten'",
|
||||||
"prompt_toolkit >= 3.0.16; platform_system!='Emscripten'",
|
"prompt_toolkit >= 3.0.16; platform_system!='Emscripten'",
|
||||||
"prettytable >= 3.6.0; platform_system!='Emscripten'",
|
"prettytable >= 3.6.0; platform_system!='Emscripten'",
|
||||||
"protobuf >= 3.12.4; platform_system!='Emscripten'",
|
|
||||||
"pyee >= 13.0.0",
|
"pyee >= 13.0.0",
|
||||||
"pyserial-asyncio >= 0.5; platform_system!='Emscripten'",
|
|
||||||
"pyserial >= 3.5; platform_system!='Emscripten'",
|
|
||||||
"pyusb >= 1.2; platform_system!='Emscripten'",
|
|
||||||
"tomli ~= 2.2.1; platform_system!='Emscripten' and python_version<'3.11'",
|
"tomli ~= 2.2.1; platform_system!='Emscripten' and python_version<'3.11'",
|
||||||
"websockets >= 15.0.1; platform_system!='Emscripten'",
|
"websockets >= 15.0.1; platform_system!='Emscripten'",
|
||||||
|
# Serial
|
||||||
|
"pyserial-asyncio >= 0.5; platform_system!='Emscripten'",
|
||||||
|
"pyserial >= 3.5; platform_system!='Emscripten'",
|
||||||
|
# USB
|
||||||
|
"libusb1 >= 2.0.1; platform_system!='Emscripten'",
|
||||||
|
"libusb-package == 1.0.26.4; platform_system!='Emscripten' and platform_system!='Android'",
|
||||||
|
"pyusb >= 1.2; platform_system!='Emscripten'",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
android = [
|
||||||
|
"grpcio >= 1.62.1; platform_system!='Emscripten'",
|
||||||
|
"protobuf >= 3.12.4; platform_system!='Emscripten'",
|
||||||
|
]
|
||||||
|
avatar = [
|
||||||
|
"pandora-avatar == 0.0.10",
|
||||||
|
"rootcanal == 1.11.1 ; python_version>='3.10'",
|
||||||
|
]
|
||||||
|
pandora = ["bt-test-interfaces >= 0.0.6"]
|
||||||
|
auracast = [
|
||||||
|
"lc3py >= 1.1.3; python_version>='3.10' and ((platform_system=='Linux' and platform_machine=='x86_64') or (platform_system=='Darwin' and platform_machine=='arm64'))",
|
||||||
|
"sounddevice >= 0.5.1",
|
||||||
|
]
|
||||||
|
all = [
|
||||||
|
"bumble[android]",
|
||||||
|
"bumble[auracast]",
|
||||||
|
]
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
build = ["build >= 0.7"]
|
build = ["build >= 0.7"]
|
||||||
test = [
|
test = [
|
||||||
"pytest >= 9.0",
|
"pytest >= 9.0",
|
||||||
@@ -48,7 +67,15 @@ test = [
|
|||||||
"pytest-html >= 4.2",
|
"pytest-html >= 4.2",
|
||||||
"coverage >= 6.4",
|
"coverage >= 6.4",
|
||||||
]
|
]
|
||||||
development = [
|
docs = [
|
||||||
|
"mkdocs >= 1.6.0",
|
||||||
|
"mkdocs-material >= 9.6",
|
||||||
|
"mkdocstrings[python] >= 0.27.0",
|
||||||
|
]
|
||||||
|
dev = [
|
||||||
|
{include-group = "build"},
|
||||||
|
{include-group = "test"},
|
||||||
|
{include-group = "docs"},
|
||||||
"black ~= 25.1",
|
"black ~= 25.1",
|
||||||
"bt-test-interfaces >= 0.0.6",
|
"bt-test-interfaces >= 0.0.6",
|
||||||
"grpcio-tools >= 1.62.1",
|
"grpcio-tools >= 1.62.1",
|
||||||
@@ -63,20 +90,6 @@ development = [
|
|||||||
"types-invoke >= 1.7.3",
|
"types-invoke >= 1.7.3",
|
||||||
"types-protobuf >= 4.21.0",
|
"types-protobuf >= 4.21.0",
|
||||||
]
|
]
|
||||||
avatar = [
|
|
||||||
"pandora-avatar == 0.0.10",
|
|
||||||
"rootcanal == 1.11.1 ; python_version>='3.10'",
|
|
||||||
]
|
|
||||||
pandora = ["bt-test-interfaces >= 0.0.6"]
|
|
||||||
documentation = [
|
|
||||||
"mkdocs >= 1.6.0",
|
|
||||||
"mkdocs-material >= 9.6",
|
|
||||||
"mkdocstrings[python] >= 0.27.0",
|
|
||||||
]
|
|
||||||
auracast = [
|
|
||||||
"lc3py >= 1.1.3; python_version>='3.10' and ((platform_system=='Linux' and platform_machine=='x86_64') or (platform_system=='Darwin' and platform_machine=='arm64'))",
|
|
||||||
"sounddevice >= 0.5.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
bumble-auracast = "bumble.apps.auracast:main"
|
bumble-auracast = "bumble.apps.auracast:main"
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ def build(ctx, install=False):
|
|||||||
if install:
|
if install:
|
||||||
ctx.run('python -m pip install .[build]')
|
ctx.run('python -m pip install .[build]')
|
||||||
|
|
||||||
ctx.run("python -m build")
|
ctx.run("python -I -m build")
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools
|
import functools
|
||||||
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
@@ -595,6 +596,25 @@ async def test_cis_setup_failure():
|
|||||||
await asyncio.wait_for(cis_create_task, _TIMEOUT)
|
await asyncio.wait_for(cis_create_task, _TIMEOUT)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
def test_cis_parameters_unidirectional():
|
||||||
|
# Test C2P unidirectional (P to C not used)
|
||||||
|
cis_c2p = CigParameters.CisParameters(cis_id=1, max_sdu_p_to_c=0)
|
||||||
|
assert cis_c2p.max_sdu_c_to_p != 0
|
||||||
|
assert cis_c2p.rtn_c_to_p != 0
|
||||||
|
assert cis_c2p.phy_c_to_p != hci.PhyBit(0)
|
||||||
|
assert cis_c2p.rtn_p_to_c == 0
|
||||||
|
assert cis_c2p.phy_p_to_c != hci.PhyBit(0)
|
||||||
|
|
||||||
|
# Test P2C unidirectional (C to P not used)
|
||||||
|
cis_p2c = CigParameters.CisParameters(cis_id=2, max_sdu_c_to_p=0)
|
||||||
|
assert cis_p2c.max_sdu_p_to_c != 0
|
||||||
|
assert cis_p2c.rtn_p_to_c != 0
|
||||||
|
assert cis_p2c.phy_p_to_c != hci.PhyBit(0)
|
||||||
|
assert cis_p2c.rtn_c_to_p == 0
|
||||||
|
assert cis_p2c.phy_c_to_p != hci.PhyBit(0)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_enter_and_exit_sniff_mode():
|
async def test_enter_and_exit_sniff_mode():
|
||||||
@@ -674,6 +694,25 @@ async def test_power_on_default_static_address_should_not_be_any():
|
|||||||
assert devices[0].static_address != Address.ANY_RANDOM
|
assert devices[0].static_address != Address.ANY_RANDOM
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
def test_cs_channel_map_excludes_forbidden_channels():
|
||||||
|
forbidden = {0, 1, 23, 24, 25, 76, 77, 78, 79}
|
||||||
|
default_map = (
|
||||||
|
inspect.signature(Device.create_cs_config).parameters['channel_map'].default
|
||||||
|
)
|
||||||
|
|
||||||
|
enabled = {
|
||||||
|
byte_idx * 8 + bit
|
||||||
|
for byte_idx, byte in enumerate(default_map)
|
||||||
|
for bit in range(8)
|
||||||
|
if byte & (1 << bit)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert enabled.isdisjoint(
|
||||||
|
forbidden
|
||||||
|
), f"Default channel_map enables forbidden CS channels: {enabled & forbidden}"
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
def test_gatt_services_with_gas_and_gatt():
|
def test_gatt_services_with_gas_and_gatt():
|
||||||
device = Device(host=Host(None, None))
|
device = Device(host=Host(None, None))
|
||||||
|
|||||||
Reference in New Issue
Block a user