Skip to content

Instantly share code, notes, and snippets.

@dhilst
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhilst/b0bc4e29a3147b0e6d3b to your computer and use it in GitHub Desktop.
Save dhilst/b0bc4e29a3147b0e6d3b to your computer and use it in GitHub Desktop.
How to export out-of-tree ioctls to userspace?
CFLAGS_mymodule.o := -DDEBUG
obj-m := mymodule.o
header-y += mymodule.h
SRC := $(CURDIR)
KERNEL_SRC := "$(CURDIR)/../linux-3.15.5/"
all:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
modules_install:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
headers_install:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC) headers_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC) clean
/**
* @file hello-world.c
* @author Daniel Hilst Selli <danielhilst@gmail.com>
* @brief Create a device that spits "Hello World"
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include "mymodule.h"
#define MODULE_NAME "mymodule"
static dev_t dev;
static struct class *class;
static struct cdev cdev;
static struct device *device;
static int dev_open(struct inode *ip, struct file *fp)
{
return 0;
}
static int dev_release(struct inode *ip, struct file *fp)
{
return 0;
}
long dev_ioctl (struct file * filp, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case MYMODULE_IOCGFOO:
pr_debug("ioctl MYMODULE_IOCGFOO");
break;
case MYMODULE_IOCSFOO:
pr_debug("ioctl MYMODULE_IOCSFOO");
break;
default:
return -ENOTTY;
break;
}
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = dev_ioctl,
.open = dev_open,
.release = dev_release,
};
static int __init dev_init(void)
{
int error;
int rval;
error = alloc_chrdev_region(&dev, 0, 1, MODULE_NAME);
if (error) {
pr_debug("alloc_chrdev_region() fails");
return -1;
}
cdev_init(&cdev, &fops);
rval = cdev_add(&cdev, dev, 1);
if (rval < 0) {
pr_debug("cdev_add() fails");
goto unregister_chrdev_region;
}
class = class_create(THIS_MODULE, MODULE_NAME);
if (IS_ERR(class)) {
pr_debug("class_create() fails");
goto cdev_del;
}
device = device_create(class, NULL, dev, NULL, MODULE_NAME);
if (IS_ERR(device)) {
pr_debug("device_create() fails");
goto class_destroy;
}
return 0;
class_destroy:
class_unregister(class);
class_destroy(class);
cdev_del:
cdev_del(&cdev);
unregister_chrdev_region:
unregister_chrdev_region(dev, 1);
return -1;
}
static void __exit dev_exit(void)
{
device_destroy(class, dev);
class_unregister(class);
class_destroy(class);
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_AUTHOR("Daniel Hilst Selli <danielhilst@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CHANGE HERE");
#ifndef _MYMODULE_H
#define _MYMODULE_H
#ifdef __KERNEL__
#include <linux/ioctl.h>
#else
#include <sysfs/ioctl.h>
#endif
#define MYMODULE_IOCMAGIC 'f'
#define MYMODULE_IOCGFOO _IOR(MYMODULE_IOCMAGIC, 0x20, int)
#define MYMODULE_IOCSFOO _IOW(MYMODULE_IOCMAGIC, 0x21, int)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment