Commit | Line | Data |
---|---|---|
09aaf268 AD |
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> | |
84902b7a | 14 | #include <linux/uaccess.h> |
09aaf268 AD |
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"); |