Revision 72

View differences:

logic/trunk/measurement_reader/src/startup/main.c
1
/*
2
 * main.c
3
 *
4
 * 2011, Janez Barbic (jhnsmth64@gmail.com)
5
 *
6
 */
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <pthread.h>
10
#include <syslog.h>
11
#include <unistd.h>
12
#include "../drv_comm/dev01/drv_comm.h"
13

  
14
const char *dev1 = "/dev/dev_thermometer_01";
15
const char *dev2 = "/dev/dev_thermometer_02";
16
const char *dev3 = "/dev/dev_barometer_01";
17
const char *dev4 = "/dev/dev_hygrometer_01";
18
const char *dev5 = "/dev/dev_light_sensor_01";
19
const char *dev6 = "/dev/dev_smart_meter_01";
20

  
21
// Application entry point
22
int main(int argc, char *argv[]) {
23
    /** //DAEMON
24
    pid_t pid, sid;
25

  
26
    pid = fork();
27
    if (pid < 0) {
28
            exit(EXIT_FAILURE);
29
    }
30
    // EXIT PARENT
31
    if (pid > 0) {
32
            exit(EXIT_SUCCESS);
33
    }
34

  
35
    //umask(0);
36

  
37
    // Open any logs here
38

  
39
    // Create a new SID for the child process
40
    sid = setsid();
41
    if (sid < 0) {
42
            // Log the failure
43
            exit(EXIT_FAILURE);
44
    }
45

  
46
    // Close out the standard file descriptors
47
    // Because daemons generally dont interact directly with user so there is no need of keeping these open
48
    close(STDIN_FILENO);
49
    close(STDOUT_FILENO);
50
    close(STDERR_FILENO);
51
    /**/
52

  
53
    // read devices in a loop
54
    while(1)
55
    {
56
        set_device_value(dev1,1); // termometer1
57
        set_device_value(dev2,2); //
58
        set_device_value(dev3,3); //
59
        set_device_value(dev4,4); //
60
        set_device_value(dev5,5); //
61
        set_device_value(dev6,6); //
62
        sleep(60); //update every minute
63
    }
64

  
65
	exit(0);
66
}
logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.h
1
/*
2
* chardev.h − the header file with the ioctl definitions.
3
* The declarations here have to be in a header file, because
4
* they need to be known both to the kernel module
5
* (in chardev.c) and the process calling ioctl (ioctl.c)
6
*/
7
#ifndef DRV_COMM_H
8
#define DRV_COMM_H
9
#include <linux/ioctl.h>
10
/*
11
* The major device number. We can't rely on dynamic
12
* registration any more, because ioctls need to know
13
* it.
14
*/
15
#define MAJOR_NUM_1 100
16
#define MAJOR_NUM_2 101
17
#define MAJOR_NUM_3 102
18
#define MAJOR_NUM_4 103
19
#define MAJOR_NUM_5 104
20
#define MAJOR_NUM_6 105
21
/*
22
* Set the message of the device driver
23
*/
24
#define IOCTL_SET_MSG_1 _IOR(MAJOR_NUM_1, 0, char *)
25
#define IOCTL_SET_MSG_2 _IOR(MAJOR_NUM_1, 0, char *)
26
#define IOCTL_SET_MSG_3 _IOR(MAJOR_NUM_1, 0, char *)
27
#define IOCTL_SET_MSG_4 _IOR(MAJOR_NUM_1, 0, char *)
28
#define IOCTL_SET_MSG_5 _IOR(MAJOR_NUM_1, 0, char *)
29
#define IOCTL_SET_MSG_6 _IOR(MAJOR_NUM_1, 0, char *)
30

  
31
ioctl_set_msg_1(int file_desc, char *message);
32
ioctl_set_msg_2(int file_desc, char *message);
33
ioctl_set_msg_3(int file_desc, char *message);
34
ioctl_set_msg_4(int file_desc, char *message);
35
ioctl_set_msg_5(int file_desc, char *message);
36
ioctl_set_msg_6(int file_desc, char *message);
37
void set_device_value(const char *dev,int devIdx);
38

  
39
#endif //DRV_COMM_H
logic/trunk/measurement_reader/src/drv_comm/dev01/generator.h
1
#ifndef GENERATOR_H_INCLUDED
2
#define GENERATOR_H_INCLUDED
3
int generate_value();
4
char *int_to_str(int nbr);
5

  
6
#endif // GENERATOR_H_INCLUDED
logic/trunk/measurement_reader/src/drv_comm/dev01/drv_comm.c
1
/*
2
* ioctl.c − the process to use ioctl's to control the kernel module
3
*
4
* Until now we could have used cat for input and output. But now
5
* we need to do ioctl's, which require writing our own process.
6
*/
7
/*
8
* device specifics, such as ioctl numbers and the
9
* major device file.
10
*/
11
#include "drv_comm.h"
12
#include "generator.h"
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <syslog.h>
16
#include <fcntl.h>	    /* open */
17
#include <unistd.h>	    /* exit */
18
//#include <sys/ioctl.h>  /* ioctl */
19
/*
20
* Functions for the ioctl calls
21
*/
22
ioctl_set_msg_1(int file_desc, char *message)
23
{
24
	int ret_val;
25
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_1, message);
26
	if (ret_val < 0) {
27
		printf("ioctl_set_msg failed:%d\n", ret_val);
28
		exit(-1);
29
	}
