blob: 5ee74ff29de2af161b46fd0974f15759dfa82fa6 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Data structures for commands of virtio video devices.
use std::io;
use data_model::{Le32, Le64};
use crate::virtio::video::command::QueueType;
use crate::virtio::video::control::*;
use crate::virtio::video::error::VideoError;
use crate::virtio::video::format::*;
use crate::virtio::video::params::Params;
use crate::virtio::video::protocol::*;
use crate::virtio::Writer;
pub trait Response {
/// Writes an object to virtqueue.
fn write(&self, w: &mut Writer) -> Result<(), io::Error>;
}
#[derive(Debug)]
pub enum CmdError {
InvalidResourceId,
InvalidStreamId,
InvalidParameter,
InvalidOperation,
}
/// A response to a `VideoCmd`. These correspond to `VIRTIO_VIDEO_RESP_*`.
#[derive(Debug)]
pub enum CmdResponse {
NoData,
QueryCapability(Vec<FormatDesc>),
ResourceQueue {
timestamp: u64,
flags: u32,
size: u32,
},
GetParams {
queue_type: QueueType,
params: Params,
},
QueryControl(QueryCtrlResponse),
GetControl(CtrlVal),
// TODO(alexlau): SetControl is unused, remove this after encoder CL lands.
#[allow(dead_code)]
SetControl,
Error(CmdError),
}
impl From<VideoError> for CmdResponse {
fn from(error: VideoError) -> Self {
let cmd_error = match error {
VideoError::InvalidResourceId { .. } => CmdError::InvalidResourceId,
VideoError::InvalidStreamId(_) => CmdError::InvalidStreamId,
VideoError::InvalidParameter => CmdError::InvalidParameter,
_ => CmdError::InvalidOperation,
};
CmdResponse::Error(cmd_error)
}
}
impl Response for CmdResponse {
/// Writes a response to virtqueue.
fn write(&self, w: &mut Writer) -> Result<(), io::Error> {
use CmdResponse::*;
let type_ = Le32::from(match self {
NoData => VIRTIO_VIDEO_RESP_OK_NODATA,
QueryCapability(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CAPABILITY,
ResourceQueue { .. } => VIRTIO_VIDEO_RESP_OK_RESOURCE_QUEUE,
GetParams { .. } => VIRTIO_VIDEO_RESP_OK_GET_PARAMS,
QueryControl(_) => VIRTIO_VIDEO_RESP_OK_QUERY_CONTROL,
GetControl(_) => VIRTIO_VIDEO_RESP_OK_GET_CONTROL,
SetControl => VIRTIO_VIDEO_RESP_OK_NODATA,
Error(e) => {
match e {
// TODO(b/1518105): Add more detailed error code when a new protocol supports
// them.
CmdError::InvalidResourceId => VIRTIO_VIDEO_RESP_ERR_INVALID_RESOURCE_ID,
CmdError::InvalidStreamId => VIRTIO_VIDEO_RESP_ERR_INVALID_STREAM_ID,
CmdError::InvalidParameter => VIRTIO_VIDEO_RESP_ERR_INVALID_PARAMETER,
CmdError::InvalidOperation => VIRTIO_VIDEO_RESP_ERR_INVALID_OPERATION,
}
}
});
let hdr = virtio_video_cmd_hdr {
type_,
..Default::default()
};
match self {
NoData | Error(_) => w.write_obj(hdr),
QueryCapability(descs) => {
w.write_obj(virtio_video_query_capability_resp {
hdr,
num_descs: Le32::from(descs.len() as u32),
..Default::default()
})?;
descs.iter().map(|d| d.write(w)).collect()
}
ResourceQueue {
timestamp,
flags,
size,
} => w.write_obj(virtio_video_resource_queue_resp {
hdr,
timestamp: Le64::from(*timestamp),
flags: Le32::from(*flags),
size: Le32::from(*size),
}),
GetParams { queue_type, params } => {
let params = params.to_virtio_video_params(*queue_type);
w.write_obj(virtio_video_get_params_resp { hdr, params })
}
QueryControl(r) => {
w.write_obj(virtio_video_query_control_resp { hdr })?;
r.write(w)
}
GetControl(val) => {
w.write_obj(virtio_video_get_control_resp { hdr })?;
val.write(w)
}
SetControl => w.write_obj(virtio_video_set_control_resp { hdr }),
}
}
}