mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-26 14:41:23 +00:00
scmi: sensor axis extended attributes support
For Android requirment, virtio-scmi axis descriptor should support extended attributes. This patch does this things. We get axis's resolution during reading "scale" and store. When agent wants to get axis descriptions, device will add resolution value to extend attribute field. At the same time, max and min range also have been configured. Signed-off-by: Junnan Wu <junnan01.wu@samsung.com>
This commit is contained in:
parent
d19a265bed
commit
53ded3f04d
@ -3,6 +3,8 @@
|
||||
|
||||
### Added
|
||||
|
||||
- [[#798]](https://github.com/rust-vmm/vhost-device/pull/798) scmi: extended sensor attributes support
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -359,6 +359,11 @@ pub trait SensorT: Send {
|
||||
0
|
||||
}
|
||||
|
||||
/// Returns the resolution of the sensor scale.
|
||||
fn resolution(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
/// Returns the prefix of axes names.
|
||||
///
|
||||
/// Usually no need to redefine this.
|
||||
@ -383,8 +388,10 @@ pub trait SensorT: Send {
|
||||
/// Usually no need to redefine this.
|
||||
fn axis_description(&self, axis: u32) -> Vec<MessageValue> {
|
||||
let mut values = vec![];
|
||||
let axis_exponent = self.unit_exponent(0);
|
||||
let axis_resolution = self.resolution();
|
||||
values.push(MessageValue::Unsigned(axis)); // axis id
|
||||
values.push(MessageValue::Unsigned(0)); // attributes low
|
||||
values.push(MessageValue::Unsigned(1 << 8)); // attributes low (Extended attributes support)
|
||||
values.push(MessageValue::Unsigned(self.format_unit(axis))); // attributes high
|
||||
|
||||
// Name in the recommended format, 16 bytes:
|
||||
@ -394,6 +401,22 @@ pub trait SensorT: Send {
|
||||
format!("{prefix}_{suffix}"),
|
||||
MAX_SIMPLE_STRING_LENGTH,
|
||||
));
|
||||
|
||||
// Extended attribute
|
||||
values.push(MessageValue::Unsigned(
|
||||
axis_resolution | ((axis_exponent as u32) << 27),
|
||||
)); //resolution
|
||||
|
||||
// In SCMI spec, it specifies that if the sensor does not report the min and max range,
|
||||
// the following field should be as as:
|
||||
// axis_min_range_low 0x0
|
||||
// axis_min_range_high 0x80000000
|
||||
// axis_max_range_low 0xFFFFFFFF
|
||||
// axis_max_range_high 0x7FFFFFFF
|
||||
values.push(MessageValue::Signed(0)); // min_range_low
|
||||
values.push(MessageValue::Signed(i32::MIN)); // min_range_high
|
||||
values.push(MessageValue::Signed(-1i32)); // max_range_low
|
||||
values.push(MessageValue::Signed(i32::MAX)); // max_range_high
|
||||
values
|
||||
}
|
||||
|
||||
|
||||
@ -255,6 +255,10 @@ struct Axis {
|
||||
/// sufficiently accurate SCMI value that is represented by an integer (not
|
||||
/// a float) + decadic exponent.
|
||||
custom_exponent: i8,
|
||||
/// This is an extended attribute field. It reports the resolution of the sensor axis.
|
||||
/// The representation is in [custom_resolution] x 10^[custom_exponent] format.
|
||||
/// This field is present only if Bit[8] of axis_attributes_low is set to 1.
|
||||
custom_resolution: u64,
|
||||
/// Channel scan type, necessary if the sensor supports notifications.
|
||||
/// The data from /dev/iio:deviceX will be formatted according to this.
|
||||
/// The ChanScanType is parsed from "scan_elements/<channel>_type"
|
||||
@ -262,7 +266,7 @@ struct Axis {
|
||||
}
|
||||
|
||||
impl Axis {
|
||||
fn new(path: OsString, unit_exponent: i8, custom_exponent: i8) -> Axis {
|
||||
fn new(path: OsString, unit_exponent: i8, custom_exponent: i8, custom_resolution: u64) -> Axis {
|
||||
let scan_path = Path::new(&path).parent().unwrap().join("scan_elements");
|
||||
let mut scan_name = path.clone();
|
||||
scan_name.push("_type");
|
||||
@ -273,6 +277,7 @@ impl Axis {
|
||||
path,
|
||||
unit_exponent,
|
||||
custom_exponent,
|
||||
custom_resolution,
|
||||
scan_type: ChanScanType::new(scan_type),
|
||||
}
|
||||
} else {
|
||||
@ -280,6 +285,7 @@ impl Axis {
|
||||
path,
|
||||
unit_exponent,
|
||||
custom_exponent,
|
||||
custom_resolution,
|
||||
scan_type: None,
|
||||
}
|
||||
}
|
||||
@ -371,6 +377,13 @@ impl SensorT for IIOSensor {
|
||||
axis.unit_exponent + axis.custom_exponent
|
||||
}
|
||||
|
||||
fn resolution(&self) -> u32 {
|
||||
// All the axes are supposed to have the same value for resolution.
|
||||
// We are just using the values from the Axis 0 here.
|
||||
let axis: &Axis = self.axes.first().unwrap();
|
||||
axis.custom_resolution as u32
|
||||
}
|
||||
|
||||
fn number_of_axes(&self) -> u32 {
|
||||
if self.scalar {
|
||||
0
|
||||
@ -579,14 +592,23 @@ impl IIOSensor {
|
||||
}
|
||||
}
|
||||
|
||||
fn custom_exponent(&self, path: &OsStr, unit_exponent: i8) -> i8 {
|
||||
// This function gets both custom exponent and resolution by reading "scale"
|
||||
// A scale value should be parsed as "[resolution]e[exponent]"
|
||||
fn custom_exponent_and_resolution(&self, path: &OsStr, unit_exponent: i8) -> (i8, u64) {
|
||||
let mut custom_exponent: i8 = 0;
|
||||
let mut custom_resolution: u64 = 0;
|
||||
if let Ok(Some(scale)) = self.read_axis_scale(path) {
|
||||
// Crash completely OK if *this* doesn't fit:
|
||||
custom_exponent = scale.log10() as i8;
|
||||
if scale < 1.0 {
|
||||
// The logarithm is truncated towards zero, we need floor
|
||||
custom_exponent -= 1;
|
||||
// Calculate the resolution of scale
|
||||
custom_resolution =
|
||||
(scale * 10i32.pow(-custom_exponent as u32) as f64).trunc() as u64;
|
||||
} else {
|
||||
custom_resolution =
|
||||
(scale / 10i32.pow(custom_exponent as u32) as f64).trunc() as u64;
|
||||
}
|
||||
// The SCMI exponent (unit_exponent + custom_exponent) can have max. 5 bits:
|
||||
custom_exponent = min(15 - unit_exponent, custom_exponent);
|
||||
@ -596,7 +618,7 @@ impl IIOSensor {
|
||||
&path, custom_exponent
|
||||
);
|
||||
}
|
||||
custom_exponent
|
||||
(custom_exponent, custom_resolution)
|
||||
}
|
||||
|
||||
fn add_axis(&mut self, axes: &mut Vec<Axis>, path: &OsStr) {
|
||||
@ -606,11 +628,13 @@ impl IIOSensor {
|
||||
.map_or(0, |mapping| mapping.unit_exponent);
|
||||
// To get meaningful integer values, we must adjust exponent to
|
||||
// the provided scale if any.
|
||||
let custom_exponent = self.custom_exponent(path, unit_exponent);
|
||||
let (custom_exponent, custom_resolution) =
|
||||
self.custom_exponent_and_resolution(path, unit_exponent);
|
||||
axes.push(Axis::new(
|
||||
OsString::from(path),
|
||||
unit_exponent,
|
||||
custom_exponent,
|
||||
custom_resolution,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@ -1384,9 +1384,15 @@ mod tests {
|
||||
let name = format!("acc_{}", char::from_u32('X' as u32 + axis_index).unwrap()).to_string();
|
||||
let mut description = vec![
|
||||
MessageValue::Unsigned(axis_index),
|
||||
MessageValue::Unsigned(0),
|
||||
MessageValue::Unsigned(1 << 8),
|
||||
MessageValue::Unsigned(u32::from(SENSOR_UNIT_METERS_PER_SECOND_SQUARED)),
|
||||
MessageValue::String(name, MAX_SIMPLE_STRING_LENGTH),
|
||||
// Add extended attributes
|
||||
MessageValue::Unsigned(0),
|
||||
MessageValue::Signed(0),
|
||||
MessageValue::Signed(i32::MIN),
|
||||
MessageValue::Signed(-1i32),
|
||||
MessageValue::Signed(i32::MAX),
|
||||
];
|
||||
result.append(&mut description);
|
||||
test_message(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user