30
}
31

  
32
ioctl_set_msg_2(int file_desc, char *message)
33
{
34
	int ret_val;
35
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_2, message);
36
	if (ret_val < 0) {
37
		printf("ioctl_set_msg failed:%d\n", ret_val);
38
		exit(-1);
39
	}
40
}
41

  
42
ioctl_set_msg_3(int file_desc, char *message)
43
{
44
	int ret_val;
45
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_3, message);
46
	if (ret_val < 0) {
47
		printf("ioctl_set_msg failed:%d\n", ret_val);
48
		exit(-1);
49
	}
50
}
51

  
52
ioctl_set_msg_4(int file_desc, char *message)
53
{
54
	int ret_val;
55
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_4, message);
56
	if (ret_val < 0) {
57
		printf("ioctl_set_msg failed:%d\n", ret_val);
58
		exit(-1);
59
	}
60
}
61

  
62
ioctl_set_msg_5(int file_desc, char *message)
63
{
64
	int ret_val;
65
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_5, message);
66
	if (ret_val < 0) {
67
		printf("ioctl_set_msg failed:%d\n", ret_val);
68
		exit(-1);
69
	}
70
}
71

  
72
ioctl_set_msg_6(int file_desc, char *message)
73
{
74
	int ret_val;
75
	ret_val = ioctl(file_desc, IOCTL_SET_MSG_6, message);
76
	if (ret_val < 0) {
77
		printf("ioctl_set_msg failed:%d\n", ret_val);
78
		exit(-1);
79
	}
80
}
81

  
82
void set_device_value(const char *dev, int devIdx)
83
{
84
    //TODO use mutex?
85
    int file_desc;
86

  
87
	char *msg = int_to_str(generate_value());
88

  
89
	file_desc = open(dev, 0);
90

  
91
	if (file_desc < 0) {
92
		printf("Can't open device file: %s\n", dev);
93
	}
94
	else{
95
		//printf("Open device file: %s\n", dev);
96
		switch(devIdx)
97
		{
98
		    case 1:
99
                //printf("Setting message dev %d\n", devIdx);
100
                ioctl_set_msg_1(file_desc, msg);
101
                break;
102
		    case 2:
103
                //printf("Setting message dev %d\n", devIdx);
104
                ioctl_set_msg_2(file_desc, msg);
105
                break;
106
		    case 3:
107
                //printf("Setting message dev %d\n", devIdx);
108
                ioctl_set_msg_3(file_desc, msg);
109
                break;
110
		    case 4:
111
                //printf("Setting message dev %d\n", devIdx);
112
                ioctl_set_msg_4(file_desc, msg);
113
                break;
114
		    case 5:
115
                //printf("Setting message dev %d\n", devIdx);
116
                ioctl_set_msg_5(file_desc, msg);
117
                break;
118
		    case 6:
119
                //printf("Setting message dev %d\n", devIdx);
120
                ioctl_set_msg_6(file_desc, msg);
121
                break;
122

  
123
		}
124
        syslog(LOG_MAIL, "%s:%s", dev, msg);
125
        // TODO syslog
126
	}
127

  
128
	close(file_desc);
129
}
130

  
logic/trunk/measurement_reader/src/drv_comm/dev01/generator.c
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <time.h>
4
#include <string.h>
5
#include <unistd.h>
6

  
7
#include "generator.h"
8

  
9
//funkcija:
10
int generate_value() {
11
	// nastavitev, minimalne in maksimalne temperature:
12
	//funkcija, torej od ure 00:00 raste od minimalne do maximalne, ki jo doseže pri uri 12:00 in nato spet pada do minimalne pri 24:00
13
	double minimum=20;
14
	double maximum=27;
15

  
16
	time_t     now;
17
    struct tm  *ts;
18
    char       buf1[80];
19

  
20
    now = time(NULL);
21

  
22
    ts = localtime(&now);
23
    strcpy(buf1, asctime(ts));
24

  
25
	int x1 = buf1[11]-48;
26
	int x2 = buf1[12]-48;
27
	int m1 = buf1[14]-48;
28
	int m2 = buf1[15]-48;
29

  
30
	int minutes = (x1*10+x2)*60 + m1*10+m2;
31
	int variable = minutes;
32

  
33
	if(variable>720) {
34
        variable= 720-(variable-720);
35
	}
36

  
37
	double k = ((double)variable)/((double)720);
38

  
39
    //funkcija vraca vrednost na eno decimalko natancno, podobno kot preproste i2c naprave
40
	return (int) (minimum + k * (maximum-minimum))*10;
41
}
42
//*
43
char *int_to_str(int nbr)
44
{
45
  int   div;
46
  int   len;
47
  int   i;
48
  char  *res;
49

  
50
  res = malloc(4 * sizeof(*res));
51
  i = 0;
52
  while (i < 3)
53
    res[i++] = '\0';
54
  res[3] = '\0';
55
  i = 0;
56
  div = 1;
57
  len = 1;
58
  while (nbr / div >= 10)
59
    {
60
      div *= 10;
61
      len++;
62
    }
63
  while (len)
64
    {
65
      res[i++] = '0' + (nbr / div);
66
      len--;
67
      nbr %= div;
68
      div /= 10;
69
    }
70
  return (res);
71
}
72
/**/
logic/trunk/measurement_reader/measurement_reader.cbp
1
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2
<CodeBlocks_project_file>
3
	<FileVersion major="1" minor="6" />
