| 
					
				 | 
			
			
				@@ -47,10 +47,14 @@ static EXT_RAM_ATTR struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     uint64_t wake_gpio, wake_level; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     uint64_t rtc_gpio, rtc_level; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     uint32_t delay; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} sleep_config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    float battery_level; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int battery_count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void (*idle_chain)(uint32_t now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void (*battery_chain)(float level, int cells); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void (*suspend[10])(void); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint32_t (*sleeper[10])(void);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} sleep_context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static EXT_RAM_ATTR void (*sleep_hooks[16])(void);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static const char *TAG = "services"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**************************************************************************************** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -102,6 +106,43 @@ static void sleep_gpio_handler(void *id, button_event_e event, button_press_e mo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void sleep_timer(uint32_t now) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    static uint32_t last; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // first chain the calls to psudo_idle function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.idle_chain) sleep_context.idle_chain(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // only query callbacks every 30s if we have at least one sleeper 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!*sleep_context.sleeper || now < last + 30*1000) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    last = now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // call all sleep hooks that might want to do something 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (uint32_t (**sleeper)(void) = sleep_context.sleeper; *sleeper; sleeper++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ((*sleeper)() < sleep_context.delay) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // if we are here, we are ready to sleep; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    services_sleep_activate(SLEEP_ONTIMER);    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void sleep_battery(float level, int cells) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // chain if any 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.battery_chain) sleep_context.battery_chain(level, cells); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // then assess if we have to stop because of low batt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (level < sleep_context.battery_level) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (sleep_context.battery_count++ == 2) services_sleep_activate(SLEEP_ONBATTERY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sleep_context.battery_count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -110,10 +151,20 @@ static void sleep_init(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     char *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // do we want delay sleep 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    PARSE_PARAM(config, "delay", '=', sleep_config.delay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    sleep_config.delay *= 60*1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (sleep_config.delay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ESP_LOGI(TAG, "Sleep inactivity of %d minute(s)", sleep_config.delay / (60*1000)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PARSE_PARAM(config, "delay", '=', sleep_context.delay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sleep_context.delay *= 60*1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.delay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sleep_context.idle_chain = pseudo_idle_svc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pseudo_idle_svc = sleep_timer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ESP_LOGI(TAG, "Sleep inactivity of %d minute(s)", sleep_context.delay / (60*1000)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // do we want battery safety 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PARSE_PARAM_FLOAT(config, "batt", '=', sleep_context.battery_level); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.battery_level != 0.0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sleep_context.battery_chain = battery_handler_svc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        battery_handler_svc = sleep_battery; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // get the wake criteria 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -126,15 +177,15 @@ static void sleep_init(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!rtc_gpio_is_valid_gpio(gpio)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 ESP_LOGE(TAG, "invalid wake GPIO %d (not in RTC domain)", gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                sleep_config.wake_gpio |= 1LL << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sleep_context.wake_gpio |= 1LL << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (sscanf(item, "%*[^:]:%d", &level)) sleep_config.wake_level |= level << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.wake_level |= level << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             p = strchr(p, '|'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (sleep_config.wake_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_config.wake_gpio, sleep_config.wake_level);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (sleep_context.wake_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -148,15 +199,15 @@ static void sleep_init(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!rtc_gpio_is_valid_gpio(gpio)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 ESP_LOGE(TAG, "invalid rtc GPIO %d", gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                sleep_config.rtc_gpio |= 1LL << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sleep_context.rtc_gpio |= 1LL << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (sscanf(item, "%*[^:]:%d", &level)) sleep_config.rtc_level |= level << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (sscanf(item, "%*[^:]:%d", &level)) sleep_context.rtc_level |= level << gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             p = strchr(p, '|'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (sleep_config.rtc_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_config.rtc_gpio, sleep_config.rtc_level);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (sleep_context.rtc_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -172,49 +223,40 @@ static void sleep_init(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void services_sleep_callback(uint32_t elapsed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (sleep_config.delay && elapsed >= sleep_config.delay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        services_sleep_activate(SLEEP_ONTIMER); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void services_sleep_activate(sleep_cause_e cause) {    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // call all sleep hooks that might want to do something 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (void (**hook)(void) = sleep_hooks; *hook; hook++) (*hook)(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) (*suspend)(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // isolate all possible GPIOs, except the wake-up and RTC-maintaines ones 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     esp_sleep_config_gpio_isolate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // keep RTC domain up if we need to maintain pull-up/down of some GPIO from RTC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (sleep_config.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (int i = 0; i < GPIO_NUM_MAX; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // must be a RTC GPIO 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!rtc_gpio_is_valid_gpio(i)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // do we need to maintain a pull-up or down of that GPIO 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if ((1LL << i) & sleep_config.rtc_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if ((sleep_config.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ((1LL << i) & sleep_context.rtc_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             else rtc_gpio_pulldown_en(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // or is this not wake-up GPIO, just isolate it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } else if (!((1LL << i) & sleep_config.wake_gpio)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if (!((1LL << i) & sleep_context.wake_gpio)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             rtc_gpio_isolate(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // is there just one GPIO 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (sleep_config.wake_gpio & (sleep_config.wake_gpio - 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_config.wake_gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        esp_sleep_enable_ext1_wakeup(sleep_config.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else if (sleep_config.wake_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        int gpio = __builtin_ctz(sleep_config.wake_gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        int level = (sleep_config.wake_level >> gpio) & 0x01; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_context.wake_gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (sleep_context.wake_gpio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int gpio = __builtin_ctz(sleep_context.wake_gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int level = (sleep_context.wake_level >> gpio) & 0x01; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         ESP_LOGI(TAG, "going to sleep cause %d, wake-up on GPIO %d level %d", cause, gpio, level); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         esp_sleep_enable_ext0_wakeup(gpio, level); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -226,18 +268,31 @@ void services_sleep_activate(sleep_cause_e cause) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else esp_deep_sleep_start(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void services_sleep_sethook(void (*hook)(void)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < sizeof(sleep_hooks)/sizeof(void(*)(void)); i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!sleep_hooks[i]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            sleep_hooks[i] = hook; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void register_method(void **store, size_t size, void *method) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < size; i++, *store++) if (!*store) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        *store = method; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void services_sleep_setsuspend(void (*hook)(void)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    register_method((void**) sleep_context.suspend, sizeof(sleep_context.suspend)/sizeof(*sleep_context.suspend), (void*) hook); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void services_sleep_setsleeper(uint32_t (*sleeper)(void)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    register_method((void**) sleep_context.sleeper, sizeof(sleep_context.sleeper)/sizeof(*sleep_context.sleeper), (void*) sleeper); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**************************************************************************************** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 |