diff --git a/src/i2c/src/i2c.rs b/src/i2c/src/i2c.rs index 6622b68..47baa4c 100644 --- a/src/i2c/src/i2c.rs +++ b/src/i2c/src/i2c.rs @@ -11,6 +11,8 @@ use std::os::unix::io::AsRawFd; use libc::{c_ulong, ioctl, EINVAL}; use vmm_sys_util::errno::{errno_result, Error, Result}; +use super::AdapterConfig; + // The type of the `req` parameter is different for the `musl` library. This will enable // successful build for other non-musl libraries. #[cfg(target_env = "musl")] @@ -231,12 +233,6 @@ pub struct I2cReq { pub buf: Vec, } -pub struct I2cAdapter { - device: D, - adapter_no: u32, - smbus: bool, -} - /// Trait that represents an I2C Device. /// /// This trait is introduced for development purposes only, and should not @@ -295,6 +291,12 @@ impl I2cDevice for PhysDevice { } } +pub struct I2cAdapter { + device: D, + adapter_no: u32, + smbus: bool, +} + impl I2cAdapter { // Creates a new adapter corresponding to the specified number. fn new(adapter_no: u32) -> Result> { @@ -425,68 +427,6 @@ pub struct I2cMap { device_map: [u32; MAX_I2C_VDEV], } -#[derive(Debug, PartialEq)] -pub(crate) struct DeviceConfig { - adapter_no: u32, - addr: Vec, -} - -impl DeviceConfig { - pub fn new(adapter_no: u32) -> Self { - DeviceConfig { - adapter_no, - addr: Vec::new(), - } - } - - pub fn push(&mut self, addr: u16) -> std::result::Result<(), String> { - if addr as usize > MAX_I2C_VDEV { - return Err(format!("Invalid address: {} (> maximum allowed)", addr)); - } - - if self.addr.contains(&addr) { - return Err(format!("Address already in use: {}", addr)); - } - - self.addr.push(addr); - Ok(()) - } -} - -#[derive(Debug, PartialEq)] -pub(crate) struct AdapterConfig { - inner: Vec, -} - -impl AdapterConfig { - pub fn new() -> Self { - Self { inner: Vec::new() } - } - - fn contains_adapter_no(&self, adapter_no: u32) -> bool { - self.inner.iter().any(|elem| elem.adapter_no == adapter_no) - } - - fn contains_addr(&self, addr: u16) -> bool { - self.inner.iter().any(|elem| elem.addr.contains(&addr)) - } - - pub fn push(&mut self, device: DeviceConfig) -> std::result::Result<(), String> { - if self.contains_adapter_no(device.adapter_no) { - return Err("Duplicated adapter number".to_string()); - } - - for addr in device.addr.iter() { - if self.contains_addr(*addr) { - return Err(format!("Address already in use: {}", addr)); - } - } - - self.inner.push(device); - Ok(()) - } -} - impl I2cMap { pub(crate) fn new(device_config: &AdapterConfig) -> Result where @@ -529,7 +469,7 @@ impl I2cMap { return Err(Error::new(EINVAL)); } - // get the corresponding adapter based on teh device config. + // get the corresponding adapter based on the device config. let adapter = &self.adapters[index as usize]; // Set device's address @@ -543,18 +483,6 @@ pub mod tests { use super::*; use std::convert::TryFrom; - impl DeviceConfig { - pub fn new_with(adapter_no: u32, addr: Vec) -> Self { - DeviceConfig { adapter_no, addr } - } - } - - impl AdapterConfig { - pub fn new_with(devices: Vec) -> Self { - AdapterConfig { inner: devices } - } - } - #[derive(Debug, Default)] pub struct DummyDevice { funcs_result: i32, diff --git a/src/i2c/src/main.rs b/src/i2c/src/main.rs index 0f1079a..b5d1bf7 100644 --- a/src/i2c/src/main.rs +++ b/src/i2c/src/main.rs @@ -17,15 +17,69 @@ use vhost::{vhost_user, vhost_user::Listener}; use vhost_user_backend::VhostUserDaemon; use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap}; -use crate::i2c::DeviceConfig; -use i2c::{AdapterConfig, I2cDevice, I2cMap, PhysDevice}; +use i2c::{I2cDevice, I2cMap, PhysDevice, MAX_I2C_VDEV}; use vhu_i2c::VhostUserI2cBackend; -#[derive(PartialEq, Debug)] -struct I2cConfiguration { - socket_path: String, - socket_count: usize, - devices: AdapterConfig, +#[derive(Debug, PartialEq)] +struct DeviceConfig { + adapter_no: u32, + addr: Vec, +} + +impl DeviceConfig { + fn new(adapter_no: u32) -> Self { + DeviceConfig { + adapter_no, + addr: Vec::new(), + } + } + + fn push(&mut self, addr: u16) -> std::result::Result<(), String> { + if addr as usize > MAX_I2C_VDEV { + return Err(format!("Invalid address: {} (> maximum allowed)", addr)); + } + + if self.addr.contains(&addr) { + return Err(format!("Address already in use: {}", addr)); + } + + self.addr.push(addr); + Ok(()) + } +} + +#[derive(Debug, PartialEq)] +pub(crate) struct AdapterConfig { + inner: Vec, +} + +impl AdapterConfig { + fn new() -> Self { + Self { inner: Vec::new() } + } + + fn contains_adapter_no(&self, adapter_no: u32) -> bool { + self.inner.iter().any(|elem| elem.adapter_no == adapter_no) + } + + fn contains_addr(&self, addr: u16) -> bool { + self.inner.iter().any(|elem| elem.addr.contains(&addr)) + } + + fn push(&mut self, device: DeviceConfig) -> std::result::Result<(), String> { + if self.contains_adapter_no(device.adapter_no) { + return Err("Duplicated adapter number".to_string()); + } + + for addr in device.addr.iter() { + if self.contains_addr(*addr) { + return Err(format!("Address already in use: {}", addr)); + } + } + + self.inner.push(device); + Ok(()) + } } impl TryFrom<&str> for AdapterConfig { @@ -53,6 +107,13 @@ impl TryFrom<&str> for AdapterConfig { } } +#[derive(PartialEq, Debug)] +struct I2cConfiguration { + socket_path: String, + socket_count: usize, + devices: AdapterConfig, +} + impl TryFrom for I2cConfiguration { type Error = String; @@ -153,6 +214,18 @@ fn main() -> Result<(), String> { mod tests { use super::*; + impl DeviceConfig { + pub fn new_with(adapter_no: u32, addr: Vec) -> Self { + DeviceConfig { adapter_no, addr } + } + } + + impl AdapterConfig { + pub fn new_with(devices: Vec) -> Self { + AdapterConfig { inner: devices } + } + } + fn get_cmd_args(name: &str, devices: &str, count: u32) -> ArgMatches { let yaml = load_yaml!("cli.yaml"); let app = App::from(yaml); diff --git a/src/i2c/src/vhu_i2c.rs b/src/i2c/src/vhu_i2c.rs index 798f59f..14e8540 100644 --- a/src/i2c/src/vhu_i2c.rs +++ b/src/i2c/src/vhu_i2c.rs @@ -5,10 +5,10 @@ // // SPDX-License-Identifier: Apache-2.0 -use crate::i2c::*; use std::mem::size_of; use std::sync::Arc; use std::{convert, error, fmt, io}; + use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; use vhost_user_backend::{VhostUserBackendMut, VringRwLock, VringT}; use virtio_bindings::bindings::virtio_net::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1}; @@ -18,6 +18,8 @@ use virtio_bindings::bindings::virtio_ring::{ use vm_memory::{ByteValued, Bytes, GuestMemoryAtomic, GuestMemoryMmap, Le16, Le32}; use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK}; +use crate::i2c::*; + const QUEUE_SIZE: usize = 1024; const NUM_QUEUES: usize = 1; @@ -306,6 +308,7 @@ impl VhostUserBackendMut mod tests { use super::*; use crate::i2c::tests::DummyDevice; + use crate::AdapterConfig; use std::convert::TryFrom; #[test]