4
	<Project>
5
		<Option title="measurement_reader" />
6
		<Option pch_mode="2" />
7
		<Option compiler="gcc" />
8
		<Build>
9
			<Target title="Debug">
10
				<Option output="bin/Debug/measurement_reader" prefix_auto="1" extension_auto="1" />
11
				<Option object_output="obj/Debug/" />
12
				<Option type="1" />
13
				<Option compiler="gcc" />
14
				<Compiler>
15
					<Add option="-g" />
16
				</Compiler>
17
			</Target>
18
			<Target title="Release">
19
				<Option output="bin/Release/measurement_reader" prefix_auto="1" extension_auto="1" />
20
				<Option object_output="obj/Release/" />
21
				<Option type="1" />
22
				<Option compiler="gcc" />
23
				<Compiler>
24
					<Add option="-O2" />
25
				</Compiler>
26
				<Linker>
27
					<Add option="-s" />
28
				</Linker>
29
			</Target>
30
		</Build>
31
		<Compiler>
32
			<Add option="-Wall" />
33
		</Compiler>
34
		<Unit filename="src/drv_comm/dev01/drv_comm.c">
35
			<Option compilerVar="CC" />
36
		</Unit>
37
		<Unit filename="src/drv_comm/dev01/drv_comm.h" />
38
		<Unit filename="src/drv_comm/dev01/generator.c">
39
			<Option compilerVar="CC" />
40
		</Unit>
41
		<Unit filename="src/drv_comm/dev01/generator.h" />
42
		<Unit filename="src/startup/main.c">
43
			<Option compilerVar="CC" />
44
		</Unit>
45
		<Extensions>
46
			<code_completion />
47
			<debugger />
48
		</Extensions>
49
	</Project>
50
</CodeBlocks_project_file>
logic/trunk/measurement_reader/Makefile
1
# 
2
# 2011, Aleksander Besir (alex.besir@gmail.com)
3
#
4

  
5
CC=arm-linux-gcc
6
CFLAGS=-Wall -I. -pthread --sysroot=/home/arm/buildroot-2009.11-fri/output/staging
7
BIN=bin
8
SRC=src
9

  
10
OBJ=$(SRC)/drv_comm/dev01/drv_comm.o $(SRC)/startup/main.o $(SRC)/drv_comm/dev01/generator.o
11

  
12
all: $(BIN)/startup
13

  
14
%.o: %.c
15
	$(CC) -c -o $@ $< $(CFLAGS)
16
	
17
$(BIN)/startup: $(OBJ)
18
	$(CC) -o $(BIN)/measure_writer $^ $(CFLAGS)
logic/trunk/driver/dev02/dev_thermometer_02.c
1
/*
2
* chardev.c − Create an input/output character device
3
*/
4
#include <linux/kernel.h> /* We're doing kernel work */
5
#include <linux/module.h> /* Specifically, a module */
6
#include <linux/fs.h>     /* for get_user and put_user */
7
#include <linux/i2c.h>     /* for get_user and put_user */
8
#include <linux/hwmon.h>     /* for get_user and put_user */
9
#include <linux/err.h>     /* for get_user and put_user */
10
#include <asm/uaccess.h>
11
#include "dev_thermometer_02.h"
12

  
13
#define SUCCESS 0
14
#define DEVICE_NAME "dev_thermometer_01"
15
#define BUF_LEN 80
16
/*
17
* Is the device open right now? Used to prevent
18
* concurent access into the same device
19
*/
20
static int Device_Open = 0;
21
/*
22
* The message the device will give when asked
23
*/
24
static char Message[BUF_LEN];
25
/*
26
* How far did the process reading the message get?
27
* Useful if the message is larger than the size of the
28
* buffer we get to fill in device_read.
29
*/
30
static char *Message_Ptr;
31
/*
32
* This is called whenever a process attempts to open the device file
33
*/
34
static int device_open(struct inode *inode, struct file *file)
35
{
36
	#ifdef DEBUG
37
	printk(KERN_INFO "device_open(%p)\n", file);
38
	#endif
39
	/*
40
	* We don't want to talk to two processes at the same time
41
	*/
42
	if (Device_Open)
43
		return -EBUSY;
44
	Device_Open++;
45
	/*
46
	* Initialize the message
47
	*/
48
	Message_Ptr = Message;
49
	try_module_get(THIS_MODULE);
50
	return SUCCESS;
51
}
52

  
53
static int device_release(struct inode *inode, struct file *file)
54
{
55
	#ifdef DEBUG
56
	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
57
	#endif
58
	/*
59
	* We're now ready for our next caller
60
	*/
61
	Device_Open--;
62
	module_put(THIS_MODULE);
63
	return SUCCESS;
64
}
65

  
66
/*
67
* This function is called whenever a process which has already opened the
68
* device file attempts to read from it.
69
*/
70
static ssize_t device_read(struct file *file,
71
				/* see include/linux/fs.h*/
72
				char __user * buffer,
73
				/* buffer to be
74
				* filled with data */
75
				size_t length,
76
				loff_t * offset)
77
				/* length of the buffer*/
