Index: logic/trunk/measurement_reader/Makefile
===================================================================
--- logic/trunk/measurement_reader/Makefile	(revision 0)
+++ logic/trunk/measurement_reader/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+# 
+# 2011, Aleksander Besir (alex.besir@gmail.com)
+#
+
+CC=arm-linux-gcc
+CFLAGS=-Wall -I. -pthread --sysroot=/home/arm/buildroot-2009.11-fri/output/staging
+BIN=bin
+SRC=src
+
+OBJ=$(SRC)/drv_comm/dev01/drv_comm.o $(SRC)/startup/main.o $(SRC)/drv_comm/dev01/generator.o
+
+all: $(BIN)/startup
+
+%.o: %.c
+	$(CC) -c -o $@ $< $(CFLAGS)
+	
+$(BIN)/startup: $(OBJ)
+	$(CC) -o $(BIN)/measure_writer $^ $(CFLAGS)
Index: logic/trunk/measurement_reader/src/startup/main.c
===================================================================
--- logic/trunk/measurement_reader/src/startup/main.c	(revision 0)
+++ logic/trunk/measurement_reader/src/startup/main.c	(revision 72)
@@ -0,0 +1,66 @@
+/*
+ * main.c
+ *
+ * 2011, Janez Barbic (jhnsmth64@gmail.com)
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "../drv_comm/dev01/drv_comm.h"
+
+const char *dev1 = "/dev/dev_thermometer_01";
+const char *dev2 = "/dev/dev_thermometer_02";
+const char *dev3 = "/dev/dev_barometer_01";
+const char *dev4 = "/dev/dev_hygrometer_01";
+const char *dev5 = "/dev/dev_light_sensor_01";
+const char *dev6 = "/dev/dev_smart_meter_01";
+
+// Application entry point
+int main(int argc, char *argv[]) {
+    /** //DAEMON
+    pid_t pid, sid;
+
+    pid = fork();
+    if (pid < 0) {
+            exit(EXIT_FAILURE);
+    }
+    // EXIT PARENT
+    if (pid > 0) {
+            exit(EXIT_SUCCESS);
+    }
+
+    //umask(0);
+
+    // Open any logs here
+
+    // Create a new SID for the child process
+    sid = setsid();
+    if (sid < 0) {
+            // Log the failure
+            exit(EXIT_FAILURE);
+    }
+
+    // Close out the standard file descriptors
+    // Because daemons generally dont interact directly with user so there is no need of keeping these open
+    close(STDIN_FILENO);
+    close(STDOUT_FILENO);
+    close(STDERR_FILENO);
+    /**/
+
+    // read devices in a loop
+    while(1)
+    {
+        set_device_value(dev1,1); // termometer1
+        set_device_value(dev2,2); //
+        set_device_value(dev3,3); //
+        set_device_value(dev4,4); //
+        set_device_value(dev5,5); //
+        set_device_value(dev6,6); //
+        sleep(60); //update every minute
+    }
+
+	exit(0);
+}
Index: logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.h
===================================================================
--- logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.h	(revision 0)
+++ logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.h	(revision 72)
@@ -0,0 +1,39 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef DRV_COMM_H
+#define DRV_COMM_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM_1 100
+#define MAJOR_NUM_2 101
+#define MAJOR_NUM_3 102
+#define MAJOR_NUM_4 103
+#define MAJOR_NUM_5 104
+#define MAJOR_NUM_6 105
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG_1 _IOR(MAJOR_NUM_1, 0, char *)
+#define IOCTL_SET_MSG_2 _IOR(MAJOR_NUM_1, 0, char *)
+#define IOCTL_SET_MSG_3 _IOR(MAJOR_NUM_1, 0, char *)
+#define IOCTL_SET_MSG_4 _IOR(MAJOR_NUM_1, 0, char *)
+#define IOCTL_SET_MSG_5 _IOR(MAJOR_NUM_1, 0, char *)
+#define IOCTL_SET_MSG_6 _IOR(MAJOR_NUM_1, 0, char *)
+
+ioctl_set_msg_1(int file_desc, char *message);
+ioctl_set_msg_2(int file_desc, char *message);
+ioctl_set_msg_3(int file_desc, char *message);
+ioctl_set_msg_4(int file_desc, char *message);
+ioctl_set_msg_5(int file_desc, char *message);
+ioctl_set_msg_6(int file_desc, char *message);
+void set_device_value(const char *dev,int devIdx);
+
+#endif //DRV_COMM_H
Index: logic/trunk/measurement_reader/src/drv_comm/dev01/generator.h
===================================================================
--- logic/trunk/measurement_reader/src/drv_comm/dev01/generator.h	(revision 0)
+++ logic/trunk/measurement_reader/src/drv_comm/dev01/generator.h	(revision 72)
@@ -0,0 +1,6 @@
+#ifndef GENERATOR_H_INCLUDED
+#define GENERATOR_H_INCLUDED
+int generate_value();
+char *int_to_str(int nbr);
+
+#endif // GENERATOR_H_INCLUDED
Index: logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.c
===================================================================
--- logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.c	(revision 0)
+++ logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.c	(revision 72)
@@ -0,0 +1,130 @@
+/*
+* ioctl.c − the process to use ioctl's to control the kernel module
+*
+* Until now we could have used cat for input and output. But now
+* we need to do ioctl's, which require writing our own process.
+*/
+/*
+* device specifics, such as ioctl numbers and the
+* major device file.
+*/
+#include "drv_comm.h"
+#include "generator.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <fcntl.h>	    /* open */
+#include <unistd.h>	    /* exit */
+//#include <sys/ioctl.h>  /* ioctl */
+/*
+* Functions for the ioctl calls
+*/
+ioctl_set_msg_1(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_1, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+ioctl_set_msg_2(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_2, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+ioctl_set_msg_3(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_3, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+ioctl_set_msg_4(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_4, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+ioctl_set_msg_5(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_5, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+ioctl_set_msg_6(int file_desc, char *message)
+{
+	int ret_val;
+	ret_val = ioctl(file_desc, IOCTL_SET_MSG_6, message);
+	if (ret_val < 0) {
+		printf("ioctl_set_msg failed:%d\n", ret_val);
+		exit(-1);
+	}
+}
+
+void set_device_value(const char *dev, int devIdx)
+{
+    //TODO use mutex?
+    int file_desc;
+
+	char *msg = int_to_str(generate_value());
+
+	file_desc = open(dev, 0);
+
+	if (file_desc < 0) {
+		printf("Can't open device file: %s\n", dev);
+	}
+	else{
+		//printf("Open device file: %s\n", dev);
+		switch(devIdx)
+		{
+		    case 1:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_1(file_desc, msg);
+                break;
+		    case 2:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_2(file_desc, msg);
+                break;
+		    case 3:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_3(file_desc, msg);
+                break;
+		    case 4:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_4(file_desc, msg);
+                break;
+		    case 5:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_5(file_desc, msg);
+                break;
+		    case 6:
+                //printf("Setting message dev %d\n", devIdx);
+                ioctl_set_msg_6(file_desc, msg);
+                break;
+
+		}
+        syslog(LOG_MAIL, "%s:%s", dev, msg);
+        // TODO syslog
+	}
+
+	close(file_desc);
+}
+
Index: logic/trunk/measurement_reader/src/drv_comm/dev01/generator.c
===================================================================
--- logic/trunk/measurement_reader/src/drv_comm/dev01/generator.c	(revision 0)
+++ logic/trunk/measurement_reader/src/drv_comm/dev01/generator.c	(revision 72)
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "generator.h"
+
+//funkcija:
+int generate_value() {
+	// nastavitev, minimalne in maksimalne temperature:
+	//funkcija, torej od ure 00:00 raste od minimalne do maximalne, ki jo dosee pri uri 12:00 in nato spet pada do minimalne pri 24:00
+	double minimum=20;
+	double maximum=27;
+
+	time_t     now;
+    struct tm  *ts;
+    char       buf1[80];
+
+    now = time(NULL);
+
+    ts = localtime(&now);
+    strcpy(buf1, asctime(ts));
+
+	int x1 = buf1[11]-48;
+	int x2 = buf1[12]-48;
+	int m1 = buf1[14]-48;
+	int m2 = buf1[15]-48;
+
+	int minutes = (x1*10+x2)*60 + m1*10+m2;
+	int variable = minutes;
+
+	if(variable>720) {
+        variable= 720-(variable-720);
+	}
+
+	double k = ((double)variable)/((double)720);
+
+    //funkcija vraca vrednost na eno decimalko natancno, podobno kot preproste i2c naprave
+	return (int) (minimum + k * (maximum-minimum))*10;
+}
+//*
+char *int_to_str(int nbr)
+{
+  int   div;
+  int   len;
+  int   i;
+  char  *res;
+
+  res = malloc(4 * sizeof(*res));
+  i = 0;
+  while (i < 3)
+    res[i++] = '\0';
+  res[3] = '\0';
+  i = 0;
+  div = 1;
+  len = 1;
+  while (nbr / div >= 10)
+    {
+      div *= 10;
+      len++;
+    }
+  while (len)
+    {
+      res[i++] = '0' + (nbr / div);
+      len--;
+      nbr %= div;
+      div /= 10;
+    }
+  return (res);
+}
+/**/
Index: logic/trunk/measurement_reader/bin/measure_writer
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/measurement_reader/bin/measure_writer
===================================================================
--- logic/trunk/measurement_reader/bin/measure_writer	(revision 0)
+++ logic/trunk/measurement_reader/bin/measure_writer	(revision 72)

Property changes on: logic/trunk/measurement_reader/bin/measure_writer
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/measurement_reader/measurement_reader.cbp
===================================================================
--- logic/trunk/measurement_reader/measurement_reader.cbp	(revision 0)
+++ logic/trunk/measurement_reader/measurement_reader.cbp	(revision 72)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="measurement_reader" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug">
+				<Option output="bin/Debug/measurement_reader" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release">
+				<Option output="bin/Release/measurement_reader" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wall" />
+		</Compiler>
+		<Unit filename="src/drv_comm/dev01/drv_comm.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/drv_comm/dev01/drv_comm.h" />
+		<Unit filename="src/drv_comm/dev01/generator.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/drv_comm/dev01/generator.h" />
+		<Unit filename="src/startup/main.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Extensions>
+			<code_completion />
+			<debugger />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>
Index: logic/trunk/driver/dev03/dev_barometer_01.h
===================================================================
--- logic/trunk/driver/dev03/dev_barometer_01.h	(revision 0)
+++ logic/trunk/driver/dev03/dev_barometer_01.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 102
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "char_dev"
+#endif
+
Index: logic/trunk/driver/dev03/Makefile
===================================================================
--- logic/trunk/driver/dev03/Makefile	(revision 0)
+++ logic/trunk/driver/dev03/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_barometer_01.o
+
+endif
Index: logic/trunk/driver/dev03/dev_barometer_01.c
===================================================================
--- logic/trunk/driver/dev03/dev_barometer_01.c	(revision 0)
+++ logic/trunk/driver/dev03/dev_barometer_01.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_barometer_01.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev04/Makefile
===================================================================
--- logic/trunk/driver/dev04/Makefile	(revision 0)
+++ logic/trunk/driver/dev04/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_hygrometer_01.o
+
+endif
Index: logic/trunk/driver/dev04/dev_hygrometer_01.c
===================================================================
--- logic/trunk/driver/dev04/dev_hygrometer_01.c	(revision 0)
+++ logic/trunk/driver/dev04/dev_hygrometer_01.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_hygrometer_01.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev04/dev_hygrometer_01.h
===================================================================
--- logic/trunk/driver/dev04/dev_hygrometer_01.h	(revision 0)
+++ logic/trunk/driver/dev04/dev_hygrometer_01.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 103
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "char_dev"
+#endif
+
Index: logic/trunk/driver/dev05/dev_light_sensor_01.h
===================================================================
--- logic/trunk/driver/dev05/dev_light_sensor_01.h	(revision 0)
+++ logic/trunk/driver/dev05/dev_light_sensor_01.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 104
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "char_dev"
+#endif
+
Index: logic/trunk/driver/dev05/Makefile
===================================================================
--- logic/trunk/driver/dev05/Makefile	(revision 0)
+++ logic/trunk/driver/dev05/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_light_sensor_01.o
+
+endif
Index: logic/trunk/driver/dev05/dev_light_sensor_01.c
===================================================================
--- logic/trunk/driver/dev05/dev_light_sensor_01.c	(revision 0)
+++ logic/trunk/driver/dev05/dev_light_sensor_01.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_light_sensor_01.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev06/Makefile
===================================================================
--- logic/trunk/driver/dev06/Makefile	(revision 0)
+++ logic/trunk/driver/dev06/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_smart_meter_01.o
+
+endif
Index: logic/trunk/driver/dev06/dev_smart_meter_01.c
===================================================================
--- logic/trunk/driver/dev06/dev_smart_meter_01.c	(revision 0)
+++ logic/trunk/driver/dev06/dev_smart_meter_01.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_smart_meter_01.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev06/dev_smart_meter_01.h
===================================================================
--- logic/trunk/driver/dev06/dev_smart_meter_01.h	(revision 0)
+++ logic/trunk/driver/dev06/dev_smart_meter_01.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 105
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "char_dev"
+#endif
+
Index: logic/trunk/driver/modules/arm/dev_thermometer_02.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_thermometer_02.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_thermometer_02.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_thermometer_02.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_thermometer_02.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/modules/arm/dev_barometer_01.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_barometer_01.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_barometer_01.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_barometer_01.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_barometer_01.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/modules/arm/dev_light_sensor_01.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_light_sensor_01.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_light_sensor_01.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_light_sensor_01.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_light_sensor_01.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/modules/arm/dev_smart_meter_01.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_smart_meter_01.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_smart_meter_01.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_smart_meter_01.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_smart_meter_01.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/modules/arm/dev_hygrometer_01.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_hygrometer_01.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_hygrometer_01.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_hygrometer_01.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_hygrometer_01.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/modules/arm/dev_thermometer_01.ko
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: logic/trunk/driver/modules/arm/dev_thermometer_01.ko
===================================================================
--- logic/trunk/driver/modules/arm/dev_thermometer_01.ko	(revision 0)
+++ logic/trunk/driver/modules/arm/dev_thermometer_01.ko	(revision 72)

Property changes on: logic/trunk/driver/modules/arm/dev_thermometer_01.ko
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: logic/trunk/driver/dev01/make_ukaz_arm
===================================================================
--- logic/trunk/driver/dev01/make_ukaz_arm	(revision 0)
+++ logic/trunk/driver/dev01/make_ukaz_arm	(revision 72)
@@ -0,0 +1 @@
+make -C /home/janez/Documents/Linux_tests/linux-2.6.27-fri/ CROSS_COMPILE=/home/arm/buildroot-2009.11-fri/output/staging/usr/bin/arm-linux- M=/home/janez/Documents/Linux_tests/linux-2.6.27-fri/ac/ modules
Index: logic/trunk/driver/dev01/dev_thermometer_01.c
===================================================================
--- logic/trunk/driver/dev01/dev_thermometer_01.c	(revision 0)
+++ logic/trunk/driver/dev01/dev_thermometer_01.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_thermometer_01.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev01/Makefile
===================================================================
--- logic/trunk/driver/dev01/Makefile	(revision 0)
+++ logic/trunk/driver/dev01/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_thermometer_01.o
+
+endif
Index: logic/trunk/driver/dev01/dev_thermometer_01.h
===================================================================
--- logic/trunk/driver/dev01/dev_thermometer_01.h	(revision 0)
+++ logic/trunk/driver/dev01/dev_thermometer_01.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 100
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "dev_thermometer_01"
+#endif
+
Index: logic/trunk/driver/dev02/dev_thermometer_02.h
===================================================================
--- logic/trunk/driver/dev02/dev_thermometer_02.h	(revision 0)
+++ logic/trunk/driver/dev02/dev_thermometer_02.h	(revision 72)
@@ -0,0 +1,58 @@
+/*
+* chardev.h − the header file with the ioctl definitions.
+* The declarations here have to be in a header file, because
+* they need to be known both to the kernel module
+* (in chardev.c) and the process calling ioctl (ioctl.c)
+*/
+#ifndef CHARDEV_H
+#define CHARDEV_H
+#include <linux/ioctl.h>
+/*
+* The major device number. We can't rely on dynamic
+* registration any more, because ioctls need to know
+* it.
+*/
+#define MAJOR_NUM 101
+/*
+* Set the message of the device driver
+*/
+#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
+/*
+* _IOR means that we're creating an ioctl command
+* number for passing information from a user process
+* to the kernel module.
+*
+* The first arguments, MAJOR_NUM, is the major device
+* number we're using.
+*
+* The second argument is the number of the command
+* (there could be several with different meanings).
+*
+* The third argument is the type we want to get from
+* the process to the kernel.
+*/
+/*
+* Get the message of the device driver
+*/
+#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
+/*
+* This IOCTL is used for output, to get the message
+* of the device driver. However, we still need the
+* buffer to place the message in to be input,
+* as it is allocated by the process.
+*/
+/*
+* Get the n'th byte of the message
+*/
+#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
+/*
+* The IOCTL is used for both input and output. It
+* receives from the user a number, n, and returns
+* Message[n].
+*/
+/*
+* The name of the device file
+*/
+#define DEVICE_FILE_NAME "char_dev"
+#endif
+
Index: logic/trunk/driver/dev02/dev_thermometer_02.c
===================================================================
--- logic/trunk/driver/dev02/dev_thermometer_02.c	(revision 0)
+++ logic/trunk/driver/dev02/dev_thermometer_02.c	(revision 72)
@@ -0,0 +1,261 @@
+/*
+* chardev.c − Create an input/output character device
+*/
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+#include <linux/fs.h>     /* for get_user and put_user */
+#include <linux/i2c.h>     /* for get_user and put_user */
+#include <linux/hwmon.h>     /* for get_user and put_user */
+#include <linux/err.h>     /* for get_user and put_user */
+#include <asm/uaccess.h>
+#include "dev_thermometer_02.h"
+
+#define SUCCESS 0
+#define DEVICE_NAME "dev_thermometer_01"
+#define BUF_LEN 80
+/*
+* Is the device open right now? Used to prevent
+* concurent access into the same device
+*/
+static int Device_Open = 0;
+/*
+* The message the device will give when asked
+*/
+static char Message[BUF_LEN];
+/*
+* How far did the process reading the message get?
+* Useful if the message is larger than the size of the
+* buffer we get to fill in device_read.
+*/
+static char *Message_Ptr;
+/*
+* This is called whenever a process attempts to open the device file
+*/
+static int device_open(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_open(%p)\n", file);
+	#endif
+	/*
+	* We don't want to talk to two processes at the same time
+	*/
+	if (Device_Open)
+		return -EBUSY;
+	Device_Open++;
+	/*
+	* Initialize the message
+	*/
+	Message_Ptr = Message;
+	try_module_get(THIS_MODULE);
+	return SUCCESS;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+	#ifdef DEBUG
+	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
+	#endif
+	/*
+	* We're now ready for our next caller
+	*/
+	Device_Open--;
+	module_put(THIS_MODULE);
+	return SUCCESS;
+}
+
+/*
+* This function is called whenever a process which has already opened the
+* device file attempts to read from it.
+*/
+static ssize_t device_read(struct file *file,
+				/* see include/linux/fs.h*/
+				char __user * buffer,
+				/* buffer to be
+				* filled with data */
+				size_t length,
+				loff_t * offset)
+				/* length of the buffer*/
+{
+	/*
+	* Number of bytes actually written to the buffer
+	*/
+	int bytes_read = 0;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
+	#endif
+	/*
+	* If we're at the end of the message, return 0
+	* (which signifies end of file)
+	*/
+	if (*Message_Ptr == 0)
+		return 0;
+	/*
+	* Actually put the data into the buffer
+	*/
+	while (length && *Message_Ptr) {
+		/*
+		* Because the buffer is in the user data segment,
+		* not the kernel data segment, assignment wouldn't
+		* work. Instead, we have to use put_user which
+		* copies data from the kernel data segment to the
+		* user data segment.
+		*/
+		put_user(*(Message_Ptr++), buffer++);
+		length--;
+		bytes_read++;
+	}
+	#ifdef DEBUG
+	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
+	#endif
+	/*
+	* Read functions are supposed to return the number
+	* of bytes actually inserted into the buffer
+	*/
+	return bytes_read;
+}
+
+/*
+* This function is called when somebody tries to
+* write into our device file.
+*/
+static ssize_t
+device_write(struct file *file,
+const char __user * buffer, size_t length, loff_t * offset)
+{
+	int i;
+	#ifdef DEBUG
+	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
+	#endif
+	for (i = 0; i < length && i < BUF_LEN; i++)
+		get_user(Message[i], buffer + i);
+	Message_Ptr = Message;
+	/*
+	* Again, return the number of input characters used
+	*/
+	return i;
+}
+
+/*
+* This function is called whenever a process tries to do an ioctl on our
+* device file. We get two extra parameters (additional to the inode and file
+* structures, which all device functions get): the number of the ioctl called
+* and the parameter given to the ioctl function.
+*
+* If the ioctl is write or read/write (meaning output is returned to the
+* calling process), the ioctl call returns the output of this function.
+*
+*/
+int device_ioctl(struct inode *inode,
+	/* see include/linux/fs.h */
+	struct file *file,
+	/* ditto */
+	unsigned int ioctl_num,
+	/* number and param for ioctl */
+	unsigned long ioctl_param)
+{
+	int i;
+	char *temp;
+	char ch;
+	/*
+	* Switch according to the ioctl called
+	*/
+	switch (ioctl_num) {
+	case IOCTL_SET_MSG:
+		/*
+		* Receive a pointer to a message (in user space) and set that
+		* to be the device's message. Get the parameter given to
+		* ioctl by the process.
+		*/
+		temp = (char *)ioctl_param;
+		/*
+		* Find the length of the message
+		*/
+		get_user(ch, temp);
+		for (i = 0; ch && i < BUF_LEN; i++, temp++)
+			get_user(ch, temp);
+		device_write(file, (char *)ioctl_param, i, 0);
+		break;
+	case IOCTL_GET_MSG:
+		/*
+		* Give the current message to the calling process −
+		* the parameter we got is a pointer, fill it.
+		*/
+		i = device_read(file, (char *)ioctl_param, 99, 0);
+		/*
+		* Put a zero at the end of the buffer, so it will be
+		* properly terminated
+		*/
+		put_user('\0', (char *)ioctl_param + i);
+		break;
+	case IOCTL_GET_NTH_BYTE:
+		/*
+		* This ioctl is both input (ioctl_param) and
+		* output (the return value of this function)
+		*/
+		return Message[ioctl_param];
+		break;
+	}
+	return SUCCESS;
+}
+
+/* Module Declarations */
+/*
+* This structure will hold the functions to be called
+* when a process does something to the device we
+* created. Since a pointer to this structure is kept in
+* the devices table, it can't be local to
+* init_module. NULL is for unimplemented functions.
+*/
+struct file_operations Fops = {
+	.read = device_read,
+	.write = device_write,
+	.ioctl = device_ioctl,
+	.open = device_open,
+	.release = device_release,
+	/* a.k.a. close */
+};
+
+/*
+* Initialize the module − Register the character device
+*/
+int init_module()
+{
+	int ret_val;
+	/*
+	* Register the character device (atleast try)
+	*/
+	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
+	/*
+	* Negative values signify an error
+	*/
+	if (ret_val < 0) {
+		printk(KERN_ALERT "%s failed with %d\n",
+		"Sorry, registering the character device ", ret_val);
+		return ret_val;
+	}
+	printk(KERN_INFO "%s The major device number is %d.\n",
+	"Registeration is a success", MAJOR_NUM);
+	return 0;
+}
+
+/*
+* Cleanup − unregister the appropriate file from /proc
+*/
+void cleanup_module()
+{
+	//int ret;
+	/*
+	* Unregister the device
+	*/
+	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+    printk(KERN_INFO "Unregistering module.\n");
+	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
+	/*
+	* If there's an error, report it
+	*/
+	/*
+	if (ret < 0)
+		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
+	/**/
+}
+
Index: logic/trunk/driver/dev02/Makefile
===================================================================
--- logic/trunk/driver/dev02/Makefile	(revision 0)
+++ logic/trunk/driver/dev02/Makefile	(revision 72)
@@ -0,0 +1,18 @@
+ifeq ($(KERNELRELEASE),)
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c  *.symvers *.order
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m := dev_thermometer_02.o
+
+endif
