m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--surface.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/surface.c b/surface.c
index 3c24871..8400e3f 100644
--- a/surface.c
+++ b/surface.c
@@ -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;
+}