Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* drivers/sharp/shboot/shboot_daemon_drv.c
- *
- * Copyright (C) 2011 Sharp Corporation
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <asm/uaccess.h>
- #include <linux/module.h>
- #include <linux/cdev.h>
- #include <linux/semaphore.h>
- #include <linux/sched.h>
- #include <linux/wait.h>
- #include <linux/fs.h>
- #include <linux/mm.h>
- #include <linux/device.h>
- #include "shboot_daemon_drv.h"
- #define DEVICE_NAME "boot_daemon_drv"
- #define GETTING_REQUEST 0
- #define GETTING_RESULT 1
- #define GET_RESULT 2
- struct s_shboot_request {
- int offset;
- size_t len;
- };
- static struct s_shboot_request shboot_request = {
- .offset = 0,
- .len = 0
- };
- static void *shboot_buf = NULL;
- static wait_queue_head_t shboot_call_q;
- static wait_queue_head_t shboot_daemon_q;
- static struct semaphore shboot_sem;
- static volatile int shboot_state = GETTING_REQUEST;
- static int shboot_daemon_drv_opened = 0;
- int shboot_daemon_drv_read_process(int offset, size_t len, void *buf)
- {
- int ret = 0;
- if (!shboot_daemon_drv_opened) {
- printk(KERN_ALERT "%s: sharp bootinfo device driver can't be opened.\n", __func__);
- return -EPERM;
- }
- ret = down_interruptible(&shboot_sem);
- shboot_request.offset = offset;
- shboot_request.len = len;
- shboot_buf = buf;
- shboot_state = GETTING_RESULT;
- wake_up_interruptible(&shboot_daemon_q);
- wait_event_interruptible(shboot_call_q, (shboot_state == GET_RESULT));
- if (!strncmp(shboot_buf, "invalid request", sizeof("invalid request"))) {
- printk(KERN_ALERT "%s :invalid request: offset = 0x%x, len = 0x%x\n", __func__, offset, len);
- ret = -EPERM;
- }
- shboot_state = GETTING_REQUEST;
- shboot_buf = NULL;
- up(&shboot_sem);
- return ret;
- }
- static ssize_t shboot_daemon_read(struct file *filp, char __user *buf,
- size_t count, loff_t *f_pos)
- {
- wait_event_interruptible(shboot_daemon_q, (shboot_state == GETTING_RESULT));
- /* copy request */
- if (copy_to_user(buf, &shboot_request, count)) {
- printk(KERN_ALERT "%s :copy_to_user failed.: \n", __func__);
- return 0;
- }
- return count;
- }
- static ssize_t shboot_daemon_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos)
- {
- int ret = 0;
- if(!shboot_buf) {
- wake_up_interruptible(&shboot_call_q);
- return ret;
- }
- if (copy_from_user(shboot_buf, buf, count)) {
- printk(KERN_ALERT "%s :copy_from_user failed.: \n", __func__);
- ret = 0;
- } else {
- ret = count;
- }
- shboot_state = GET_RESULT;
- wake_up_interruptible(&shboot_call_q);
- return ret;
- }
- static int shboot_daemon_mmap(struct file *filp, struct vm_area_struct *vma)
- {
- int err;
- // err = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot);
- err = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot);
- if (err) {
- printk(KERN_ALERT "%s :io_remap_pfn_range failed.: \n", __func__);
- return -EAGAIN;
- }
- return 0;
- }
- static int shboot_daemon_open(struct inode *inode, struct file *filp)
- {
- shboot_daemon_drv_opened = 1;
- return 0;
- }
- static int shboot_daemon_release(struct inode *inode, struct file *filp)
- {
- shboot_daemon_drv_opened = 0;
- return 0;
- }
- static struct file_operations shboot_daemon_fops = {
- .owner = THIS_MODULE,
- .read = shboot_daemon_read,
- .write = shboot_daemon_write,
- .mmap = shboot_daemon_mmap,
- .open = shboot_daemon_open,
- .release = shboot_daemon_release
- };
- static int alloc_chrdev_region_ok = 0; /* false */
- static int cdev_add_ok = 0; /* false */
- static int class_create_ok = 0; /* false */
- static int device_create_ok = 0; /* false */
- static struct cdev shboot_daemon_cdev;
- static dev_t shboot_daemon_dev;
- static struct class *shboot_daemon_class;
- static void cleanup(void)
- {
- if (device_create_ok) {
- device_destroy(shboot_daemon_class, shboot_daemon_dev);
- }
- if (class_create_ok) {
- class_destroy(shboot_daemon_class);
- }
- if (cdev_add_ok) {
- cdev_del(&shboot_daemon_cdev);
- }
- if (alloc_chrdev_region_ok) {
- unregister_chrdev_region(shboot_daemon_dev, 1);
- }
- return;
- }
- static int __init shboot_daemon_drv_init(void)
- {
- int err = -1;
- err = alloc_chrdev_region(&shboot_daemon_dev, 0, 1, DEVICE_NAME);
- if (err) {
- printk(KERN_ALERT "%s :alloc_chrdev_region failed.: %d\n", __func__, err);
- goto fail;
- } else {
- alloc_chrdev_region_ok = 1; /* true */
- }
- cdev_init(&shboot_daemon_cdev, &shboot_daemon_fops);
- shboot_daemon_cdev.owner = THIS_MODULE;
- err = cdev_add(&shboot_daemon_cdev, shboot_daemon_dev, 1);
- if (err) {
- printk(KERN_ALERT "%s :cdev_add failed.: %d\n", __func__, err);
- goto fail;
- } else {
- cdev_add_ok = 1; /* true */
- }
- /* make device file */
- shboot_daemon_class = class_create(THIS_MODULE, DEVICE_NAME);
- if (IS_ERR(shboot_daemon_class)) {
- printk(KERN_ALERT "%s :class_create failed.: \n", __func__);
- goto fail;
- } else {
- class_create_ok = 1; /* true */
- }
- if (device_create(shboot_daemon_class, NULL, shboot_daemon_dev,
- &shboot_daemon_cdev, DEVICE_NAME) < 0) {
- printk(KERN_ALERT "%s :device_create failed.: \n", __func__);
- goto fail;
- } else {
- device_create_ok = 1; /* true */
- }
- init_MUTEX(&shboot_sem);
- init_waitqueue_head(&shboot_call_q);
- init_waitqueue_head(&shboot_daemon_q);
- return 0;
- fail:
- cleanup();
- return err;
- }
- module_init(shboot_daemon_drv_init);
- static void __exit shboot_daemon_drv_exit(void)
- {
- cleanup();
- return;
- }
- module_exit(shboot_daemon_drv_exit);
- MODULE_DESCRIPTION("SHARP BOOTINFO DAEMON DRIVER MODULE");
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("SHARP CORPORATION");
- MODULE_VERSION("1.00");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement