- This is an experiment - project. It is about adding off-mode alarm clock to the HD2.
(If you don't have cLK installed (at least v1.5.1.4), then this is not applicable for you)
Quote:
Originally Posted by kokotas (Post 21158811)Is it even possible to include something like auto-power-on in cLK, for alarm clock purposes? :)
Quote:
Originally Posted by zicoxx (Post 33758859)i want to suggest a feature for clk and our hd2..offline alarms
- This project depends on 3 factors, (1)Kernel, (2)Android application, (3)Bootloader.
- Kernel
The kernel has a function in arch\arm\mach-msm\pm.c which handles the reboot reason:
Code:static int msm_reboot_call(struct notifier_block *this, unsigned long code, void *_cmd)
{
if((code == SYS_RESTART) && _cmd) {
char *cmd = _cmd;
if (!strcmp(cmd, "bootloader")) {
restart_reason = 0x77665500;
} else if (!strcmp(cmd, "recovery")) {
restart_reason = 0x77665502;
} else if (!strcmp(cmd, "eraseflash")) {
restart_reason = 0x776655EF;
} else if (!strncmp(cmd, "oem-", 4)) {
unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
restart_reason = 0x6f656d00 | code;
//This is the proposed patch to our kernel
//(thanks Rick_1995 for suggesting it to bypass the time limit of 255 min)
} else if (!strncmp(cmd, "S", 1)) {
unsigned code = simple_strtoul(cmd + 1, 0, 16) & 0x00ffffff;
restart_reason = 0x53000000 | code;
} else if (!strcmp(cmd, "force-hard")) {
restart_reason = 0x776655AA;
} else {
restart_reason = 0x77665501;
}
}
return NOTIFY_DONE;
}
- Application
The application is able to:- reboot the device using the PowerManager class since it is signed and placed in /system/app:
Code://MinutesToSuspend is set using a TimePicker
mPowerManager.reboot("oem-" + MinutesToSuspend);
//In case we have a kernel with the above patch included
mPowerManager.reboot("S" + MinutesToSuspend);
- play the alarm when the device has booted usind the BroadcastReceiver class that will get the BOOT_COMPLETED action.
- reboot the device using the PowerManager class since it is signed and placed in /system/app:
- Bootloader
The bootloader (in this case cLK):- detects the boot reason and decodes the MinutesToSuspend from it and enters a sort of suspend mode with a timeout equal to MinutesToSuspend converted to msec
Code:if(target_check_reboot_mode() == (target_check_reboot_mode() | 0x6f656d00)) {
char str[16];
char *endptr;
unsigned MinutesToSuspend;
unsigned msecToSuspend = 0;
// Decode the MinutesToSuspend from the reboot_mode
sprintf(str, "%i", (target_check_reboot_mode() ^ 0x6f656d00));
MinutesToSuspend = strtol(str, &endptr, 16);
if (MinutesToSuspend < 3)
msecToSuspend = (MinutesToSuspend * 60000);
else
msecToSuspend = (MinutesToSuspend * 60000) - (120000);
suspend_time = msecToSuspend;
show_multi_boot_screen = 0;
boot_into_recovery = 0;
}
//In case we have a kernel with the above patch included
#define MARK_ALARM_TAG 0x53000000
if(target_check_reboot_mode() & 0xFF000000 == MARK_ALARM_TAG) {
uint32_t MinutesToSuspend;
// Decode the MinutesToSuspend from the reboot_mode
MinutesToSuspend = target_check_reboot_mode() ^ MARK_ALARM_TAG;
if (MinutesToSuspend > 3)
MinutesToSuspend -= 2;
suspend_time = MinutesToSuspend * 60000;
show_multi_boot_screen = 0;
boot_into_recovery = 0;
}
if(suspend_time) {
msm_acpu_clock_init(1); // 384MHz (acpu_freq_tbl[0])
//Could try setting cpu clock at 245...
//msm_acpu_clock_init(0); // 245MHz (acpu_freq_tbl[0])
htcleo_suspend(suspend_time);
}
- the suspend mode is implemented using this function
Code:#define DS2746_SAFE_CHG_VOLTAGE 4200 // mV
void htcleo_suspend(unsigned timeout)
{
uint32_t voltage;
//int16_t current;
bool usb_cable_connected;
time_t start_time;
start_time = current_time();
if (timeout)
htcleo_panel_bkl_pwr(0);
do {
//current = ds2746_current(DS2746_I2C_SLAVE_ADDR, 1200);
voltage = ds2746_voltage(DS2746_I2C_SLAVE_ADDR);
usb_cable_connected = htcleo_usb_online();
if (usb_cable_connected) {
if (voltage < DS2746_SAFE_CHG_VOLTAGE) {
// If battery needs charging, set new charger state
if (htcleo_ac_online()) {
if (htcleo_charger_state() != CHG_AC ) {
writel(0x00080000, USB_USBCMD);
ulpi_write(0x48, 0x04);
htcleo_set_charger(CHG_AC);
}
} else {
if (htcleo_charger_state() != CHG_USB_LOW ) {
writel(0x00080001, USB_USBCMD);
mdelay(10);
htcleo_set_charger(CHG_USB_LOW);
}
}
// Led = solid amber
if (htcleo_notif_led_mode != 2)
thread_resume(thread_create("htcleo_notif_led_set_mode_2",
&htcleo_notif_led_set_mode,
(void *)2,
HIGH_PRIORITY,
DEFAULT_STACK_SIZE));
} else {
// Battery is full
if(timeout) {
// Set charger state to CHG_OFF_FULL_BAT
if (htcleo_charger_state() != CHG_OFF_FULL_BAT ) {
writel(0x00080001, USB_USBCMD);
mdelay(10);
htcleo_set_charger(CHG_OFF_FULL_BAT);
}
// and turn led solid green
if (htcleo_usb_online() && (htcleo_notif_led_mode != 1))
thread_resume(thread_create("htcleo_notif_led_set_mode_1",
&htcleo_notif_led_set_mode,
(void *)1,
HIGH_PRIORITY,
DEFAULT_STACK_SIZE));
} else {
// exit while if we don't have a timeout
break;
}
}
} else {
// Set charger state to CHG_OFF
if (htcleo_charger_state() != CHG_OFF ) {
writel(0x00080001, USB_USBCMD);
mdelay(10);
htcleo_set_charger(CHG_OFF);
}
// and turn off led
if (htcleo_notif_led_mode != 0)
thread_resume(thread_create("htcleo_notif_led_set_off",
&htcleo_notif_led_set_mode,
(void *)0,
HIGH_PRIORITY,
DEFAULT_STACK_SIZE));
}
// While in loop keep tracking if POWER button is pressed
// in order to (re)boot the device
for (int i=0; i<6; i++) {
if(keys_get_state(KEY_POWER)!=0) {
target_reboot(0);
return;//:)
}
mdelay(96);//total delay ~500ms per loop
}
// And check if timeout exceeded in order to reboot
if (timeout && (current_time() - start_time >= timeout))
target_reboot(0);
} while ( (usb_cable_connected) /* && current >= 0) */
||(timeout) ); // If we have a timeout this while-loop never breaks if we don't reboot.
// Double check voltage
mdelay(10);
voltage = ds2746_voltage(DS2746_I2C_SLAVE_ADDR);
if (voltage < DS2746_SAFE_CHG_VOLTAGE) {
// If battery is not full then
// EITHER the cable is unplugged
// OR the double check of voltage gave us
// a value less than the safe voltage.
// Set charger state to CHG_OFF
writel(0x00080001, USB_USBCMD);
mdelay(10);
htcleo_set_charger(CHG_OFF);
} else {
// If battery is full
// set charger state to CHG_OFF_FULL_BAT
writel(0x00080001, USB_USBCMD);
mdelay(10);
htcleo_set_charger(CHG_OFF_FULL_BAT);
// and turn led solid green
if (htcleo_usb_online() && (htcleo_notif_led_mode != 1))
thread_resume(thread_create("htcleo_notif_led_set_mode_1",
&htcleo_notif_led_set_mode,
(void *)1,
HIGH_PRIORITY,
DEFAULT_STACK_SIZE));
// While usb cable is connected
// keep tracking if POWER button is pressed OR timeout exceeded
// in order to (re)boot the device
while (htcleo_usb_online()) {
if(keys_get_state(KEY_POWER)!=0)
target_reboot(0);
/* if (timeout && (current_time() - start_time >= timeout))
break; */
}
}
// If we've set a timeout and reached it, reboot the device
/* if (timeout && (current_time() - start_time >= timeout))
target_reboot(0); */
// Shutdown the device
enter_critical_section();
platform_exit();
msm_proc_comm(PCOM_POWER_DOWN, 0, 0);
for (;;) ;
}
- detects the boot reason and decodes the MinutesToSuspend from it and enters a sort of suspend mode with a timeout equal to MinutesToSuspend converted to msec
- Kernel
- Any suggestions or observations are welcomed!
- This is open for everyone to use or contribute. Source is available at https://github.com/n0d3/HD2_Alarm_Clock
- If you have to ask for an apk to test, then you may download this example's apk from here.But don't consider this as an application release thread.
↧
[DEV][14/Nov/2012]HD2 off-mode Alarm Clock(cLK)[WIP]
↧