Implemented notification API

This commit is contained in:
Connor Wood
2017-08-29 17:29:07 +01:00
parent d23241d800
commit 9f55367906
3 changed files with 59 additions and 10 deletions

View File

@@ -1,10 +1,12 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::btree_map::BTreeMap;
use super::AmlError;
use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState };
use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string,
Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion};
Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion,
Device, ThermalZone};
use super::namestring::{parse_name_string, parse_name_seg};
use super::termlist::{parse_term_arg, parse_object_list};
use super::pkglength::parse_pkg_length;
@@ -428,7 +430,10 @@ fn parse_def_device(data: &[u8],
parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?;
ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone()))?;
ctx.add_to_namespace(local_scope_string, AmlValue::Device(Device {
obj_list: local_ctx.namespace_delta.clone(),
notify_methods: BTreeMap::new()
}))?;
Ok(AmlParseType {
val: AmlValue::None,
@@ -893,7 +898,8 @@ fn parse_def_processor(data: &[u8],
ctx.add_to_namespace(local_scope_string, AmlValue::Processor(Processor {
proc_id: proc_id,
p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None },
obj_list: local_ctx.namespace_delta.clone()
obj_list: local_ctx.namespace_delta.clone(),
notify_methods: BTreeMap::new()
}))?;
Ok(AmlParseType {
@@ -922,7 +928,10 @@ fn parse_def_thermal_zone(data: &[u8],
let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone());
parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?;
ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone()))?;
ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(ThermalZone {
obj_list: local_ctx.namespace_delta.clone(),
notify_methods: BTreeMap::new()
}))?;
Ok(AmlParseType {
val: AmlValue::None,

View File

@@ -2,6 +2,7 @@ use alloc::boxed::Box;
use collections::string::String;
use collections::string::ToString;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use core::fmt::{Debug, Formatter, Error};
use core::str::FromStr;
@@ -57,11 +58,24 @@ pub struct FieldUnit {
pub length: usize
}
#[derive(Clone)]
pub struct Device {
pub obj_list: Vec<String>,
pub notify_methods: BTreeMap<u8, Vec<fn()>>
}
#[derive(Clone)]
pub struct ThermalZone {
pub obj_list: Vec<String>,
pub notify_methods: BTreeMap<u8, Vec<fn()>>
}
#[derive(Clone)]
pub struct Processor {
pub proc_id: u8,
pub p_blk: Option<u32>,
pub obj_list: Vec<String>
pub obj_list: Vec<String>,
pub notify_methods: BTreeMap<u8, Vec<fn()>>
}
#[derive(Clone)]
@@ -103,7 +117,7 @@ pub enum AmlValue {
BufferField(BufferField),
DDBHandle(Vec<String>),
DebugObject,
Device(Vec<String>),
Device(Device),
Event(u64),
FieldUnit(FieldUnit),
Integer(u64),
@@ -117,7 +131,7 @@ pub enum AmlValue {
PowerResource(PowerResource),
Processor(Processor),
RawDataBuffer(Vec<u8>),
ThermalZone(Vec<String>)
ThermalZone(ThermalZone)
}
impl Debug for AmlValue {
@@ -246,7 +260,7 @@ impl AmlValue {
}
}
pub fn get_as_device(&self) -> Result<Vec<String>, AmlError> {
pub fn get_as_device(&self) -> Result<Device, AmlError> {
match *self {
AmlValue::Device(ref s) => Ok(s.clone()),
_ => Err(AmlError::AmlValueError)
@@ -397,7 +411,7 @@ impl AmlValue {
}
}
pub fn get_as_thermal_zone(&self) -> Result<Vec<String>, AmlError> {
pub fn get_as_thermal_zone(&self) -> Result<ThermalZone, AmlError> {
match *self {
AmlValue::ThermalZone(ref p) => Ok(p.clone()),
_ => Err(AmlError::AmlValueError)

View File

@@ -177,12 +177,38 @@ fn parse_def_notify(data: &[u8],
})
}
// TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6
parser_opcode!(data, 0x86);
let object = parse_super_name(&data[1..], ctx)?;
let value = parse_term_arg(&data[1 + object.len..], ctx)?;
let number = value.val.get_as_integer()? as u8;
match ctx.get(object.val)? {
AmlValue::Device(d) => {
if let Some(methods) = d.notify_methods.get(&number) {
for method in methods {
method();
}
}
},
AmlValue::Processor(d) => {
if let Some(methods) = d.notify_methods.get(&number) {
for method in methods {
method();
}
}
},
AmlValue::ThermalZone(d) => {
if let Some(methods) = d.notify_methods.get(&number) {
for method in methods {
method();
}
}
},
_ => return Err(AmlError::AmlValueError)
}
Ok(AmlParseType {
val: AmlValue::None,
len: 1 + object.len + value.len