1# Copyright (C) 2024 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from threading import Thread 16from time import sleep 17 18from mmi2grpc._helpers import assert_description, match_description 19from mmi2grpc._proxy import ProfileProxy 20from pandora.host_grpc import Host 21from pandora_experimental.hid_grpc import HID 22from pandora_experimental.hid_pb2 import HID_REPORT_TYPE_OUTPUT 23 24 25class HIDProxy(ProfileProxy): 26 27 def __init__(self, channel, rootcanal): 28 super().__init__(channel) 29 self.hid = HID(channel) 30 self.host = Host(channel) 31 self.rootcanal = rootcanal 32 self.connection = None 33 34 @assert_description 35 def TSC_MMI_iut_enable_connection(self, pts_addr: bytes, **kwargs): 36 """ 37 Click Ok, then using the Implementation Under Test (IUT) connect to the 38 PTS. 39 """ 40 41 self.rootcanal.move_in_range() 42 self.connection = self.host.Connect(address=pts_addr).connection 43 44 return "OK" 45 46 @assert_description 47 def TSC_MMI_iut_release_connection(self, pts_addr: bytes, **kwargs): 48 """ 49 Click Ok, then release the HID connection from the Implementation Under 50 Test (IUT) by closing the Interrupt Channel followed by the Control 51 Channel. 52 53 Description: This can be done using the anticipated L2CAP 54 Disconnection Requests. If the host is unable to perform the connection 55 request, the IUT may break the ACL or Baseband Link by going out of 56 range. 57 """ 58 59 # Performing out of range action 60 def disconnect(): 61 sleep(2) 62 self.rootcanal.move_out_of_range() 63 64 Thread(target=disconnect).start() 65 66 return "OK" 67 68 @assert_description 69 def TSC_MMI_iut_disable_connection(self, pts_addr: bytes, **kwargs): 70 """ 71 Disable the connection using the Implementation UnderTest (IUT). 72 73 Note: 74 The IUT may either disconnect the Interupt Control Channels or send a 75 host initiated virtual cable unplug and wait for the PTS to disconnect 76 the channels. 77 """ 78 79 self.host.Disconnect(connection=self.connection) 80 self.connection = None 81 82 return "OK" 83 84 @assert_description 85 def TSC_HID_MMI_iut_accept_connection_ready_confirm(self, **kwargs): 86 """ 87 Please prepare the IUT to accept connection from PTS and then click OK. 88 """ 89 90 self.rootcanal.move_in_range() 91 92 return "OK" 93 94 @assert_description 95 def TSC_MMI_iut_connectable_enter_pw_dev(self, **kwargs): 96 """ 97 Make the Implementation Under Test (IUT) connectable, then click Ok. 98 """ 99 100 self.rootcanal.move_in_range() 101 102 return "OK" 103 104 @assert_description 105 def TSC_HID_MMI_iut_accept_control_channel(self, pts_addr: bytes, **kwargs): 106 """ 107 Accept the control channel connection from the Implementation Under Test 108 (IUT). 109 """ 110 111 return "OK" 112 113 @assert_description 114 def TSC_MMI_tester_release_connection(self, **kwargs): 115 """ 116 Place the Implementation Under Test (IUT) in a state which will allow 117 the PTS to perform an HID connection release, then click Ok. 118 119 Note: The 120 PTS will send an L2CAP disconnect request for the Interrupt channel, 121 then the control channel. 122 """ 123 124 return "OK" 125 126 @assert_description 127 def TSC_MMI_host_iut_prepare_to_receive_pointing_data(self, **kwargs): 128 """ 129 Place the Implementation Under Test (IUT) in a state to receive and 130 verify HID pointing data, then click Ok. 131 """ 132 133 return "OK" 134 135 @assert_description 136 def TSC_MMI_host_iut_verify_pointing_data(self, **kwargs): 137 """ 138 Verify that the pointer on the Implementation Under Test (IUT) moved to 139 the left (X< 0), then click Ok. 140 """ 141 142 # TODO: implement! 143 144 return "OK" 145 146 @assert_description 147 def TSC_MMI_host_send_output_report(self, pts_addr: bytes, **kwargs): 148 """ 149 Send an output report from the HOST. 150 """ 151 152 self.hid.SendHostReport( 153 address=pts_addr, 154 report_type=HID_REPORT_TYPE_OUTPUT, 155 report="8", # keyboard enable num-lock 156 ) 157 158 return "OK" 159 160 @match_description 161 def TSC_MMI_verify_output_report(self, **kwargs): 162 """ 163 Verify that the output report is correct. nnOutput Report =0(?:0|1)' 164 """ 165 166 # TODO: check the report matches the num-lock setting 167 168 return "OK" 169 170 @assert_description 171 def TSC_MMI_rf_shield_iut_or_tester(self, pts_addr: bytes, **kwargs): 172 """ 173 Click Ok, then perform one of the following actions: 174 175 1. Move the PTS 176 and Implementation Under Test (IUT) out of range of each other. 177 2. Place 178 either the PTS or IUT in an RF sheild box. 179 """ 180 181 def disconnect(): 182 sleep(2) 183 self.rootcanal.move_out_of_range() 184 185 Thread(target=disconnect).start() 186 187 return "OK" 188 189 @assert_description 190 def TSC_MMI_iut_auto_connection(self, pts_addr: bytes, **kwargs): 191 """ 192 Click OK, then initiate a HID connection automatically from the IUT to 193 the PTS 194 """ 195 196 def connect(): 197 sleep(1) 198 self.rootcanal.move_in_range() 199 self.connection = self.host.Connect(address=pts_addr).connection 200 201 Thread(target=connect).start() 202 203 return "OK" 204