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