From 5f86cddc8570fd0b97342d2544335466cd358fb1 Mon Sep 17 00:00:00 2001 From: Gilles Boccon-Gibod Date: Wed, 18 Jan 2023 23:27:06 +0000 Subject: [PATCH] cleanup doc (+6 squashed commits) Squashed commits: [6b97b93] add gRPC publish support for netsim [439717b] fix doc [5f679d7] fix linting and type errors [ca7b734] merge 2 [f29c909] update docs [7800ef9] cleanup (+5 squashed commits) Squashed commits: [c501eac] update to latest protos [e51a3fb] wip [d6a58fc] wip [eaa9fa6] wip [68d9490] wip wip wip wip update to latest protos cleanup --- bumble/transport/__init__.py | 5 + bumble/transport/android_emulator.py | 10 +- bumble/transport/android_netsim.py | 409 ++++++++++++++++++ .../emulated_bluetooth_packets_pb2.py | 45 -- .../emulated_bluetooth_packets_pb2_grpc.py | 17 - bumble/transport/emulated_bluetooth_pb2.py | 46 -- bumble/transport/emulated_bluetooth_pb2.pyi | 26 -- .../transport/emulated_bluetooth_pb2_grpc.py | 244 ----------- .../transport/emulated_bluetooth_vhci_pb2.py | 46 -- .../transport/emulated_bluetooth_vhci_pb2.pyi | 19 - bumble/transport/grpc_protobuf/__init__.py | 0 bumble/transport/grpc_protobuf/common_pb2.py | 25 ++ bumble/transport/grpc_protobuf/common_pb2.pyi | 12 + .../grpc_protobuf/common_pb2_grpc.py | 4 + .../emulated_bluetooth_device_pb2.py | 64 +++ .../emulated_bluetooth_device_pb2.pyi | 158 +++++++ .../emulated_bluetooth_device_pb2_grpc.py | 193 +++++++++ .../emulated_bluetooth_packets_pb2.py | 28 ++ .../emulated_bluetooth_packets_pb2.pyi | 21 +- .../emulated_bluetooth_packets_pb2_grpc.py | 4 + .../grpc_protobuf/emulated_bluetooth_pb2.py | 32 ++ .../grpc_protobuf/emulated_bluetooth_pb2.pyi | 19 + .../emulated_bluetooth_pb2_grpc.py | 237 ++++++++++ .../emulated_bluetooth_vhci_pb2.py | 27 ++ .../emulated_bluetooth_vhci_pb2.pyi | 5 + .../emulated_bluetooth_vhci_pb2_grpc.py | 73 +--- .../grpc_endpoint_description_pb2.py | 30 ++ .../grpc_endpoint_description_pb2.pyi | 34 ++ .../grpc_endpoint_description_pb2_grpc.py | 4 + .../transport/grpc_protobuf/hci_packet_pb2.py | 28 ++ .../grpc_protobuf/hci_packet_pb2.pyi | 22 + .../grpc_protobuf/hci_packet_pb2_grpc.py | 4 + .../grpc_protobuf/packet_streamer_pb2.py | 31 ++ .../grpc_protobuf/packet_streamer_pb2.pyi | 27 ++ .../grpc_protobuf/packet_streamer_pb2_grpc.py | 109 +++++ bumble/transport/grpc_protobuf/startup_pb2.py | 32 ++ .../transport/grpc_protobuf/startup_pb2.pyi | 46 ++ .../grpc_protobuf/startup_pb2_grpc.py | 4 + docs/mkdocs/src/platforms/android.md | 89 ++-- .../mkdocs/src/transports/android_emulator.md | 41 +- docs/mkdocs/src/transports/index.md | 3 +- examples/a2dp_sink1.json | 1 + pyproject.toml | 33 +- scripts/process_android_emulator_protos.sh | 25 +- scripts/process_android_netsim_protos.sh | 14 + setup.cfg | 3 +- 46 files changed, 1752 insertions(+), 597 deletions(-) create mode 100644 bumble/transport/android_netsim.py delete mode 100644 bumble/transport/emulated_bluetooth_packets_pb2.py delete mode 100644 bumble/transport/emulated_bluetooth_packets_pb2_grpc.py delete mode 100644 bumble/transport/emulated_bluetooth_pb2.py delete mode 100644 bumble/transport/emulated_bluetooth_pb2.pyi delete mode 100644 bumble/transport/emulated_bluetooth_pb2_grpc.py delete mode 100644 bumble/transport/emulated_bluetooth_vhci_pb2.py delete mode 100644 bumble/transport/emulated_bluetooth_vhci_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/__init__.py create mode 100644 bumble/transport/grpc_protobuf/common_pb2.py create mode 100644 bumble/transport/grpc_protobuf/common_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/common_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.py rename bumble/transport/{ => grpc_protobuf}/emulated_bluetooth_packets_pb2.pyi (53%) create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.py create mode 100644 bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.pyi rename bumble/transport/{ => grpc_protobuf}/emulated_bluetooth_vhci_pb2_grpc.py (59%) create mode 100644 bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.py create mode 100644 bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/hci_packet_pb2.py create mode 100644 bumble/transport/grpc_protobuf/hci_packet_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/hci_packet_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/packet_streamer_pb2.py create mode 100644 bumble/transport/grpc_protobuf/packet_streamer_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py create mode 100644 bumble/transport/grpc_protobuf/startup_pb2.py create mode 100644 bumble/transport/grpc_protobuf/startup_pb2.pyi create mode 100644 bumble/transport/grpc_protobuf/startup_pb2_grpc.py create mode 100644 scripts/process_android_netsim_protos.sh diff --git a/bumble/transport/__init__.py b/bumble/transport/__init__.py index 2d4600f..840b3e5 100644 --- a/bumble/transport/__init__.py +++ b/bumble/transport/__init__.py @@ -145,6 +145,11 @@ async def _open_transport(name: str) -> Transport: return await open_android_emulator_transport(spec[0] if spec else None) + if scheme == 'android-netsim': + from .android_netsim import open_android_netsim_transport + + return await open_android_netsim_transport(spec[0] if spec else None) + raise ValueError('unknown transport scheme') diff --git a/bumble/transport/android_emulator.py b/bumble/transport/android_emulator.py index 6d9e4d1..b78e263 100644 --- a/bumble/transport/android_emulator.py +++ b/bumble/transport/android_emulator.py @@ -16,14 +16,14 @@ # Imports # ----------------------------------------------------------------------------- import logging -import grpc +import grpc.aio from .common import PumpedTransport, PumpedPacketSource, PumpedPacketSink -from .emulated_bluetooth_pb2_grpc import EmulatedBluetoothServiceStub -from .emulated_bluetooth_vhci_pb2_grpc import VhciForwardingServiceStub -# pylint: disable-next=no-name-in-module -from .emulated_bluetooth_packets_pb2 import HCIPacket +# pylint: disable=no-name-in-module +from .grpc_protobuf.emulated_bluetooth_pb2_grpc import EmulatedBluetoothServiceStub +from .grpc_protobuf.emulated_bluetooth_packets_pb2 import HCIPacket +from .grpc_protobuf.emulated_bluetooth_vhci_pb2_grpc import VhciForwardingServiceStub # ----------------------------------------------------------------------------- diff --git a/bumble/transport/android_netsim.py b/bumble/transport/android_netsim.py new file mode 100644 index 0000000..7172081 --- /dev/null +++ b/bumble/transport/android_netsim.py @@ -0,0 +1,409 @@ +# Copyright 2021-2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ----------------------------------------------------------------------------- +# Imports +# ----------------------------------------------------------------------------- +import asyncio +import atexit +import logging +import grpc.aio +import os +import pathlib +import sys +from typing import Optional + +from .common import ( + ParserSource, + PumpedTransport, + PumpedPacketSource, + PumpedPacketSink, + Transport, +) + +# pylint: disable=no-name-in-module +from .grpc_protobuf.packet_streamer_pb2_grpc import PacketStreamerStub +from .grpc_protobuf.packet_streamer_pb2_grpc import ( + PacketStreamerServicer, + add_PacketStreamerServicer_to_server, +) +from .grpc_protobuf.packet_streamer_pb2 import PacketRequest, PacketResponse +from .grpc_protobuf.hci_packet_pb2 import HCIPacket +from .grpc_protobuf.startup_pb2 import Chip, ChipInfo +from .grpc_protobuf.common_pb2 import ChipKind + +# ----------------------------------------------------------------------------- +# Logging +# ----------------------------------------------------------------------------- +logger = logging.getLogger(__name__) + + +# ----------------------------------------------------------------------------- +# Constants +# ----------------------------------------------------------------------------- +DEFAULT_NAME = 'bumble0' +DEFAULT_MANUFACTURER = 'Bumble' + + +# ----------------------------------------------------------------------------- +def get_ini_dir() -> Optional[pathlib.Path]: + if sys.platform == 'darwin': + if tmpdir := os.getenv('TMPDIR', None): + return pathlib.Path(tmpdir) + if home := os.getenv('HOME', None): + return pathlib.Path(home) / 'Library/Caches/TemporaryItems' + elif sys.platform == 'linux': + if xdg_runtime_dir := os.environ.get('XDG_RUNTIME_DIR', None): + return pathlib.Path(xdg_runtime_dir) + elif sys.platform == 'win32': + if local_app_data_dir := os.environ.get('LOCALAPPDATA', None): + return pathlib.Path(local_app_data_dir) / 'Temp' + + return None + + +# ----------------------------------------------------------------------------- +def find_grpc_port() -> int: + if not (ini_dir:= get_ini_dir()): + logger.debug('no known directory for .ini file') + return 0 + + ini_file = ini_dir / 'netsim.ini' + if ini_file.is_file(): + logger.debug(f'Found .ini file at {ini_file}') + with open(ini_file, 'r') as ini_file_data: + for line in ini_file_data.readlines(): + if '=' in line: + key, value = line.split('=') + if key == 'grpc.port': + logger.debug(f'gRPC port = {value}') + return int(value) + + # Not found + return 0 + + +# ----------------------------------------------------------------------------- +def publish_grpc_port(grpc_port) -> bool: + if not (ini_dir:= get_ini_dir()): + logger.debug('no known directory for .ini file') + return False + + if not ini_dir.is_dir: + logger.debug('ini directory does not exist') + return False + + ini_file = ini_dir / 'netsim.ini' + try: + ini_file.write_text(f'grpc.port={grpc_port}\n') + logger.debug(f"published gRPC port at {ini_file}") + def cleanup(): + logger.debug("removing .ini file") + ini_file.unlink() + + atexit.register(cleanup) + return True + except OSError: + logger.debug('failed to write to .ini file') + return False + + +# ----------------------------------------------------------------------------- +async def open_android_netsim_controller_transport(server_host, server_port): + if not server_port: + raise ValueError('invalid port') + if server_host == '_' or not server_host: + server_host = 'localhost' + + if not publish_grpc_port(server_port): + logger.warning("unable to publish gRPC port") + + class HciDevice: + def __init__(self, context, on_data_received): + self.context = context + self.on_data_received = on_data_received + self.name = None + self.loop = asyncio.get_running_loop() + self.done = self.loop.create_future() + self.task = self.loop.create_task(self.pump()) + + async def pump(self): + try: + await self.pump_loop() + except asyncio.CancelledError: + logger.debug('Pump task canceled') + self.done.set_result(None) + + async def pump_loop(self): + while True: + request = await self.context.read() + if request == grpc.aio.EOF: + logger.debug('End of request stream') + self.done.set_result(None) + return + + # If we're not initialized yet, wait for a init packet. + if self.name is None: + if request.WhichOneof('request_type') == 'initial_info': + logger.debug(f'Received initial info: {request}') + + # We only accept BLUETOOTH + if request.initial_info.chip.kind != ChipKind.BLUETOOTH: + logger.warning('Unsupported chip type') + error = PacketResponse(error='Unsupported chip type') + await self.context.write(error) + return + + self.name = request.initial_info.name + continue + + # Expect a data packet + request_type = request.WhichOneof('request_type') + if request_type != 'hci_packet': + logger.warning(f'Unexpected request type: {request_type}') + error = PacketResponse(error='Unexpected request type') + await self.context.write(error) + continue + + # Process the packet + data = ( + bytes([request.hci_packet.packet_type]) + request.hci_packet.packet + ) + logger.debug(f'<<< PACKET: {data.hex()}') + self.on_data_received(data) + + def send_packet(self, data): + async def send(): + await self.context.write( + PacketResponse( + hci_packet=HCIPacket(packet_type=data[0], packet=data[1:]) + ) + ) + + self.loop.create_task(send()) + + def terminate(self): + self.task.cancel() + + async def wait_for_termination(self): + await self.done + + class Server(PacketStreamerServicer, ParserSource): + def __init__(self): + PacketStreamerServicer.__init__(self) + ParserSource.__init__(self) + self.device = None + + # Create a gRPC server with `so_reuseport=0` so that if there's already + # a server listening on that port, we get an exception. + self.grpc_server = grpc.aio.server(options=(('grpc.so_reuseport', 0),)) + add_PacketStreamerServicer_to_server(self, self.grpc_server) + self.grpc_server.add_insecure_port(f'{server_host}:{server_port}') + logger.debug(f'gRPC server listening on {server_host}:{server_port}') + + async def start(self): + logger.debug('Starting gRPC server') + await self.grpc_server.start() + + async def serve(self): + # Keep serving until terminated. + try: + await self.grpc_server.wait_for_termination() + logger.debug('gRPC server terminated') + except asyncio.CancelledError: + logger.debug('gRPC server cancelled') + await self.grpc_server.stop(None) + + def on_packet(self, packet): + if not self.device: + logger.debug('no device, dropping packet') + return + + self.device.send_packet(packet) + + async def StreamPackets(self, _request_iterator, context): + logger.debug('StreamPackets request') + + # Check that we won't already have a device + if self.device: + logger.debug('busy, already serving a device') + return PacketResponse(error='Busy') + + # Instantiate a new device + self.device = HciDevice(context, self.parser.feed_data) + + # Wait for the device to terminate + logger.debug('Waiting for device to terminate') + try: + await self.device.wait_for_termination() + except asyncio.CancelledError: + logger.debug('Request canceled') + self.device.terminate() + + logger.debug('Device terminated') + self.device = None + + server = Server() + await server.start() + asyncio.get_running_loop().create_task(server.serve()) + + class GrpcServerTransport(Transport): + async def close(self): + await super().close() + + return GrpcServerTransport(server, server) + + +# ----------------------------------------------------------------------------- +async def open_android_netsim_host_transport(server_host, server_port, options): + # Wrapper for I/O operations + class HciDevice: + def __init__(self, name, manufacturer, hci_device): + self.name = name + self.manufacturer = manufacturer + self.hci_device = hci_device + + async def start(self): # Send the startup info + chip_info = ChipInfo( + name=self.name, + chip=Chip(kind=ChipKind.BLUETOOTH, manufacturer=self.manufacturer), + ) + logger.debug(f'Sending chip info to netsim: {chip_info}') + await self.hci_device.write(PacketRequest(initial_info=chip_info)) + + async def read(self): + response = await self.hci_device.read() + response_type = response.WhichOneof('response_type') + if response_type == 'error': + logger.warning(f'received error: {response.error}') + raise RuntimeError(response.error) + elif response_type == 'hci_packet': + return ( + bytes([response.hci_packet.packet_type]) + + response.hci_packet.packet + ) + + raise ValueError('unsupported response type') + + async def write(self, packet): + await self.hci_device.write( + PacketRequest( + hci_packet=HCIPacket(packet_type=packet[0], packet=packet[1:]) + ) + ) + + name = options.get('name', DEFAULT_NAME) + manufacturer = DEFAULT_MANUFACTURER + + if server_host == '_' or not server_host: + server_host = 'localhost' + + if not server_port: + # Look for the gRPC config in a .ini file + server_host = 'localhost' + server_port = find_grpc_port() + if not server_port: + raise RuntimeError('gRPC server port not found') + + # Connect to the gRPC server + server_address = f'{server_host}:{server_port}' + logger.debug(f'Connecting to gRPC server at {server_address}') + channel = grpc.aio.insecure_channel(server_address) + + # Connect as a host + service = PacketStreamerStub(channel) + hci_device = HciDevice( + name=name, + manufacturer=manufacturer, + hci_device=service.StreamPackets(), + ) + await hci_device.start() + + # Create the transport object + transport = PumpedTransport( + PumpedPacketSource(hci_device.read), + PumpedPacketSink(hci_device.write), + channel.close, + ) + transport.start() + + return transport + + +# ----------------------------------------------------------------------------- +async def open_android_netsim_transport(spec): + ''' + Open a transport connection as a client or server, implementing Android's `netsim` + simulator protocol over gRPC. + The parameter string has this syntax: + [:][] + Where is a ','-separated list of = pairs. + + General options: + mode=host|controller (default: host) + Specifies whether the transport is used + to connect *to* a netsim server (netsim is the controller), or accept + connections *as* a netsim-compatible server. + + In `host` mode: + The : part is optional. When not specified, the transport + looks for a netsim .ini file, from which it will read the `grpc.backend.port` + property. + Options for this mode are: + name= + The "chip" name, used to identify the "chip" instance. This + may be useful when several clients are connected, since each needs to use a + different name. + + In `controller` mode: + The : part is required. may be the address of a local network + interface, or '_' to accept connections on all local network interfaces. + + Examples: + (empty string) --> connect to netsim on the port specified in the .ini file + localhost:8555 --> connect to netsim on localhost:8555 + name=bumble1 --> connect to netsim, using `bumble1` as the "chip" name. + localhost:8555,name=bumble1 --> connect to netsim on localhost:8555, using + `bumble1` as the "chip" name. + _:8877,mode=controller --> accept connections as a controller on any interface + on port 8877. + ''' + + # Parse the parameters + params = spec.split(',') if spec else [] + if params and ':' in params[0]: + # Explicit : + host, port = params[0].split(':') + params_offset = 1 + else: + host = None + port = 0 + params_offset = 0 + + options = {} + for param in params[params_offset:]: + if '=' not in param: + raise ValueError('invalid parameter, expected =') + option_name, option_value = param.split('=') + options[option_name] = option_value + + mode = options.get('mode', 'host') + if mode == 'host': + return await open_android_netsim_host_transport(host, port, options) + if mode == 'controller': + if host is None: + raise ValueError(': missing') + return await open_android_netsim_controller_transport(host, port) + + raise ValueError('invalid mode option') diff --git a/bumble/transport/emulated_bluetooth_packets_pb2.py b/bumble/transport/emulated_bluetooth_packets_pb2.py deleted file mode 100644 index 2802ff1..0000000 --- a/bumble/transport/emulated_bluetooth_packets_pb2.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: emulated_bluetooth_packets.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n emulated_bluetooth_packets.proto\x12\x1b\x61ndroid.emulation.bluetooth\"\xfb\x01\n\tHCIPacket\x12?\n\x04type\x18\x01 \x01(\x0e\x32\x31.android.emulation.bluetooth.HCIPacket.PacketType\x12\x0e\n\x06packet\x18\x02 \x01(\x0c\"\x9c\x01\n\nPacketType\x12\x1b\n\x17PACKET_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17PACKET_TYPE_HCI_COMMAND\x10\x01\x12\x13\n\x0fPACKET_TYPE_ACL\x10\x02\x12\x13\n\x0fPACKET_TYPE_SCO\x10\x03\x12\x15\n\x11PACKET_TYPE_EVENT\x10\x04\x12\x13\n\x0fPACKET_TYPE_ISO\x10\x05\x42J\n\x1f\x63om.android.emulation.bluetoothP\x01\xf8\x01\x01\xa2\x02\x03\x41\x45\x42\xaa\x02\x1b\x41ndroid.Emulation.Bluetoothb\x06proto3' -) - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, 'emulated_bluetooth_packets_pb2', globals() -) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'\n\037com.android.emulation.bluetoothP\001\370\001\001\242\002\003AEB\252\002\033Android.Emulation.Bluetooth' - _HCIPACKET._serialized_start = 66 - _HCIPACKET._serialized_end = 317 - _HCIPACKET_PACKETTYPE._serialized_start = 161 - _HCIPACKET_PACKETTYPE._serialized_end = 317 -# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/emulated_bluetooth_packets_pb2_grpc.py b/bumble/transport/emulated_bluetooth_packets_pb2_grpc.py deleted file mode 100644 index 3450039..0000000 --- a/bumble/transport/emulated_bluetooth_packets_pb2_grpc.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc diff --git a/bumble/transport/emulated_bluetooth_pb2.py b/bumble/transport/emulated_bluetooth_pb2.py deleted file mode 100644 index 42015f6..0000000 --- a/bumble/transport/emulated_bluetooth_pb2.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: emulated_bluetooth.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18\x65mulated_bluetooth.proto\x12\x1b\x61ndroid.emulation.bluetooth\x1a emulated_bluetooth_packets.proto\"\x19\n\x07RawData\x12\x0e\n\x06packet\x18\x01 \x01(\x0c\x32\xcb\x02\n\x18\x45mulatedBluetoothService\x12\x64\n\x12registerClassicPhy\x12$.android.emulation.bluetooth.RawData\x1a$.android.emulation.bluetooth.RawData(\x01\x30\x01\x12`\n\x0eregisterBlePhy\x12$.android.emulation.bluetooth.RawData\x1a$.android.emulation.bluetooth.RawData(\x01\x30\x01\x12g\n\x11registerHCIDevice\x12&.android.emulation.bluetooth.HCIPacket\x1a&.android.emulation.bluetooth.HCIPacket(\x01\x30\x01\x42\"\n\x1e\x63om.android.emulator.bluetoothP\x01\x62\x06proto3' -) - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'emulated_bluetooth_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'\n\036com.android.emulator.bluetoothP\001' - _RAWDATA._serialized_start = 91 - _RAWDATA._serialized_end = 116 - _EMULATEDBLUETOOTHSERVICE._serialized_start = 119 - _EMULATEDBLUETOOTHSERVICE._serialized_end = 450 -# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/emulated_bluetooth_pb2.pyi b/bumble/transport/emulated_bluetooth_pb2.pyi deleted file mode 100644 index fb87a52..0000000 --- a/bumble/transport/emulated_bluetooth_pb2.pyi +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import emulated_bluetooth_packets_pb2 as _emulated_bluetooth_packets_pb2 -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Optional as _Optional - -DESCRIPTOR: _descriptor.FileDescriptor - -class RawData(_message.Message): - __slots__ = ["packet"] - PACKET_FIELD_NUMBER: _ClassVar[int] - packet: bytes - def __init__(self, packet: _Optional[bytes] = ...) -> None: ... diff --git a/bumble/transport/emulated_bluetooth_pb2_grpc.py b/bumble/transport/emulated_bluetooth_pb2_grpc.py deleted file mode 100644 index 8559c9e..0000000 --- a/bumble/transport/emulated_bluetooth_pb2_grpc.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc - -from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 -from . import emulated_bluetooth_pb2 as emulated__bluetooth__pb2 - - -class EmulatedBluetoothServiceStub(object): - """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the - android emulator. It allows you to register emulated bluetooth devices and - control the packets that are exchanged between the device and the world. - - This service enables you to establish a "virtual network" of emulated - bluetooth devices that can interact with each other. - - Note: This is not yet finalized, it is likely that these definitions will - evolve. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.registerClassicPhy = channel.stream_stream( - '/android.emulation.bluetooth.EmulatedBluetoothService/registerClassicPhy', - request_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, - response_deserializer=emulated__bluetooth__pb2.RawData.FromString, - ) - self.registerBlePhy = channel.stream_stream( - '/android.emulation.bluetooth.EmulatedBluetoothService/registerBlePhy', - request_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, - response_deserializer=emulated__bluetooth__pb2.RawData.FromString, - ) - self.registerHCIDevice = channel.stream_stream( - '/android.emulation.bluetooth.EmulatedBluetoothService/registerHCIDevice', - request_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, - response_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, - ) - - -class EmulatedBluetoothServiceServicer(object): - """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the - android emulator. It allows you to register emulated bluetooth devices and - control the packets that are exchanged between the device and the world. - - This service enables you to establish a "virtual network" of emulated - bluetooth devices that can interact with each other. - - Note: This is not yet finalized, it is likely that these definitions will - evolve. - """ - - def registerClassicPhy(self, request_iterator, context): - """Connect device to link layer. This will establish a direct connection - to the emulated bluetooth chip and configure the following: - - - Each connection creates a new device and attaches it to the link layer - - Link Layer packets are transmitted directly to the phy - - This should be used for classic connections. - - This is used to directly connect various android emulators together. - For example a wear device can connect to an android emulator through - this. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def registerBlePhy(self, request_iterator, context): - """Connect device to link layer. This will establish a direct connection - to root canal and execute the following: - - - Each connection creates a new device and attaches it to the link layer - - Link Layer packets are transmitted directly to the phy - - This should be used for BLE connections. - - This is used to directly connect various android emulators together. - For example a wear device can connect to an android emulator through - this. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def registerHCIDevice(self, request_iterator, context): - """Connect the device to the emulated bluetooth chip. The device will - participate in the network. You can configure the chip to scan, advertise - and setup connections with other devices that are connected to the - network. - - This is usually used when you have a need for an emulated bluetooth chip - and have a bluetooth stack that can interpret and handle the packets - correctly. - - For example the apache nimble stack can use this endpoint as the - transport layer. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_EmulatedBluetoothServiceServicer_to_server(servicer, server): - rpc_method_handlers = { - 'registerClassicPhy': grpc.stream_stream_rpc_method_handler( - servicer.registerClassicPhy, - request_deserializer=emulated__bluetooth__pb2.RawData.FromString, - response_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, - ), - 'registerBlePhy': grpc.stream_stream_rpc_method_handler( - servicer.registerBlePhy, - request_deserializer=emulated__bluetooth__pb2.RawData.FromString, - response_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, - ), - 'registerHCIDevice': grpc.stream_stream_rpc_method_handler( - servicer.registerHCIDevice, - request_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, - response_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'android.emulation.bluetooth.EmulatedBluetoothService', rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) - - -# This class is part of an EXPERIMENTAL API. -class EmulatedBluetoothService(object): - """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the - android emulator. It allows you to register emulated bluetooth devices and - control the packets that are exchanged between the device and the world. - - This service enables you to establish a "virtual network" of emulated - bluetooth devices that can interact with each other. - - Note: This is not yet finalized, it is likely that these definitions will - evolve. - """ - - @staticmethod - def registerClassicPhy( - request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.stream_stream( - request_iterator, - target, - '/android.emulation.bluetooth.EmulatedBluetoothService/registerClassicPhy', - emulated__bluetooth__pb2.RawData.SerializeToString, - emulated__bluetooth__pb2.RawData.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - ) - - @staticmethod - def registerBlePhy( - request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.stream_stream( - request_iterator, - target, - '/android.emulation.bluetooth.EmulatedBluetoothService/registerBlePhy', - emulated__bluetooth__pb2.RawData.SerializeToString, - emulated__bluetooth__pb2.RawData.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - ) - - @staticmethod - def registerHCIDevice( - request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.stream_stream( - request_iterator, - target, - '/android.emulation.bluetooth.EmulatedBluetoothService/registerHCIDevice', - emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, - emulated__bluetooth__packets__pb2.HCIPacket.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - ) diff --git a/bumble/transport/emulated_bluetooth_vhci_pb2.py b/bumble/transport/emulated_bluetooth_vhci_pb2.py deleted file mode 100644 index e8009ad..0000000 --- a/bumble/transport/emulated_bluetooth_vhci_pb2.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: emulated_bluetooth_vhci.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1d\x65mulated_bluetooth_vhci.proto\x12\x1b\x61ndroid.emulation.bluetooth\x1a emulated_bluetooth_packets.proto2y\n\x15VhciForwardingService\x12`\n\nattachVhci\x12&.android.emulation.bluetooth.HCIPacket\x1a&.android.emulation.bluetooth.HCIPacket(\x01\x30\x01\x42J\n\x1f\x63om.android.emulation.bluetoothP\x01\xf8\x01\x01\xa2\x02\x03\x41\x45\x42\xaa\x02\x1b\x41ndroid.Emulation.Bluetoothb\x06proto3' -) - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, 'emulated_bluetooth_vhci_pb2', globals() -) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'\n\037com.android.emulation.bluetoothP\001\370\001\001\242\002\003AEB\252\002\033Android.Emulation.Bluetooth' - _VHCIFORWARDINGSERVICE._serialized_start = 96 - _VHCIFORWARDINGSERVICE._serialized_end = 217 -# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/emulated_bluetooth_vhci_pb2.pyi b/bumble/transport/emulated_bluetooth_vhci_pb2.pyi deleted file mode 100644 index 0877ad0..0000000 --- a/bumble/transport/emulated_bluetooth_vhci_pb2.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import emulated_bluetooth_packets_pb2 as _emulated_bluetooth_packets_pb2 -from google.protobuf import descriptor as _descriptor -from typing import ClassVar as _ClassVar - -DESCRIPTOR: _descriptor.FileDescriptor diff --git a/bumble/transport/grpc_protobuf/__init__.py b/bumble/transport/grpc_protobuf/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bumble/transport/grpc_protobuf/common_pb2.py b/bumble/transport/grpc_protobuf/common_pb2.py new file mode 100644 index 0000000..c54a2e0 --- /dev/null +++ b/bumble/transport/grpc_protobuf/common_pb2.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: common.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x63ommon.proto\x12\rnetsim.common*=\n\x08\x43hipKind\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\r\n\tBLUETOOTH\x10\x01\x12\x08\n\x04WIFI\x10\x02\x12\x07\n\x03UWB\x10\x03\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'common_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _CHIPKIND._serialized_start=31 + _CHIPKIND._serialized_end=92 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/common_pb2.pyi b/bumble/transport/grpc_protobuf/common_pb2.pyi new file mode 100644 index 0000000..4cc934d --- /dev/null +++ b/bumble/transport/grpc_protobuf/common_pb2.pyi @@ -0,0 +1,12 @@ +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from typing import ClassVar as _ClassVar + +BLUETOOTH: ChipKind +DESCRIPTOR: _descriptor.FileDescriptor +UNSPECIFIED: ChipKind +UWB: ChipKind +WIFI: ChipKind + +class ChipKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] diff --git a/bumble/transport/grpc_protobuf/common_pb2_grpc.py b/bumble/transport/grpc_protobuf/common_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/bumble/transport/grpc_protobuf/common_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.py new file mode 100644 index 0000000..7380cb4 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: emulated_bluetooth_device.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from . import grpc_endpoint_description_pb2 as grpc__endpoint__description__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x65mulated_bluetooth_device.proto\x12\x1b\x61ndroid.emulation.bluetooth\x1a\x1fgrpc_endpoint_description.proto\x1a\x1bgoogle/protobuf/empty.proto\"&\n\x12\x43\x61llbackIdentifier\x12\x10\n\x08identity\x18\x01 \x01(\t\"#\n\x10\x44\x65viceIdentifier\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"\xf5\x02\n\x15\x43onnectionStateChange\x12K\n\x12\x63\x61llback_device_id\x18\x01 \x01(\x0b\x32/.android.emulation.bluetooth.CallbackIdentifier\x12\x42\n\x0b\x66rom_device\x18\x02 \x01(\x0b\x32-.android.emulation.bluetooth.DeviceIdentifier\x12U\n\tnew_state\x18\x03 \x01(\x0e\x32\x42.android.emulation.bluetooth.ConnectionStateChange.ConnectionState\"t\n\x0f\x43onnectionState\x12\x1e\n\x1a\x43ONNECTION_STATE_UNDEFINED\x10\x00\x12!\n\x1d\x43ONNECTION_STATE_DISCONNECTED\x10\x01\x12\x1e\n\x1a\x43ONNECTION_STATE_CONNECTED\x10\x02\"A\n\x04Uuid\x12\x0c\n\x02id\x18\x01 \x01(\rH\x00\x12\r\n\x03lsb\x18\x02 \x01(\x04H\x00\x12\x0b\n\x03msb\x18\x03 \x01(\x03\x42\x0f\n\rshort_or_long\"\xf3\x01\n\x1a\x43haracteristicValueRequest\x12K\n\x12\x63\x61llback_device_id\x18\x01 \x01(\x0b\x32/.android.emulation.bluetooth.CallbackIdentifier\x12\x42\n\x0b\x66rom_device\x18\x02 \x01(\x0b\x32-.android.emulation.bluetooth.DeviceIdentifier\x12\x36\n\x0b\x63\x61llback_id\x18\x03 \x01(\x0b\x32!.android.emulation.bluetooth.Uuid\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\"\xdd\x01\n\x1b\x43haracteristicValueResponse\x12S\n\x06status\x18\x01 \x01(\x0e\x32\x43.android.emulation.bluetooth.CharacteristicValueResponse.GattStatus\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"[\n\nGattStatus\x12\x1b\n\x17GATT_STATUS_UNSPECIFIED\x10\x00\x12\x17\n\x13GATT_STATUS_SUCCESS\x10\x01\x12\x17\n\x13GATT_STATUS_FAILURE\x10\x02\"\xb3\x05\n\x12GattCharacteristic\x12/\n\x04uuid\x18\x01 \x01(\x0b\x32!.android.emulation.bluetooth.Uuid\x12\x12\n\nproperties\x18\x02 \x01(\r\x12\x13\n\x0bpermissions\x18\x03 \x01(\r\x12\x36\n\x0b\x63\x61llback_id\x18\x04 \x01(\x0b\x32!.android.emulation.bluetooth.Uuid\"\xea\x01\n\nProperties\x12\x18\n\x14PROPERTY_UNSPECIFIED\x10\x00\x12\x16\n\x12PROPERTY_BROADCAST\x10\x01\x12\x11\n\rPROPERTY_READ\x10\x02\x12\x1e\n\x1aPROPERTY_WRITE_NO_RESPONSE\x10\x04\x12\x12\n\x0ePROPERTY_WRITE\x10\x08\x12\x13\n\x0fPROPERTY_NOTIFY\x10\x10\x12\x15\n\x11PROPERTY_INDICATE\x10 \x12\x19\n\x15PROPERTY_SIGNED_WRITE\x10@\x12\x1c\n\x17PROPERTY_EXTENDED_PROPS\x10\x80\x01\"\x9d\x02\n\x0bPermissions\x12\x1a\n\x16PERMISSION_UNSPECIFIED\x10\x00\x12\x13\n\x0fPERMISSION_READ\x10\x01\x12\x1d\n\x19PERMISSION_READ_ENCRYPTED\x10\x02\x12\"\n\x1ePERMISSION_READ_ENCRYPTED_MITM\x10\x04\x12\x14\n\x10PERMISSION_WRITE\x10\x10\x12\x1e\n\x1aPERMISSION_WRITE_ENCRYPTED\x10 \x12#\n\x1fPERMISSION_WRITE_ENCRYPTED_MITM\x10@\x12\x1c\n\x17PERMISSION_WRITE_SIGNED\x10\x80\x01\x12!\n\x1cPERMISSION_WRITE_SIGNED_MITM\x10\x80\x02\"\xb7\x02\n\x0bGattService\x12/\n\x04uuid\x18\x01 \x01(\x0b\x32!.android.emulation.bluetooth.Uuid\x12J\n\x0cservice_type\x18\x02 \x01(\x0e\x32\x34.android.emulation.bluetooth.GattService.ServiceType\x12H\n\x0f\x63haracteristics\x18\x03 \x03(\x0b\x32/.android.emulation.bluetooth.GattCharacteristic\"a\n\x0bServiceType\x12\x1c\n\x18SERVICE_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14SERVICE_TYPE_PRIMARY\x10\x01\x12\x1a\n\x16SERVICE_TYPE_SECONDARY\x10\x02\"I\n\x0bGattProfile\x12:\n\x08services\x18\x01 \x03(\x0b\x32(.android.emulation.bluetooth.GattService\"\xf0\x03\n\rAdvertisement\x12\x13\n\x0b\x64\x65vice_name\x18\x01 \x01(\t\x12R\n\x0f\x63onnection_mode\x18\x02 \x01(\x0e\x32\x39.android.emulation.bluetooth.Advertisement.ConnectionMode\x12P\n\x0e\x64iscovery_mode\x18\x03 \x01(\x0e\x32\x38.android.emulation.bluetooth.Advertisement.DiscoveryMode\"\x94\x01\n\x0e\x43onnectionMode\x12\x1f\n\x1b\x43ONNECTION_MODE_UNSPECIFIED\x10\x00\x12#\n\x1f\x43ONNECTION_MODE_NON_CONNECTABLE\x10\x01\x12\x1c\n\x18\x43ONNECTION_MODE_DIRECTED\x10\x02\x12\x1e\n\x1a\x43ONNECTION_MODE_UNDIRECTED\x10\x03\"\x8c\x01\n\rDiscoveryMode\x12\x1e\n\x1a\x44ISCOVERY_MODE_UNSPECIFIED\x10\x00\x12#\n\x1f\x44ISCOVERY_MODE_NON_DISCOVERABLE\x10\x01\x12\x1a\n\x16\x44ISCOVERY_MODE_LIMITED\x10\x02\x12\x1a\n\x16\x44ISCOVERY_MODE_GENERAL\x10\x03\"\xc0\x01\n\nGattDevice\x12\x34\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32\".android.emulation.remote.Endpoint\x12\x41\n\radvertisement\x18\x02 \x01(\x0b\x32*.android.emulation.bluetooth.Advertisement\x12\x39\n\x07profile\x18\x03 \x01(\x0b\x32(.android.emulation.bluetooth.GattProfile2\xb9\x04\n\x11GattDeviceService\x12\x90\x01\n\x1bOnCharacteristicReadRequest\x12\x37.android.emulation.bluetooth.CharacteristicValueRequest\x1a\x38.android.emulation.bluetooth.CharacteristicValueResponse\x12\x91\x01\n\x1cOnCharacteristicWriteRequest\x12\x37.android.emulation.bluetooth.CharacteristicValueRequest\x1a\x38.android.emulation.bluetooth.CharacteristicValueResponse\x12\x95\x01\n\x1eOnCharacteristicObserveRequest\x12\x37.android.emulation.bluetooth.CharacteristicValueRequest\x1a\x38.android.emulation.bluetooth.CharacteristicValueResponse0\x01\x12\x65\n\x17OnConnectionStateChange\x12\x32.android.emulation.bluetooth.ConnectionStateChange\x1a\x16.google.protobuf.EmptyB\"\n\x1e\x63om.android.emulator.bluetoothP\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'emulated_bluetooth_device_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\036com.android.emulator.bluetoothP\001' + _CALLBACKIDENTIFIER._serialized_start=126 + _CALLBACKIDENTIFIER._serialized_end=164 + _DEVICEIDENTIFIER._serialized_start=166 + _DEVICEIDENTIFIER._serialized_end=201 + _CONNECTIONSTATECHANGE._serialized_start=204 + _CONNECTIONSTATECHANGE._serialized_end=577 + _CONNECTIONSTATECHANGE_CONNECTIONSTATE._serialized_start=461 + _CONNECTIONSTATECHANGE_CONNECTIONSTATE._serialized_end=577 + _UUID._serialized_start=579 + _UUID._serialized_end=644 + _CHARACTERISTICVALUEREQUEST._serialized_start=647 + _CHARACTERISTICVALUEREQUEST._serialized_end=890 + _CHARACTERISTICVALUERESPONSE._serialized_start=893 + _CHARACTERISTICVALUERESPONSE._serialized_end=1114 + _CHARACTERISTICVALUERESPONSE_GATTSTATUS._serialized_start=1023 + _CHARACTERISTICVALUERESPONSE_GATTSTATUS._serialized_end=1114 + _GATTCHARACTERISTIC._serialized_start=1117 + _GATTCHARACTERISTIC._serialized_end=1808 + _GATTCHARACTERISTIC_PROPERTIES._serialized_start=1286 + _GATTCHARACTERISTIC_PROPERTIES._serialized_end=1520 + _GATTCHARACTERISTIC_PERMISSIONS._serialized_start=1523 + _GATTCHARACTERISTIC_PERMISSIONS._serialized_end=1808 + _GATTSERVICE._serialized_start=1811 + _GATTSERVICE._serialized_end=2122 + _GATTSERVICE_SERVICETYPE._serialized_start=2025 + _GATTSERVICE_SERVICETYPE._serialized_end=2122 + _GATTPROFILE._serialized_start=2124 + _GATTPROFILE._serialized_end=2197 + _ADVERTISEMENT._serialized_start=2200 + _ADVERTISEMENT._serialized_end=2696 + _ADVERTISEMENT_CONNECTIONMODE._serialized_start=2405 + _ADVERTISEMENT_CONNECTIONMODE._serialized_end=2553 + _ADVERTISEMENT_DISCOVERYMODE._serialized_start=2556 + _ADVERTISEMENT_DISCOVERYMODE._serialized_end=2696 + _GATTDEVICE._serialized_start=2699 + _GATTDEVICE._serialized_end=2891 + _GATTDEVICESERVICE._serialized_start=2894 + _GATTDEVICESERVICE._serialized_end=3463 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.pyi b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.pyi new file mode 100644 index 0000000..c14501b --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2.pyi @@ -0,0 +1,158 @@ +from . import grpc_endpoint_description_pb2 as _grpc_endpoint_description_pb2 +from google.protobuf import empty_pb2 as _empty_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Advertisement(_message.Message): + __slots__ = ["connection_mode", "device_name", "discovery_mode"] + class ConnectionMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + class DiscoveryMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + CONNECTION_MODE_DIRECTED: Advertisement.ConnectionMode + CONNECTION_MODE_FIELD_NUMBER: _ClassVar[int] + CONNECTION_MODE_NON_CONNECTABLE: Advertisement.ConnectionMode + CONNECTION_MODE_UNDIRECTED: Advertisement.ConnectionMode + CONNECTION_MODE_UNSPECIFIED: Advertisement.ConnectionMode + DEVICE_NAME_FIELD_NUMBER: _ClassVar[int] + DISCOVERY_MODE_FIELD_NUMBER: _ClassVar[int] + DISCOVERY_MODE_GENERAL: Advertisement.DiscoveryMode + DISCOVERY_MODE_LIMITED: Advertisement.DiscoveryMode + DISCOVERY_MODE_NON_DISCOVERABLE: Advertisement.DiscoveryMode + DISCOVERY_MODE_UNSPECIFIED: Advertisement.DiscoveryMode + connection_mode: Advertisement.ConnectionMode + device_name: str + discovery_mode: Advertisement.DiscoveryMode + def __init__(self, device_name: _Optional[str] = ..., connection_mode: _Optional[_Union[Advertisement.ConnectionMode, str]] = ..., discovery_mode: _Optional[_Union[Advertisement.DiscoveryMode, str]] = ...) -> None: ... + +class CallbackIdentifier(_message.Message): + __slots__ = ["identity"] + IDENTITY_FIELD_NUMBER: _ClassVar[int] + identity: str + def __init__(self, identity: _Optional[str] = ...) -> None: ... + +class CharacteristicValueRequest(_message.Message): + __slots__ = ["callback_device_id", "callback_id", "data", "from_device"] + CALLBACK_DEVICE_ID_FIELD_NUMBER: _ClassVar[int] + CALLBACK_ID_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + FROM_DEVICE_FIELD_NUMBER: _ClassVar[int] + callback_device_id: CallbackIdentifier + callback_id: Uuid + data: bytes + from_device: DeviceIdentifier + def __init__(self, callback_device_id: _Optional[_Union[CallbackIdentifier, _Mapping]] = ..., from_device: _Optional[_Union[DeviceIdentifier, _Mapping]] = ..., callback_id: _Optional[_Union[Uuid, _Mapping]] = ..., data: _Optional[bytes] = ...) -> None: ... + +class CharacteristicValueResponse(_message.Message): + __slots__ = ["data", "status"] + class GattStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + DATA_FIELD_NUMBER: _ClassVar[int] + GATT_STATUS_FAILURE: CharacteristicValueResponse.GattStatus + GATT_STATUS_SUCCESS: CharacteristicValueResponse.GattStatus + GATT_STATUS_UNSPECIFIED: CharacteristicValueResponse.GattStatus + STATUS_FIELD_NUMBER: _ClassVar[int] + data: bytes + status: CharacteristicValueResponse.GattStatus + def __init__(self, status: _Optional[_Union[CharacteristicValueResponse.GattStatus, str]] = ..., data: _Optional[bytes] = ...) -> None: ... + +class ConnectionStateChange(_message.Message): + __slots__ = ["callback_device_id", "from_device", "new_state"] + class ConnectionState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + CALLBACK_DEVICE_ID_FIELD_NUMBER: _ClassVar[int] + CONNECTION_STATE_CONNECTED: ConnectionStateChange.ConnectionState + CONNECTION_STATE_DISCONNECTED: ConnectionStateChange.ConnectionState + CONNECTION_STATE_UNDEFINED: ConnectionStateChange.ConnectionState + FROM_DEVICE_FIELD_NUMBER: _ClassVar[int] + NEW_STATE_FIELD_NUMBER: _ClassVar[int] + callback_device_id: CallbackIdentifier + from_device: DeviceIdentifier + new_state: ConnectionStateChange.ConnectionState + def __init__(self, callback_device_id: _Optional[_Union[CallbackIdentifier, _Mapping]] = ..., from_device: _Optional[_Union[DeviceIdentifier, _Mapping]] = ..., new_state: _Optional[_Union[ConnectionStateChange.ConnectionState, str]] = ...) -> None: ... + +class DeviceIdentifier(_message.Message): + __slots__ = ["address"] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + address: str + def __init__(self, address: _Optional[str] = ...) -> None: ... + +class GattCharacteristic(_message.Message): + __slots__ = ["callback_id", "permissions", "properties", "uuid"] + class Permissions(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + class Properties(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + CALLBACK_ID_FIELD_NUMBER: _ClassVar[int] + PERMISSIONS_FIELD_NUMBER: _ClassVar[int] + PERMISSION_READ: GattCharacteristic.Permissions + PERMISSION_READ_ENCRYPTED: GattCharacteristic.Permissions + PERMISSION_READ_ENCRYPTED_MITM: GattCharacteristic.Permissions + PERMISSION_UNSPECIFIED: GattCharacteristic.Permissions + PERMISSION_WRITE: GattCharacteristic.Permissions + PERMISSION_WRITE_ENCRYPTED: GattCharacteristic.Permissions + PERMISSION_WRITE_ENCRYPTED_MITM: GattCharacteristic.Permissions + PERMISSION_WRITE_SIGNED: GattCharacteristic.Permissions + PERMISSION_WRITE_SIGNED_MITM: GattCharacteristic.Permissions + PROPERTIES_FIELD_NUMBER: _ClassVar[int] + PROPERTY_BROADCAST: GattCharacteristic.Properties + PROPERTY_EXTENDED_PROPS: GattCharacteristic.Properties + PROPERTY_INDICATE: GattCharacteristic.Properties + PROPERTY_NOTIFY: GattCharacteristic.Properties + PROPERTY_READ: GattCharacteristic.Properties + PROPERTY_SIGNED_WRITE: GattCharacteristic.Properties + PROPERTY_UNSPECIFIED: GattCharacteristic.Properties + PROPERTY_WRITE: GattCharacteristic.Properties + PROPERTY_WRITE_NO_RESPONSE: GattCharacteristic.Properties + UUID_FIELD_NUMBER: _ClassVar[int] + callback_id: Uuid + permissions: int + properties: int + uuid: Uuid + def __init__(self, uuid: _Optional[_Union[Uuid, _Mapping]] = ..., properties: _Optional[int] = ..., permissions: _Optional[int] = ..., callback_id: _Optional[_Union[Uuid, _Mapping]] = ...) -> None: ... + +class GattDevice(_message.Message): + __slots__ = ["advertisement", "endpoint", "profile"] + ADVERTISEMENT_FIELD_NUMBER: _ClassVar[int] + ENDPOINT_FIELD_NUMBER: _ClassVar[int] + PROFILE_FIELD_NUMBER: _ClassVar[int] + advertisement: Advertisement + endpoint: _grpc_endpoint_description_pb2.Endpoint + profile: GattProfile + def __init__(self, endpoint: _Optional[_Union[_grpc_endpoint_description_pb2.Endpoint, _Mapping]] = ..., advertisement: _Optional[_Union[Advertisement, _Mapping]] = ..., profile: _Optional[_Union[GattProfile, _Mapping]] = ...) -> None: ... + +class GattProfile(_message.Message): + __slots__ = ["services"] + SERVICES_FIELD_NUMBER: _ClassVar[int] + services: _containers.RepeatedCompositeFieldContainer[GattService] + def __init__(self, services: _Optional[_Iterable[_Union[GattService, _Mapping]]] = ...) -> None: ... + +class GattService(_message.Message): + __slots__ = ["characteristics", "service_type", "uuid"] + class ServiceType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + CHARACTERISTICS_FIELD_NUMBER: _ClassVar[int] + SERVICE_TYPE_FIELD_NUMBER: _ClassVar[int] + SERVICE_TYPE_PRIMARY: GattService.ServiceType + SERVICE_TYPE_SECONDARY: GattService.ServiceType + SERVICE_TYPE_UNSPECIFIED: GattService.ServiceType + UUID_FIELD_NUMBER: _ClassVar[int] + characteristics: _containers.RepeatedCompositeFieldContainer[GattCharacteristic] + service_type: GattService.ServiceType + uuid: Uuid + def __init__(self, uuid: _Optional[_Union[Uuid, _Mapping]] = ..., service_type: _Optional[_Union[GattService.ServiceType, str]] = ..., characteristics: _Optional[_Iterable[_Union[GattCharacteristic, _Mapping]]] = ...) -> None: ... + +class Uuid(_message.Message): + __slots__ = ["id", "lsb", "msb"] + ID_FIELD_NUMBER: _ClassVar[int] + LSB_FIELD_NUMBER: _ClassVar[int] + MSB_FIELD_NUMBER: _ClassVar[int] + id: int + lsb: int + msb: int + def __init__(self, id: _Optional[int] = ..., lsb: _Optional[int] = ..., msb: _Optional[int] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2_grpc.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2_grpc.py new file mode 100644 index 0000000..754627d --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_device_pb2_grpc.py @@ -0,0 +1,193 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from . import emulated_bluetooth_device_pb2 as emulated__bluetooth__device__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 + + +class GattDeviceServiceStub(object): + """You can provide your own GattDevice by implementing this service + and registering it with the android emulator. + + The device will appear as a real bluetooth device, and you will + receive callbacks when the bluetooth system wants to + read, write or observe a characteristic. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.OnCharacteristicReadRequest = channel.unary_unary( + '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicReadRequest', + request_serializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + response_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + ) + self.OnCharacteristicWriteRequest = channel.unary_unary( + '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicWriteRequest', + request_serializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + response_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + ) + self.OnCharacteristicObserveRequest = channel.unary_stream( + '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicObserveRequest', + request_serializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + response_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + ) + self.OnConnectionStateChange = channel.unary_unary( + '/android.emulation.bluetooth.GattDeviceService/OnConnectionStateChange', + request_serializer=emulated__bluetooth__device__pb2.ConnectionStateChange.SerializeToString, + response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + ) + + +class GattDeviceServiceServicer(object): + """You can provide your own GattDevice by implementing this service + and registering it with the android emulator. + + The device will appear as a real bluetooth device, and you will + receive callbacks when the bluetooth system wants to + read, write or observe a characteristic. + """ + + def OnCharacteristicReadRequest(self, request, context): + """A remote client has requested to read a local characteristic. + + Return the current observed value. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def OnCharacteristicWriteRequest(self, request, context): + """A remote client has requested to write to a local characteristic. + + Return the current observed value. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def OnCharacteristicObserveRequest(self, request, context): + """Listens for notifications from the emulated device, the device should + write to the stream with a response when a change has occurred. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def OnConnectionStateChange(self, request, context): + """A remote device has been connected or disconnected. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GattDeviceServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'OnCharacteristicReadRequest': grpc.unary_unary_rpc_method_handler( + servicer.OnCharacteristicReadRequest, + request_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.FromString, + response_serializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.SerializeToString, + ), + 'OnCharacteristicWriteRequest': grpc.unary_unary_rpc_method_handler( + servicer.OnCharacteristicWriteRequest, + request_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.FromString, + response_serializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.SerializeToString, + ), + 'OnCharacteristicObserveRequest': grpc.unary_stream_rpc_method_handler( + servicer.OnCharacteristicObserveRequest, + request_deserializer=emulated__bluetooth__device__pb2.CharacteristicValueRequest.FromString, + response_serializer=emulated__bluetooth__device__pb2.CharacteristicValueResponse.SerializeToString, + ), + 'OnConnectionStateChange': grpc.unary_unary_rpc_method_handler( + servicer.OnConnectionStateChange, + request_deserializer=emulated__bluetooth__device__pb2.ConnectionStateChange.FromString, + response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'android.emulation.bluetooth.GattDeviceService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class GattDeviceService(object): + """You can provide your own GattDevice by implementing this service + and registering it with the android emulator. + + The device will appear as a real bluetooth device, and you will + receive callbacks when the bluetooth system wants to + read, write or observe a characteristic. + """ + + @staticmethod + def OnCharacteristicReadRequest(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicReadRequest', + emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def OnCharacteristicWriteRequest(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicWriteRequest', + emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def OnCharacteristicObserveRequest(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream(request, target, '/android.emulation.bluetooth.GattDeviceService/OnCharacteristicObserveRequest', + emulated__bluetooth__device__pb2.CharacteristicValueRequest.SerializeToString, + emulated__bluetooth__device__pb2.CharacteristicValueResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def OnConnectionStateChange(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/android.emulation.bluetooth.GattDeviceService/OnConnectionStateChange', + emulated__bluetooth__device__pb2.ConnectionStateChange.SerializeToString, + google_dot_protobuf_dot_empty__pb2.Empty.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.py new file mode 100644 index 0000000..8544f95 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: emulated_bluetooth_packets.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n emulated_bluetooth_packets.proto\x12\x1b\x61ndroid.emulation.bluetooth\"\xfb\x01\n\tHCIPacket\x12?\n\x04type\x18\x01 \x01(\x0e\x32\x31.android.emulation.bluetooth.HCIPacket.PacketType\x12\x0e\n\x06packet\x18\x02 \x01(\x0c\"\x9c\x01\n\nPacketType\x12\x1b\n\x17PACKET_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17PACKET_TYPE_HCI_COMMAND\x10\x01\x12\x13\n\x0fPACKET_TYPE_ACL\x10\x02\x12\x13\n\x0fPACKET_TYPE_SCO\x10\x03\x12\x15\n\x11PACKET_TYPE_EVENT\x10\x04\x12\x13\n\x0fPACKET_TYPE_ISO\x10\x05\x42J\n\x1f\x63om.android.emulation.bluetoothP\x01\xf8\x01\x01\xa2\x02\x03\x41\x45\x42\xaa\x02\x1b\x41ndroid.Emulation.Bluetoothb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'emulated_bluetooth_packets_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\037com.android.emulation.bluetoothP\001\370\001\001\242\002\003AEB\252\002\033Android.Emulation.Bluetooth' + _HCIPACKET._serialized_start=66 + _HCIPACKET._serialized_end=317 + _HCIPACKET_PACKETTYPE._serialized_start=161 + _HCIPACKET_PACKETTYPE._serialized_end=317 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/emulated_bluetooth_packets_pb2.pyi b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.pyi similarity index 53% rename from bumble/transport/emulated_bluetooth_packets_pb2.pyi rename to bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.pyi index a823e78..80cdee1 100644 --- a/bumble/transport/emulated_bluetooth_packets_pb2.pyi +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2.pyi @@ -1,17 +1,3 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message @@ -21,7 +7,6 @@ DESCRIPTOR: _descriptor.FileDescriptor class HCIPacket(_message.Message): __slots__ = ["packet", "type"] - class PacketType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): __slots__ = [] PACKET_FIELD_NUMBER: _ClassVar[int] @@ -34,8 +19,4 @@ class HCIPacket(_message.Message): TYPE_FIELD_NUMBER: _ClassVar[int] packet: bytes type: HCIPacket.PacketType - def __init__( - self, - type: _Optional[_Union[HCIPacket.PacketType, str]] = ..., - packet: _Optional[bytes] = ..., - ) -> None: ... + def __init__(self, type: _Optional[_Union[HCIPacket.PacketType, str]] = ..., packet: _Optional[bytes] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2_grpc.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_packets_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.py new file mode 100644 index 0000000..054b250 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: emulated_bluetooth.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 +from . import emulated_bluetooth_device_pb2 as emulated__bluetooth__device__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x65mulated_bluetooth.proto\x12\x1b\x61ndroid.emulation.bluetooth\x1a emulated_bluetooth_packets.proto\x1a\x1f\x65mulated_bluetooth_device.proto\"\x19\n\x07RawData\x12\x0e\n\x06packet\x18\x01 \x01(\x0c\"a\n\x12RegistrationStatus\x12K\n\x12\x63\x61llback_device_id\x18\x01 \x01(\x0b\x32/.android.emulation.bluetooth.CallbackIdentifier2\xbb\x03\n\x18\x45mulatedBluetoothService\x12\x64\n\x12registerClassicPhy\x12$.android.emulation.bluetooth.RawData\x1a$.android.emulation.bluetooth.RawData(\x01\x30\x01\x12`\n\x0eregisterBlePhy\x12$.android.emulation.bluetooth.RawData\x1a$.android.emulation.bluetooth.RawData(\x01\x30\x01\x12g\n\x11registerHCIDevice\x12&.android.emulation.bluetooth.HCIPacket\x1a&.android.emulation.bluetooth.HCIPacket(\x01\x30\x01\x12n\n\x12registerGattDevice\x12\'.android.emulation.bluetooth.GattDevice\x1a/.android.emulation.bluetooth.RegistrationStatusB\"\n\x1e\x63om.android.emulator.bluetoothP\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'emulated_bluetooth_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\036com.android.emulator.bluetoothP\001' + _RAWDATA._serialized_start=124 + _RAWDATA._serialized_end=149 + _REGISTRATIONSTATUS._serialized_start=151 + _REGISTRATIONSTATUS._serialized_end=248 + _EMULATEDBLUETOOTHSERVICE._serialized_start=251 + _EMULATEDBLUETOOTHSERVICE._serialized_end=694 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.pyi b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.pyi new file mode 100644 index 0000000..9f54383 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2.pyi @@ -0,0 +1,19 @@ +from . import emulated_bluetooth_packets_pb2 as _emulated_bluetooth_packets_pb2 +from . import emulated_bluetooth_device_pb2 as _emulated_bluetooth_device_pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class RawData(_message.Message): + __slots__ = ["packet"] + PACKET_FIELD_NUMBER: _ClassVar[int] + packet: bytes + def __init__(self, packet: _Optional[bytes] = ...) -> None: ... + +class RegistrationStatus(_message.Message): + __slots__ = ["callback_device_id"] + CALLBACK_DEVICE_ID_FIELD_NUMBER: _ClassVar[int] + callback_device_id: _emulated_bluetooth_device_pb2.CallbackIdentifier + def __init__(self, callback_device_id: _Optional[_Union[_emulated_bluetooth_device_pb2.CallbackIdentifier, _Mapping]] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2_grpc.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2_grpc.py new file mode 100644 index 0000000..9ad3bb9 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_pb2_grpc.py @@ -0,0 +1,237 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from . import emulated_bluetooth_device_pb2 as emulated__bluetooth__device__pb2 +from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 +from . import emulated_bluetooth_pb2 as emulated__bluetooth__pb2 + + +class EmulatedBluetoothServiceStub(object): + """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the + android emulator. It allows you to register emulated bluetooth devices and + control the packets that are exchanged between the device and the world. + + This service enables you to establish a "virtual network" of emulated + bluetooth devices that can interact with each other. + + Note: This is not yet finalized, it is likely that these definitions will + evolve. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.registerClassicPhy = channel.stream_stream( + '/android.emulation.bluetooth.EmulatedBluetoothService/registerClassicPhy', + request_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, + response_deserializer=emulated__bluetooth__pb2.RawData.FromString, + ) + self.registerBlePhy = channel.stream_stream( + '/android.emulation.bluetooth.EmulatedBluetoothService/registerBlePhy', + request_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, + response_deserializer=emulated__bluetooth__pb2.RawData.FromString, + ) + self.registerHCIDevice = channel.stream_stream( + '/android.emulation.bluetooth.EmulatedBluetoothService/registerHCIDevice', + request_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, + response_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, + ) + self.registerGattDevice = channel.unary_unary( + '/android.emulation.bluetooth.EmulatedBluetoothService/registerGattDevice', + request_serializer=emulated__bluetooth__device__pb2.GattDevice.SerializeToString, + response_deserializer=emulated__bluetooth__pb2.RegistrationStatus.FromString, + ) + + +class EmulatedBluetoothServiceServicer(object): + """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the + android emulator. It allows you to register emulated bluetooth devices and + control the packets that are exchanged between the device and the world. + + This service enables you to establish a "virtual network" of emulated + bluetooth devices that can interact with each other. + + Note: This is not yet finalized, it is likely that these definitions will + evolve. + """ + + def registerClassicPhy(self, request_iterator, context): + """Connect device to link layer. This will establish a direct connection + to the emulated bluetooth chip and configure the following: + + - Each connection creates a new device and attaches it to the link layer + - Link Layer packets are transmitted directly to the phy + + This should be used for classic connections. + + This is used to directly connect various android emulators together. + For example a wear device can connect to an android emulator through + this. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def registerBlePhy(self, request_iterator, context): + """Connect device to link layer. This will establish a direct connection + to root canal and execute the following: + + - Each connection creates a new device and attaches it to the link layer + - Link Layer packets are transmitted directly to the phy + + This should be used for BLE connections. + + This is used to directly connect various android emulators together. + For example a wear device can connect to an android emulator through + this. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def registerHCIDevice(self, request_iterator, context): + """Connect the device to the emulated bluetooth chip. The device will + participate in the network. You can configure the chip to scan, advertise + and setup connections with other devices that are connected to the + network. + + This is usually used when you have a need for an emulated bluetooth chip + and have a bluetooth stack that can interpret and handle the packets + correctly. + + For example the apache nimble stack can use this endpoint as the + transport layer. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def registerGattDevice(self, request, context): + """Registers an emulated bluetooth device. The emulator will reach out to + the emulated device to read/write and subscribe to properties. + + The following gRPC error codes can be returned: + - FAILED_PRECONDITION (code 9): + - root canal is not available on this device + - unable to reach the endpoint for the GattDevice + - INTERNAL (code 13) if there was an internal emulator failure. + + The device will not be discoverable in case of an error. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_EmulatedBluetoothServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'registerClassicPhy': grpc.stream_stream_rpc_method_handler( + servicer.registerClassicPhy, + request_deserializer=emulated__bluetooth__pb2.RawData.FromString, + response_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, + ), + 'registerBlePhy': grpc.stream_stream_rpc_method_handler( + servicer.registerBlePhy, + request_deserializer=emulated__bluetooth__pb2.RawData.FromString, + response_serializer=emulated__bluetooth__pb2.RawData.SerializeToString, + ), + 'registerHCIDevice': grpc.stream_stream_rpc_method_handler( + servicer.registerHCIDevice, + request_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, + response_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, + ), + 'registerGattDevice': grpc.unary_unary_rpc_method_handler( + servicer.registerGattDevice, + request_deserializer=emulated__bluetooth__device__pb2.GattDevice.FromString, + response_serializer=emulated__bluetooth__pb2.RegistrationStatus.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'android.emulation.bluetooth.EmulatedBluetoothService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class EmulatedBluetoothService(object): + """An Emulated Bluetooth Service exposes the emulated bluetooth chip from the + android emulator. It allows you to register emulated bluetooth devices and + control the packets that are exchanged between the device and the world. + + This service enables you to establish a "virtual network" of emulated + bluetooth devices that can interact with each other. + + Note: This is not yet finalized, it is likely that these definitions will + evolve. + """ + + @staticmethod + def registerClassicPhy(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/android.emulation.bluetooth.EmulatedBluetoothService/registerClassicPhy', + emulated__bluetooth__pb2.RawData.SerializeToString, + emulated__bluetooth__pb2.RawData.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def registerBlePhy(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/android.emulation.bluetooth.EmulatedBluetoothService/registerBlePhy', + emulated__bluetooth__pb2.RawData.SerializeToString, + emulated__bluetooth__pb2.RawData.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def registerHCIDevice(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/android.emulation.bluetooth.EmulatedBluetoothService/registerHCIDevice', + emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, + emulated__bluetooth__packets__pb2.HCIPacket.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def registerGattDevice(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/android.emulation.bluetooth.EmulatedBluetoothService/registerGattDevice', + emulated__bluetooth__device__pb2.GattDevice.SerializeToString, + emulated__bluetooth__pb2.RegistrationStatus.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.py new file mode 100644 index 0000000..30a2cb6 --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: emulated_bluetooth_vhci.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from . import emulated_bluetooth_packets_pb2 as emulated__bluetooth__packets__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x65mulated_bluetooth_vhci.proto\x12\x1b\x61ndroid.emulation.bluetooth\x1a emulated_bluetooth_packets.proto2y\n\x15VhciForwardingService\x12`\n\nattachVhci\x12&.android.emulation.bluetooth.HCIPacket\x1a&.android.emulation.bluetooth.HCIPacket(\x01\x30\x01\x42J\n\x1f\x63om.android.emulation.bluetoothP\x01\xf8\x01\x01\xa2\x02\x03\x41\x45\x42\xaa\x02\x1b\x41ndroid.Emulation.Bluetoothb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'emulated_bluetooth_vhci_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\037com.android.emulation.bluetoothP\001\370\001\001\242\002\003AEB\252\002\033Android.Emulation.Bluetooth' + _VHCIFORWARDINGSERVICE._serialized_start=96 + _VHCIFORWARDINGSERVICE._serialized_end=217 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.pyi b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.pyi new file mode 100644 index 0000000..3311c9b --- /dev/null +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2.pyi @@ -0,0 +1,5 @@ +import emulated_bluetooth_packets_pb2 as _emulated_bluetooth_packets_pb2 +from google.protobuf import descriptor as _descriptor +from typing import ClassVar as _ClassVar + +DESCRIPTOR: _descriptor.FileDescriptor diff --git a/bumble/transport/emulated_bluetooth_vhci_pb2_grpc.py b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2_grpc.py similarity index 59% rename from bumble/transport/emulated_bluetooth_vhci_pb2_grpc.py rename to bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2_grpc.py index 41f0feb..031f669 100644 --- a/bumble/transport/emulated_bluetooth_vhci_pb2_grpc.py +++ b/bumble/transport/grpc_protobuf/emulated_bluetooth_vhci_pb2_grpc.py @@ -1,17 +1,3 @@ -# Copyright 2021-2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" import grpc @@ -35,10 +21,10 @@ class VhciForwardingServiceStub(object): channel: A grpc.Channel. """ self.attachVhci = channel.stream_stream( - '/android.emulation.bluetooth.VhciForwardingService/attachVhci', - request_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, - response_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, - ) + '/android.emulation.bluetooth.VhciForwardingService/attachVhci', + request_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, + response_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, + ) class VhciForwardingServiceServicer(object): @@ -75,19 +61,18 @@ class VhciForwardingServiceServicer(object): def add_VhciForwardingServiceServicer_to_server(servicer, server): rpc_method_handlers = { - 'attachVhci': grpc.stream_stream_rpc_method_handler( - servicer.attachVhci, - request_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, - response_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, - ), + 'attachVhci': grpc.stream_stream_rpc_method_handler( + servicer.attachVhci, + request_deserializer=emulated__bluetooth__packets__pb2.HCIPacket.FromString, + response_serializer=emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'android.emulation.bluetooth.VhciForwardingService', rpc_method_handlers - ) + 'android.emulation.bluetooth.VhciForwardingService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) -# This class is part of an EXPERIMENTAL API. + # This class is part of an EXPERIMENTAL API. class VhciForwardingService(object): """This is a service which allows you to directly intercept the VHCI packets that are coming and going to the device before they are delivered to @@ -98,30 +83,18 @@ class VhciForwardingService(object): """ @staticmethod - def attachVhci( - request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.stream_stream( - request_iterator, + def attachVhci(request_iterator, target, - '/android.emulation.bluetooth.VhciForwardingService/attachVhci', + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/android.emulation.bluetooth.VhciForwardingService/attachVhci', emulated__bluetooth__packets__pb2.HCIPacket.SerializeToString, emulated__bluetooth__packets__pb2.HCIPacket.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - ) + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.py b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.py new file mode 100644 index 0000000..00d404c --- /dev/null +++ b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: grpc_endpoint_description.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgrpc_endpoint_description.proto\x12\x18\x61ndroid.emulation.remote\"V\n\x0b\x43redentials\x12\x16\n\x0epem_root_certs\x18\x01 \x01(\t\x12\x17\n\x0fpem_private_key\x18\x02 \x01(\t\x12\x16\n\x0epem_cert_chain\x18\x03 \x01(\t\"$\n\x06Header\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\x96\x01\n\x08\x45ndpoint\x12\x0e\n\x06target\x18\x01 \x01(\t\x12>\n\x0ftls_credentials\x18\x02 \x01(\x0b\x32%.android.emulation.remote.Credentials\x12:\n\x10required_headers\x18\x03 \x03(\x0b\x32 .android.emulation.remote.HeaderB \n\x1c\x63om.android.emulation.remoteP\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'grpc_endpoint_description_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\034com.android.emulation.remoteP\001' + _CREDENTIALS._serialized_start=61 + _CREDENTIALS._serialized_end=147 + _HEADER._serialized_start=149 + _HEADER._serialized_end=185 + _ENDPOINT._serialized_start=188 + _ENDPOINT._serialized_end=338 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.pyi b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.pyi new file mode 100644 index 0000000..3b81215 --- /dev/null +++ b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2.pyi @@ -0,0 +1,34 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Credentials(_message.Message): + __slots__ = ["pem_cert_chain", "pem_private_key", "pem_root_certs"] + PEM_CERT_CHAIN_FIELD_NUMBER: _ClassVar[int] + PEM_PRIVATE_KEY_FIELD_NUMBER: _ClassVar[int] + PEM_ROOT_CERTS_FIELD_NUMBER: _ClassVar[int] + pem_cert_chain: str + pem_private_key: str + pem_root_certs: str + def __init__(self, pem_root_certs: _Optional[str] = ..., pem_private_key: _Optional[str] = ..., pem_cert_chain: _Optional[str] = ...) -> None: ... + +class Endpoint(_message.Message): + __slots__ = ["required_headers", "target", "tls_credentials"] + REQUIRED_HEADERS_FIELD_NUMBER: _ClassVar[int] + TARGET_FIELD_NUMBER: _ClassVar[int] + TLS_CREDENTIALS_FIELD_NUMBER: _ClassVar[int] + required_headers: _containers.RepeatedCompositeFieldContainer[Header] + target: str + tls_credentials: Credentials + def __init__(self, target: _Optional[str] = ..., tls_credentials: _Optional[_Union[Credentials, _Mapping]] = ..., required_headers: _Optional[_Iterable[_Union[Header, _Mapping]]] = ...) -> None: ... + +class Header(_message.Message): + __slots__ = ["key", "value"] + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2_grpc.py b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/bumble/transport/grpc_protobuf/grpc_endpoint_description_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/bumble/transport/grpc_protobuf/hci_packet_pb2.py b/bumble/transport/grpc_protobuf/hci_packet_pb2.py new file mode 100644 index 0000000..ef014c4 --- /dev/null +++ b/bumble/transport/grpc_protobuf/hci_packet_pb2.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: hci_packet.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10hci_packet.proto\x12\rnetsim.packet\"\xb2\x01\n\tHCIPacket\x12\x38\n\x0bpacket_type\x18\x01 \x01(\x0e\x32#.netsim.packet.HCIPacket.PacketType\x12\x0e\n\x06packet\x18\x02 \x01(\x0c\"[\n\nPacketType\x12\x1a\n\x16HCI_PACKET_UNSPECIFIED\x10\x00\x12\x0b\n\x07\x43OMMAND\x10\x01\x12\x07\n\x03\x41\x43L\x10\x02\x12\x07\n\x03SCO\x10\x03\x12\t\n\x05\x45VENT\x10\x04\x12\x07\n\x03ISO\x10\x05\x42J\n\x1f\x63om.android.emulation.bluetoothP\x01\xf8\x01\x01\xa2\x02\x03\x41\x45\x42\xaa\x02\x1b\x41ndroid.Emulation.Bluetoothb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hci_packet_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\037com.android.emulation.bluetoothP\001\370\001\001\242\002\003AEB\252\002\033Android.Emulation.Bluetooth' + _HCIPACKET._serialized_start=36 + _HCIPACKET._serialized_end=214 + _HCIPACKET_PACKETTYPE._serialized_start=123 + _HCIPACKET_PACKETTYPE._serialized_end=214 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/hci_packet_pb2.pyi b/bumble/transport/grpc_protobuf/hci_packet_pb2.pyi new file mode 100644 index 0000000..04bb972 --- /dev/null +++ b/bumble/transport/grpc_protobuf/hci_packet_pb2.pyi @@ -0,0 +1,22 @@ +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class HCIPacket(_message.Message): + __slots__ = ["packet", "packet_type"] + class PacketType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = [] + ACL: HCIPacket.PacketType + COMMAND: HCIPacket.PacketType + EVENT: HCIPacket.PacketType + HCI_PACKET_UNSPECIFIED: HCIPacket.PacketType + ISO: HCIPacket.PacketType + PACKET_FIELD_NUMBER: _ClassVar[int] + PACKET_TYPE_FIELD_NUMBER: _ClassVar[int] + SCO: HCIPacket.PacketType + packet: bytes + packet_type: HCIPacket.PacketType + def __init__(self, packet_type: _Optional[_Union[HCIPacket.PacketType, str]] = ..., packet: _Optional[bytes] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/hci_packet_pb2_grpc.py b/bumble/transport/grpc_protobuf/hci_packet_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/bumble/transport/grpc_protobuf/hci_packet_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/bumble/transport/grpc_protobuf/packet_streamer_pb2.py b/bumble/transport/grpc_protobuf/packet_streamer_pb2.py new file mode 100644 index 0000000..ea07940 --- /dev/null +++ b/bumble/transport/grpc_protobuf/packet_streamer_pb2.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: packet_streamer.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from . import hci_packet_pb2 as hci__packet__pb2 +from . import startup_pb2 as startup__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15packet_streamer.proto\x12\rnetsim.packet\x1a\x10hci_packet.proto\x1a\rstartup.proto\"\x93\x01\n\rPacketRequest\x12\x30\n\x0cinitial_info\x18\x01 \x01(\x0b\x32\x18.netsim.startup.ChipInfoH\x00\x12.\n\nhci_packet\x18\x02 \x01(\x0b\x32\x18.netsim.packet.HCIPacketH\x00\x12\x10\n\x06packet\x18\x03 \x01(\x0cH\x00\x42\x0e\n\x0crequest_type\"t\n\x0ePacketResponse\x12\x0f\n\x05\x65rror\x18\x01 \x01(\tH\x00\x12.\n\nhci_packet\x18\x02 \x01(\x0b\x32\x18.netsim.packet.HCIPacketH\x00\x12\x10\n\x06packet\x18\x03 \x01(\x0cH\x00\x42\x0f\n\rresponse_type2b\n\x0ePacketStreamer\x12P\n\rStreamPackets\x12\x1c.netsim.packet.PacketRequest\x1a\x1d.netsim.packet.PacketResponse(\x01\x30\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'packet_streamer_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _PACKETREQUEST._serialized_start=74 + _PACKETREQUEST._serialized_end=221 + _PACKETRESPONSE._serialized_start=223 + _PACKETRESPONSE._serialized_end=339 + _PACKETSTREAMER._serialized_start=341 + _PACKETSTREAMER._serialized_end=439 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/packet_streamer_pb2.pyi b/bumble/transport/grpc_protobuf/packet_streamer_pb2.pyi new file mode 100644 index 0000000..d867613 --- /dev/null +++ b/bumble/transport/grpc_protobuf/packet_streamer_pb2.pyi @@ -0,0 +1,27 @@ +from . import hci_packet_pb2 as _hci_packet_pb2 +from . import startup_pb2 as _startup_pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class PacketRequest(_message.Message): + __slots__ = ["hci_packet", "initial_info", "packet"] + HCI_PACKET_FIELD_NUMBER: _ClassVar[int] + INITIAL_INFO_FIELD_NUMBER: _ClassVar[int] + PACKET_FIELD_NUMBER: _ClassVar[int] + hci_packet: _hci_packet_pb2.HCIPacket + initial_info: _startup_pb2.ChipInfo + packet: bytes + def __init__(self, initial_info: _Optional[_Union[_startup_pb2.ChipInfo, _Mapping]] = ..., hci_packet: _Optional[_Union[_hci_packet_pb2.HCIPacket, _Mapping]] = ..., packet: _Optional[bytes] = ...) -> None: ... + +class PacketResponse(_message.Message): + __slots__ = ["error", "hci_packet", "packet"] + ERROR_FIELD_NUMBER: _ClassVar[int] + HCI_PACKET_FIELD_NUMBER: _ClassVar[int] + PACKET_FIELD_NUMBER: _ClassVar[int] + error: str + hci_packet: _hci_packet_pb2.HCIPacket + packet: bytes + def __init__(self, error: _Optional[str] = ..., hci_packet: _Optional[_Union[_hci_packet_pb2.HCIPacket, _Mapping]] = ..., packet: _Optional[bytes] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py b/bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py new file mode 100644 index 0000000..45ab653 --- /dev/null +++ b/bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py @@ -0,0 +1,109 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from . import packet_streamer_pb2 as packet__streamer__pb2 + + +class PacketStreamerStub(object): + """* + This is the packet service for the network simulator. + + Android Virtual Devices (AVDs) and accessory devices use this service to + connect to the network simulator and pass packets back and forth. + + AVDs running in a guest VM are built with virtual controllers for each radio + chip. These controllers route chip requests to host emulators (qemu and + crosvm) using virtio and from there they are forwarded to this gRpc service. + + This setup provides a transparent radio environment across AVDs and + accessories because the network simulator contains libraries to emulate + Bluetooth, 80211MAC, UWB, and Rtt chips. + + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.StreamPackets = channel.stream_stream( + '/netsim.packet.PacketStreamer/StreamPackets', + request_serializer=packet__streamer__pb2.PacketRequest.SerializeToString, + response_deserializer=packet__streamer__pb2.PacketResponse.FromString, + ) + + +class PacketStreamerServicer(object): + """* + This is the packet service for the network simulator. + + Android Virtual Devices (AVDs) and accessory devices use this service to + connect to the network simulator and pass packets back and forth. + + AVDs running in a guest VM are built with virtual controllers for each radio + chip. These controllers route chip requests to host emulators (qemu and + crosvm) using virtio and from there they are forwarded to this gRpc service. + + This setup provides a transparent radio environment across AVDs and + accessories because the network simulator contains libraries to emulate + Bluetooth, 80211MAC, UWB, and Rtt chips. + + """ + + def StreamPackets(self, request_iterator, context): + """Attach a virtual radio controller to the network simulation. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_PacketStreamerServicer_to_server(servicer, server): + rpc_method_handlers = { + 'StreamPackets': grpc.stream_stream_rpc_method_handler( + servicer.StreamPackets, + request_deserializer=packet__streamer__pb2.PacketRequest.FromString, + response_serializer=packet__streamer__pb2.PacketResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'netsim.packet.PacketStreamer', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class PacketStreamer(object): + """* + This is the packet service for the network simulator. + + Android Virtual Devices (AVDs) and accessory devices use this service to + connect to the network simulator and pass packets back and forth. + + AVDs running in a guest VM are built with virtual controllers for each radio + chip. These controllers route chip requests to host emulators (qemu and + crosvm) using virtio and from there they are forwarded to this gRpc service. + + This setup provides a transparent radio environment across AVDs and + accessories because the network simulator contains libraries to emulate + Bluetooth, 80211MAC, UWB, and Rtt chips. + + """ + + @staticmethod + def StreamPackets(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/netsim.packet.PacketStreamer/StreamPackets', + packet__streamer__pb2.PacketRequest.SerializeToString, + packet__streamer__pb2.PacketResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/bumble/transport/grpc_protobuf/startup_pb2.py b/bumble/transport/grpc_protobuf/startup_pb2.py new file mode 100644 index 0000000..532ac0e --- /dev/null +++ b/bumble/transport/grpc_protobuf/startup_pb2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: startup.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from . import common_pb2 as common__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rstartup.proto\x12\x0enetsim.startup\x1a\x0c\x63ommon.proto\"\x7f\n\x0bStartupInfo\x12\x33\n\x07\x64\x65vices\x18\x01 \x03(\x0b\x32\".netsim.startup.StartupInfo.Device\x1a;\n\x06\x44\x65vice\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x05\x63hips\x18\x02 \x03(\x0b\x32\x14.netsim.startup.Chip\"<\n\x08\x43hipInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\"\n\x04\x63hip\x18\x02 \x01(\x0b\x32\x14.netsim.startup.Chip\"\x96\x01\n\x04\x43hip\x12%\n\x04kind\x18\x01 \x01(\x0e\x32\x17.netsim.common.ChipKind\x12\n\n\x02id\x18\x02 \x01(\t\x12\x14\n\x0cmanufacturer\x18\x03 \x01(\t\x12\x14\n\x0cproduct_name\x18\x04 \x01(\t\x12\r\n\x05\x66\x64_in\x18\x05 \x01(\x05\x12\x0e\n\x06\x66\x64_out\x18\x06 \x01(\x05\x12\x10\n\x08loopback\x18\x07 \x01(\x08\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'startup_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _STARTUPINFO._serialized_start=47 + _STARTUPINFO._serialized_end=174 + _STARTUPINFO_DEVICE._serialized_start=115 + _STARTUPINFO_DEVICE._serialized_end=174 + _CHIPINFO._serialized_start=176 + _CHIPINFO._serialized_end=236 + _CHIP._serialized_start=239 + _CHIP._serialized_end=389 +# @@protoc_insertion_point(module_scope) diff --git a/bumble/transport/grpc_protobuf/startup_pb2.pyi b/bumble/transport/grpc_protobuf/startup_pb2.pyi new file mode 100644 index 0000000..604d915 --- /dev/null +++ b/bumble/transport/grpc_protobuf/startup_pb2.pyi @@ -0,0 +1,46 @@ +from . import common_pb2 as _common_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Chip(_message.Message): + __slots__ = ["fd_in", "fd_out", "id", "kind", "loopback", "manufacturer", "product_name"] + FD_IN_FIELD_NUMBER: _ClassVar[int] + FD_OUT_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] + KIND_FIELD_NUMBER: _ClassVar[int] + LOOPBACK_FIELD_NUMBER: _ClassVar[int] + MANUFACTURER_FIELD_NUMBER: _ClassVar[int] + PRODUCT_NAME_FIELD_NUMBER: _ClassVar[int] + fd_in: int + fd_out: int + id: str + kind: _common_pb2.ChipKind + loopback: bool + manufacturer: str + product_name: str + def __init__(self, kind: _Optional[_Union[_common_pb2.ChipKind, str]] = ..., id: _Optional[str] = ..., manufacturer: _Optional[str] = ..., product_name: _Optional[str] = ..., fd_in: _Optional[int] = ..., fd_out: _Optional[int] = ..., loopback: bool = ...) -> None: ... + +class ChipInfo(_message.Message): + __slots__ = ["chip", "name"] + CHIP_FIELD_NUMBER: _ClassVar[int] + NAME_FIELD_NUMBER: _ClassVar[int] + chip: Chip + name: str + def __init__(self, name: _Optional[str] = ..., chip: _Optional[_Union[Chip, _Mapping]] = ...) -> None: ... + +class StartupInfo(_message.Message): + __slots__ = ["devices"] + class Device(_message.Message): + __slots__ = ["chips", "name"] + CHIPS_FIELD_NUMBER: _ClassVar[int] + NAME_FIELD_NUMBER: _ClassVar[int] + chips: _containers.RepeatedCompositeFieldContainer[Chip] + name: str + def __init__(self, name: _Optional[str] = ..., chips: _Optional[_Iterable[_Union[Chip, _Mapping]]] = ...) -> None: ... + DEVICES_FIELD_NUMBER: _ClassVar[int] + devices: _containers.RepeatedCompositeFieldContainer[StartupInfo.Device] + def __init__(self, devices: _Optional[_Iterable[_Union[StartupInfo.Device, _Mapping]]] = ...) -> None: ... diff --git a/bumble/transport/grpc_protobuf/startup_pb2_grpc.py b/bumble/transport/grpc_protobuf/startup_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/bumble/transport/grpc_protobuf/startup_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/docs/mkdocs/src/platforms/android.md b/docs/mkdocs/src/platforms/android.md index cbb62db..4b08d88 100644 --- a/docs/mkdocs/src/platforms/android.md +++ b/docs/mkdocs/src/platforms/android.md @@ -9,19 +9,20 @@ The two main use cases are: * Connecting the Bumble host stack to the Android emulator's virtual controller. * Using Bumble as an HCI bridge to connect the Android emulator to a physical - Bluetooth controller, such as a USB dongle + Bluetooth controller, such as a USB dongle, or other HCI transport. !!! warning Bluetooth support in the Android emulator is a recent feature that may still be evolving. The information contained here be somewhat out of sync with the version of the emulator you are using. - You will need version 31.3.8.0 or later. + You will need version 33.1.4.0 or later. The Android emulator supports Bluetooth in two ways: either by exposing virtual Bluetooth controllers to which you can connect a virtual Bluetooth host stack, or -by exposing an way to connect your own virtual controller to the Android Bluetooth +by exposing a way to connect your own virtual controller to the Android Bluetooth stack via a virtual HCI interface. -Both ways are controlled via gRPC requests to the Android emulator. +Both ways are controlled via gRPC requests to the Android emulator controller and/or +from the Android emulator. ## Launching the Emulator @@ -33,48 +34,82 @@ the command line. For details on how to launch the Android emulator from the command line, visit [this Android Studio user guide page](https://developer.android.com/studio/run/emulator-commandline) -The `-grpc ` command line option may be used to select a gRPC port other than the default. +The `-packet-streamer-endpoint ` command line option may be used to enable +Bluetooth emulation and tell the emulator which virtual controller to connect to. -## Connecting to Root Canal +## Connecting to Netsim -The Android emulator's virtual Bluetooth controller is called **Root Canal**. -Multiple instances of Root Canal virtual controllers can be instantiated, they -communicate link layer packets between them, thus creating a virtual radio network. -Configuring a Bumble Device instance to use Root Canal as a virtual controller +If the emulator doesn't have Bluetooth emulation enabled by default, use the +`-packet-streamer-endpoint default` option to tell it to connect to Netsim. +If Netsim is not running, the emulator will start it automatically. + +The Android emulator's virtual Bluetooth controller is called **Netsim**. +Netsim runs as a background process and allows multiple clients to connect to it, +each connecting to its own virtual controller instance hosted by Netsim. All the +clients connected to the same Netsim process can then "talk" to each other over a +virtual radio link layer. +Netsim supports other wireless protocols than Bluetooth, but the relevant part here +is Bluetooth. The virtual Bluetooth controller used by Netsim is sometimes referred to +as **Root Canal**. + +Configuring a Bumble Device instance to use netsim as a virtual controller allows that virtual device to communicate with the Android Bluetooth stack, and through it with Android applications as well as system-managed profiles. -To connect a Bumble host stack to a Root Canal virtual controller instance, use -the bumble `android-emulator` transport in `host` mode (the default). +To connect a Bumble host stack to a netsim virtual controller instance, use +the Bumble `android-netsim` transport in `host` mode (the default). -!!! example "Run the example GATT server connected to the emulator" +!!! example "Run the example GATT server connected to the emulator via Netsim" ``` shell - $ python run_gatt_server.py device1.json android-emulator + $ python run_gatt_server.py device1.json android-netsim ``` +By default, the Bumble `android-netsim` transport will try to automatically discover +the port number on which the netsim process is exposing its gRPC server interface. If +that discovery process fails, or if you want to specify the interface manually, you +can pass a `hostname` and `port` as parameters to the transport, as: `android-netsim::`. + +!!! example "Run the example GATT server connected to the emulator via Netsim on a localhost, port 8877" + ``` shell + $ python run_gatt_server.py device1.json android-netsim:localhost:8877 + ``` + +### Multiple Instances + +If you want to connect multiple Bumble devices to netsim, it may be useful to give each one +a netsim controller with a specific name. This can be done using the `name=` transport option. +For example: `android-netsim:localhost:8877,name=bumble1` + ## Connecting a Custom Virtual Controller This is an advanced use case, which may not be officially supported, but should work in recent versions of the emulator. -You will likely need to start the emulator from the command line, in order to specify the `-forward-vhci` option (unless the emulator offers a way to control that feature from a user/ui menu). -!!! example "Launch the emulator with VHCI forwarding" - In this example, we launch an emulator AVD named "Tiramisu" - ```shell - $ emulator -forward-vhci -avd Tiramisu - ``` +The first step is to run the Bumble HCI bridge, specifying netsim as the "host" end of the +bridge, and another controller (typically a USB Bluetooth dongle, but any other supported +transport can work as well) as the "controller" end of the bridge. -!!! tip - Attaching a virtual controller use the VHCI forwarder while the Android Bluetooth stack - is running isn't supported. So you need to disable Bluetooth in your running Android guest - before attaching the virtual controller, then re-enable it once attached. - -To connect a virtual controller to the Android Bluetooth stack, use the bumble `android-emulator` transport in `controller` mode. For example, using the default gRPC port, the transport name would be: `android-emulator:mode=controller`. +To connect a virtual controller to the Android Bluetooth stack, use the bumble `android-netsim` transport in `controller` mode. For example, with port number 8877, the transport name would be: `android-netsim:_:8877,mode=controller`. !!! example "Connect the Android emulator to the first USB Bluetooth dongle, using the `hci_bridge` application" ```shell - $ bumble-hci-bridge android-emulator:mode=controller usb:0 + $ bumble-hci-bridge android-netsim:_:8877,mode=controller usb:0 ``` +Then, you can start the emulator and tell it to connect to this bridge, instead of netsim. +You will likely need to start the emulator from the command line, in order to specify the `-packet-streamer-endpoint :` option (unless the emulator offers a way to control that feature from a user/ui menu). + +!!! example "Launch the emulator with a netsim replacement" + In this example, we launch an emulator AVD named "Tiramisu", with a Bumble HCI bridge running + on port 8877. + ```shell + $ emulator -packet-streamer-endpoint localhost:8877 -avd Tiramisu + ``` + +!!! tip + Attaching a virtual controller while the Android Bluetooth stack is running may not be well supported. So you may need to disable Bluetooth in your running Android guest + before attaching the virtual controller, then re-enable it once attached. + + ## Other Tools The `show` application that's included with Bumble can be used to parse and pretty-print the HCI packets diff --git a/docs/mkdocs/src/transports/android_emulator.md b/docs/mkdocs/src/transports/android_emulator.md index ead71b8..974ba4f 100644 --- a/docs/mkdocs/src/transports/android_emulator.md +++ b/docs/mkdocs/src/transports/android_emulator.md @@ -1,22 +1,41 @@ ANDROID EMULATOR TRANSPORT ========================== -The Android emulator transport either connects, as a host, to a "Root Canal" virtual controller -("host" mode), or attaches a virtual controller to the Android Bluetooth host stack ("controller" mode). +!!! warning + Bluetooth support in the Android emulator has recently changed. The older mode, using + the `android-emulator` transport name with Bumble, while still implemented, is now + obsolete, and may not be supported by recent versions of the emulator. + Use the `android-netsim` transport name instead. + + +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 +connections. ## Moniker -The moniker syntax for an Android Emulator transport is: `android-emulator:[mode=][:]`, where -the `mode` parameter can specify running as a host or a controller, and `:` can specify a host name (or IP address) and TCP port number on which to reach the gRPC server for the emulator. -Both the `mode=` and `:` parameters are optional (so the moniker `android-emulator` by itself is a valid moniker, which will create a transport in `host` mode, connected to `localhost` on the default gRPC port for the emulator). +The moniker syntax for an Android Emulator "netsim" transport is: `android-netsim:[:][]`, +where `` is a ','-separated list of `=` pairs`. +The `mode` parameter name can specify running as a host or a controller, and `:` can specify a host name (or IP address) and TCP port number on which to reach the gRPC server for the emulator (in "host" mode), or to accept gRPC connections (in "controller" mode). +Both the `mode=` and `:` parameters are optional (so the moniker `android-netsim` by itself is a valid moniker, which will create a transport in `host` mode, connected to `localhost` on the default gRPC port for the Netsim background process). !!! example Example - `android-emulator` - connect as a host to the emulator on localhost:8554 + `android-netsim` + connect as a host to Netsim on the gRPC port discovered automatically. !!! example Example - `android-emulator:mode=controller` - connect as a controller to the emulator on localhost:8554 + `android-netsim:_:8555,mode=controller` + Run as a controller, accepting gRPC connection on port 8555. !!! example Example - `android-emulator:localhost:8555` - connect as a host to the emulator on localhost:8555 + `android-netsim:localhost:8555` + connect as a host to Netsim on localhost:8555 + +!!! example Example + `android-netsim:localhost:8555` + connect as a host to Netsim on localhost:8555 + +!!! example Example + `android-netsim:name=bumble1234` + connect as a host to Netsim on the discovered gRPC port, using `bumble1234` as the + controller instance name. + diff --git a/docs/mkdocs/src/transports/index.md b/docs/mkdocs/src/transports/index.md index 70827c1..feb57e5 100644 --- a/docs/mkdocs/src/transports/index.md +++ b/docs/mkdocs/src/transports/index.md @@ -16,5 +16,6 @@ Several types of transports are supported: * [PTY](pty.md): a PTY (pseudo terminal) is used to send/receive HCI packets. This is convenient to expose a virtual controller as if it were an HCI UART * [VHCI](vhci.md): used to attach a virtual controller to a Bluetooth stack on platforms that support it. * [HCI Socket](hci_socket.md): an HCI socket, on platforms that support it, to send/receive HCI packets to/from an HCI controller managed by the OS. - * [Android Emulator](android_emulator.md): a gRPC connection to an Android emulator is used to setup either an HCI interface to the emulator's "Root Canal" virtual controller, or attach a virtual controller to the Android Bluetooth host stack. + * [Android Emulator](android_emulator.md): a gRPC connection to the Android emulator's "netsim" + virtual controller, or from the Android emulator, is used to setup either an HCI interface to the emulator's "netsim" virtual controller, or serve as a virtual controller for the Android Bluetooth host stack. * [File](file.md): HCI packets are read/written to a file-like node in the filesystem. diff --git a/examples/a2dp_sink1.json b/examples/a2dp_sink1.json index 61ce80d..8603194 100644 --- a/examples/a2dp_sink1.json +++ b/examples/a2dp_sink1.json @@ -1,5 +1,6 @@ { "name": "Bumble Speaker", + "address": "F0:F1:F2:F3:F4:F5", "class_of_device": 2360324, "keystore": "JsonKeyStore" } diff --git a/pyproject.toml b/pyproject.toml index ff9588c..f6abc31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,9 @@ testpaths = [ [tool.pylint.master] init-hook = 'import sys; sys.path.append(".")' +ignore-paths = [ + '.*_pb2(_grpc)?.py' +] [tool.pylint.messages_control] max-line-length = "88" @@ -37,44 +40,32 @@ disable = [ "too-many-statements", ] -ignore = [ - "emulated_bluetooth_pb2.py", - "emulated_bluetooth_pb2_grpc.py", - "emulated_bluetooth_vhci_pb2_grpc.py", - "emulated_bluetooth_packets_pb2.py", - "emulated_bluetooth_vhci_pb2.py" -] - [tool.pylint.typecheck] signature-mutators="AsyncRunner.run_in_task" [tool.black] skip-string-normalization = true +extend-exclude = ''' +( + .*_pb2(_grpc)?.py # exclude autogenerated Protocol Buffer files anywhere in the project +) +''' + +[tool.mypy] +exclude = ['bumble/transport/grpc_protobuf'] [[tool.mypy.overrides]] -module = "bumble.transport.emulated_bluetooth_pb2_grpc" -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "bumble.transport.emulated_bluetooth_packets_pb2" +module = "bumble.transport.grpc_protobuf.*" ignore_errors = true [[tool.mypy.overrides]] module = "aioconsole.*" ignore_missing_imports = true -[[tool.mypy.overrides]] -module = "colors.*" -ignore_missing_imports = true - [[tool.mypy.overrides]] module = "construct.*" ignore_missing_imports = true -[[tool.mypy.overrides]] -module = "emulated_bluetooth_packets_pb2.*" -ignore_missing_imports = true - [[tool.mypy.overrides]] module = "grpc.*" ignore_missing_imports = true diff --git a/scripts/process_android_emulator_protos.sh b/scripts/process_android_emulator_protos.sh index e60e4cf..d5070df 100644 --- a/scripts/process_android_emulator_protos.sh +++ b/scripts/process_android_emulator_protos.sh @@ -1,27 +1,16 @@ -# Invoke this script with an argument pointing to where the Android emulator .proto files are. -# The .proto files should be slightly modified from their original version (as distributed with -# the Android emulator): -# --> Remove unused types/methods from emulated_bluetooth.proto +# Invoke this script with an argument pointing to where the Android emulator .proto files are +# (for example, ~/Library/Android/sdk/emulator/lib on a mac, or +# $AOSP/external/qemu/android/android-grpc/python/aemu-grpc/src/aemu/proto from the AOSP sources) +PROTOC_OUT=bumble/transport/grpc_protobuf -PROTOC_OUT=bumble/transport -LICENSE_FILE_INPUT=bumble/transport/android_emulator.py - -proto_files=(emulated_bluetooth.proto emulated_bluetooth_vhci.proto emulated_bluetooth_packets.proto) +proto_files=(emulated_bluetooth.proto emulated_bluetooth_vhci.proto emulated_bluetooth_packets.proto emulated_bluetooth_device.proto grpc_endpoint_description.proto) for proto_file in "${proto_files[@]}" do python -m grpc_tools.protoc -I$1 --proto_path=bumble/transport --python_out=$PROTOC_OUT --pyi_out=$PROTOC_OUT --grpc_python_out=$PROTOC_OUT $1/$proto_file done -python_files=(emulated_bluetooth_pb2.py emulated_bluetooth_pb2_grpc.py emulated_bluetooth_packets_pb2.py emulated_bluetooth_packets_pb2_grpc.py emulated_bluetooth_vhci_pb2_grpc.py emulated_bluetooth_vhci_pb2.py) +python_files=(emulated_bluetooth_pb2_grpc.py emulated_bluetooth_pb2.py emulated_bluetooth_packets_pb2.py emulated_bluetooth_vhci_pb2_grpc.py emulated_bluetooth_vhci_pb2.py emulated_bluetooth_device_pb2.py grpc_endpoint_description_pb2.py) for python_file in "${python_files[@]}" do - sed -i '' 's/^import .*_pb2 as/from . &/' $PROTOC_OUT/$python_file -done - -stub_files=(emulated_bluetooth_pb2.pyi emulated_bluetooth_packets_pb2.pyi emulated_bluetooth_vhci_pb2.pyi) -for source_file in "${python_files[@]}" "${stub_files[@]}" -do - head -14 $LICENSE_FILE_INPUT > $PROTOC_OUT/${source_file}.lic - cat $PROTOC_OUT/$source_file >> $PROTOC_OUT/${source_file}.lic - mv $PROTOC_OUT/${source_file}.lic $PROTOC_OUT/$source_file + sed -i 's/^import .*_pb2 as/from . \0/' $PROTOC_OUT/$python_file done \ No newline at end of file diff --git a/scripts/process_android_netsim_protos.sh b/scripts/process_android_netsim_protos.sh new file mode 100644 index 0000000..5a26602 --- /dev/null +++ b/scripts/process_android_netsim_protos.sh @@ -0,0 +1,14 @@ +# Invoke this script with an argument pointing to where the AOSP `tools/netsim/src/proto` is +PROTOC_OUT=bumble/transport/grpc_protobuf + +proto_files=(common.proto packet_streamer.proto hci_packet.proto startup.proto) +for proto_file in "${proto_files[@]}" +do + python -m grpc_tools.protoc -I$1 --proto_path=bumble/transport --python_out=$PROTOC_OUT --pyi_out=$PROTOC_OUT --grpc_python_out=$PROTOC_OUT $1/$proto_file +done + +python_files=(packet_streamer_pb2_grpc.py packet_streamer_pb2.py hci_packet_pb2.py startup_pb2.py) +for python_file in "${python_files[@]}" +do + sed -i 's/^import .*_pb2 as/from . \0/' $PROTOC_OUT/$python_file +done diff --git a/setup.cfg b/setup.cfg index 8a4bbe1..1644b28 100644 --- a/setup.cfg +++ b/setup.cfg @@ -74,8 +74,9 @@ test = coverage >= 6.4 development = black == 22.10 + grpcio-tools >= 1.51.1 invoke >= 1.7.3 - mypy == 1.1.1 + mypy == 1.2.0 nox >= 2022 pylint == 2.15.8 types-appdirs >= 1.4.3