m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-03 12:52:32 +0200
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-03 12:52:32 +0200
commit391f8bee7ef5a2e92d24d73f0072915b7cb12b6b (patch)
tree33f48bf55069bc3a2f26d7d3e3866f519959fa3a
parent66bcebae16314268dfc64ed89072feca862be108 (diff)
Create basic char device
-rw-r--r--Kbuild2
-rw-r--r--char.c92
-rw-r--r--char.h9
-rw-r--r--harddoom_main.c16
-rw-r--r--pci.c19
-rw-r--r--util.h22
6 files changed, 142 insertions, 18 deletions
diff --git a/Kbuild b/Kbuild
index d4a3e64..0214343 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1,2 +1,2 @@
obj-m := harddoom.o
-harddoom-objs := harddoom_main.o pci.o
+harddoom-objs := harddoom_main.o pci.o char.o
diff --git a/char.c b/char.c
new file mode 100644
index 0000000..7fe7652
--- /dev/null
+++ b/char.c
@@ -0,0 +1,92 @@
+#include "char.h"
+
+#include "linux/cdev.h"
+#include "linux/device.h"
+#include "linux/fs.h"
+
+#include "util.h"
+
+#define DOOMDEV_COUNT 256
+#define DOOMDEV_NAME "doom"
+
+dev_t first;
+int major;
+int next_minor = 0;
+
+long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return -1;
+}
+
+int doom_open(struct inode *inode, struct file *filp)
+{
+ return -1;
+}
+
+struct file_operations doomdev_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = doom_ioctl,
+ .compat_ioctl = doom_ioctl,
+ .open = doom_open
+};
+
+struct class *doom_class;
+
+int new_doomdev(void)
+{
+ int err = 0;
+ int minor;
+ dev_t devt;
+ struct cdev *doom_cdev;
+ struct device *doomdev;
+ if (next_minor >= DOOMDEV_COUNT) {
+ return -ENOMEM;
+ }
+
+ doom_cdev = cdev_alloc();
+ if (doom_cdev == NULL) {
+ return -ENOMEM;
+ }
+
+ doom_cdev->ops = &doomdev_fops;
+ ORFAIL(cdev_add(doom_cdev, first, 1), error_add);
+ minor = next_minor++;
+ devt = MKDEV(major, minor);
+ ORFAIL_PTR(device_create(doom_class, NULL, devt, NULL,
+ "doom%d", minor),
+ doomdev, error_create);
+
+error_create:
+ cdev_del(doom_cdev);
+error_add:
+ return err;
+}
+
+void destroy_doomdev(void)
+{
+ device_destroy(doom_class, first);
+}
+
+int char_init(void)
+{
+ int err = 0;
+ ORFAIL(alloc_chrdev_region(&first, 0, DOOMDEV_COUNT, DOOMDEV_NAME),
+ error_region);
+ major = MAJOR(first);
+ doom_class = class_create(THIS_MODULE, "doom");
+ if (IS_ERR(doom_class)) {
+ err = PTR_ERR(doom_class);
+ goto error_create;
+ }
+
+error_create:
+ unregister_chrdev_region(first, DOOMDEV_COUNT);
+error_region:
+ return err;
+}
+
+void char_cleanup(void)
+{
+ unregister_chrdev_region(first, DOOMDEV_COUNT);
+ class_unregister(doom_class);
+}
diff --git a/char.h b/char.h
new file mode 100644
index 0000000..503ba04
--- /dev/null
+++ b/char.h
@@ -0,0 +1,9 @@
+#ifndef CHAR_H
+#define CHAR_H
+
+int new_doomdev(void);
+void destroy_doomdev(void);
+int char_init(void);
+void char_cleanup(void);
+
+#endif
diff --git a/harddoom_main.c b/harddoom_main.c
index 9ffe62f..300c910 100644
--- a/harddoom_main.c
+++ b/harddoom_main.c
@@ -1,29 +1,31 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include "char.h"
#include "pci.h"
+#include "util.h"
MODULE_LICENSE("GPL");
int harddoom_init(void)
{
int err = 0;
- printk(KERN_INFO "Initializing harddoom\n");
- err = pci_init();
- if (err < 0) {
- goto error;
- }
+
+ ORFAIL(char_init(), error_char) ;
+ ORFAIL(pci_init(), error_pci);
return 0;
-error:
+error_pci:
+ char_cleanup();
+error_char:
return err;
}
void harddoom_cleanup(void)
{
- printk(KERN_INFO "Removing harddoom\n");
pci_cleanup();
+ char_cleanup();
}
module_init(harddoom_init);
diff --git a/pci.c b/pci.c
index 36f1ad8..3850633 100644
--- a/pci.c
+++ b/pci.c
@@ -3,46 +3,47 @@
#include <linux/kernel.h>
#include <linux/pci.h>
+#include "char.h"
#include "harddoom.h"
+#include "pci.h"
+#include "util.h"
int doom_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
- printk(KERN_INFO "In probe\n");
- return 0;
+ int err = 0;
+ ORFAIL(new_doomdev(), error_doomdev);
+
+error_doomdev:
+ return err;
}
void doom_remove (struct pci_dev *dev)
{
- printk(KERN_INFO "In remove\n");
+ destroy_doomdev();
}
int doom_suspend (struct pci_dev *dev, pm_message_t state)
{
- printk(KERN_INFO "In suspend\n");
return 0;
}
int doom_suspend_late (struct pci_dev *dev, pm_message_t state)
{
- printk(KERN_INFO "In suspend_late\n");
return 0;
}
int doom_resume_early (struct pci_dev *dev)
{
- printk(KERN_INFO "In resume_early\n");
return 0;
}
int doom_resume (struct pci_dev *dev)
{
- printk(KERN_INFO "In resume\n");
return 0;
}
void doom_shutdown (struct pci_dev *dev)
{
- printk(KERN_INFO "In shutdown\n");
}
struct pci_device_id device_ids[1] = {
@@ -63,12 +64,10 @@ struct pci_driver driver = {
int pci_init(void)
{
- printk(KERN_INFO "In pci init\n");
return pci_register_driver(&driver);
}
void pci_cleanup(void)
{
- printk(KERN_INFO "In pci cleanup\n");
pci_unregister_driver(&driver);
}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..bd9bcc3
--- /dev/null
+++ b/util.h
@@ -0,0 +1,22 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#define ORFAIL(cond, label) \
+({ \
+ err = (cond); \
+ if (err < 0) { \
+ goto label; \
+ } \
+})
+
+#define ORFAIL_PTR(cond, lvalue, label) \
+({ \
+ lvalue = (cond); \
+ if (IS_ERR(lvalue)) { \
+ err = PTR_ERR(lvalue); \
+ goto label; \
+ } \
+})
+
+
+#endif