Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/virtio/video/async_cmd_desc_map.rs
5394 views
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
use std::collections::BTreeMap;
6
7
use crate::virtio::video::command::QueueType;
8
use crate::virtio::video::device::AsyncCmdResponse;
9
use crate::virtio::video::device::AsyncCmdTag;
10
use crate::virtio::video::error::VideoError;
11
use crate::virtio::video::protocol;
12
use crate::virtio::video::response::CmdResponse;
13
use crate::virtio::DescriptorChain;
14
15
/// AsyncCmdDescMap is a BTreeMap which stores descriptor chains in which asynchronous
16
/// responses will be written.
17
#[derive(Default)]
18
pub struct AsyncCmdDescMap(BTreeMap<AsyncCmdTag, DescriptorChain>);
19
20
impl AsyncCmdDescMap {
21
pub fn insert(&mut self, tag: AsyncCmdTag, descriptor_chain: DescriptorChain) {
22
self.0.insert(tag, descriptor_chain);
23
}
24
25
pub fn remove(&mut self, tag: &AsyncCmdTag) -> Option<DescriptorChain> {
26
self.0.remove(tag)
27
}
28
29
/// Returns a list of `AsyncCmdResponse`s to cancel pending commands that target
30
/// stream `target_stream_id`.
31
/// If `target_queue_type` is specified, then only create the requests for the specified queue.
32
/// Otherwise, create the requests for both input and output queue.
33
/// If `processing_tag` is specified, a cancellation request for that tag will
34
/// not be created.
35
pub fn create_cancellation_responses(
36
&self,
37
target_stream_id: &u32,
38
target_queue_type: Option<QueueType>,
39
processing_tag: Option<AsyncCmdTag>,
40
) -> Vec<AsyncCmdResponse> {
41
let mut responses = vec![];
42
for tag in self.0.keys().filter(|&&k| Some(k) != processing_tag) {
43
match tag {
44
AsyncCmdTag::Queue {
45
stream_id,
46
queue_type,
47
..
48
} if stream_id == target_stream_id
49
&& target_queue_type.as_ref().unwrap_or(queue_type) == queue_type =>
50
{
51
responses.push(AsyncCmdResponse::from_response(
52
*tag,
53
CmdResponse::ResourceQueue {
54
timestamp: 0,
55
flags: protocol::VIRTIO_VIDEO_BUFFER_FLAG_ERR,
56
size: 0,
57
},
58
));
59
}
60
AsyncCmdTag::Drain { stream_id } if stream_id == target_stream_id => {
61
// TODO(b/1518105): Use more appropriate error code if a new protocol supports
62
// one.
63
responses.push(AsyncCmdResponse::from_error(
64
*tag,
65
VideoError::InvalidOperation,
66
));
67
}
68
AsyncCmdTag::Clear {
69
stream_id,
70
queue_type,
71
} if stream_id == target_stream_id
72
&& target_queue_type.as_ref().unwrap_or(queue_type) == queue_type =>
73
{
74
// TODO(b/1518105): Use more appropriate error code if a new protocol supports
75
// one.
76
responses.push(AsyncCmdResponse::from_error(
77
*tag,
78
VideoError::InvalidOperation,
79
));
80
}
81
_ => {
82
// Keep commands for other streams.
83
}
84
}
85
}
86
responses
87
}
88
}
89
90