diff options
Diffstat (limited to 'surface.c')
-rw-r--r-- | surface.c | 76 |
1 files changed, 75 insertions, 1 deletions
@@ -1,8 +1,82 @@ +#include <linux/anon_inodes.h> +#include <linux/file.h> #include <linux/fs.h> #include "surface.h" -int new_surface(struct doomdev_ioctl_create_surface *params) +long surface_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { return -1; } + +ssize_t surface_read(struct file *filp, char __user *buf, size_t count, + loff_t *offset) +{ + return -1; +} + +loff_t surface_llseek(struct file *filp, loff_t offset, int origin) +{ + return -1; +} + +struct file_operations surface_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = surface_ioctl, + .compat_ioctl = surface_ioctl, + .llseek = surface_llseek, + .read = surface_read +}; + +int verify_params(struct doomdev_ioctl_create_surface *params) +{ + if (params->width < 64) { + printk(KERN_DEBUG "Surface width too small\n"); + return -EINVAL; + } + + if (params->width > 2048) { + printk(KERN_DEBUG "Surface width too large\n"); + return -EOVERFLOW; + } + + if (params->width % 64 != 0) { + printk(KERN_DEBUG "Surface width not a multiple of 64\n"); + return -EINVAL; + } + + if (params->height < 1) { + printk(KERN_DEBUG "Surface height too small\n"); + return -EINVAL; + } + + if (params->height > 2048) { + printk(KERN_DEBUG "Surface height too large\n"); + return -EOVERFLOW; + } + + return 0; +} + +int new_surface(struct doomdev_ioctl_create_surface *params) +{ + int err; + int fd; + struct fd fd_s; + + err = verify_params(params); + if (err < 0) { + return err; + } + + fd = anon_inode_getfd("doom_surface", &surface_fops, NULL, 0); + fd_s = fdget(fd); + if (fd_s.file->f_op != &surface_fops) { + printk(KERN_DEBUG "fdget failed\n"); + return -ENOENT; + } + + fd_s.file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; + + return fd; +} |