devices/virtio/video/
response.rs1use std::io;
8
9use data_model::Le32;
10use data_model::Le64;
11
12use crate::virtio::video::command::QueueType;
13use crate::virtio::video::control::*;
14use crate::virtio::video::error::VideoError;
15use crate::virtio::video::format::*;
16use crate::virtio::video::params::Params;
17use crate::virtio::video::protocol::*;
18use crate::virtio::Writer;
19
20pub trait Response {
21 fn write(&self, w: &mut Writer) -> Result<(), io::Error>;
23}
24
25#[derive(Debug, Clone)]
26pub enum CmdError {
27 InvalidResourceId,
28 InvalidStreamId,
29 InvalidParameter,
30 InvalidOperation,
31 UnsupportedControl,
32}
33
34#[derive(Debug, Clone)]
36pub enum CmdResponse {
37 NoData,
38 QueryCapability(Vec<FormatDesc>),
39 ResourceQueue {
40 timestamp: u64,
41 flags: u32,
42 size: u32,
43 },
44 GetParams {
45 queue_type: QueueType,
46 params: Params,
47 is_ext: bool,
48 },
49 QueryControl(QueryCtrlResponse),
50 GetControl(CtrlVal),
51 #[allow(dead_code)]
53 SetControl,
54 Error(CmdError),
55}
56
57impl From<VideoError> for CmdResponse {
58 fn from(error: VideoError) -> Self {
59 let cmd_error = match error {
60 VideoError::InvalidResourceId { .. } => CmdError::InvalidResourceId,
61 VideoError::InvalidStreamId(_) => CmdError::InvalidStreamId,
62 VideoError::InvalidParameter => CmdError::InvalidParameter,
63 VideoError::UnsupportedControl(_) => CmdError::UnsupportedControl,
64 _ => CmdError::InvalidOperation,
65 };
66 CmdResponse::Error(cmd_error)
67 }
68}
69
70impl Response for CmdResponse {
71 fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
73 use CmdResponse::*;
74
75 let type_ = Le32::from(match self {
76 NoData => VIRTIO_VIDEO_RESP_OK_NODATA,
77 QueryCapability(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CAPABILITY,
78 ResourceQueue { .. } => VIRTIO_VIDEO_RESP_OK_RESOURCE_QUEUE,
79 GetParams { .. } => VIRTIO_VIDEO_RESP_OK_GET_PARAMS,
80 QueryControl(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CONTROL,
81 GetControl(_) => VIRTIO_VIDEO_RESP_OK_GET_CONTROL,
82 SetControl => VIRTIO_VIDEO_RESP_OK_NODATA,
83 Error(e) => {
84 match e {
85 CmdError::InvalidResourceId => VIRTIO_VIDEO_RESP_ERR_INVALID_RESOURCE_ID,
88 CmdError::InvalidStreamId => VIRTIO_VIDEO_RESP_ERR_INVALID_STREAM_ID,
89 CmdError::InvalidParameter => VIRTIO_VIDEO_RESP_ERR_INVALID_PARAMETER,
90 CmdError::InvalidOperation => VIRTIO_VIDEO_RESP_ERR_INVALID_OPERATION,
91 CmdError::UnsupportedControl => VIRTIO_VIDEO_RESP_ERR_UNSUPPORTED_CONTROL,
92 }
93 }
94 });
95
96 let hdr = virtio_video_cmd_hdr {
97 type_,
98 ..Default::default()
99 };
100
101 match self {
102 NoData | Error(_) => w.write_obj(hdr),
103 QueryCapability(descs) => {
104 w.write_obj(virtio_video_query_capability_resp {
105 hdr,
106 num_descs: Le32::from(descs.len() as u32),
107 ..Default::default()
108 })?;
109 descs.iter().try_for_each(|d| d.write(w))
110 }
111 ResourceQueue {
112 timestamp,
113 flags,
114 size,
115 } => w.write_obj(virtio_video_resource_queue_resp {
116 hdr,
117 timestamp: Le64::from(*timestamp),
118 flags: Le32::from(*flags),
119 size: Le32::from(*size),
120 }),
121 GetParams {
122 queue_type,
123 params,
124 is_ext,
125 } => {
126 if *is_ext {
127 let params = params.to_virtio_video_params_ext(*queue_type);
128 w.write_obj(virtio_video_get_params_ext_resp { hdr, params })
129 } else {
130 let params = params.to_virtio_video_params(*queue_type);
131 w.write_obj(virtio_video_get_params_resp { hdr, params })
132 }
133 }
134 QueryControl(r) => {
135 w.write_obj(virtio_video_query_control_resp { hdr })?;
136 r.write(w)
137 }
138 GetControl(val) => {
139 w.write_obj(virtio_video_get_control_resp { hdr })?;
140 val.write(w)
141 }
142 SetControl => w.write_obj(virtio_video_set_control_resp { hdr }),
143 }
144 }
145}