// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. // // StratoVirt is licensed under Mulan PSL v2. // You can use this software according to the terms and conditions of the Mulan // PSL v2. // You may obtain a copy of Mulan PSL v2 at: // http://license.coscl.org.cn/MulanPSL2 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. use crate::{ client::ClientIoHandler, pixman::{get_image_height, get_image_width}, }; use log::error; use usb::{ keyboard::keyboard_event, tablet::{pointer_event, pointer_sync}, INPUT, }; // Logical window size for mouse. const ABS_MAX: u64 = 0x7fff; // Up flag. const SCANCODE_UP: u16 = 0x80; // Grey keys. const SCANCODE_GREY: u16 = 0x80; // Used to expand Grey keys. const SCANCODE_EMUL0: u16 = 0xe0; // Event type of Point. const INPUT_POINT_LEFT: u8 = 0x01; const INPUT_POINT_MIDDLE: u8 = 0x02; const INPUT_POINT_RIGHT: u8 = 0x04; // ASCII value. const ASCII_A: i32 = 65; const ASCII_Z: i32 = 90; const UPPERCASE_TO_LOWERCASE: i32 = 32; impl ClientIoHandler { /// Keyboard event. pub fn key_envent(&mut self) { if self.expect == 1 { self.expect = 8; return; } let buf = self.read_incoming_msg(); let down = buf[1] as u8; let mut keysym = i32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]); // Uppercase -> Lowercase. if (ASCII_A..=ASCII_Z).contains(&keysym) { keysym += UPPERCASE_TO_LOWERCASE; } let keycode: u16; match self .server .keysym2keycode .lock() .unwrap() .get(&(keysym as u16)) { Some(k) => keycode = *k, None => { keycode = 0; } } self.do_key_event(down, keycode); self.update_event_handler(1, ClientIoHandler::handle_protocol_msg); } // Mouse event. pub fn point_event(&mut self) { if self.expect == 1 { self.expect = 6; return; } let buf = self.read_incoming_msg(); let mut x = ((buf[2] as u16) << 8) + buf[3] as u16; let mut y = ((buf[4] as u16) << 8) + buf[5] as u16; // Window size alignment. let locked_surface = self.server.vnc_surface.lock().unwrap(); let width = get_image_width(locked_surface.server_image); let height = get_image_height(locked_surface.server_image); drop(locked_surface); x = ((x as u64 * ABS_MAX) / width as u64) as u16; y = ((y as u64 * ABS_MAX) / height as u64) as u16; // ASCII -> HidCode. let button_mask: u8 = match buf[1] as u8 { INPUT_POINT_LEFT => 0x01, INPUT_POINT_MIDDLE => 0x04, INPUT_POINT_RIGHT => 0x02, _ => buf[1] as u8, }; let locked_input = INPUT.lock().unwrap(); if let Some(tablet) = &locked_input.tablet { if let Err(e) = pointer_event(tablet, button_mask as u32, x as i32, y as i32) { error!("Point event error: {}", e); } if let Err(e) = pointer_sync(tablet) { error!("Point event sync error: {}", e); } } self.update_event_handler(1, ClientIoHandler::handle_protocol_msg); } /// Do keyboard event. /// /// # Arguments /// /// * `down` - press keyboard down or up. /// * `keycode` - keycode. pub fn do_key_event(&mut self, down: u8, keycode: u16) { let mut scancode = Vec::new(); let mut keycode = keycode; if keycode & SCANCODE_GREY != 0 { scancode.push(SCANCODE_EMUL0 as u32); keycode &= !SCANCODE_GREY; } if down == 0 { keycode |= SCANCODE_UP; } scancode.push(keycode as u32); // Send key event. let locked_input = INPUT.lock().unwrap(); if let Some(keyboard) = &locked_input.keyboard { if let Err(e) = keyboard_event(keyboard, scancode.as_slice()) { error!("Key event error: {}", e); } } } /// Client cut text. pub fn client_cut_event(&mut self) { let buf = self.read_incoming_msg(); if self.expect == 1 { self.expect = 8; return; } if self.expect == 8 { let buf = [buf[4], buf[5], buf[6], buf[7]]; let len = u32::from_be_bytes(buf); if len > 0 { self.expect += len as usize; return; } } self.update_event_handler(1, ClientIoHandler::handle_protocol_msg); } }