static int gen_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct rtc_time wtime; struct rtc_pll_info pll; switch (cmd) { case RTC_PLL_GET: if (get_rtc_pll(&pll)) return -EINVAL; else return copy_to_user((void *)arg, &pll, sizeof pll) ? -EFAULT : 0; case RTC_PLL_SET: if (!capable(CAP_SYS_TIME)) return -EACCES; if (copy_from_user(&pll, (struct rtc_pll_info*)arg, sizeof(pll))) return -EFAULT; return set_rtc_pll(&pll); case RTC_UIE_OFF: /* disable ints from RTC updates. */ gen_clear_rtc_irq_bit(RTC_UIE); return 0; case RTC_UIE_ON: /* enable ints for RTC updates. */ return gen_set_rtc_irq_bit(RTC_UIE); case RTC_RD_TIME: /* Read the time/date from RTC */ /* this doesn't get week-day, who cares */ memset(&wtime, 0, sizeof(wtime)); get_rtc_time(&wtime); return copy_to_user((void *)arg, &wtime, sizeof(wtime)) ? -EFAULT : 0; case RTC_SET_TIME: /* Set the RTC */ { int year; unsigned char leap_yr; if (!capable(CAP_SYS_TIME)) return -EACCES; if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(wtime))) return -EFAULT; year = wtime.tm_year + 1900; leap_yr = ((!(year % 4) && (year % 100)) || !(year % 400)); if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1)) return -EINVAL; if (wtime.tm_mday < 0 || wtime.tm_mday > (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr))) return -EINVAL; if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || wtime.tm_min < 0 || wtime.tm_min >= 60 || wtime.tm_sec < 0 || wtime.tm_sec >= 60) return -EINVAL; return set_rtc_time(&wtime); } } return -EINVAL; }
static int gen_rtc_proc_output(char *buf) { char *p; struct rtc_time tm; unsigned int flags; struct rtc_pll_info pll; p = buf; flags = get_rtc_time(&tm); p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n" "rtc_epoch\t: %04u\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900); tm.tm_hour = tm.tm_min = tm.tm_sec = 0; p += sprintf(p, "alarm\t\t: "); if (tm.tm_hour <= 24) p += sprintf(p, "%02d:", tm.tm_hour); else p += sprintf(p, "**:"); if (tm.tm_min <= 59) p += sprintf(p, "%02d:", tm.tm_min); else p += sprintf(p, "**:"); if (tm.tm_sec <= 59) p += sprintf(p, "%02d\n", tm.tm_sec); else p += sprintf(p, "**\n"); p += sprintf(p, "DST_enable\t: %s\n" "BCD\t\t: %s\n" "24hr\t\t: %s\n" "square_wave\t: %s\n" "alarm_IRQ\t: %s\n" "update_IRQ\t: %s\n" "periodic_IRQ\t: %s\n" "periodic_freq\t: %ld\n" "batt_status\t: %s\n", (flags & RTC_DST_EN) ? "yes" : "no", (flags & RTC_DM_BINARY) ? "no" : "yes", (flags & RTC_24H) ? "yes" : "no", (flags & RTC_SQWE) ? "yes" : "no", (flags & RTC_AIE) ? "yes" : "no", irq_active ? "yes" : "no", (flags & RTC_PIE) ? "yes" : "no", 0L /* freq */, (flags & RTC_BATT_BAD) ? "bad" : "okay"); if (!get_rtc_pll(&pll)) p += sprintf(p, "PLL adjustment\t: %d\n" "PLL max +ve adjustment\t: %d\n" "PLL max -ve adjustment\t: %d\n" "PLL +ve adjustment factor\t: %d\n" "PLL -ve adjustment factor\t: %d\n" "PLL frequency\t: %ld\n", pll.pll_value, pll.pll_max, pll.pll_min, pll.pll_posmult, pll.pll_negmult, pll.pll_clock); return p - buf; }
static int gen_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct rtc_time wtime; struct rtc_pll_info pll; void __user *argp = (void __user *)arg; switch (cmd) { #ifdef CONFIG_REALTEK_VENUS case RTC_ALM_READ: /* Read the present alarm time */ { /* * This returns a struct rtc_time. Reading >= 0xc0 * means "don't care" or "match all". Only the tm_hour, * tm_min, and tm_sec values are filled in. */ memset(&wtime, 0, sizeof(wtime)); get_rtc_alarm_time(&wtime); return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; } case RTC_ALM_SET: /* Store a time into the alarm */ { int year; unsigned char leap_yr; if (copy_from_user(&wtime, argp, sizeof(wtime))) return -EFAULT; year = wtime.tm_year + 1900; leap_yr = ((!(year % 4) && (year % 100)) || !(year % 400)); if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1)) return -EINVAL; if (wtime.tm_mday < 0 || wtime.tm_mday > (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr))) return -EINVAL; if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || wtime.tm_min < 0 || wtime.tm_min >= 60 || wtime.tm_sec < 0 || wtime.tm_sec >= 60) return -EINVAL; return set_rtc_alarm_time(&wtime); } #endif case RTC_PLL_GET: if (get_rtc_pll(&pll)) return -EINVAL; else return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0; case RTC_PLL_SET: if (!capable(CAP_SYS_TIME)) return -EACCES; if (copy_from_user(&pll, argp, sizeof(pll))) return -EFAULT; return set_rtc_pll(&pll); case RTC_UIE_OFF: /* disable ints from RTC updates. */ gen_clear_rtc_irq_bit(RTC_UIE); return 0; case RTC_UIE_ON: /* enable ints for RTC updates. */ return gen_set_rtc_irq_bit(RTC_UIE); case RTC_RD_TIME: /* Read the time/date from RTC */ /* this doesn't get week-day, who cares */ memset(&wtime, 0, sizeof(wtime)); get_rtc_time(&wtime); return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; case RTC_SET_TIME: /* Set the RTC */ { int year; unsigned char leap_yr; if (!capable(CAP_SYS_TIME)) return -EACCES; if (copy_from_user(&wtime, argp, sizeof(wtime))) return -EFAULT; year = wtime.tm_year + 1900; leap_yr = ((!(year % 4) && (year % 100)) || !(year % 400)); if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1)) return -EINVAL; if (wtime.tm_mday < 0 || wtime.tm_mday > (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr))) return -EINVAL; if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || wtime.tm_min < 0 || wtime.tm_min >= 60 || wtime.tm_sec < 0 || wtime.tm_sec >= 60) return -EINVAL; return set_rtc_time(&wtime); } } return -EINVAL; }