From 9f55367906dbf13492f4b05a5e678d70de14b0a9 Mon Sep 17 00:00:00 2001
From: Connor Wood <connorwood71@gmail.com>
Date: Tue, 29 Aug 2017 17:29:07 +0100
Subject: [PATCH] Implemented notification API

---
 src/acpi/aml/namedobj.rs    | 17 +++++++++++++----
 src/acpi/aml/namespace.rs   | 24 +++++++++++++++++++-----
 src/acpi/aml/type1opcode.rs | 28 +++++++++++++++++++++++++++-
 3 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs
index 1d2a8e5c..bd813a8e 100644
--- a/src/acpi/aml/namedobj.rs
+++ b/src/acpi/aml/namedobj.rs
@@ -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,
diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs
index 64f02abc..ca51fe54 100644
--- a/src/acpi/aml/namespace.rs
+++ b/src/acpi/aml/namespace.rs
@@ -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)
diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs
index 2ea0482b..18e43bdf 100644
--- a/src/acpi/aml/type1opcode.rs
+++ b/src/acpi/aml/type1opcode.rs
@@ -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
-- 
GitLab