diff options
Diffstat (limited to 'drivers/video/fbdev/fb_sys_fops.c')
-rw-r--r-- | drivers/video/fbdev/fb_sys_fops.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/video/fbdev/fb_sys_fops.c b/drivers/video/fbdev/fb_sys_fops.c new file mode 100644 index 000000000000..ff275d7f3eaf --- /dev/null +++ b/drivers/video/fbdev/fb_sys_fops.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/fb_sys_read.c - Generic file operations where | ||
3 | * framebuffer is in system RAM | ||
4 | * | ||
5 | * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file COPYING in the main directory of this archive | ||
9 | * for more details. | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/fb.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/uaccess.h> | ||
15 | |||
16 | ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, | ||
17 | loff_t *ppos) | ||
18 | { | ||
19 | unsigned long p = *ppos; | ||
20 | void *src; | ||
21 | int err = 0; | ||
22 | unsigned long total_size; | ||
23 | |||
24 | if (info->state != FBINFO_STATE_RUNNING) | ||
25 | return -EPERM; | ||
26 | |||
27 | total_size = info->screen_size; | ||
28 | |||
29 | if (total_size == 0) | ||
30 | total_size = info->fix.smem_len; | ||
31 | |||
32 | if (p >= total_size) | ||
33 | return 0; | ||
34 | |||
35 | if (count >= total_size) | ||
36 | count = total_size; | ||
37 | |||
38 | if (count + p > total_size) | ||
39 | count = total_size - p; | ||
40 | |||
41 | src = (void __force *)(info->screen_base + p); | ||
42 | |||
43 | if (info->fbops->fb_sync) | ||
44 | info->fbops->fb_sync(info); | ||
45 | |||
46 | if (copy_to_user(buf, src, count)) | ||
47 | err = -EFAULT; | ||
48 | |||
49 | if (!err) | ||
50 | *ppos += count; | ||
51 | |||
52 | return (err) ? err : count; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(fb_sys_read); | ||
55 | |||
56 | ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, | ||
57 | size_t count, loff_t *ppos) | ||
58 | { | ||
59 | unsigned long p = *ppos; | ||
60 | void *dst; | ||
61 | int err = 0; | ||
62 | unsigned long total_size; | ||
63 | |||
64 | if (info->state != FBINFO_STATE_RUNNING) | ||
65 | return -EPERM; | ||
66 | |||
67 | total_size = info->screen_size; | ||
68 | |||
69 | if (total_size == 0) | ||
70 | total_size = info->fix.smem_len; | ||
71 | |||
72 | if (p > total_size) | ||
73 | return -EFBIG; | ||
74 | |||
75 | if (count > total_size) { | ||
76 | err = -EFBIG; | ||
77 | count = total_size; | ||
78 | } | ||
79 | |||
80 | if (count + p > total_size) { | ||
81 | if (!err) | ||
82 | err = -ENOSPC; | ||
83 | |||
84 | count = total_size - p; | ||
85 | } | ||
86 | |||
87 | dst = (void __force *) (info->screen_base + p); | ||
88 | |||
89 | if (info->fbops->fb_sync) | ||
90 | info->fbops->fb_sync(info); | ||
91 | |||
92 | if (copy_from_user(dst, buf, count)) | ||
93 | err = -EFAULT; | ||
94 | |||
95 | if (!err) | ||
96 | *ppos += count; | ||
97 | |||
98 | return (err) ? err : count; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(fb_sys_write); | ||
101 | |||
102 | MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); | ||
103 | MODULE_DESCRIPTION("Generic file read (fb in system RAM)"); | ||
104 | MODULE_LICENSE("GPL"); | ||