| /* |
| * 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, c; |
| ssize_t ret; |
| |
| if (!(info->flags & FBINFO_VIRTFB)) |
| fb_warn_once(info, "Framebuffer is not in virtual address space."); |
| |
| if (!info->screen_buffer) |
| return -ENODEV; |
| |
| 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 = info->screen_buffer + p; |
| |
| if (info->fbops->fb_sync) |
| info->fbops->fb_sync(info); |
| |
| c = copy_to_user(buf, src, count); |
| if (c) |
| err = -EFAULT; |
| ret = count - c; |
| |
| *ppos += ret; |
| |
| return ret ? ret : err; |
| } |
| 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, c; |
| size_t ret; |
| |
| if (!(info->flags & FBINFO_VIRTFB)) |
| fb_warn_once(info, "Framebuffer is not in virtual address space."); |
| |
| if (!info->screen_buffer) |
| return -ENODEV; |
| |
| 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 = info->screen_buffer + p; |
| |
| if (info->fbops->fb_sync) |
| info->fbops->fb_sync(info); |
| |
| c = copy_from_user(dst, buf, count); |
| if (c) |
| err = -EFAULT; |
| ret = count - c; |
| |
| *ppos += ret; |
| |
| return ret ? ret : err; |
| } |
| 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"); |