- 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)
Is it even possible to include something like auto-power-on in cLK, for alarm clock purposes?
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; [COLOR="YellowGreen"] //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; [/COLOR] } 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); [COLOR="YellowGreen"] //In case we have a kernel with the above patch included mPowerManager.reboot("S" + MinutesToSuspend);[/COLOR]
- 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; } [COLOR="YellowGreen"] //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; } [/COLOR] 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.
Attachments
Last edited: