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