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, c; |
23 | ssize_t ret; |
24 | |
25 | if (!(info->flags & FBINFO_VIRTFB)) |
26 | fb_warn_once(info, "Framebuffer is not in virtual address space." ); |
27 | |
28 | if (!info->screen_buffer) |
29 | return -ENODEV; |
30 | |
31 | total_size = info->screen_size; |
32 | |
33 | if (total_size == 0) |
34 | total_size = info->fix.smem_len; |
35 | |
36 | if (p >= total_size) |
37 | return 0; |
38 | |
39 | if (count >= total_size) |
40 | count = total_size; |
41 | |
42 | if (count + p > total_size) |
43 | count = total_size - p; |
44 | |
45 | src = info->screen_buffer + p; |
46 | |
47 | if (info->fbops->fb_sync) |
48 | info->fbops->fb_sync(info); |
49 | |
50 | c = copy_to_user(to: buf, from: src, n: count); |
51 | if (c) |
52 | err = -EFAULT; |
53 | ret = count - c; |
54 | |
55 | *ppos += ret; |
56 | |
57 | return ret ? ret : err; |
58 | } |
59 | EXPORT_SYMBOL_GPL(fb_sys_read); |
60 | |
61 | ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, |
62 | size_t count, loff_t *ppos) |
63 | { |
64 | unsigned long p = *ppos; |
65 | void *dst; |
66 | int err = 0; |
67 | unsigned long total_size, c; |
68 | size_t ret; |
69 | |
70 | if (!(info->flags & FBINFO_VIRTFB)) |
71 | fb_warn_once(info, "Framebuffer is not in virtual address space." ); |
72 | |
73 | if (!info->screen_buffer) |
74 | return -ENODEV; |
75 | |
76 | total_size = info->screen_size; |
77 | |
78 | if (total_size == 0) |
79 | total_size = info->fix.smem_len; |
80 | |
81 | if (p > total_size) |
82 | return -EFBIG; |
83 | |
84 | if (count > total_size) { |
85 | err = -EFBIG; |
86 | count = total_size; |
87 | } |
88 | |
89 | if (count + p > total_size) { |
90 | if (!err) |
91 | err = -ENOSPC; |
92 | |
93 | count = total_size - p; |
94 | } |
95 | |
96 | dst = info->screen_buffer + p; |
97 | |
98 | if (info->fbops->fb_sync) |
99 | info->fbops->fb_sync(info); |
100 | |
101 | c = copy_from_user(to: dst, from: buf, n: count); |
102 | if (c) |
103 | err = -EFAULT; |
104 | ret = count - c; |
105 | |
106 | *ppos += ret; |
107 | |
108 | return ret ? ret : err; |
109 | } |
110 | EXPORT_SYMBOL_GPL(fb_sys_write); |
111 | |
112 | MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>" ); |
113 | MODULE_DESCRIPTION("Generic file read (fb in system RAM)" ); |
114 | MODULE_LICENSE("GPL" ); |
115 | |