*
*/
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/time.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/alarmtimer.h>
#include "android_alarm.h"
+#include <linux/xlog.h>
+#include <linux/ioctl.h>
+#define LOG_MYTAG "Power/Alarm"
#define ANDROID_ALARM_PRINT_INFO (1U << 0)
#define ANDROID_ALARM_PRINT_IO (1U << 1)
static int debug_mask = ANDROID_ALARM_PRINT_INFO;
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
-#define alarm_dbg(debug_level_mask, fmt, ...) \
+#define alarm_dbg(debug_level_mask, fmt, args...) \
do { \
if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \
- pr_info(fmt, ##__VA_ARGS__); \
+ xlog_printk(ANDROID_LOG_INFO, LOG_MYTAG, fmt, ##args); \
} while (0)
#define ANDROID_ALARM_WAKEUP_MASK ( \
hrtimer_cancel(&alrm->u.hrt);
}
-static void alarm_clear(enum android_alarm_type alarm_type)
+static void alarm_clear(enum android_alarm_type alarm_type,
+ struct timespec *ts)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
-
- spin_lock_irqsave(&alarm_slock, flags);
+
+
alarm_dbg(IO, "alarm %d clear\n", alarm_type);
+ if (alarm_type == ANDROID_ALARM_POWER_ON ||
+ alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
+ ts->tv_sec = 0;
+ alarm_set_power_on(*ts, false);
+ return;
+ }
+ spin_lock_irqsave(&alarm_slock, flags);
devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) {
alarm_pending &= ~alarm_type_mask;
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
- spin_lock_irqsave(&alarm_slock, flags);
- alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
+ alarm_dbg(INFO, "alarm %d set %ld.%09ld\n",
alarm_type, ts->tv_sec, ts->tv_nsec);
+ if (alarm_type == ANDROID_ALARM_POWER_ON) {
+ alarm_set_power_on(*ts, false);
+ return;
+ }
+ if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
+ alarm_set_power_on(*ts, true);
+ return;
+ }
+
+ spin_lock_irqsave(&alarm_slock, flags);
alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
spin_unlock_irqrestore(&alarm_slock, flags);
int rv = 0;
rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
+ alarm_dbg(INFO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
+ ts->tv_sec, ts->tv_nsec,
+ new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
+ new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
+ new_rtc_tm.tm_mday,
+ new_rtc_tm.tm_year + 1900);
rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(ts);
if (rv < 0)
case ANDROID_ALARM_SYSTEMTIME:
ktime_get_ts(ts);
break;
+ case ANDROID_ALARM_POWER_ON:
+ case ANDROID_ALARM_POWER_ON_LOGO:
+ break;
default:
rv = -EINVAL;
}
}
static long alarm_do_ioctl(struct file *file, unsigned int cmd,
- struct timespec *ts)
+ struct timespec *ts, struct rtc_wkalrm *alm)
{
int rv = 0;
unsigned long flags;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
- if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
+ if (alarm_type >= ANDROID_ALARM_TYPE_COUNT &&
+ alarm_type != ANDROID_ALARM_POWER_ON &&
+ alarm_type != ANDROID_ALARM_POWER_ON_LOGO) {
return -EINVAL;
-
- if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
+ }
+ if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)
+ && ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_IPO(0)
+ && ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_POWER_ON_IPO) {
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
return -EPERM;
if (file->private_data == NULL &&
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_CLEAR(0):
- alarm_clear(alarm_type);
+ alarm_clear(alarm_type, ts);
break;
case ANDROID_ALARM_SET(0):
alarm_set(alarm_type, ts);
case ANDROID_ALARM_WAIT:
rv = alarm_wait();
break;
+ case ANDROID_ALARM_SET_IPO(0):
+ alarm_set(alarm_type, ts);
+ break;
+ case ANDROID_ALARM_SET_AND_WAIT_IPO(0):
+ alarm_set(alarm_type, ts);
+ /* fall though */
+ case ANDROID_ALARM_WAIT_IPO:
+ rv = alarm_wait();
+ break;
case ANDROID_ALARM_SET_RTC:
rv = alarm_set_rtc(ts);
break;
case ANDROID_ALARM_GET_TIME(0):
rv = alarm_get_time(alarm_type, ts);
break;
-
+ case ANDROID_ALARM_GET_POWER_ON:
+ alarm_get_power_on(alm);
+ break;
+ case ANDROID_ALARM_GET_POWER_ON_IPO:
+ alarm_get_power_on(alm);
+ break;
+
default:
rv = -EINVAL;
}
{
struct timespec ts;
+ struct rtc_wkalrm pwron_alm;
+
int rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_SET_AND_WAIT(0):
case ANDROID_ALARM_SET(0):
case ANDROID_ALARM_SET_RTC:
+ case ANDROID_ALARM_SET_IPO(0):
if (copy_from_user(&ts, (void __user *)arg, sizeof(ts)))
return -EFAULT;
break;
}
- rv = alarm_do_ioctl(file, cmd, &ts);
+ rv = alarm_do_ioctl(file, cmd, &ts, &pwron_alm);
if (rv)
return rv;
if (copy_to_user((void __user *)arg, &ts, sizeof(ts)))
return -EFAULT;
break;
+ case ANDROID_ALARM_GET_POWER_ON:
+ case ANDROID_ALARM_GET_POWER_ON_IPO:
+ if (copy_to_user((void __user *)arg, &pwron_alm,
+ sizeof(struct rtc_wkalrm))) {
+ rv = -EFAULT;
+ return rv;
+ }
+ break;
+ default :
+ break;
}
return 0;
{
struct timespec ts;
+ struct rtc_wkalrm pwron_alm;
int rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0):
case ANDROID_ALARM_SET_COMPAT(0):
case ANDROID_ALARM_SET_RTC_COMPAT:
+ case ANDROID_ALARM_SET_IPO_COMPAT(0):
if (compat_get_timespec(&ts, (void __user *)arg))
return -EFAULT;
/* fall through */
break;
}
- rv = alarm_do_ioctl(file, cmd, &ts);
+ rv = alarm_do_ioctl(file, cmd, &ts, &pwron_alm);
if (rv)
return rv;
if (compat_put_timespec(&ts, (void __user *)arg))
return -EFAULT;
break;
- }
+
+ case ANDROID_ALARM_GET_POWER_ON:
+ case ANDROID_ALARM_GET_POWER_ON_IPO:
+ if (copy_to_user((void __user *)arg, &pwron_alm,
+ sizeof(struct rtc_wkalrm))) {
+ rv = -EFAULT;
+ return rv;
+ }
+ break;
+ }
return 0;
}
#endif
static int alarm_open(struct inode *inode, struct file *file)
{
file->private_data = NULL;
+ alarm_dbg(INFO, "alarm_open (%d:%d)\n", current->tgid, current->pid);
return 0;
}
alarm_opened = 0;
}
spin_unlock_irqrestore(&alarm_slock, flags);
+ alarm_dbg(INFO, "alarm_release (%d:%d)(%lu)\n",
+ current->tgid, current->pid, (uintptr_t)file->private_data);
return 0;
}
{
struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
+ alarm_dbg(INT, "devalarm_hrthandler\n");
devalarm_triggered(devalrm);
return HRTIMER_NORESTART;
}
{
struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
+ alarm_dbg(INT, "devalarm_alarmhandler\n");
devalarm_triggered(devalrm);
return ALARMTIMER_NORESTART;
}