1use crate::keyboard::Keyboard;
7use crate::mouse::Mouse;
8use crate::video::Video;
9use async_trait::async_trait;
10use thiserror::Error;
11use uidevices_resources::SynthKeyboardHandle;
12use uidevices_resources::SynthMouseHandle;
13use uidevices_resources::SynthVideoHandle;
14use vm_resource::AsyncResolveResource;
15use vm_resource::ResolveError;
16use vm_resource::ResourceResolver;
17use vm_resource::declare_static_async_resolver;
18use vm_resource::kind::VmbusDeviceHandleKind;
19use vmbus_channel::resources::ResolveVmbusDeviceHandleParams;
20use vmbus_channel::resources::ResolvedVmbusDevice;
21use vmbus_channel::simple::SimpleDeviceWrapper;
22
23pub struct VmbusUiResolver;
26
27declare_static_async_resolver! {
28 VmbusUiResolver,
29 (VmbusDeviceHandleKind, SynthVideoHandle),
30 (VmbusDeviceHandleKind, SynthKeyboardHandle),
31 (VmbusDeviceHandleKind, SynthMouseHandle),
32}
33
34#[derive(Debug, Error)]
36#[expect(missing_docs)]
37pub enum VideoError {
38 #[error("failed to create video device")]
39 Video(#[source] anyhow::Error),
40 #[error("failed to resolve framebuffer")]
41 Framebuffer(#[source] ResolveError),
42}
43
44#[async_trait]
45impl AsyncResolveResource<VmbusDeviceHandleKind, SynthVideoHandle> for VmbusUiResolver {
46 type Output = ResolvedVmbusDevice;
47 type Error = VideoError;
48
49 async fn resolve(
50 &self,
51 resolver: &ResourceResolver,
52 resource: SynthVideoHandle,
53 input: ResolveVmbusDeviceHandleParams<'_>,
54 ) -> Result<Self::Output, Self::Error> {
55 let framebuffer = resolver
56 .resolve(resource.framebuffer, ())
57 .await
58 .map_err(VideoError::Framebuffer)?;
59 let device = SimpleDeviceWrapper::new(
60 input.driver_source.simple(),
61 Video::new(framebuffer.0).map_err(VideoError::Video)?,
62 );
63 Ok(device.into())
64 }
65}
66
67#[derive(Debug, Error)]
69#[expect(missing_docs)]
70pub enum InputError {
71 #[error("failed to resolve input source")]
72 InputSource(#[source] ResolveError),
73}
74
75#[async_trait]
76impl AsyncResolveResource<VmbusDeviceHandleKind, SynthKeyboardHandle> for VmbusUiResolver {
77 type Output = ResolvedVmbusDevice;
78 type Error = InputError;
79
80 async fn resolve(
81 &self,
82 resolver: &ResourceResolver,
83 resource: SynthKeyboardHandle,
84 input: ResolveVmbusDeviceHandleParams<'_>,
85 ) -> Result<Self::Output, Self::Error> {
86 let source = resolver
87 .resolve(resource.source, "synthkbd")
88 .await
89 .map_err(InputError::InputSource)?;
90 let device =
91 SimpleDeviceWrapper::new(input.driver_source.simple(), Keyboard::new(source.0));
92 Ok(device.into())
93 }
94}
95
96#[async_trait]
97impl AsyncResolveResource<VmbusDeviceHandleKind, SynthMouseHandle> for VmbusUiResolver {
98 type Output = ResolvedVmbusDevice;
99 type Error = InputError;
100
101 async fn resolve(
102 &self,
103 resolver: &ResourceResolver,
104 resource: SynthMouseHandle,
105 input: ResolveVmbusDeviceHandleParams<'_>,
106 ) -> Result<Self::Output, Self::Error> {
107 let source = resolver
108 .resolve(resource.source, "synthmouse")
109 .await
110 .map_err(InputError::InputSource)?;
111 let device = SimpleDeviceWrapper::new(input.driver_source.simple(), Mouse::new(source.0));
112 Ok(device.into())
113 }
114}