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 }, 47 QueryControl(QueryCtrlResponse), 48 GetControl(CtrlVal), 49 // TODO(alexlau): SetControl is unused, remove this after encoder CL lands. 50 #[allow(dead_code)] 51 SetControl, 52 Error(CmdError), 53 } 54 55 impl From<VideoError> for CmdResponse { from(error: VideoError) -> Self56 fn from(error: VideoError) -> Self { 57 let cmd_error = match error { 58 VideoError::InvalidResourceId { .. } => CmdError::InvalidResourceId, 59 VideoError::InvalidStreamId(_) => CmdError::InvalidStreamId, 60 VideoError::InvalidParameter => CmdError::InvalidParameter, 61 VideoError::UnsupportedControl(_) => CmdError::UnsupportedControl, 62 _ => CmdError::InvalidOperation, 63 }; 64 CmdResponse::Error(cmd_error) 65 } 66 } 67 68 impl Response for CmdResponse { 69 /// Writes a response to virtqueue. write(&self, w: &mut Writer) -> Result<(), io::Error>70 fn write(&self, w: &mut Writer) -> Result<(), io::Error> { 71 use CmdResponse::*; 72 73 let type_ = Le32::from(match self { 74 NoData => VIRTIO_VIDEO_RESP_OK_NODATA, 75 QueryCapability(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CAPABILITY, 76 ResourceQueue { .. } => VIRTIO_VIDEO_RESP_OK_RESOURCE_QUEUE, 77 GetParams { .. } => VIRTIO_VIDEO_RESP_OK_GET_PARAMS, 78 QueryControl(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CONTROL, 79 GetControl(_) => VIRTIO_VIDEO_RESP_OK_GET_CONTROL, 80 SetControl => VIRTIO_VIDEO_RESP_OK_NODATA, 81 Error(e) => { 82 match e { 83 // TODO(b/1518105): Add more detailed error code when a new protocol supports 84 // them. 85 CmdError::InvalidResourceId => VIRTIO_VIDEO_RESP_ERR_INVALID_RESOURCE_ID, 86 CmdError::InvalidStreamId => VIRTIO_VIDEO_RESP_ERR_INVALID_STREAM_ID, 87 CmdError::InvalidParameter => VIRTIO_VIDEO_RESP_ERR_INVALID_PARAMETER, 88 CmdError::InvalidOperation => VIRTIO_VIDEO_RESP_ERR_INVALID_OPERATION, 89 CmdError::UnsupportedControl => VIRTIO_VIDEO_RESP_ERR_UNSUPPORTED_CONTROL, 90 } 91 } 92 }); 93 94 let hdr = virtio_video_cmd_hdr { 95 type_, 96 ..Default::default() 97 }; 98 99 match self { 100 NoData | Error(_) => w.write_obj(hdr), 101 QueryCapability(descs) => { 102 w.write_obj(virtio_video_query_capability_resp { 103 hdr, 104 num_descs: Le32::from(descs.len() as u32), 105 ..Default::default() 106 })?; 107 descs.iter().try_for_each(|d| d.write(w)) 108 } 109 ResourceQueue { 110 timestamp, 111 flags, 112 size, 113 } => w.write_obj(virtio_video_resource_queue_resp { 114 hdr, 115 timestamp: Le64::from(*timestamp), 116 flags: Le32::from(*flags), 117 size: Le32::from(*size), 118 }), 119 GetParams { queue_type, params } => { 120 let params = params.to_virtio_video_params(*queue_type); 121 w.write_obj(virtio_video_get_params_resp { hdr, params }) 122 } 123 QueryControl(r) => { 124 w.write_obj(virtio_video_query_control_resp { hdr })?; 125 r.write(w) 126 } 127 GetControl(val) => { 128 w.write_obj(virtio_video_get_control_resp { hdr })?; 129 val.write(w) 130 } 131 SetControl => w.write_obj(virtio_video_set_control_resp { hdr }), 132 } 133 } 134 } 135