uidevices/
resolver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Resolver for UI devices.
5
6use 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
23/// A resolver for [`SynthVideoHandle`], [`SynthKeyboardHandle`], and
24/// [`SynthMouseHandle`].
25pub struct VmbusUiResolver;
26
27declare_static_async_resolver! {
28    VmbusUiResolver,
29    (VmbusDeviceHandleKind, SynthVideoHandle),
30    (VmbusDeviceHandleKind, SynthKeyboardHandle),
31    (VmbusDeviceHandleKind, SynthMouseHandle),
32}
33
34/// Error returned when resolving video device handles.
35#[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/// Error returned when resolving input device handles.
68#[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}