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