summaryrefslogtreecommitdiff
path: root/pandora
diff options
context:
space:
mode:
author Gopi Sakshihally Bhuthaiah <bhuthaiah@google.com> 2024-06-25 13:03:40 +0000
committer Gopi Sakshihally Bhuthaiah (xWF) <bhuthaiah@google.com> 2024-07-31 07:04:41 +0000
commit393507e5d92b6147994533bffccc1a3e18f3d0cb (patch)
tree813b743cec5463cb75ecd3fb8f29de31d0cf9186 /pandora
parentcd3675b5d7743886fcd01e5ea5fb4a25a841a3ae (diff)
Bumble test infra changes
1. added support for set API's(set protocol mode and set report) to validate set data Bug: 340549544 Test: atest -v HidHostTest Flag: EXEMPT Test case Change-Id: If246e311ac75dca8095017c88e98500018fb3a6b
Diffstat (limited to 'pandora')
-rw-r--r--pandora/interfaces/pandora_experimental/hid.proto26
-rw-r--r--pandora/server/bumble_experimental/hid.py89
2 files changed, 108 insertions, 7 deletions
diff --git a/pandora/interfaces/pandora_experimental/hid.proto b/pandora/interfaces/pandora_experimental/hid.proto
index 7b1e7d2c8a..709d1577ff 100644
--- a/pandora/interfaces/pandora_experimental/hid.proto
+++ b/pandora/interfaces/pandora_experimental/hid.proto
@@ -15,8 +15,11 @@ service HID {
rpc VirtualCableUnplugHost(google.protobuf.Empty) returns (google.protobuf.Empty);
// Send a SET_REPORT command, acting as a HID host, to a connected HID device
rpc SendHostReport(SendHostReportRequest) returns (SendHostReportResponse);
+ // receive Protocol Mode Event
+ rpc OnSetProtocolMode(google.protobuf.Empty) returns (stream ProtocolModeEvent);
+ // receive Report Event
+ rpc OnSetReport(google.protobuf.Empty) returns (stream ReportEvent);
}
-
// Enum values match those in BluetoothHidHost.java
enum HidReportType {
HID_REPORT_TYPE_UNSPECIFIED = 0;
@@ -24,6 +27,17 @@ enum HidReportType {
HID_REPORT_TYPE_OUTPUT = 2;
HID_REPORT_TYPE_FEATURE = 3;
}
+// Enum values match those in BluetoothHidHost.java
+enum ProtocolMode {
+ PROTOCOL_REPORT_MODE = 0;
+ PROTOCOL_BOOT_MODE = 1;
+ PROTOCOL_UNSUPPORTED_MODE = 255;
+}
+enum HidReportId {
+ HID_KEYBD_RPT_ID = 0;
+ HID_MOUSE_RPT_ID = 1;
+ HID_INVALID_RPT_ID = 3;
+}
message SendHostReportRequest {
bytes address = 1;
@@ -34,3 +48,13 @@ message SendHostReportRequest {
message SendHostReportResponse {
}
+
+message ProtocolModeEvent {
+ ProtocolMode protocol_mode = 1;
+}
+
+message ReportEvent {
+ HidReportType report_type = 1;
+ HidReportId report_id = 2;
+ string report_data = 3;
+}
diff --git a/pandora/server/bumble_experimental/hid.py b/pandora/server/bumble_experimental/hid.py
index 512ff2204f..d68ca1eb3c 100644
--- a/pandora/server/bumble_experimental/hid.py
+++ b/pandora/server/bumble_experimental/hid.py
@@ -11,6 +11,14 @@ from google.protobuf import empty_pb2 # pytype: disable=pyi-error
from pandora_experimental.hid_grpc_aio import HIDServicer
from bumble.pandora import utils
+from pandora_experimental.hid_pb2 import (
+ ProtocolModeEvent,
+ ReportEvent,
+ PROTOCOL_REPORT_MODE,
+ PROTOCOL_BOOT_MODE,
+ PROTOCOL_UNSUPPORTED_MODE,
+)
+
from bumble.core import (
BT_BR_EDR_TRANSPORT,
BT_L2CAP_PROTOCOL_ID,
@@ -489,20 +497,30 @@ def sdp_records():
# -----------------------------------------------------------------------------
def hogp_device(device):
- global input_report_characteristic
# Create an 'input report' characteristic to send keyboard reports to the host
- input_report_characteristic = Characteristic(
+ input_report_kb_characteristic = Characteristic(
GATT_REPORT_CHARACTERISTIC,
Characteristic.Properties.READ | Characteristic.Properties.WRITE | Characteristic.Properties.NOTIFY,
Characteristic.READABLE | Characteristic.WRITEABLE,
- bytes([0, 0, 0, 0, 0, 0, 0, 0]),
+ bytes([0, 0, 0, 0, 0, 0, 0, 0, 0]),
[Descriptor(
GATT_REPORT_REFERENCE_DESCRIPTOR,
Descriptor.READABLE,
bytes([0x01, HID_INPUT_REPORT]),
)],
)
-
+ # Create an 'input report' characteristic to send mouse reports to the host
+ input_report_mouse_characteristic = Characteristic(
+ GATT_REPORT_CHARACTERISTIC,
+ Characteristic.Properties.READ | Characteristic.Properties.WRITE | Characteristic.Properties.NOTIFY,
+ Characteristic.READABLE | Characteristic.WRITEABLE,
+ bytes([0, 0, 0, 0]),
+ [Descriptor(
+ GATT_REPORT_REFERENCE_DESCRIPTOR,
+ Descriptor.READABLE,
+ bytes([0x02, HID_INPUT_REPORT]),
+ )],
+ )
# Create an 'output report' characteristic to receive keyboard reports from the host
output_report_characteristic = Characteristic(
GATT_REPORT_CHARACTERISTIC,
@@ -558,7 +576,8 @@ def hogp_device(device):
Characteristic.READABLE,
HID_KEYBOARD_REPORT_MAP,
),
- input_report_characteristic,
+ input_report_kb_characteristic,
+ input_report_mouse_characteristic,
output_report_characteristic,
],
),
@@ -630,6 +649,12 @@ def on_set_report_cb(report_id: int, report_type: int, report_size: int, data: b
logging.info("SET_REPORT report_id: " + str(report_id) + "report_type: " + str(report_type) + "report_size " +
str(report_size) + "data:" + str(data))
+ report = ReportEvent()
+ report.report_type = report_type
+ report.report_id = report_id
+ report.report_data = str(data.hex())
+ hid_report_queue.put_nowait(report)
+
if report_type == Message.ReportType.FEATURE_REPORT:
retValue.status = hid_device.GetSetReturn.ERR_INVALID_PARAMETER
elif report_type == Message.ReportType.INPUT_REPORT:
@@ -657,7 +682,15 @@ def on_get_protocol_cb():
def on_set_protocol_cb(protocol: int):
retValue = hid_device.GetSetStatus()
# We do not support SET_PROTOCOL.
- logging.info(f"SET_PROTOCOL report_id: {protocol}")
+ logging.info(f"SET_PROTOCOL mode: {protocol}")
+ mode = ProtocolModeEvent()
+ if protocol == PROTOCOL_REPORT_MODE:
+ mode.protocol_mode = PROTOCOL_REPORT_MODE
+ elif protocol == PROTOCOL_BOOT_MODE:
+ mode.protocol_mode = PROTOCOL_BOOT_MODE
+ else:
+ mode.protocol_mode = PROTOCOL_UNSUPPORTED_MODE
+ hid_protoMode_queue.put_nowait(mode)
retValue.status = hid_device.GetSetReturn.ERR_UNSUPPORTED_REQUEST
return retValue
@@ -667,6 +700,9 @@ def on_virtual_cable_unplug_cb():
asyncio.create_task(handle_virtual_cable_unplug())
+hid_protoMode_queue = None
+
+
# This class implements the Hid Pandora interface.
class HIDService(HIDServicer):
@@ -676,6 +712,7 @@ class HIDService(HIDServicer):
super().__init__()
self.device = device
self.device.sdp_service_records.update(sdp_records())
+ self.event_queue: Optional[asyncio.Queue[ProtocolModeEvent]] = None
hogp_device(self.device)
logging.info(f'Hid device register: ')
global hid_device
@@ -742,3 +779,43 @@ class HIDService(HIDServicer):
logging.exception(f'Device does not exist')
raise e
return empty_pb2.Empty()
+
+ @utils.rpc
+ async def OnSetProtocolMode(self, request: empty_pb2.Empty,
+ context: grpc.ServicerContext) -> AsyncGenerator[ProtocolModeEvent, None]:
+ logging.info(f'OnSetProtocolMode')
+
+ if self.event_queue is not None:
+ raise RuntimeError('already streaming OnSetProtocolMode events')
+
+ self.event_queue = asyncio.Queue()
+ global hid_protoMode_queue
+ hid_protoMode_queue = self.event_queue
+
+ try:
+ while event := await hid_protoMode_queue.get():
+ yield event
+
+ finally:
+ self.event_queue = None
+ hid_protoMode_queue = None
+
+ @utils.rpc
+ async def OnSetReport(self, request: empty_pb2.Empty,
+ context: grpc.ServicerContext) -> AsyncGenerator[ReportEvent, None]:
+ logging.info(f'OnSetReport')
+
+ if self.event_queue is not None:
+ raise RuntimeError('already streaming OnSetReport events')
+
+ self.event_queue = asyncio.Queue()
+ global hid_report_queue
+ hid_report_queue = self.event_queue
+
+ try:
+ while event := await hid_report_queue.get():
+ yield event
+
+ finally:
+ self.event_queue = None
+ hid_report_queue = None