|  | /* | 
|  | * linux/drivers/video/fb_sys_read.c - Generic file operations where | 
|  | * framebuffer is in system RAM | 
|  | * | 
|  | * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> | 
|  | * | 
|  | * This file is subject to the terms and conditions of the GNU General Public | 
|  | * License.  See the file COPYING in the main directory of this archive | 
|  | * for more details. | 
|  | * | 
|  | */ | 
|  | #include <linux/fb.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/uaccess.h> | 
|  |  | 
|  | ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, | 
|  | loff_t *ppos) | 
|  | { | 
|  | unsigned long p = *ppos; | 
|  | void *src; | 
|  | int err = 0; | 
|  | unsigned long total_size; | 
|  |  | 
|  | if (info->state != FBINFO_STATE_RUNNING) | 
|  | return -EPERM; | 
|  |  | 
|  | total_size = info->screen_size; | 
|  |  | 
|  | if (total_size == 0) | 
|  | total_size = info->fix.smem_len; | 
|  |  | 
|  | if (p >= total_size) | 
|  | return 0; | 
|  |  | 
|  | if (count >= total_size) | 
|  | count = total_size; | 
|  |  | 
|  | if (count + p > total_size) | 
|  | count = total_size - p; | 
|  |  | 
|  | src = (void __force *)(info->screen_base + p); | 
|  |  | 
|  | if (info->fbops->fb_sync) | 
|  | info->fbops->fb_sync(info); | 
|  |  | 
|  | if (copy_to_user(buf, src, count)) | 
|  | err = -EFAULT; | 
|  |  | 
|  | if  (!err) | 
|  | *ppos += count; | 
|  |  | 
|  | return (err) ? err : count; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(fb_sys_read); | 
|  |  | 
|  | ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, | 
|  | size_t count, loff_t *ppos) | 
|  | { | 
|  | unsigned long p = *ppos; | 
|  | void *dst; | 
|  | int err = 0; | 
|  | unsigned long total_size; | 
|  |  | 
|  | if (info->state != FBINFO_STATE_RUNNING) | 
|  | return -EPERM; | 
|  |  | 
|  | total_size = info->screen_size; | 
|  |  | 
|  | if (total_size == 0) | 
|  | total_size = info->fix.smem_len; | 
|  |  | 
|  | if (p > total_size) | 
|  | return -EFBIG; | 
|  |  | 
|  | if (count > total_size) { | 
|  | err = -EFBIG; | 
|  | count = total_size; | 
|  | } | 
|  |  | 
|  | if (count + p > total_size) { | 
|  | if (!err) | 
|  | err = -ENOSPC; | 
|  |  | 
|  | count = total_size - p; | 
|  | } | 
|  |  | 
|  | dst = (void __force *) (info->screen_base + p); | 
|  |  | 
|  | if (info->fbops->fb_sync) | 
|  | info->fbops->fb_sync(info); | 
|  |  | 
|  | if (copy_from_user(dst, buf, count)) | 
|  | err = -EFAULT; | 
|  |  | 
|  | if  (!err) | 
|  | *ppos += count; | 
|  |  | 
|  | return (err) ? err : count; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(fb_sys_write); | 
|  |  | 
|  | MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); | 
|  | MODULE_DESCRIPTION("Generic file read (fb in system RAM)"); | 
|  | MODULE_LICENSE("GPL"); |