+
+\subsection{Device ID}\label{sec:Device Types / Sound Device /
Device ID}
+
+25
+
+\subsection{Virtqueues}\label{sec:Device Types / Sound Device /
Virtqueues}
+
+\begin{description}
+\item[0] controlq
+\item[1] pcmq
+\end{description}
+
+The controlq virtqueue always exists, the pcmq virtqueue only exists
if
+the VIRTIO_SND_F_PCM_OUTPUT and/or VIRTIO_SND_F_PCM_INPUT feature is
negotiated.
+
+\subsection{Feature bits}\label{sec:Device Types / Sound Device /
Feature bits}
+
+\begin{description}
+\item[VIRTIO_SND_F_PCM_OUTPUT (0)] Output PCM stream support.
+\item[VIRTIO_SND_F_PCM_INPUT (1)] Input PCM stream support.
+\end{description}
+
+\subsection{Device configuration layout}\label{sec:Device Types /
Sound Device / Device configuration layout}
+
+\begin{lstlisting}
+/* supported PCM sample formats */
+enum {
+ VIRTIO_SND_PCM_FMT_S8 = 0,
+ VIRTIO_SND_PCM_FMT_U8,
+ VIRTIO_SND_PCM_FMT_S16,
+ VIRTIO_SND_PCM_FMT_U16,
+ VIRTIO_SND_PCM_FMT_S32,
+ VIRTIO_SND_PCM_FMT_U32,
+ VIRTIO_SND_PCM_FMT_FLOAT,
+ VIRTIO_SND_PCM_FMT_FLOAT64
+};
+
+/* supported PCM frame rates */
+enum {
+ VIRTIO_SND_PCM_RATE_8000 = 0,
+ VIRTIO_SND_PCM_RATE_11025,
+ VIRTIO_SND_PCM_RATE_16000,
+ VIRTIO_SND_PCM_RATE_22050,
+ VIRTIO_SND_PCM_RATE_32000,
+ VIRTIO_SND_PCM_RATE_44100,
+ VIRTIO_SND_PCM_RATE_48000,
+ VIRTIO_SND_PCM_RATE_64000,
+ VIRTIO_SND_PCM_RATE_88200,
+ VIRTIO_SND_PCM_RATE_96000,
+ VIRTIO_SND_PCM_RATE_176400,
+ VIRTIO_SND_PCM_RATE_192000
+};
+
+/* a PCM stream configuration */
+struct virtio_pcm_stream_config {
+ u8 channels_min;
+ u8 channels_max;
+ le16 formats; /* 1 << VIRTIO_SND_PCM_FMT_XXX */
+ le16 rates; /* 1 << VIRTIO_SND_PCM_RATE_XXX */
+ u16 padding;
+};
Should this be packed ? Btw, padding alignment is to a non 32bit size ?
What about buffer/period formats e.g interleaved ?
+
+/* a device configuration space */
+struct virtio_snd_config {
+ struct virtio_pcm_config {
+ struct virtio_pcm_stream_config output;
+ struct virtio_pcm_stream_config input;
+ } pcm;
+};
+\end{lstlisting}
I assuming this is sent to configure PCM capabilities ? What about
buffer and period size capabilities ?
+
+\subsubsection{Device configuration fields}
+
+The \field{pcm.output} and \field{pcm.input} fields contain PCM
stream
+configuration:
+
+\begin{description}
+\item[\field{channels_min}] (driver-read-only) is a minimum number
of supported
+channels.
+\item[\field{channels_max}] (driver-read-only) is a maximum number
of supported
+channels.
+\item[\field{formats}] (driver-read-only) is supported sample format
bit map.
+\item[\field{rates}] (driver-read-only) is supported frame rate bit
map.
+\end{description}
+
+\subsection{Device Initialization}
+
+\begin{enumerate}
+\item If the VIRTIO_SND_F_PCM_OUTPUT feature is negotiated,
\field{pcm.output}
+contains valid output PCM stream configuration.
+\item If the VIRTIO_SND_F_PCM_INPUT feature is negotiated,
\field{pcm.input}
+contains valid input PCM stream configuration.
+\end{enumerate}
+
+\devicenormative{\subsubsection}{Device Initialization}{Device Types
/ Sound Device / Device Initialization}
+
+\begin{enumerate}
+\item The device MUST NOT set the not defined format and rate bits.
+\item The device MUST initialize padding bytes
\field{pcm.output.padding} and
+\field{pcm.input.padding} to 0.
+\end{enumerate}
+
+\drivernormative{\subsubsection}{Device Initialization}{Device Types
/ Sound Device / Device Initialization}
+
+\begin{enumerate}
+\item The driver MUST configure and initialize all virtqueues.
+\item The driver SHOULD ignore the not defined format and rate bits.
+\end{enumerate}
+
+\subsection{Device Operation}\label{sec:Device Types / Sound Device
/ Device Operation}
+
+All control messages are placed into the controlq virtqueue and use
the following
+layout structure and definitions:
+
+\begin{lstlisting}
+enum {
+ /* PCM control request types */
+ VIRTIO_SND_R_PCM_CHMAP_INFO = 0,
+ VIRTIO_SND_R_PCM_SET_FORMAT,
+ VIRTIO_SND_R_PCM_PREPARE,
+ VIRTIO_SND_R_PCM_START,
+ VIRTIO_SND_R_PCM_STOP,
+ VIRTIO_SND_R_PCM_PAUSE,
+ VIRTIO_SND_R_PCM_UNPAUSE,
+
+ /* generic status codes */
+ VIRTIO_SND_S_OK = 0x8000,
+ VIRTIO_SND_S_BAD_MSG,
+ VIRTIO_SND_S_NOT_SUPP,
+ VIRTIO_SND_S_IO_ERR
+};
+
+struct virtio_snd_ctl_msg {
+ /* device-read-only data */
+ le32 request_code;
+ u8 request_payload[];
How do I know how much data to read here ? Is size embedded in
request_code ?
+ /* device-writable data */
+ le32 response_status;
+ u8 response_payload[];
+};
+\end{lstlisting}
+
+A generic control message consists of request and response parts and
contains
+the following fields:
+
+\begin{description}
+\item[\field{request_code}] (device-read-only) specifies a device
request code
+(VIRTIO_SND_R_*).
+\item[\field{request_payload}] (device-read-only) contains request-
specific
+data.
+\item[\field{response_status}] (device-writable) specifies a device
response
+status (VIRTIO_SND_S_*).
+\item[\field{response_payload}] (device-writable) contains response-
specific
+data.
+\end{description}
+
+Unless stated otherwise, the \field{request_payload} and
\field{response_payload}
+fields are empty.
+
+The \field{response_status} field contains one of the following
values:
+
+\begin{itemize*}
+\item VIRTIO_SND_S_OK: success.
+\item VIRTIO_SND_S_BAD_MSG: a control message is malformed or
contains invalid
+parameters.
+\item VIRTIO_SND_S_NOT_SUPP: requested operation or parameters are
not supported.
+\item VIRTIO_SND_S_IO_ERR: an I/O error occurred.
+\end{itemize*}
+
+\subsubsection{Device Operation: PCM control requests}
+
+A PCM stream has the following command lifecycle:
+
+\begin{enumerate}
+\item Set format
+\item Prepare
+\item Output only: transfer data for prebuffing
+\item Start
+\item Transfer data to/from the PCM device
+\begin{enumerate}
+ \item Pause
+ \item Unpause
+\end{enumerate}
+\item Stop
+\end{enumerate}
+
+PCM control requests have or consist of a fixed header with the
following
+layout structure:
+
+\begin{lstlisting}
+/* supported PCM stream types */
+enum {
+ VIRTIO_SND_PCM_T_OUTPUT = 0,
+ VIRTIO_SND_PCM_T_INPUT
Can we rename these PLAYBACK and CAPTURE
+};
+
+/* PCM control request header */
+struct virtio_snd_pcm_hdr {
+ le32 code;
+ le32 stream;
+};
+\end{lstlisting}
+
+PCM control request fields:
+
+\begin{description}
+\item[\field{code}] (device-read-only) specifies a PCM device
request code
+(VIRTIO_SND_R_PCM_*).
+\item[\field{stream}] (device-read-only) specifies a PCM stream type
+(VIRTIO_SND_PCM_T_*).
+\end{description}
+
+\begin{description}
+
+\item[VIRTIO_SND_R_PCM_CHMAP_INFO]
+Query a PCM channel map information for specified stream type.
+
+A response uses the following layout structure and definitions:
+
+\begin{lstlisting}
+/* standard channel position definition */
+enum {
+ VIRTIO_SND_PCM_CH_NONE = 0, /* undefined */
+ VIRTIO_SND_PCM_CH_NA, /* silent */
+ VIRTIO_SND_PCM_CH_MONO, /* mono stream */
+ VIRTIO_SND_PCM_CH_FL, /* front left */
+ VIRTIO_SND_PCM_CH_FR, /* front right */
+ VIRTIO_SND_PCM_CH_RL, /* rear left */
+ VIRTIO_SND_PCM_CH_RR, /* rear right */
+ VIRTIO_SND_PCM_CH_FC, /* front center */
+ VIRTIO_SND_PCM_CH_LFE, /* low frequency (LFE) */
+ VIRTIO_SND_PCM_CH_SL, /* side left */
+ VIRTIO_SND_PCM_CH_SR, /* side right */
+ VIRTIO_SND_PCM_CH_RC, /* rear center */
+ VIRTIO_SND_PCM_CH_FLC, /* front left center */
+ VIRTIO_SND_PCM_CH_FRC, /* front right center */
+ VIRTIO_SND_PCM_CH_RLC, /* rear left center */
+ VIRTIO_SND_PCM_CH_RRC, /* rear right center */
+ VIRTIO_SND_PCM_CH_FLW, /* front left wide */
+ VIRTIO_SND_PCM_CH_FRW, /* front right wide */
+ VIRTIO_SND_PCM_CH_FLH, /* front left high */
+ VIRTIO_SND_PCM_CH_FCH, /* front center high */
+ VIRTIO_SND_PCM_CH_FRH, /* front right high */
+ VIRTIO_SND_PCM_CH_TC, /* top center */
+ VIRTIO_SND_PCM_CH_TFL, /* top front left */
+ VIRTIO_SND_PCM_CH_TFR, /* top front right */
+ VIRTIO_SND_PCM_CH_TFC, /* top front center */
+ VIRTIO_SND_PCM_CH_TRL, /* top rear left */
+ VIRTIO_SND_PCM_CH_TRR, /* top rear right */
+ VIRTIO_SND_PCM_CH_TRC, /* top rear center */
+ VIRTIO_SND_PCM_CH_TFLC, /* top front left center */
+ VIRTIO_SND_PCM_CH_TFRC, /* top front right center */
+ VIRTIO_SND_PCM_CH_TSL, /* top side left */
+ VIRTIO_SND_PCM_CH_TSR, /* top side right */
+ VIRTIO_SND_PCM_CH_LLFE, /* left LFE */
+ VIRTIO_SND_PCM_CH_RLFE, /* right LFE */
+ VIRTIO_SND_PCM_CH_BC, /* bottom center */
+ VIRTIO_SND_PCM_CH_BLC, /* bottom left center */
+ VIRTIO_SND_PCM_CH_BRC /* bottom right center */
+};
+
+/* a maximum possible number of channels */
+#define VIRTIO_SND_PCM_CH_MAX 256
+
+/* response containing a PCM channel map information */
+struct virtio_snd_pcm_chmap_info {
+ le32 status;
+ le32 npositions;
+ u8 positions[VIRTIO_SND_PCM_CH_MAX];
+};
+\end{lstlisting}
+
+PCM channel map information fields:
+
+\begin{description}
+\item[\field{status}] (device-writable) specifies a device response
status
+(VIRTIO_SND_S_*).
+\item[\field{npositions}] (device-writable) is a number of valid
entries in
+the \field{positions} array.
+\item[\field{positions}] (device-writable) contains PCM channel
positions
+(VIRTIO_SND_PCM_CH_*).
+\end{description}
+
+\item[VIRTIO_SND_R_PCM_SET_FORMAT]
+Set selected PCM format.
+
+\begin{lstlisting}
+struct virtio_snd_pcm_set_format {
+ struct virtio_snd_pcm_hdr hdr;
+ le16 channels;
+ le16 format;
+ le16 rate;
+ u16 padding;
+};
+\end{lstlisting}
+
+PCM control request fields:
+
+\begin{description}
+\item[\field{hdr}] (device-read-only) is a PCM control request
header.
+\item[\field{channels}] (device-read-only) specifies a desired
number of channels.
+\item[\field{format}] (device-read-only) specifies a desired PCM
sample format
+(VIRTIO_SND_PCM_FMT_*).
+\item[\field{rate}] (device-read-only) specifies a desired PCM frame
rate
+(VIRTIO_SND_PCM_RATE_*).
+\end{description}
+
+\item[VIRTIO_SND_R_PCM_PREPARE]
+Prepare the PCM device.
+
+\item[VIRTIO_SND_R_PCM_START]
+Start the PCM device.
+
+\item[VIRTIO_SND_R_PCM_STOP]
+Stop the PCM device.
+
+\item[VIRTIO_SND_R_PCM_PAUSE]
+Set the PCM device on pause.
+
+\item[VIRTIO_SND_R_PCM_UNPAUSE]
+Unset the PCM device from pause.
+
+\end{description}
+
+\devicenormative{\subsubsection}{PCM control requests}{Device Types
/ Sound Device / PCM control requests}
+
+In a VIRTIO_SND_R_PCM_CHMAP_INFO request:
+
+\begin{itemize*}
+\item the device MUST return the VIRTIO_SND_S_NOT_SUPP status code,
if it does not
+support a channel map for a specified stream type;
+\item the device MUST set the \field{npositions} field to 0, if the
operation
+failed.
+\end{itemize*}
+
+\drivernormative{\subsubsection}{PCM control requests}{Device Types
/ Sound Device / PCM control requests}
+
+The driver MUST NOT specify VIRTIO_SND_PCM_T_OUTPUT as a stream type
if
+the VIRTIO_SND_F_PCM_OUTPUT feature is not negotiated.
+
+The driver MUST NOT specify VIRTIO_SND_PCM_T_INPUT as a stream type
if
+the VIRTIO_SND_F_PCM_INPUT feature is not negotiated.
+
+In a VIRTIO_SND_R_PCM_SET_FORMAT request:
+
+\begin{itemize*}
+\item the driver MUST NOT specify the \field{channels} value less
than the \field{channels_min}
+or greater than the \field{channels_max} values reported in stream
configuration;
+\item the driver MUST specify the \field{format} and \field{rate}
values according
+to the \field{formats} and \field{rates} values reported in stream
configuration;
+\item the driver MUST NOT specify the not defined format and rate
values;
+\item the driver MUST initialize \field{padding} bytes to 0.
+\end{itemize*}
+
+\subsubsection{Device Operation: PCM I/O requests}
+
+All I/O requests are placed into the pcmq virtqueue. Each request is
of form:
+
+\begin{lstlisting}
+struct virtio_snd_pcm_xfer {
+ le32 stream;
+ u8 data[];
+ le32 status;
+ le32 actual_length;