1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Definition of the trait `Device` that each backend video device must implement.
6 
7 use base::{PollToken, Tube, WaitContext};
8 
9 use crate::virtio::video::async_cmd_desc_map::AsyncCmdDescMap;
10 use crate::virtio::video::command::{QueueType, VideoCmd};
11 use crate::virtio::video::error::*;
12 use crate::virtio::video::event::VideoEvt;
13 use crate::virtio::video::response;
14 
15 #[derive(PollToken, Debug)]
16 pub enum Token {
17     CmdQueue,
18     EventQueue,
19     Event { id: u32 },
20     Kill,
21     InterruptResample,
22 }
23 
24 /// A tag for commands being processed asynchronously in the back-end device.
25 /// TODO(b/149720783): Remove this enum by using async primitives.
26 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
27 pub enum AsyncCmdTag {
28     Queue {
29         stream_id: u32,
30         queue_type: QueueType,
31         resource_id: u32,
32     },
33     Drain {
34         stream_id: u32,
35     },
36     Clear {
37         stream_id: u32,
38         queue_type: QueueType,
39     },
40     // Used exclusively by the encoder.
41     GetParams {
42         stream_id: u32,
43         queue_type: QueueType,
44     },
45 }
46 
47 /// A return value when a command from the guest is processed.
48 #[derive(Debug)]
49 pub enum VideoCmdResponseType {
50     /// The response for a synchronous command. This can be returned to the guest immediately via
51     /// command virtqueue.
52     Sync(response::CmdResponse),
53     /// The tag for an asynchronous command that the back-end device will complete.
54     /// Once the command is completed, its result will be sent with the same tag.
55     /// This can be seen as a poor man's future pattern.
56     Async(AsyncCmdTag),
57 }
58 
59 /// A response for an asynchronous command that was enqueued through `process_cmd` before.
60 /// The `tag` must be same as the one returned when the command was enqueued.
61 #[derive(Debug)]
62 pub struct AsyncCmdResponse {
63     pub tag: AsyncCmdTag,
64     pub response: VideoResult<response::CmdResponse>,
65 }
66 
67 impl AsyncCmdResponse {
from_response(tag: AsyncCmdTag, response: response::CmdResponse) -> Self68     pub fn from_response(tag: AsyncCmdTag, response: response::CmdResponse) -> Self {
69         Self {
70             tag,
71             response: Ok(response),
72         }
73     }
74 
from_error(tag: AsyncCmdTag, error: VideoError) -> Self75     pub fn from_error(tag: AsyncCmdTag, error: VideoError) -> Self {
76         Self {
77             tag,
78             response: Err(error),
79         }
80     }
81 }
82 
83 /// A return value when processing a event the back-end device sent.
84 #[derive(Debug)]
85 pub enum VideoEvtResponseType {
86     /// The responses for an asynchronous command.
87     AsyncCmd(AsyncCmdResponse),
88     /// The event that happened in the back-end device.
89     Event(VideoEvt),
90 }
91 
92 pub trait Device {
93     /// Processes a virtio-video command.
94     /// If the command expects a synchronous response, it returns a response as `VideoCmdResponseType::Sync`.
95     /// Otherwise, it returns a name of the descriptor chain that will be used when a response is prepared.
96     /// Implementations of this method is passed a WaitContext object which can be used to add or remove
97     /// FDs to poll. It is expected that only Token::Event items would be added. When a Token::Event
98     /// event arrives, process_event() will be invoked.
99     /// TODO(b/149720783): Make this an async function.
process_cmd( &mut self, cmd: VideoCmd, wait_ctx: &WaitContext<Token>, resource_bridge: &Tube, ) -> ( VideoCmdResponseType, Option<(u32, Vec<VideoEvtResponseType>)>, )100     fn process_cmd(
101         &mut self,
102         cmd: VideoCmd,
103         wait_ctx: &WaitContext<Token>,
104         resource_bridge: &Tube,
105     ) -> (
106         VideoCmdResponseType,
107         Option<(u32, Vec<VideoEvtResponseType>)>,
108     );
109 
110     /// Processes an available `Token::Event` event and returns a list of `VideoEvtResponseType`
111     /// responses. It returns None if an invalid event comes.
112     /// For responses to be sent via command queue, the return type is `VideoEvtResponseType::AsyncCmd`.
113     /// For responses to be sent via event queue, the return type is `VideoEvtResponseType::Event`.
114     /// TODO(b/149720783): Make this an async function.
process_event( &mut self, desc_map: &mut AsyncCmdDescMap, stream_id: u32, ) -> Option<Vec<VideoEvtResponseType>>115     fn process_event(
116         &mut self,
117         desc_map: &mut AsyncCmdDescMap,
118         stream_id: u32,
119     ) -> Option<Vec<VideoEvtResponseType>>;
120 }
121