78
{
79
	/*
80
	* Number of bytes actually written to the buffer
81
	*/
82
	int bytes_read = 0;
83
	#ifdef DEBUG
84
	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
85
	#endif
86
	/*
87
	* If we're at the end of the message, return 0
88
	* (which signifies end of file)
89
	*/
90
	if (*Message_Ptr == 0)
91
		return 0;
92
	/*
93
	* Actually put the data into the buffer
94
	*/
95
	while (length && *Message_Ptr) {
96
		/*
97
		* Because the buffer is in the user data segment,
98
		* not the kernel data segment, assignment wouldn't
99
		* work. Instead, we have to use put_user which
100
		* copies data from the kernel data segment to the
101
		* user data segment.
102
		*/
103
		put_user(*(Message_Ptr++), buffer++);
104
		length--;
105
		bytes_read++;
106
	}
107
	#ifdef DEBUG
108
	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
109
	#endif
110
	/*
111
	* Read functions are supposed to return the number
112
	* of bytes actually inserted into the buffer
113
	*/
114
	return bytes_read;
115
}
116

  
117
/*
118
* This function is called when somebody tries to
119
* write into our device file.
120
*/
121
static ssize_t
122
device_write(struct file *file,
123
const char __user * buffer, size_t length, loff_t * offset)
124
{
125
	int i;
126
	#ifdef DEBUG
127
	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
128
	#endif
129
	for (i = 0; i < length && i < BUF_LEN; i++)
130
		get_user(Message[i], buffer + i);
131
	Message_Ptr = Message;
132
	/*
133
	* Again, return the number of input characters used
134
	*/
135
	return i;
136
}
137

  
138
/*
139
* This function is called whenever a process tries to do an ioctl on our
140
* device file. We get two extra parameters (additional to the inode and file
141
* structures, which all device functions get): the number of the ioctl called
142
* and the parameter given to the ioctl function.
143
*
144
* If the ioctl is write or read/write (meaning output is returned to the
145
* calling process), the ioctl call returns the output of this function.
146
*
147
*/
148
int device_ioctl(struct inode *inode,
149
	/* see include/linux/fs.h */
150
	struct file *file,
151
	/* ditto */
152
	unsigned int ioctl_num,
153
	/* number and param for ioctl */
154
	unsigned long ioctl_param)
