static int alarm_release(struct inode *inode, struct file *file) { int i; unsigned long flags; spin_lock_irqsave(&alarm_slock, flags); if (file->private_data) { for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { uint32_t alarm_type_mask = 1U << i; if (alarm_enabled & alarm_type_mask) { alarm_dbg(INFO, "%s: clear alarm, pending %d\n", __func__, !!(alarm_pending & alarm_type_mask)); alarm_enabled &= ~alarm_type_mask; } spin_unlock_irqrestore(&alarm_slock, flags); devalarm_cancel(&alarms[i]); spin_lock_irqsave(&alarm_slock, flags); } if (alarm_pending | wait_pending) { if (alarm_pending) alarm_dbg(INFO, "%s: clear pending alarms %x\n", __func__, alarm_pending); __pm_relax(&alarm_wake_lock); wait_pending = 0; alarm_pending = 0; } alarm_opened = 0; } spin_unlock_irqrestore(&alarm_slock, flags); return 0; }
static int alarm_set_rtc(struct timespec *ts) { struct rtc_time new_rtc_tm; struct rtc_device *rtc_dev; unsigned long 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) return rv; if (rtc_dev) rv = rtc_set_time(rtc_dev, &new_rtc_tm); spin_lock_irqsave(&alarm_slock, flags); alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; wake_up(&alarm_wait_queue); spin_unlock_irqrestore(&alarm_slock, flags); return rv; }
void alarm_set_power_on(struct timespec new_pwron_time, bool logo) { unsigned long pwron_time; struct rtc_wkalrm alm; struct rtc_device *alarm_rtc_dev; alarm_dbg(INFO, "alarm set power on\n"); #ifdef RTC_PWRON_SEC /* round down the second */ new_pwron_time.tv_sec = (new_pwron_time.tv_sec / 60) * 60; #endif if (new_pwron_time.tv_sec > 0) { pwron_time = new_pwron_time.tv_sec; #ifdef RTC_PWRON_SEC pwron_time += RTC_PWRON_SEC; #endif alm.enabled = (logo ? 3 : 2); } else { pwron_time = 0; alm.enabled = 4; } alarm_rtc_dev = alarmtimer_get_rtcdev(); rtc_time_to_tm(pwron_time, &alm.time); rtc_set_alarm(alarm_rtc_dev, &alm); rtc_set_alarm_poweron(alarm_rtc_dev, &alm); }
static int alarm_wait(void) { unsigned long flags; int rv = 0; spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm wait\n"); if (!alarm_pending && wait_pending) { __pm_relax(&alarm_wake_lock); wait_pending = 0; } spin_unlock_irqrestore(&alarm_slock, flags); rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); if (rv) return rv; spin_lock_irqsave(&alarm_slock, flags); rv = alarm_pending; wait_pending = 1; alarm_pending = 0; spin_unlock_irqrestore(&alarm_slock, flags); return rv; }
static void alarm_clear(enum android_alarm_type alarm_type, struct timespec *ts) { uint32_t alarm_type_mask = 1U << alarm_type; unsigned long 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; if (!alarm_pending && !wait_pending) __pm_relax(&alarm_wake_lock); } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); }
static void alarm_clear(enum android_alarm_type alarm_type) { uint32_t alarm_type_mask = 1U << alarm_type; unsigned long flags; #ifdef CONFIG_BCM_RTC_ALARM_BOOT if (alarm_type == ANDROID_ALARM_RTC_POWERON) alarm_poweron_cancel(); #endif spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm %d clear\n", alarm_type); #ifdef CONFIG_BCM_RTC_ALARM_BOOT if (alarm_type != ANDROID_ALARM_RTC_POWERON) devalarm_try_to_cancel(&alarms[alarm_type]); #else devalarm_try_to_cancel(&alarms[alarm_type]); #endif /*CONFIG_BCM_RTC_ALARM_BOOT*/ if (alarm_pending) { alarm_pending &= ~alarm_type_mask; if (!alarm_pending && !wait_pending) __pm_relax(&alarm_wake_lock); } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); }
static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) { struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); alarm_dbg(INT, "devalarm_hrthandler\n"); devalarm_triggered(devalrm); return HRTIMER_NORESTART; }
static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, ktime_t now) { struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); alarm_dbg(INT, "devalarm_alarmhandler\n"); devalarm_triggered(devalrm); return ALARMTIMER_NORESTART; }
static ssize_t alarm_sysfs_store_rtc_local_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int retval; retval = sscanf(buf, " %d ", &rtc_local_time); if (retval != 1) { alarm_dbg(INFO, "Failed to store rtc local time.\n"); return -EINVAL; } return retval ? retval : count; }
static void alarm_set(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 set %ld.%09ld\n", alarm_type, ts->tv_sec, ts->tv_nsec); alarm_enabled |= alarm_type_mask; devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); spin_unlock_irqrestore(&alarm_slock, flags); }
static void devalarm_triggered(struct devalarm *alarm) { unsigned long flags; uint32_t alarm_type_mask = 1U << alarm->type; alarm_dbg(INT, "devalarm_triggered type %d\n", alarm->type); spin_lock_irqsave(&alarm_slock, flags); if (alarm_enabled & alarm_type_mask) { wake_lock_timeout(&alarm_wake_lock, 5 * HZ); alarm_enabled &= ~alarm_type_mask; alarm_pending |= alarm_type_mask; wake_up(&alarm_wait_queue); } spin_unlock_irqrestore(&alarm_slock, flags); }
static void devalarm_triggered(struct devalarm *alarm) { unsigned long flags; uint32_t alarm_type_mask = 1U << alarm->type; alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); spin_lock_irqsave(&alarm_slock, flags); if (alarm_enabled & alarm_type_mask) { __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ alarm_enabled &= ~alarm_type_mask; alarm_pending |= alarm_type_mask; wake_up(&alarm_wait_queue); } spin_unlock_irqrestore(&alarm_slock, flags); }
static void alarm_set(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 set %ld.%09ld\n", alarm_type, ts->tv_sec, ts->tv_nsec); alarm_enabled |= alarm_type_mask; devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); spin_unlock_irqrestore(&alarm_slock, flags); if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) set_power_on_alarm(ts->tv_sec, 1); }
static void alarm_clear(enum android_alarm_type alarm_type) { 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); devalarm_try_to_cancel(&alarms[alarm_type]); if (alarm_pending) { alarm_pending &= ~alarm_type_mask; if (!alarm_pending && !wait_pending) __pm_relax(&alarm_wake_lock); } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); }
static void alarm_clear(enum android_alarm_type alarm_type, struct timespec *ts) { uint32_t alarm_type_mask = 1U << alarm_type; unsigned long flags; mutex_lock(&alarm_mutex); spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm %d clear\n", alarm_type); devalarm_try_to_cancel(&alarms[alarm_type]); if (alarm_pending) { alarm_pending &= ~alarm_type_mask; if (!alarm_pending && !wait_pending) __pm_relax(&alarm_wake_lock); } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) set_power_on_alarm(ts->tv_sec, 0); mutex_unlock(&alarm_mutex); }
static void alarm_set(enum android_alarm_type alarm_type, struct timespec *ts) { uint32_t alarm_type_mask = 1U << alarm_type; unsigned long flags; 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); }
static int alarm_wait(void) { unsigned long flags; int rv = 0; spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm wait\n"); if (!alarm_pending && wait_pending) { __pm_relax(&alarm_wake_lock); wait_pending = 0; } spin_unlock_irqrestore(&alarm_slock, flags); rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); if (rv) return rv; spin_lock_irqsave(&alarm_slock, flags); //AndyPan add #ifdef LENOVO_ALARM if (alarm_pending & pwoff_mask) { printk("andy alarm_pending &= ~ pwoff_mask =%d \r\n",alarm_pending); alarm_pending &= ~ pwoff_mask; alarm_pending |= deviceup_mask; printk("andy alarm_pending |= deviceup_mask =%d \r\n",alarm_pending); } //AndyPan add #endif rv = alarm_pending; wait_pending = 1; alarm_pending = 0; spin_unlock_irqrestore(&alarm_slock, flags); return rv; }
static void alarm_set(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 set %ld.%09ld\n", alarm_type, ts->tv_sec, ts->tv_nsec); alarm_enabled |= alarm_type_mask; #ifdef CONFIG_BCM_RTC_ALARM_BOOT if (alarm_type != ANDROID_ALARM_RTC_POWERON) devalarm_start(&alarms[alarm_type], timespec_to_ktime(new_alarm_time)); #else devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); #endif /*CONFIG_BCM_RTC_ALARM_BOOT*/ spin_unlock_irqrestore(&alarm_slock, flags); #ifdef CONFIG_BCM_RTC_ALARM_BOOT if (alarm_type == ANDROID_ALARM_RTC_POWERON) alarm_poweron_set_alarm(new_alarm_time); #endif }
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rv = 0; unsigned long flags; struct timespec new_alarm_time; struct timespec new_rtc_time; struct timespec tmp_time; struct rtc_time new_rtc_tm; struct rtc_device *rtc_dev; enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); uint32_t alarm_type_mask = 1U << alarm_type; if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) return -EINVAL; if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { if ((file->f_flags & O_ACCMODE) == O_RDONLY) return -EPERM; if (file->private_data == NULL && cmd != ANDROID_ALARM_SET_RTC) { spin_lock_irqsave(&alarm_slock, flags); if (alarm_opened) { spin_unlock_irqrestore(&alarm_slock, flags); return -EBUSY; } alarm_opened = 1; file->private_data = (void *)1; spin_unlock_irqrestore(&alarm_slock, flags); } } switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_CLEAR(0): spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm %d clear\n", alarm_type); devalarm_try_to_cancel(&alarms[alarm_type]); if (alarm_pending) { alarm_pending &= ~alarm_type_mask; if (!alarm_pending && !wait_pending) __pm_relax(&alarm_wake_lock); } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); break; case ANDROID_ALARM_SET_OLD: case ANDROID_ALARM_SET_AND_WAIT_OLD: if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { rv = -EFAULT; goto err1; } new_alarm_time.tv_nsec = 0; goto from_old_alarm_set; case ANDROID_ALARM_SET_AND_WAIT(0): case ANDROID_ALARM_SET(0): if (copy_from_user(&new_alarm_time, (void __user *)arg, sizeof(new_alarm_time))) { rv = -EFAULT; goto err1; } from_old_alarm_set: spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm %d set %ld.%09ld\n", alarm_type, new_alarm_time.tv_sec, new_alarm_time.tv_nsec); alarm_enabled |= alarm_type_mask; devalarm_start(&alarms[alarm_type], timespec_to_ktime(new_alarm_time)); spin_unlock_irqrestore(&alarm_slock, flags); if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) break; /* fall though */ case ANDROID_ALARM_WAIT: spin_lock_irqsave(&alarm_slock, flags); alarm_dbg(IO, "alarm wait\n"); if (!alarm_pending && wait_pending) { __pm_relax(&alarm_wake_lock); wait_pending = 0; } spin_unlock_irqrestore(&alarm_slock, flags); rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); if (rv) goto err1; spin_lock_irqsave(&alarm_slock, flags); rv = alarm_pending; wait_pending = 1; alarm_pending = 0; spin_unlock_irqrestore(&alarm_slock, flags); break; case ANDROID_ALARM_SET_RTC: if (copy_from_user(&new_rtc_time, (void __user *)arg, sizeof(new_rtc_time))) { rv = -EFAULT; goto err1; } rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm); rtc_dev = alarmtimer_get_rtcdev(); rv = do_settimeofday(&new_rtc_time); if (rv < 0) goto err1; if (rtc_dev) rv = rtc_set_time(rtc_dev, &new_rtc_tm); spin_lock_irqsave(&alarm_slock, flags); alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; wake_up(&alarm_wait_queue); spin_unlock_irqrestore(&alarm_slock, flags); if (rv < 0) goto err1; break; case ANDROID_ALARM_GET_TIME(0): switch (alarm_type) { case ANDROID_ALARM_RTC_WAKEUP: case ANDROID_ALARM_RTC: getnstimeofday(&tmp_time); break; case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: case ANDROID_ALARM_ELAPSED_REALTIME: get_monotonic_boottime(&tmp_time); break; case ANDROID_ALARM_SYSTEMTIME: ktime_get_ts(&tmp_time); break; default: rv = -EINVAL; goto err1; } if (copy_to_user((void __user *)arg, &tmp_time, sizeof(tmp_time))) { rv = -EFAULT; goto err1; } break; default: rv = -EINVAL; } err1: return rv; }
static long alarm_do_ioctl(struct file *file, unsigned int cmd, 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); alarm_dbg(INFO, "alarm_do_ioctl cmd:%d type:%d (%lu)\n", cmd, alarm_type, (uintptr_t)file->private_data); 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) && 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 && cmd != ANDROID_ALARM_SET_RTC) { spin_lock_irqsave(&alarm_slock, flags); if (alarm_opened) { spin_unlock_irqrestore(&alarm_slock, flags); alarm_dbg(INFO, "alarm_do_ioctl EBUSY\n"); file->private_data = NULL; return -EBUSY; } alarm_opened = 1; file->private_data = (void *)1; spin_unlock_irqrestore(&alarm_slock, flags); alarm_dbg(INFO, "alarm_do_ioctl opened\n"); } } switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_CLEAR(0): alarm_clear(alarm_type, ts); break; case ANDROID_ALARM_SET(0): alarm_set(alarm_type, ts); break; case ANDROID_ALARM_SET_AND_WAIT(0): alarm_set(alarm_type, ts); /* fall though */ 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; } return rv; }
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; }