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