diff options
Diffstat (limited to 'drivers/pps/pps.c')
-rw-r--r-- | drivers/pps/pps.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index 9e15cf1da946..2baadd21b7a6 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c @@ -33,6 +33,8 @@ #include <linux/pps_kernel.h> #include <linux/slab.h> +#include "kc.h" + /* * Local variables */ @@ -198,9 +200,43 @@ static long pps_cdev_ioctl(struct file *file, break; } + case PPS_KC_BIND: { + struct pps_bind_args bind_args; + + dev_dbg(pps->dev, "PPS_KC_BIND\n"); + + /* Check the capabilities */ + if (!capable(CAP_SYS_TIME)) + return -EPERM; + + if (copy_from_user(&bind_args, uarg, + sizeof(struct pps_bind_args))) + return -EFAULT; + + /* Check for supported capabilities */ + if ((bind_args.edge & ~pps->info.mode) != 0) { + dev_err(pps->dev, "unsupported capabilities (%x)\n", + bind_args.edge); + return -EINVAL; + } + + /* Validate parameters roughly */ + if (bind_args.tsformat != PPS_TSFMT_TSPEC || + (bind_args.edge & ~PPS_CAPTUREBOTH) != 0 || + bind_args.consumer != PPS_KC_HARDPPS) { + dev_err(pps->dev, "invalid kernel consumer bind" + " parameters (%x)\n", bind_args.edge); + return -EINVAL; + } + + err = pps_kc_bind(pps, &bind_args); + if (err < 0) + return err; + + break; + } default: return -ENOTTY; - break; } return 0; |