m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/surface.c
blob: 7dd4793ea2eb9ede81ca5c62b8ea292fd4d22401 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/fs.h>

#include "private_data.h"
#include "surface.h"

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;
}