Слияние кода завершено, страница обновится автоматически
// 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 std::fmt::{Display, Formatter, Result as FmtResult};
use log::error;
use super::config::*;
use super::{UsbDeviceRequest, UsbPacket, UsbPacketStatus};
use ui::input::set_kbd_led_state;
/// HID keycode
const HID_KEYBOARD_LEFT_CONTROL: u8 = 0xe0;
#[allow(unused)]
const HID_KEYBOARD_LEFT_SHIFT: u8 = 0xe1;
#[allow(unused)]
const HID_KEYBOARD_LEFT_ALT: u8 = 0xe2;
#[allow(unused)]
const HID_KEYBOARD_LEFT_GUI: u8 = 0xe3;
#[allow(unused)]
const HID_KEYBOARD_RIGHT_CONTROL: u8 = 0xe4;
#[allow(unused)]
const HID_KEYBOARD_RIGHT_SHIFT: u8 = 0xe5;
#[allow(unused)]
const HID_KEYBOARD_RIGHT_ALT: u8 = 0xe6;
const HID_KEYBOARD_RIGHT_GUI: u8 = 0xe7;
/// See the spec section 7.2 Class-Specific Requests
pub const HID_GET_REPORT: u8 = 0x01;
pub const HID_GET_IDLE: u8 = 0x02;
pub const HID_GET_PROTOCOL: u8 = 0x03;
pub const HID_SET_REPORT: u8 = 0x09;
pub const HID_SET_IDLE: u8 = 0x0a;
pub const HID_SET_PROTOCOL: u8 = 0x0b;
/// See the spec section 7.2.5 Get Protocol Request
#[allow(unused)]
const HID_PROTOCTL_BOOT: u8 = 0;
const HID_PROTOCOL_REPORT: u8 = 1;
const KEYCODE_UP: u32 = 0x80;
pub const QUEUE_LENGTH: u32 = 16;
pub const QUEUE_MASK: u32 = QUEUE_LENGTH - 1;
const HID_USAGE_ERROR_ROLLOVER: u8 = 0x1;
/// QKeyCode to HID code table
const HID_CODE: [u8; 0x100] = [
0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, 0xe2, 0x2c, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
0x5a, 0x5b, 0x62, 0x63, 0x46, 0x00, 0x64, 0x44, 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x89, 0xe7, 0x65,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x4a, 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x66, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
/// Tablet report descriptor
const TABLET_REPORT_DESCRIPTOR: [u8; 89] = [
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xa1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xa1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x81, 0x01, // Input (Constant)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xff, 0x7f, // Logical Maximum (0x7fff)
0x35, 0x00, // Physical Minimum (0)
0x46, 0xff, 0x7f, // Physical Maximum (0x7fff)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-0x7f)
0x25, 0x7f, // Logical Maximum (0x7f)
0x35, 0x00, // Physical Minimum (same as logical)
0x45, 0x00, // Physical Maximum (same as logical)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data, Variable, Relative)
0x05, 0x0c, // Usage Page (Consumer Device)
0x0a, 0x38, 0x02, // Usage (AC Pan)
0x15, 0x81, // Logical Minimum (-0x7f)
0x25, 0x7f, // Logical Maximum (0x7f)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data, Variable, Relative)
0xc0, 0xc0, // End Collection
];
/// Keyboard report descriptor
const KEYBOARD_REPORT_DESCRIPTOR: [u8; 63] = [
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xa1, 0x01, // Collection (Application)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Constant)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xff, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0xff, // Usage Maximum (255)
0x81, 0x00, // Input (Data, Array)
0xc0, // End Collection
];
/// HID type
#[derive(Debug)]
pub enum HidType {
Mouse,
Tablet,
Keyboard,
UnKnown,
}
/// HID keyboard including keycode and modifier.
pub struct HidKeyboard {
/// Receive keycode from VNC.
pub keycodes: [u32; QUEUE_LENGTH as usize],
pub modifiers: u16,
/// Send keycode to driver.
pub key_buf: [u8; QUEUE_LENGTH as usize],
pub key_num: u32,
}
impl HidKeyboard {
fn new() -> HidKeyboard {
HidKeyboard {
keycodes: [0; QUEUE_LENGTH as usize],
modifiers: 0,
key_buf: [0; QUEUE_LENGTH as usize],
key_num: 0,
}
}
fn reset(&mut self) {
self.keycodes.iter_mut().for_each(|x| *x = 0);
self.modifiers = 0;
self.key_buf.iter_mut().for_each(|x| *x = 0);
self.key_num = 0;
}
}
/// HID pointer event including position and button state.
#[derive(Debug, Clone, Copy, Default)]
pub struct HidPointerEvent {
/// Direction: left to right.
pub pos_x: u32,
/// Direction: up to down.
pub pos_y: u32,
/// Vertical scroll wheel.
pub v_wheel: i32,
/// Horizontal scroll wheel.
pub h_wheel: i32,
pub button_state: u32,
}
/// HID pointer which include hid pointer event.
pub struct HidPointer {
pub queue: [HidPointerEvent; QUEUE_LENGTH as usize],
}
impl HidPointer {
fn new() -> Self {
HidPointer {
queue: [HidPointerEvent::default(); QUEUE_LENGTH as usize],
}
}
fn reset(&mut self) {
self.queue
.iter_mut()
.for_each(|x| *x = HidPointerEvent::default());
}
}
/// Human Interface Device.
pub struct Hid {
pub(crate) head: u32,
pub(crate) num: u32,
pub(crate) kind: HidType,
protocol: u8,
idle: u8,
pub(crate) keyboard: HidKeyboard,
pub(crate) pointer: HidPointer,
}
impl Hid {
pub fn new(kind: HidType) -> Self {
Hid {
head: 0,
num: 0,
kind,
protocol: 0,
idle: 0,
keyboard: HidKeyboard::new(),
pointer: HidPointer::new(),
}
}
pub fn reset(&mut self) {
self.head = 0;
self.num = 0;
self.protocol = HID_PROTOCOL_REPORT;
self.idle = 0;
self.keyboard.reset();
self.pointer.reset();
}
fn convert_to_hid_code(&mut self) {
if self.num == 0 {
return;
}
let slot = self.head & QUEUE_MASK;
self.increase_head();
self.num -= 1;
let keycode = self.keyboard.keycodes[slot as usize];
let key = keycode & 0x7f;
let index = key | ((self.keyboard.modifiers as u32 & (1 << 8)) >> 1);
let hid_code = HID_CODE[index as usize];
self.keyboard.modifiers &= !(1 << 8);
trace::usb_convert_to_hid_code(&hid_code, &index, &key);
if hid_code == 0x0 {
return;
}
if hid_code == HID_KEYBOARD_LEFT_CONTROL && self.keyboard.modifiers & (1 << 9) == (1 << 9) {
self.keyboard.modifiers ^= (1 << 8) | (1 << 9);
return;
}
if (HID_KEYBOARD_LEFT_CONTROL..=HID_KEYBOARD_RIGHT_GUI).contains(&hid_code)
&& keycode & KEYCODE_UP == KEYCODE_UP
{
self.keyboard.modifiers &= !(1 << (hid_code & 0x0f));
return;
}
if (HID_KEYBOARD_LEFT_CONTROL..=0xe9).contains(&hid_code) {
self.keyboard.modifiers |= 1 << (hid_code & 0x0f);
return;
}
// Invalid code.
if (0xea..=0xef).contains(&hid_code) {
error!("Convert error, invalid code {}", hid_code);
return;
}
if keycode & KEYCODE_UP == KEYCODE_UP {
let mut i = self.keyboard.key_num as i32 - 1;
while i >= 0 {
if self.keyboard.key_buf[i as usize] == hid_code {
self.keyboard.key_num -= 1;
self.keyboard.key_buf[i as usize] =
self.keyboard.key_buf[self.keyboard.key_num as usize];
self.keyboard.key_buf[self.keyboard.key_num as usize] = 0x0;
break;
}
i -= 1;
}
} else {
let mut i = self.keyboard.key_num as i32 - 1;
while i >= 0 {
if self.keyboard.key_buf[i as usize] == hid_code {
break;
}
i -= 1;
}
if i < 0 && self.keyboard.key_num < self.keyboard.key_buf.len() as u32 {
self.keyboard.key_buf[self.keyboard.key_num as usize] = hid_code;
self.keyboard.key_num += 1;
}
}
}
fn keyboard_poll(&mut self) -> Vec<u8> {
let mut data = vec![0; 8];
self.convert_to_hid_code();
data[0] = self.keyboard.modifiers as u8;
data[1] = 0;
let len = data.len() - 2;
if self.keyboard.key_num > 6 {
for i in 0..len {
data[i + 2] = HID_USAGE_ERROR_ROLLOVER;
}
} else {
data[2..(len + 2)].clone_from_slice(&self.keyboard.key_buf[..len]);
}
data
}
fn pointer_poll(&mut self) -> Vec<u8> {
let index = self.head;
if self.num != 0 {
self.increase_head();
self.num -= 1;
}
let evt = &mut self.pointer.queue[(index & QUEUE_MASK) as usize];
vec![
evt.button_state as u8,
evt.pos_x as u8,
(evt.pos_x >> 8) as u8,
evt.pos_y as u8,
(evt.pos_y >> 8) as u8,
evt.v_wheel as u8,
evt.h_wheel as u8,
]
}
fn increase_head(&mut self) {
if self.head + 1 >= QUEUE_LENGTH {
self.head = 0;
} else {
self.head += 1;
}
}
/// USB HID device handle control packet.
pub fn handle_control_packet(
&mut self,
packet: &mut UsbPacket,
device_req: &UsbDeviceRequest,
data: &mut [u8],
) {
match device_req.request_type {
USB_INTERFACE_IN_REQUEST => {
self.do_interface_in_request(packet, device_req, data);
}
USB_INTERFACE_CLASS_IN_REQUEST => {
self.do_interface_class_in_request(packet, device_req, data);
}
USB_INTERFACE_CLASS_OUT_REQUEST => {
self.do_interface_class_out_request(packet, device_req, data);
}
_ => {
error!("Unhandled request {}", device_req.request);
packet.status = UsbPacketStatus::Stall;
}
}
}
fn do_interface_in_request(
&mut self,
packet: &mut UsbPacket,
device_req: &UsbDeviceRequest,
data: &mut [u8],
) {
match device_req.request {
USB_REQUEST_GET_DESCRIPTOR => match device_req.value >> 8 {
0x22 => match self.kind {
HidType::Tablet => {
data[..TABLET_REPORT_DESCRIPTOR.len()]
.clone_from_slice(&TABLET_REPORT_DESCRIPTOR[..]);
packet.actual_length = TABLET_REPORT_DESCRIPTOR.len() as u32;
}
HidType::Keyboard => {
data[..KEYBOARD_REPORT_DESCRIPTOR.len()]
.clone_from_slice(&KEYBOARD_REPORT_DESCRIPTOR[..]);
packet.actual_length = KEYBOARD_REPORT_DESCRIPTOR.len() as u32;
}
_ => {
error!("Unknown HID type");
packet.status = UsbPacketStatus::Stall;
}
},
_ => {
error!("Invalid value: {:?}", device_req);
packet.status = UsbPacketStatus::Stall;
}
},
_ => {
error!("Unhandled request {}", device_req.request);
packet.status = UsbPacketStatus::Stall;
}
}
}
fn do_interface_class_in_request(
&mut self,
packet: &mut UsbPacket,
device_req: &UsbDeviceRequest,
data: &mut [u8],
) {
match device_req.request {
HID_GET_REPORT => match self.kind {
HidType::Tablet => {
let buf = self.pointer_poll();
data[0..buf.len()].copy_from_slice(buf.as_slice());
packet.actual_length = buf.len() as u32;
}
HidType::Keyboard => {
let buf = self.keyboard_poll();
data[0..buf.len()].copy_from_slice(buf.as_slice());
packet.actual_length = buf.len() as u32;
}
_ => {
error!("Unsupported HID type for report");
packet.status = UsbPacketStatus::Stall;
}
},
HID_GET_PROTOCOL => {
data[0] = self.protocol;
packet.actual_length = 1;
}
HID_GET_IDLE => {
data[0] = self.idle;
packet.actual_length = 1;
}
_ => {
error!("Unhandled request {}", device_req.request);
packet.status = UsbPacketStatus::Stall;
}
}
}
fn do_interface_class_out_request(
&mut self,
packet: &mut UsbPacket,
device_req: &UsbDeviceRequest,
data: &[u8],
) {
match device_req.request {
HID_SET_REPORT => match self.kind {
HidType::Keyboard => {
trace::usb_keyboard_set_report(&data[0]);
set_kbd_led_state(data[0]);
}
_ => {
error!("Unsupported to set report");
packet.status = UsbPacketStatus::Stall;
}
},
HID_SET_PROTOCOL => {
self.protocol = device_req.value as u8;
}
HID_SET_IDLE => {
self.idle = (device_req.value >> 8) as u8;
}
_ => {
error!("Unhandled request {}", device_req.request);
packet.status = UsbPacketStatus::Stall;
}
}
}
/// USB HID device handle data packet.
pub fn handle_data_packet(&mut self, p: &mut UsbPacket) {
match p.pid as u8 {
USB_TOKEN_IN => {
self.handle_token_in(p);
}
_ => {
error!("Unhandled packet {}", p.pid);
p.status = UsbPacketStatus::Stall;
}
};
}
fn handle_token_in(&mut self, p: &mut UsbPacket) {
let mut buf = Vec::new();
if p.ep_number == 1 {
if self.num == 0 {
trace::usb_no_data_in_usb_device();
p.status = UsbPacketStatus::Nak;
return;
}
match self.kind {
HidType::Keyboard => {
buf = self.keyboard_poll();
}
HidType::Tablet => {
buf = self.pointer_poll();
}
_ => {
error!("Unsupported HID device");
p.status = UsbPacketStatus::Stall;
}
}
let len = buf.len();
p.transfer_packet(&mut buf, len);
} else {
error!("Unhandled endpoint {}", p.ep_number);
p.status = UsbPacketStatus::Stall;
}
}
}
impl Display for Hid {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(
f,
"HID head {} num {} kind {:?} protocol {} idle {}",
self.head, self.num, self.kind, self.protocol, self.idle
)
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )