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