#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL /* * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling
*/ staticvoid rtc_uie_task(struct work_struct *work)
{ struct rtc_device *rtc =
container_of(work, struct rtc_device, uie_task); struct rtc_time tm; int num = 0; int err;
if (count != sizeof(unsignedint) && count < sizeof(unsignedlong)) return -EINVAL;
add_wait_queue(&rtc->irq_queue, &wait); do {
__set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irq(&rtc->irq_lock);
data = rtc->irq_data;
rtc->irq_data = 0;
spin_unlock_irq(&rtc->irq_lock);
if (data != 0) {
ret = 0; break;
} if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN; break;
} if (signal_pending(current)) {
ret = -ERESTARTSYS; break;
}
schedule();
} while (1);
set_current_state(TASK_RUNNING);
remove_wait_queue(&rtc->irq_queue, &wait);
if (ret == 0) { if (sizeof(int) != sizeof(long) &&
count == sizeof(unsignedint))
ret = put_user(data, (unsignedint __user *)buf) ?: sizeof(unsignedint); else
ret = put_user(data, (unsignedlong __user *)buf) ?: sizeof(unsignedlong);
} return ret;
}
err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err;
/* check that the calling task has appropriate permissions * for certain ioctls. doing this check here is useful * to avoid duplicate code in each driver.
*/ switch (cmd) { case RTC_EPOCH_SET: case RTC_SET_TIME: case RTC_PARAM_SET: if (!capable(CAP_SYS_TIME))
err = -EACCES; break;
case RTC_IRQP_SET: if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
err = -EACCES; break;
case RTC_PIE_ON: if (rtc->irq_freq > rtc->max_user_freq &&
!capable(CAP_SYS_RESOURCE))
err = -EACCES; break;
}
if (err) goto done;
/* * Drivers *SHOULD NOT* provide ioctl implementations * for these requests. Instead, provide methods to * support the following code, so that the RTC's main * features are accessible without using ioctls. * * RTC and alarm times will be in UTC, by preference, * but dual-booting with MS-Windows implies RTCs must * use the local wall clock time.
*/
switch (cmd) { case RTC_ALM_READ:
mutex_unlock(&rtc->ops_lock);
err = rtc_read_alarm(rtc, &alarm); if (err < 0) return err;
if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
err = -EFAULT; return err;
case RTC_ALM_SET:
mutex_unlock(&rtc->ops_lock);
if (copy_from_user(&alarm.time, uarg, sizeof(tm))) return -EFAULT;
/* RTC_ALM_SET alarms may be up to 24 hours in the future. * Rather than expecting every RTC to implement "don't care" * for day/month/year fields, just force the alarm to have * the right values for those fields. * * RTC_WKALM_SET should be used instead. Not only does it * eliminate the need for a separate RTC_AIE_ON call, it * doesn't have the "alarm 23:59:59 in the future" race. * * NOTE: some legacy code may have used invalid fields as * wildcards, exposing hardware "periodic alarm" capabilities. * Not supported here.
*/
{
time64_t now, then;
err = rtc_read_time(rtc, &tm); if (err < 0) return err;
now = rtc_tm_to_time64(&tm);
/* We shut down the repeating IRQs that userspace enabled, * since nothing is listening to them. * - Update (UIE) ... currently only managed through ioctls * - Periodic (PIE) ... also used through rtc_*() interface calls * * Leave the alarm alone; it may be set to trigger a system wakeup * later, or be used by kernel code, and is a one-shot event anyway.
*/
/* Keep ioctl until all drivers are converted */
rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
rtc_update_irq_enable(rtc, 0);
rtc_irq_set_state(rtc, 0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.