Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 393507e5 authored by Gopi Sakshihally Bhuthaiah's avatar Gopi Sakshihally Bhuthaiah Committed by Gopi Sakshihally Bhuthaiah (xWF)
Browse files

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
parent cd3675b5
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -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;
}
+83 −6
Original line number Diff line number Diff line
@@ -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