Bluetooth: Add config to select Rfcomm services We don't need Dev-kit's all Rfcomm services to be running every time. Add config option for tests to select Echo, MAP or PBAP Rfcomm services. Default to Rfcomm Echo service, if not specified. BUG=b:424465503 TEST=Run BeTo test_concurrent_connections test Change-Id: I5700d270b048276091daf3fae10e1df9bd53776a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/chameleon/+/7115464 Commit-Queue: Manish Mandlik <mmandlik@chromium.org> Reviewed-by: John Lai <johnlai@google.com> Tested-by: Manish Mandlik <mmandlik@chromium.org>
diff --git a/chameleond/bluetooth_grpc/blueship/interface/manager.proto b/chameleond/bluetooth_grpc/blueship/interface/manager.proto index badef77..c4390cc 100644 --- a/chameleond/bluetooth_grpc/blueship/interface/manager.proto +++ b/chameleond/bluetooth_grpc/blueship/interface/manager.proto
@@ -109,6 +109,19 @@ message RepeatedPlayerCommands { repeated PlayerCmd player_cmd_list = 1; } +message DevKitConfig { + ConfigVariant rfcomm_services = 1; // RepeatedRfcommService +} + +enum RfcommService { + UNKNOWN_SERVICE = 0; + ECHO_SERVICE = 1; + MAP_SERVICE = 2; + PBAP_SERVICE = 3; +} + +message RepeatedRfcommService { repeated RfcommService service_list = 1; } + message ConfigVariant { bool writable = 1; @@ -127,6 +140,7 @@ RepeatedString string_list = 201; RepeatedCodec codec_list = 202; RepeatedPlayerCommands player_cmd_list = 203; + RepeatedRfcommService service_list = 204; } } @@ -139,6 +153,7 @@ ControllerConfig controller = 3; SecurityConfig security = 4; AudioConfig audio = 5; + DevKitConfig devkit = 6; } message RestartServerRequest { Configuration next_config = 1; }
diff --git a/chameleond/bluetooth_grpc/server/device_config.py b/chameleond/bluetooth_grpc/server/device_config.py index ee1033a..d315c9a 100644 --- a/chameleond/bluetooth_grpc/server/device_config.py +++ b/chameleond/bluetooth_grpc/server/device_config.py
@@ -74,4 +74,12 @@ ), ), ), + devkit=manager_pb2.DevKitConfig( + rfcomm_services=manager_pb2.ConfigVariant( + writable=True, + service_list=manager_pb2.RepeatedRfcommService( + service_list=[manager_pb2.ECHO_SERVICE] + ), + ), + ), )
diff --git a/chameleond/bluetooth_grpc/server/server.py b/chameleond/bluetooth_grpc/server/server.py index f4f880e..7619044 100644 --- a/chameleond/bluetooth_grpc/server/server.py +++ b/chameleond/bluetooth_grpc/server/server.py
@@ -214,7 +214,11 @@ if not self.btd.ExportMediaPlayer(): logging.info("Failed to export media player") - self.btd.SpecifyDeviceType(self.device_type) + self.btd.SpecifyDeviceType( + self.device_type, + self.config.devkit.rfcomm_services.service_list.service_list, + ) + # Delay 1 second to wait for power on. time.sleep(1)
diff --git a/chameleond/utils/bluetooth_raspi.py b/chameleond/utils/bluetooth_raspi.py index a1049f2..6e99b26 100644 --- a/chameleond/utils/bluetooth_raspi.py +++ b/chameleond/utils/bluetooth_raspi.py
@@ -502,7 +502,7 @@ return device_type - def SpecifyDeviceType(self, device_type): + def SpecifyDeviceType(self, device_type, rfcomm_services=None): """Instantiates one of our supported devices The raspi stack is designed to emulate a single device at a time. This @@ -511,6 +511,8 @@ Args: device_type: String device type, e.g. "MOUSE" + rfcomm_services: A list of Rfcomm services to start (applicable only + when the device_type is DEV_KIT) """ # Do nothing if we were already bound to this device @@ -546,7 +548,9 @@ # Set device type and initiate service based on it if "DEV_KIT" in device_type: self._bluez_service = BluezRfcommService( - self.device_type, self.GetLocalBluetoothAddress() + self.device_type, + self.GetLocalBluetoothAddress(), + rfcomm_services, ) else: self._bluez_service = BluezHIDService(
diff --git a/chameleond/utils/raspi_bluez_service.py b/chameleond/utils/raspi_bluez_service.py index 67d2d2a..c114937 100644 --- a/chameleond/utils/raspi_bluez_service.py +++ b/chameleond/utils/raspi_bluez_service.py
@@ -17,6 +17,7 @@ import socket import time +from blueship import manager_pb2 from bluetooth import BluetoothSocket from bluetooth import L2CAP import dbus @@ -113,6 +114,7 @@ dbus.service.Object.__init__(self, bus, path) self.fd = None self.path = path + logging.info("EchoProfile: init") @dbus.service.method( "org.bluez.Profile1", in_signature="", out_signature="" @@ -139,6 +141,7 @@ if not data: time.sleep(0.1) continue + logging.debug(f"EchoProfile: Writing back {data}") self.fd.write(data) # Echo back the received data except OSError as e: logging.warn(f"EchoProfile: Connection closed or error: {e}") @@ -171,6 +174,7 @@ self.fd = None self.path = path self.map_handler = MapServer() + logging.info("MapProfile: init") @dbus.service.method( "org.bluez.Profile1", in_signature="", out_signature="" @@ -242,6 +246,7 @@ self.fd = None self.path = path self.pbap_handler = PbapServer() + logging.info("PbapProfile: init") @dbus.service.method( "org.bluez.Profile1", in_signature="", out_signature="" @@ -639,7 +644,7 @@ class BluezRfcommService(dbus.service.Object): """Bluez Service implementation for RFCOMM Service.""" - def __init__(self, device_type, adapter_address): + def __init__(self, device_type, adapter_address, rfcomm_services): self._profiles = [] self._bus = dbus.SystemBus() self._bus_name = dbus.service.BusName( @@ -652,10 +657,16 @@ self._bus_name, BLUEZ_RFCOMM_SERVICE_PATH ) + logging.debug(f"Rfcomm services to start {rfcomm_services}") + # Init profile only if one is declared for this device type profile_uuid = PERIPHERAL_PROFILE_UUID.get(device_type, None) - if profile_uuid and ECHO_SERVICE_UUID in profile_uuid: + if ( + manager_pb2.ECHO_SERVICE in rfcomm_services + and profile_uuid + and ECHO_SERVICE_UUID in profile_uuid + ): sdp_path = SERVICE_PROFILE_SDP_PATH.get(device_type, None) if sdp_path and ECHO_SERVICE_UUID in sdp_path: self._InitBluezProfile( @@ -664,7 +675,11 @@ ECHO_SERVICE_UUID, ) - if profile_uuid and MAP_SERVICE_UUID in profile_uuid: + if ( + manager_pb2.MAP_SERVICE in rfcomm_services + and profile_uuid + and MAP_SERVICE_UUID in profile_uuid + ): sdp_path = SERVICE_PROFILE_SDP_PATH.get(device_type, None) if sdp_path and MAP_SERVICE_UUID in sdp_path: self._InitBluezProfile( @@ -673,7 +688,11 @@ MAP_SERVICE_UUID, ) - if profile_uuid and PBAP_SERVICE_UUID in profile_uuid: + if ( + manager_pb2.PBAP_SERVICE in rfcomm_services + and profile_uuid + and PBAP_SERVICE_UUID in profile_uuid + ): sdp_path = SERVICE_PROFILE_SDP_PATH.get(device_type, None) if sdp_path and PBAP_SERVICE_UUID in sdp_path: self._InitBluezProfile(