xref: /aosp_15_r20/external/crosvm/devices/src/i8042.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
6*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
7*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker /// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
16*bb4ee6a4SAndroid Build Coastguard Worker pub struct I8042Device {
17*bb4ee6a4SAndroid Build Coastguard Worker     reset_evt_wrtube: SendTube,
18*bb4ee6a4SAndroid Build Coastguard Worker }
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker impl I8042Device {
21*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a i8042 device that will signal the given event when the guest requests it.
new(reset_evt_wrtube: SendTube) -> I8042Device22*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(reset_evt_wrtube: SendTube) -> I8042Device {
23*bb4ee6a4SAndroid Build Coastguard Worker         I8042Device { reset_evt_wrtube }
24*bb4ee6a4SAndroid Build Coastguard Worker     }
25*bb4ee6a4SAndroid Build Coastguard Worker }
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker // i8042 device is mapped I/O address 0x61. We partially implement two 8-bit
28*bb4ee6a4SAndroid Build Coastguard Worker // registers: port 0x61 (I8042_PORT_B_REG), and port 0x64 (I8042_COMMAND_REG).
29*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for I8042Device {
device_id(&self) -> DeviceId30*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
31*bb4ee6a4SAndroid Build Coastguard Worker         CrosvmDeviceId::I8042.into()
32*bb4ee6a4SAndroid Build Coastguard Worker     }
33*bb4ee6a4SAndroid Build Coastguard Worker 
debug_label(&self) -> String34*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
35*bb4ee6a4SAndroid Build Coastguard Worker         "i8042".to_owned()
36*bb4ee6a4SAndroid Build Coastguard Worker     }
37*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])38*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
39*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() == 1 && info.address == 0x64 {
40*bb4ee6a4SAndroid Build Coastguard Worker             data[0] = 0x0;
41*bb4ee6a4SAndroid Build Coastguard Worker         } else if data.len() == 1 && info.address == 0x61 {
42*bb4ee6a4SAndroid Build Coastguard Worker             // Like kvmtool, we return bit 5 set in I8042_PORT_B_REG to
43*bb4ee6a4SAndroid Build Coastguard Worker             // avoid hang in pit_calibrate_tsc() in Linux kernel.
44*bb4ee6a4SAndroid Build Coastguard Worker             data[0] = 0x20;
45*bb4ee6a4SAndroid Build Coastguard Worker         }
46*bb4ee6a4SAndroid Build Coastguard Worker     }
47*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])48*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
49*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() == 1 && data[0] == 0xfe && info.address == 0x64 {
50*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self
51*bb4ee6a4SAndroid Build Coastguard Worker                 .reset_evt_wrtube
52*bb4ee6a4SAndroid Build Coastguard Worker                 .send::<VmEventType>(&VmEventType::Reset)
53*bb4ee6a4SAndroid Build Coastguard Worker             {
54*bb4ee6a4SAndroid Build Coastguard Worker                 error!("failed to trigger i8042 reset event: {}", e);
55*bb4ee6a4SAndroid Build Coastguard Worker             }
56*bb4ee6a4SAndroid Build Coastguard Worker         }
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for I8042Device {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>61*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
62*bb4ee6a4SAndroid Build Coastguard Worker         Ok(serde_json::Value::Object(serde_json::Map::new()))
63*bb4ee6a4SAndroid Build Coastguard Worker     }
64*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, _data: serde_json::Value) -> anyhow::Result<()>65*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, _data: serde_json::Value) -> anyhow::Result<()> {
66*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
67*bb4ee6a4SAndroid Build Coastguard Worker     }
68*bb4ee6a4SAndroid Build Coastguard Worker 
sleep(&mut self) -> anyhow::Result<()>69*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
70*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
71*bb4ee6a4SAndroid Build Coastguard Worker     }
72*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>73*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
74*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
75*bb4ee6a4SAndroid Build Coastguard Worker     }
76*bb4ee6a4SAndroid Build Coastguard Worker }
77