155
{
156
	int i;
157
	char *temp;
158
	char ch;
159
	/*
160
	* Switch according to the ioctl called
161
	*/
162
	switch (ioctl_num) {
163
	case IOCTL_SET_MSG:
164
		/*
165
		* Receive a pointer to a message (in user space) and set that
166
		* to be the device's message. Get the parameter given to
167
		* ioctl by the process.
168
		*/
169
		temp = (char *)ioctl_param;
170
		/*
171
		* Find the length of the message
172
		*/
173
		get_user(ch, temp);
174
		for (i = 0; ch && i < BUF_LEN; i++, temp++)
175
			get_user(ch, temp);
176
		device_write(file, (char *)ioctl_param, i, 0);
177
		break;
178
	case IOCTL_GET_MSG:
179
		/*
180
		* Give the current message to the calling process −
181
		* the parameter we got is a pointer, fill it.
182
		*/
183
		i = device_read(file, (char *)ioctl_param, 99, 0);
184
		/*
185
		* Put a zero at the end of the buffer, so it will be
186
		* properly terminated
187
		*/
188
		put_user('\0', (char *)ioctl_param + i);
189
		break;
190
	case IOCTL_GET_NTH_BYTE:
191
		/*
192
		* This ioctl is both input (ioctl_param) and
193
		* output (the return value of this function)
194
		*/
195
		return Message[ioctl_param];
196
		break;
197
	}
198
	return SUCCESS;
199
}
200

  
201
/* Module Declarations */
202
/*
203
* This structure will hold the functions to be called
204
* when a process does something to the device we
205
* created. Since a pointer to this structure is kept in
206
* the devices table, it can't be local to
207
* init_module. NULL is for unimplemented functions.
208
*/
209
struct file_operations Fops = {
210
	.read = device_read,
211
	.write = device_write,
212
	.ioctl = device_ioctl,
213
	.open = device_open,
214
	.release = device_release,
215
	/* a.k.a. close */
216
};
217

  
218
/*
219
* Initialize the module − Register the character device
220
*/
221
int init_module()
222
{
223
	int ret_val;
224
	/*
225
	* Register the character device (atleast try)
226
	*/
227
	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
228
	/*
229
	* Negative values signify an error
230
	*/
231
	if (ret_val < 0) {
232
		printk(KERN_ALERT "%s failed with %d\n",
233
		"Sorry, registering the character device ", ret_val);
234
		return ret_val;
235
	}
236
	printk(KERN_INFO "%s The major device number is %d.\n",
237
	"Registeration is a success", MAJOR_NUM);
238
	return 0;
239
}
240

  
241
/*
242
* Cleanup − unregister the appropriate file from /proc
243
*/
244
void cleanup_module()
245
{
246
	//int ret;
247
	/*
248
	* Unregister the device
249
	*/
250
	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
251
    printk(KERN_INFO "Unregistering module.\n");
252
	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
253
	/*
254
	* If there's an error, report it
255
	*/
256
	/*
257
	if (ret < 0)
258
		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
259
	/**/
260
}
261

  
logic/trunk/driver/dev02/Makefile
1
ifeq ($(KERNELRELEASE),)
2

  
3
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
4
PWD := $(shell pwd)
5

  
6
.PHONY: build clean
7

  
8
build:
9
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
10

  
11
clean:
12
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c  *.symvers *.order
13
else
14

  
15
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
16
obj-m := dev_thermometer_02.o
17

  
18
endif
logic/trunk/driver/dev02/dev_thermometer_02.h
1
/*
2
* chardev.h − the header file with the ioctl definitions.
3
* The declarations here have to be in a header file, because
4
* they need to be known both to the kernel module
5
* (in chardev.c) and the process calling ioctl (ioctl.c)
6
*/
7
#ifndef CHARDEV_H
8
#define CHARDEV_H
9
#include <linux/ioctl.h>
10
/*
11
* The major device number. We can't rely on dynamic
12
* registration any more, because ioctls need to know
13
* it.
14
*/
15
#define MAJOR_NUM 101
16
/*
17
* Set the message of the device driver
18
*/
19
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
20
/*
21
* _IOR means that we're creating an ioctl command
22
* number for passing information from a user process
23
* to the kernel module.
24
*
25
* The first arguments, MAJOR_NUM, is the major device
26
* number we're using.
27
*
28
* The second argument is the number of the command
29
* (there could be several with different meanings).
30
*
31
* The third argument is the type we want to get from
32
* the process to the kernel.
33
*/
34
/*
35
* Get the message of the device driver
36
*/
37
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
38
/*
39
* This IOCTL is used for output, to get the message
40
* of the device driver. However, we still need the
41
* buffer to place the message in to be input,
42
* as it is allocated by the process.
43
*/
44
/*
45
* Get the n'th byte of the message
46
*/
47
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
48
/*
49
* The IOCTL is used for both input and output. It
50
* receives from the user a number, n, and returns
51
* Message[n].
52
*/
53
/*
54
* The name of the device file
55
*/
56
#define DEVICE_FILE_NAME "char_dev"
57
#endif
58

  
logic/trunk/driver/dev03/Makefile
1
ifeq ($(KERNELRELEASE),)
2

  
3
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
4
PWD := $(shell pwd)
5

  
6
.PHONY: build clean
7

  
8
build:
9
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
10

  
11
clean:
12
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
13
else
14

  
15
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
16
obj-m := dev_barometer_01.o
17

  
18
endif
logic/trunk/driver/dev03/dev_barometer_01.c
1
/*
2
* chardev.c − Create an input/output character device
3
*/
4
#include <linux/kernel.h> /* We're doing kernel work */
5
#include <linux/module.h> /* Specifically, a module */
6
#include <linux/fs.h>     /* for get_user and put_user */
7
#include <linux/i2c.h>     /* for get_user and put_user */
8
#include <linux/hwmon.h>     /* for get_user and put_user */
9
#include <linux/err.h>     /* for get_user and put_user */
10
#include <asm/uaccess.h>
11
#include "dev_barometer_01.h"
12

  
13
#define SUCCESS 0
14
#define DEVICE_NAME "dev_thermometer_01"
15
#define BUF_LEN 80
16
/*
17
* Is the device open right now? Used to prevent
18
* concurent access into the same device
19
*/
20
static int Device_Open = 0;
21
/*
22
* The message the device will give when asked
23
*/
24
static char Message[BUF_LEN];
25
/*
26
* How far did the process reading the message get?
27
* Useful if the message is larger than the size of the
28
* buffer we get to fill in device_read.
29
*/
30
static char *Message_Ptr;
31
/*
32
* This is called whenever a process attempts to open the device file
33
*/
34
static int device_open(struct inode *inode, struct file *file)
35
{
36
	#ifdef DEBUG
37
	printk(KERN_INFO "device_open(%p)\n", file);
38
	#endif
39
	/*
40
	* We don't want to talk to two processes at the same time
41
	*/
42
	if (Device_Open)
43
		return -EBUSY;
44
	Device_Open++;
45
	/*
46
	* Initialize the message
47
	*/
48
	Message_Ptr = Message;
49
	try_module_get(THIS_MODULE);
50
	return SUCCESS;
51
}
52

  
53
static int device_release(struct inode *inode, struct file *file)
54
{
55
	#ifdef DEBUG
56
	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
57
	#endif
58
	/*
59
	* We're now ready for our next caller
60
	*/
61
	Device_Open--;
62
	module_put(THIS_MODULE);
63
	return SUCCESS;
64
}
65

  
66
/*
67
* This function is called whenever a process which has already opened the
68
* device file attempts to read from it.
69
*/
70
static ssize_t device_read(struct file *file,
71
				/* see include/linux/fs.h*/
72
				char __user * buffer,
73
				/* buffer to be
74
				* filled with data */
75
				size_t length,
76
				loff_t * offset)
77
				/* length of the buffer*/
