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