diff --git a/20160425/Makefile b/20160425/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..263a0a5effc01e8110f1626a3d9540e646715deb
--- /dev/null
+++ b/20160425/Makefile
@@ -0,0 +1,8 @@
+obj-m += hellomod-1.o
+obj-m += chardev-1.o
+
+all:
+	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+clean:
+	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/20160425/chardev-1.c b/20160425/chardev-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..17a6651a33313322de202fbcb6bbf82333c0b766
--- /dev/null
+++ b/20160425/chardev-1.c
@@ -0,0 +1,166 @@
+/*
+ *  chardev.c: Creates a read-only char device that says how many times
+ *  you've read from the dev file
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>	/* for put_user */
+
+/*  
+ *  Prototypes - this would normally go in a .h file
+ */
+int init_module(void);
+void cleanup_module(void);
+static int device_open(struct inode *, struct file *);
+static int device_release(struct inode *, struct file *);
+static ssize_t device_read(struct file *, char *, size_t, loff_t *);
+static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
+
+#define SUCCESS 0
+#define DEVICE_NAME "chardev"	/* Dev name as it appears in /proc/devices   */
+#define BUF_LEN 80		/* Max length of the message from the device */
+
+/* 
+ * Global variables are declared as static, so are global within the file. 
+ */
+
+static int Major;		/* Major number assigned to our device driver */
+static int Device_Open = 0;	/* Is device open?  
+				 * Used to prevent multiple access to device */
+static char msg[BUF_LEN];	/* The msg the device will give when asked */
+static char *msg_Ptr;
+
+static struct file_operations fops = {
+	.read = device_read,
+	.write = device_write,
+	.open = device_open,
+	.release = device_release
+};
+
+/*
+ * This function is called when the module is loaded
+ */
+int init_module(void)
+{
+        Major = register_chrdev(0, DEVICE_NAME, &fops);
+
+	if (Major < 0) {
+	  printk(KERN_ALERT "Registering char device failed with %d\n", Major);
+	  return Major;
+	}
+
+	printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
+	printk(KERN_INFO "the driver, create a dev file with\n");
+	printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
+	printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
+	printk(KERN_INFO "the device file.\n");
+	printk(KERN_INFO "Remove the device file and module when done.\n");
+
+	return SUCCESS;
+}
+
+/*
+ * This function is called when the module is unloaded
+ */
+void cleanup_module(void)
+{
+	/* 
+	 * Unregister the device 
+	 */
+	unregister_chrdev(Major, DEVICE_NAME);
+}
+
+/*
+ * Methods
+ */
+
+/* 
+ * Called when a process tries to open the device file, like
+ * "cat /dev/mycharfile"
+ */
+static int device_open(struct inode *inode, struct file *file)
+{
+	static int counter = 0;
+
+	if (Device_Open)
+		return -EBUSY;
+
+	Device_Open++;
+	sprintf(msg, "I already told you %d times Hello world!\n", counter++);
+	msg_Ptr = msg;
+	try_module_get(THIS_MODULE);
+
+	return SUCCESS;
+}
+
+/* 
+ * Called when a process closes the device file.
+ */
+static int device_release(struct inode *inode, struct file *file)
+{
+	Device_Open--;		/* We're now ready for our next caller */
+
+	/* 
+	 * Decrement the usage count, or else once you opened the file, you'll
+	 * never get get rid of the module. 
+	 */
+	module_put(THIS_MODULE);
+
+	return 0;
+}
+
+/* 
+ * Called when a process, which already opened the dev file, attempts to
+ * read from it.
+ */
+static ssize_t device_read(struct file *filp,	/* see include/linux/fs.h   */
+			   char *buffer,	/* buffer to fill with data */
+			   size_t length,	/* length of the buffer     */
+			   loff_t * offset)
+{
+	/*
+	 * Number of bytes actually written to the buffer 
+	 */
+	int bytes_read = 0;
+
+	/*
+	 * If we're at the end of the message, 
+	 * return 0 signifying end of file 
+	 */
+	if (*msg_Ptr == 0)
+		return 0;
+
+	/* 
+	 * Actually put the data into the buffer 
+	 */
+	while (length && *msg_Ptr) {
+
+		/* 
+		 * The buffer is in the user data segment, not the kernel 
+		 * segment so "*" assignment won't work.  We have to use 
+		 * put_user which copies data from the kernel data segment to
+		 * the user data segment. 
+		 */
+		put_user(*(msg_Ptr++), buffer++);
+
+		length--;
+		bytes_read++;
+	}
+
+	/* 
+	 * Most read functions return the number of bytes put into the buffer
+	 */
+	return bytes_read;
+}
+
+/*  
+ * Called when a process writes to dev file: echo "hi" > /dev/hello 
+ */
+static ssize_t
+device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
+{
+	printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
+	return -EINVAL;
+}
diff --git a/20160425/hellomod-1.c b/20160425/hellomod-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9fef793369a4e24da98b91e1bb7c651190ceea2
--- /dev/null
+++ b/20160425/hellomod-1.c
@@ -0,0 +1,20 @@
+/*  
+ *  hello-1.c - The simplest kernel module.
+ */
+#include <linux/module.h>	/* Needed by all modules */
+#include <linux/kernel.h>	/* Needed for KERN_INFO */
+
+int init_module(void)
+{
+	printk(KERN_INFO "Hello world 1.\n");
+
+	/* 
+	 * A non 0 return means init_module failed; module can't be loaded. 
+	 */
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	printk(KERN_INFO "Goodbye world 1.\n");
+}