78
{
79
	/*
80
	* Number of bytes actually written to the buffer
81
	*/
82
	int bytes_read = 0;
83
	#ifdef DEBUG
84
	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
85
	#endif
86
	/*
87
	* If we're at the end of the message, return 0
88
	* (which signifies end of file)
89
	*/
90
	if (*Message_Ptr == 0)
91
		return 0;
92
	/*
93
	* Actually put the data into the buffer
94
	*/
95
	while (length && *Message_Ptr) {
96
		/*
97
		* Because the buffer is in the user data segment,
98
		* not the kernel data segment, assignment wouldn't
99
		* work. Instead, we have to use put_user which
100
		* copies data from the kernel data segment to the
101
		* user data segment.
102
		*/
103
		put_user(*(Message_Ptr++), buffer++);
104
		length--;
105
		bytes_read++;
106
	}
107
	#ifdef DEBUG
108
	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
109
	#endif
110
	/*
111
	* Read functions are supposed to return the number
112
	* of bytes actually inserted into the buffer
113
	*/
114
	return bytes_read;
115
}
116

  
117
/*
118
* This function is called when somebody tries to
119
* write into our device file.
120
*/
121
static ssize_t
122
device_write(struct file *file,
123
const char __user * buffer, size_t length, loff_t * offset)
124
{
125
	int i;
126
	#ifdef DEBUG
127
	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
128
	#endif
129
	for (i = 0; i < length && i < BUF_LEN; i++)
130
		get_user(Message[i], buffer + i);
131
	Message_Ptr = Message;
132
	/*
133
	* Again, return the number of input characters used
134
	*/
135
	return i;
136
}
137

  
138
/*
139
* This function is called whenever a process tries to do an ioctl on our
140
* device file. We get two extra parameters (additional to the inode and file
141
* structures, which all device functions get): the number of the ioctl called
142
* and the parameter given to the ioctl function.
143
*
144
* If the ioctl is write or read/write (meaning output is returned to the
145
* calling process), the ioctl call returns the output of this function.
146
*
147
*/
148
int device_ioctl(struct inode *inode,
149
	/* see include/linux/fs.h */
150
	struct file *file,
151
	/* ditto */
152
	unsigned int ioctl_num,
153
	/* number and param for ioctl */
154
	unsigned long ioctl_param)
155
{
156
	int i;
157
	char *temp;
158
	char ch;
159
	/*
160
	* Switch according to the ioctl called
161
	*/
162
	switch (ioctl_num) {
163
	case IOCTL_SET_MSG:
164
		/*
165
		* Receive a pointer to a message (in user space) and set that
166
		* to be the device's message. Get the parameter given to
167
		* ioctl by the process.
168
		*/
169
		temp = (char *)ioctl_param;
170
		/*
171
		* Find the length of the message
172
		*/
173
		get_user(ch, temp);
174
		for (i = 0; ch && i < BUF_LEN; i++, temp++)
175
			get_user(ch, temp);
176
		device_write(file, (char *)ioctl_param, i, 0);
177
		break;
178
	case IOCTL_GET_MSG:
179
		/*
180
		* Give the current message to the calling process −
181
		* the parameter we got is a pointer, fill it.
182
		*/
183
		i = device_read(file, (char *)ioctl_param, 99, 0);
184
		/*
185
		* Put a zero at the end of the buffer, so it will be
186
		* properly terminated
187
		*/
188
		put_user('\0', (char *)ioctl_param + i);
189
		break;
190
	case IOCTL_GET_NTH_BYTE:
191
		/*
192
		* This ioctl is both input (ioctl_param) and
193
		* output (the return value of this function)
194
		*/
195
		return Message[ioctl_param];
196
		break;
197
	}
198
	return SUCCESS;
199
}
200

  
201
/* Module Declarations */
202
/*
203
* This structure will hold the functions to be called
204
* when a process does something to the device we
205
* created. Since a pointer to this structure is kept in
206
* the devices table, it can't be local to
207
* init_module. NULL is for unimplemented functions.
208
*/
209
struct file_operations Fops = {
210
	.read = device_read,
211
	.write = device_write,
212
	.ioctl = device_ioctl,
213
	.open = device_open,
214
	.release = device_release,
215
	/* a.k.a. close */
216
};
217

  
218
/*
219
* Initialize the module − Register the character device
220
*/
221
int init_module()
222
{
223
	int ret_val;
224
	/*
225
	* Register the character device (atleast try)
226
	*/
227
	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
228
	/*
229
	* Negative values signify an error
230
	*/
231
	if (ret_val < 0) {
232
		printk(KERN_ALERT "%s failed with %d\n",
233
		"Sorry, registering the character device ", ret_val);
234
		return ret_val;
235
	}
236
	printk(KERN_INFO "%s The major device number is %d.\n",
237
	"Registeration is a success", MAJOR_NUM);
238
	return 0;
239
}
240

  
241
/*
242
* Cleanup − unregister the appropriate file from /proc
243
*/
244
void cleanup_module()
245
{
246
	//int ret;
247
	/*
248
	* Unregister the device
249
	*/
250
	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
251
    printk(KERN_INFO "Unregistering module.\n");
252
	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
253
	/*
254
	* If there's an error, report it
255
	*/
256
	/*
257
	if (ret < 0)
258
		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
259
	/**/
260
}
261

  
logic/trunk/driver/dev03/dev_barometer_01.h
1
/*
2
* chardev.h − the header file with the ioctl definitions.
3
* The declarations here have to be in a header file, because
4
* they need to be known both to the kernel module
5
* (in chardev.c) and the process calling ioctl (ioctl.c)
6
*/
7
#ifndef CHARDEV_H
8
#define CHARDEV_H
9
#include <linux/ioctl.h>
10
/*
11
* The major device number. We can't rely on dynamic
12
* registration any more, because ioctls need to know
13
* it.
14
*/
15
#define MAJOR_NUM 102
16
/*
17
* Set the message of the device driver
18
*/
19
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
20
/*
21
* _IOR means that we're creating an ioctl command
22
* number for passing information from a user process
23
* to the kernel module.
24
*
25
* The first arguments, MAJOR_NUM, is the major device
26
* number we're using.
27
*
28
* The second argument is the number of the command
29
* (there could be several with different meanings).
30
*
31
* The third argument is the type we want to get from
32
* the process to the kernel.
33
*/
34
/*
35
* Get the message of the device driver
36
*/
37
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
38
/*
39
* This IOCTL is used for output, to get the message
40
* of the device driver. However, we still need the
41
* buffer to place the message in to be input,
42
* as it is allocated by the process.
43
*/
44
/*
45
* Get the n'th byte of the message
46
*/
47
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
48
/*
49
* The IOCTL is used for both input and output. It
50
* receives from the user a number, n, and returns
51
* Message[n].
52
*/
53
/*
54
* The name of the device file
55
*/
56
#define DEVICE_FILE_NAME "char_dev"
57
#endif
58

  
logic/trunk/driver/dev04/dev_hygrometer_01.h
1
/*
2
* chardev.h − the header file with the ioctl definitions.
3
* The declarations here have to be in a header file, because
4
* they need to be known both to the kernel module
5
* (in chardev.c) and the process calling ioctl (ioctl.c)
6
*/
7
#ifndef CHARDEV_H
8
#define CHARDEV_H
9
#include <linux/ioctl.h>
10
/*
11
* The major device number. We can't rely on dynamic
12
* registration any more, because ioctls need to know
13
* it.
14
*/
15
#define MAJOR_NUM 103
16
/*
17
* Set the message of the device driver
18
*/
19
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
20
/*
21
* _IOR means that we're creating an ioctl command
22
* number for passing information from a user process
23
* to the kernel module.
24
*
25
* The first arguments, MAJOR_NUM, is the major device
26
* number we're using.
27
*
28
* The second argument is the number of the command
29
* (there could be several with different meanings).
30
*
31
* The third argument is the type we want to get from
32
* the process to the kernel.
33
*/
34
/*
35
* Get the message of the device driver
36
*/
37
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
38
/*
39
* This IOCTL is used for output, to get the message
40
* of the device driver. However, we still need the
41
* buffer to place the message in to be input,
42
* as it is allocated by the process.
43
*/
44
/*
45
* Get the n'th byte of the message
46
*/
47
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
48
/*
49
* The IOCTL is used for both input and output. It
50
* receives from the user a number, n, and returns
51
* Message[n].
52
*/
53
/*
54
* The name of the device file
55
*/
56
#define DEVICE_FILE_NAME "char_dev"
57
#endif
58

  
logic/trunk/driver/dev04/Makefile
1
ifeq ($(KERNELRELEASE),)
2

  
3
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
4
PWD := $(shell pwd)
5

  
6
.PHONY: build clean
7

  
8
build:
9
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
10

  
11
clean:
12
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers *.order
13
else
14

  
15
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
16
obj-m := dev_hygrometer_01.o
17

  
18
endif
logic/trunk/driver/dev04/dev_hygrometer_01.c
1
/*
2
* chardev.c − Create an input/output character device
3
*/
4
#include <linux/kernel.h> /* We're doing kernel work */
5
#include <linux/module.h> /* Specifically, a module */
6
#include <linux/fs.h>     /* for get_user and put_user */
7
#include <linux/i2c.h>     /* for get_user and put_user */
8
#include <linux/hwmon.h>     /* for get_user and put_user */
9
#include <linux/err.h>     /* for get_user and put_user */
10
#include <asm/uaccess.h>
11
#include "dev_hygrometer_01.h"
12

  
13
#define SUCCESS 0
14
#define DEVICE_NAME "dev_thermometer_01"
15
#define BUF_LEN 80
16
/*
17
* Is the device open right now? Used to prevent
18
* concurent access into the same device
19
*/
20
static int Device_Open = 0;
21
/*
22
* The message the device will give when asked
23
*/
24
static char Message[BUF_LEN];
25
/*
26
* How far did the process reading the message get?
27
* Useful if the message is larger than the size of the
28
* buffer we get to fill in device_read.
29
*/
30
static char *Message_Ptr;
31
/*
32
* This is called whenever a process attempts to open the device file
33
*/
34
static int device_open(struct inode *inode, struct file *file)
35
{
36
	#ifdef DEBUG
37
	printk(KERN_INFO "device_open(%p)\n", file);
38
	#endif
39
	/*
40
	* We don't want to talk to two processes at the same time
41
	*/
42
	if (Device_Open)
43
		return -EBUSY;
44
	Device_Open++;
45
	/*
46
	* Initialize the message
47
	*/
48
	Message_Ptr = Message;
49
	try_module_get(THIS_MODULE);
50
	return SUCCESS;
51
}
52

  
53
static int device_release(struct inode *inode, struct file *file)
54
{
55
	#ifdef DEBUG
56
	printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
57
	#endif
58
	/*
59
	* We're now ready for our next caller
60
	*/
61
	Device_Open--;
62
	module_put(THIS_MODULE);
63
	return SUCCESS;
64
}
65

  
66
/*
67
* This function is called whenever a process which has already opened the
68
* device file attempts to read from it.
69
*/
70
static ssize_t device_read(struct file *file,
71
				/* see include/linux/fs.h*/
72
				char __user * buffer,
73
				/* buffer to be
74
				* filled with data */
75
				size_t length,
76
				loff_t * offset)
77
				/* length of the buffer*/
78
{
79
	/*
80
	* Number of bytes actually written to the buffer
81
	*/
82
	int bytes_read = 0;
83
	#ifdef DEBUG
84
	printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
85
	#endif
86
	/*
87
	* If we're at the end of the message, return 0
88
	* (which signifies end of file)
89
	*/
90
	if (*Message_Ptr == 0)
91
		return 0;
92
	/*
93
	* Actually put the data into the buffer
94
	*/
95
	while (length && *Message_Ptr) {
96
		/*
97
		* Because the buffer is in the user data segment,
98
		* not the kernel data segment, assignment wouldn't
99
		* work. Instead, we have to use put_user which
100
		* copies data from the kernel data segment to the
101
		* user data segment.
102
		*/
103
		put_user(*(Message_Ptr++), buffer++);
104
		length--;
105
		bytes_read++;
106
	}
107
	#ifdef DEBUG
108
	printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
109
	#endif
110
	/*
111
	* Read functions are supposed to return the number
112
	* of bytes actually inserted into the buffer
113
	*/
114
	return bytes_read;
115
}
116

  
117
/*
118
* This function is called when somebody tries to
119
* write into our device file.
120
*/
121
static ssize_t
122
device_write(struct file *file,
123
const char __user * buffer, size_t length, loff_t * offset)
124
{
125
	int i;
126
	#ifdef DEBUG
127
	printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
128
	#endif
129
	for (i = 0; i < length && i < BUF_LEN; i++)
130
		get_user(Message[i], buffer + i);
131
	Message_Ptr = Message;
132
	/*
133
	* Again, return the number of input characters used
134
	*/
135
	return i;
136
}
137

  
138
/*
139
* This function is called whenever a process tries to do an ioctl on our
140
* device file. We get two extra parameters (additional to the inode and file
141
* structures, which all device functions get): the number of the ioctl called
142
* and the parameter given to the ioctl function.
143
*
144
* If the ioctl is write or read/write (meaning output is returned to the
145
* calling process), the ioctl call returns the output of this function.
146
*
147
*/
148
int device_ioctl(struct inode *inode,
149
	/* see include/linux/fs.h */
150
	struct file *file,
151
	/* ditto */
152
	unsigned int ioctl_num,
153
	/* number and param for ioctl */
154
	unsigned long ioctl_param)
155
{
156
	int i;
157
	char *temp;
158
	char ch;
159
	/*
160
	* Switch according to the ioctl called
161
	*/
162
	switch (ioctl_num) {
163
	case IOCTL_SET_MSG:
164
		/*
165
		* Receive a pointer to a message (in user space) and set that
166
		* to be the device's message. Get the parameter given to
167
		* ioctl by the process.
168
		*/
169
		temp = (char *)ioctl_param;
170
		/*
171
		* Find the length of the message
172
		*/
173
		get_user(ch, temp);
174
		for (i = 0; ch && i < BUF_LEN; i++, temp++)
175
			get_user(ch, temp);
176
		device_write(file, (char *)ioctl_param, i, 0);
177
		break;
178
	case IOCTL_GET_MSG:
179
		/*
180
		* Give the current message to the calling process −
181
		* the parameter we got is a pointer, fill it.
182
		*/
183
		i = device_read(file, (char *)ioctl_param, 99, 0);
184
		/*
185
		* Put a zero at the end of the buffer, so it will be
186
		* properly terminated
187
		*/
188
		put_user('\0', (char *)ioctl_param + i);
189
		break;
190
	case IOCTL_GET_NTH_BYTE:
191
		/*
192
		* This ioctl is both input (ioctl_param) and
193
		* output (the return value of this function)
194
		*/
195
		return Message[ioctl_param];
196
		break;
197
	}
198
	return SUCCESS;
199
}
200

  
201
/* Module Declarations */
202
/*
203
* This structure will hold the functions to be called
204
* when a process does something to the device we
205
* created. Since a pointer to this structure is kept in
206
* the devices table, it can't be local to
207
* init_module. NULL is for unimplemented functions.
208
*/
209
struct file_operations Fops = {
210
	.read = device_read,
211
	.write = device_write,
212
	.ioctl = device_ioctl,
213
	.open = device_open,
214
	.release = device_release,
215
	/* a.k.a. close */
216
};
217

  
218
/*
219
* Initialize the module − Register the character device
220
*/
221
int init_module()
222
{
223
	int ret_val;
224
	/*
225
	* Register the character device (atleast try)
226
	*/
227
	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
228
	/*
229
	* Negative values signify an error
230
	*/
231
	if (ret_val < 0) {
232
		printk(KERN_ALERT "%s failed with %d\n",
233
		"Sorry, registering the character device ", ret_val);
234
		return ret_val;
235
	}
236
	printk(KERN_INFO "%s The major device number is %d.\n",
237
	"Registeration is a success", MAJOR_NUM);
238
	return 0;
239
}
240

  
241
/*
242
* Cleanup − unregister the appropriate file from /proc
243
*/
244
void cleanup_module()
245
{
246
	//int ret;
247
	/*
248
	* Unregister the device
249
	*/
250
	//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
251
    printk(KERN_INFO "Unregistering module.\n");
252
	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
253
	/*
254
	* If there's an error, report it
255
	*/
256
	/*
257
	if (ret < 0)
258
		printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
259
	/**/
260
}
261

  
logic/trunk/driver/dev05/dev_light_sensor_01.h
1
/*
2
* chardev.h − the header file with the ioctl definitions.
3
* The declarations here have to be in a header file, because
4
* they need to be known both to the kernel module
5
* (in chardev.c) and the process calling ioctl (ioctl.c)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff