Revision 71
logic/trunk/eneraptor.cbp | ||
---|---|---|
38 | 38 |
<Add option="-lmxml" /> |
39 | 39 |
<Add library="pthread" /> |
40 | 40 |
</Linker> |
41 |
<Unit filename="src/drv_comm/drv_comm.c"> |
|
42 |
<Option compilerVar="CC" /> |
|
43 |
</Unit> |
|
44 |
<Unit filename="src/drv_comm/drv_comm.h" /> |
|
45 |
<Unit filename="src/drv_comm/generator.c"> |
|
46 |
<Option compilerVar="CC" /> |
|
47 |
</Unit> |
|
48 |
<Unit filename="src/drv_comm/generator.h" /> |
|
41 | 49 |
<Unit filename="src/hci_comm/hciChanged.h" /> |
42 | 50 |
<Unit filename="src/hci_comm/hci_comm.h" /> |
43 | 51 |
<Unit filename="src/hci_comm/hci_comm_listener.c"> |
logic/trunk/src/drv_comm/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 <fcntl.h> /* open */ |
|
16 |
#include <unistd.h> /* exit */ |
|
17 |
//#include <sys/ioctl.h> /* ioctl */ |
|
18 |
/* |
|
19 |
* Functions for the ioctl calls |
|
20 |
*/ |
|
21 |
ioctl_set_msg(int file_desc, char *message) |
|
22 |
{ |
|
23 |
int ret_val; |
|
24 |
ret_val = ioctl(file_desc, IOCTL_SET_MSG, message); |
|
25 |
if (ret_val < 0) { |
|
26 |
printf("ioctl_set_msg failed:%d\n", ret_val); |
|
27 |
exit(-1); |
|
28 |
} |
|
29 |
} |
|
30 |
|
|
31 |
ioctl_get_msg(int file_desc) |
|
32 |
{ |
|
33 |
int ret_val; |
|
34 |
char message[100]; |
|
35 |
/* |
|
36 |
* Warning − this is dangerous because we don't tell |
|
37 |
* the kernel how far it's allowed to write, so it |
|
38 |
* might overflow the buffer. In a real production |
|
39 |
* program, we would have used two ioctls − one to tell |
|
40 |
* the kernel the buffer length and another to give |
|
41 |
* it the buffer to fill |
|
42 |
*/ |
|
43 |
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message); |
|
44 |
if (ret_val < 0) { |
|
45 |
printf("ioctl_get_msg failed:%d\n", ret_val); |
|
46 |
exit(-1); |
|
47 |
} |
|
48 |
//printf("get_msg message:%s\n", message); |
|
49 |
} |
|
50 |
|
|
51 |
int ioctl_get_nth_byte(int file_desc) |
|
52 |
{ |
|
53 |
int i, val; |
|
54 |
char c; |
|
55 |
|
|
56 |
val=0; |
|
57 |
i = 0; |
|
58 |
do { |
|
59 |
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++); |
|
60 |
if (c < 0) { |
|
61 |
printf("ioctl_get_nth_byte failed at the %d'th byte:\n",i); |
|
62 |
exit(-1); |
|
63 |
} |
|
64 |
val=val*10+atoi(&c); |
|
65 |
} while (c != 0); |
|
66 |
return (int)val/10; //because string termination character also gets read in loop we have to divide by 10 |
|
67 |
} |
|
68 |
|
|
69 |
int get_device_value(const char *dev) |
|
70 |
{ |
|
71 |
//TODO use mutex? |
|
72 |
int file_desc, ret_val; |
|
73 |
|
|
74 |
char *msg = int_to_str(generate_value()); |
|
75 |
|
|
76 |
file_desc = open(dev, 0); |
|
77 |
|
|
78 |
if (file_desc < 0) { |
|
79 |
printf("Can't open device file: %s\n", dev); |
|
80 |
ret_val = generate_value(); // TODO fake value in case driver doesnt work |
|
81 |
} |
|
82 |
else{ |
|
83 |
//printf("Open device file: %s\n", dev); |
|
84 |
//ioctl_set_msg(file_desc, msg); |
|
85 |
ret_val = ioctl_get_nth_byte(file_desc); |
|
86 |
} |
|
87 |
|
|
88 |
close(file_desc); |
|
89 |
ret_val = ret_val+((random()%3-1)*5); //+- 5 (conversion to fload needed later) |
|
90 |
printf("Returning val %d\n", ret_val); |
|
91 |
|
|
92 |
return ret_val; |
|
93 |
} |
|
94 |
|
logic/trunk/src/drv_comm/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 dosee 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/src/drv_comm/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 100 |
|
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 "/dev/dev_thermometer_01" |
|
57 |
|
|
58 |
ioctl_set_msg(int file_desc, char *message); |
|
59 |
ioctl_get_msg(int file_desc); |
|
60 |
int ioctl_get_nth_byte(int file_desc); |
|
61 |
int get_device_value(); |
|
62 |
|
|
63 |
#endif //DRV_COMM_H |
logic/trunk/src/drv_comm/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/src/kernel_modules/generic/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 |
|
13 |
else |
|
14 |
|
|
15 |
$(info Building with KERNELRELEASE = ${KERNELRELEASE}) |
|
16 |
obj-m := chardev.o |
|
17 |
|
|
18 |
endif |
logic/trunk/src/kernel_modules/generic/chardev.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 "chardev.h" |
|
12 |
|
|
13 |
#define SUCCESS 0 |
|
14 |
#define DEVICE_NAME "char_dev" |
|
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 |
printk(KERN_INFO "If you want to talk to the device driver,\n"); |
|
239 |
printk(KERN_INFO "you'll have to create a device file. \n"); |
|
240 |
printk(KERN_INFO "We suggest you use:\n"); |
|
241 |
printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM); |
|
242 |
printk(KERN_INFO "The device file name is important, because\n"); |
|
243 |
printk(KERN_INFO "the ioctl program assumes that's the\n"); |
|
244 |
printk(KERN_INFO "file you'll use.\n"); |
|
245 |
return 0; |
|
246 |
} |
|
247 |
|
|
248 |
/* |
|
249 |
* Cleanup − unregister the appropriate file from /proc |
|
250 |
*/ |
|
251 |
void cleanup_module() |
|
252 |
{ |
|
253 |
//int ret; |
|
254 |
/* |
|
255 |
* Unregister the device |
|
256 |
*/ |
|
257 |
//ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME); |
|
258 |
printk(KERN_INFO "Unregistering module.\n"); |
|
259 |
unregister_chrdev(MAJOR_NUM, DEVICE_NAME); |
|
260 |
/* |
|
261 |
* If there's an error, report it |
|
262 |
*/ |
|
263 |
/* |
|
264 |
if (ret < 0) |
|
265 |
printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret); |
|
266 |
/**/ |
|
267 |
} |
|
268 |
|
logic/trunk/src/kernel_modules/generic/chardev.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 100 |
|
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/src/kernel_modules/generic/ioctl.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 "chardev.h" |
|
12 |
#include <stdio.h> |
|
13 |
#include <stdlib.h> |
|
14 |
#include <fcntl.h> /* open */ |
|
15 |
#include <unistd.h> /* exit */ |
|
16 |
#include <sys/ioctl.h> /* ioctl */ |
|
17 |
/* |
|
18 |
* Functions for the ioctl calls |
|
19 |
*/ |
|
20 |
ioctl_set_msg(int file_desc, char *message) |
|
21 |
{ |
|
22 |
int ret_val; |
|
23 |
ret_val = ioctl(file_desc, IOCTL_SET_MSG, message); |
|
24 |
if (ret_val < 0) { |
|
25 |
printf("ioctl_set_msg failed:%d\n", ret_val); |
|
26 |
exit(-1); |
|
27 |
} |
|
28 |
} |
|
29 |
|
|
30 |
ioctl_get_msg(int file_desc) |
|
31 |
{ |
|
32 |
int ret_val; |
|
33 |
char message[100]; |
|
34 |
/* |
|
35 |
* Warning − this is dangerous because we don't tell |
|
36 |
* the kernel how far it's allowed to write, so it |
|
37 |
* might overflow the buffer. In a real production |
|
38 |
* program, we would have used two ioctls − one to tell |
|
39 |
* the kernel the buffer length and another to give |
|
40 |
* it the buffer to fill |
|
41 |
*/ |
|
42 |
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message); |
|
43 |
if (ret_val < 0) { |
|
44 |
printf("ioctl_get_msg failed:%d\n", ret_val); |
|
45 |
exit(-1); |
|
46 |
} |
|
47 |
printf("get_msg message:%s\n", message); |
|
48 |
} |
|
49 |
|
|
50 |
ioctl_get_nth_byte(int file_desc) |
|
51 |
{ |
|
52 |
int i; |
|
53 |
char c; |
|
54 |
printf("get_nth_byte message:"); |
|
55 |
i = 0; |
|
56 |
do { |
|
57 |
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++); |
|
58 |
if (c < 0) { |
|
59 |
printf("ioctl_get_nth_byte failed at the %d'th byte:\n",i); |
|
60 |
exit(-1); |
|
61 |
} |
|
62 |
putchar(c); |
|
63 |
} while (c != 0); |
|
64 |
putchar('\n'); |
|
65 |
} |
|
66 |
|
|
67 |
/* |
|
68 |
* Main − Call the ioctl functions |
|
69 |
*/ |
|
70 |
main() |
|
71 |
{ |
|
72 |
int file_desc, ret_val; |
|
73 |
char *msg = "Message passed by ioctl\n"; |
|
74 |
file_desc = open(DEVICE_FILE_NAME, 0); |
|
75 |
if (file_desc < 0) { |
|
76 |
printf("Can't open device file: %s\n", DEVICE_FILE_NAME); |
|
77 |
exit(-1); |
|
78 |
} |
|
79 |
ioctl_set_msg(file_desc, msg); |
|
80 |
ioctl_get_nth_byte(file_desc); |
|
81 |
ioctl_get_msg(file_desc); |
|
82 |
close(file_desc); |
|
83 |
} |
|
84 |
|
logic/trunk/src/logics/conditions.c | ||
---|---|---|
68 | 68 |
int getPowerPercentage(int a, int b, int o, float *val, int func) |
69 | 69 |
{ |
70 | 70 |
int pwr; |
71 |
printf( "getPowerPercentage(%d, %d, %d, %.2f, %d)\n",a,b,o,*val,func); |
|
71 |
//printf( "getPowerPercentage(%d, %d, %d, %.2f, %d)\n",a,b,o,*val,func); |
|
72 |
|
|
72 | 73 |
if(func == FUNCTION_STATIC) |
73 | 74 |
{ |
74 | 75 |
if(*val>o) // right |
... | ... | |
84 | 85 |
{ |
85 | 86 |
if(*val>o) // right |
86 | 87 |
{ |
87 |
pwr=(int)((*val-o)/(b-o)*100); |
|
88 |
if(*val >= a) |
|
89 |
pwr=100; |
|
90 |
else |
|
91 |
pwr=(int)((*val-o)/(b-o)*100); |
|
88 | 92 |
} |
89 | 93 |
else //left |
90 | 94 |
{ |
91 |
pwr=(int)((1-(*val-a)/(o-a))*100); |
|
95 |
if(*val <= a) |
|
96 |
pwr=0; |
|
97 |
else |
|
98 |
pwr=(int)((1-(*val-a)/(o-a))*100); |
|
92 | 99 |
} |
93 | 100 |
} |
94 |
else if(func == FUNCTION_LOGARITHMIC) |
|
101 |
else if(func == FUNCTION_LOGARITHMIC) //TODO implement log func
|
|
95 | 102 |
{ |
96 | 103 |
if(*val>o) // right |
97 | 104 |
{ |
... | ... | |
102 | 109 |
pwr=(int)((1-(*val-a)/(o-a))*100); |
103 | 110 |
} |
104 | 111 |
} |
105 |
else if(func == FUNCTION_QUADRATIC) |
|
112 |
else if(func == FUNCTION_QUADRATIC) //implement square func
|
|
106 | 113 |
{ |
107 | 114 |
if(*val>o) // right |
108 | 115 |
{ |
logic/trunk/src/startup/main.c | ||
---|---|---|
11 | 11 |
#include <unistd.h> |
12 | 12 |
#include "../hci_comm/hciChanged.h" |
13 | 13 |
#include "../hci_comm/hci_comm.h" |
14 |
#include "../drv_comm/drv_comm.h" |
|
14 | 15 |
#include "../init/scenariolist.h" |
15 | 16 |
#include "../init/devicelist.h" |
16 | 17 |
#include "../logics/device_threads.h" |
... | ... | |
55 | 56 |
int reinitialiseLogic(); // on HCI request |
56 | 57 |
int shutDownLogic(); |
57 | 58 |
|
59 |
// devices |
|
60 |
const char *dev1="/dev/dev_thermometer_01"; |
|
58 | 61 |
// Application entry point |
59 | 62 |
int main(int argc, char *argv[]) { |
60 |
//** //DAEMON
|
|
63 |
/** //DAEMON |
|
61 | 64 |
pid_t pid, sid; |
62 | 65 |
|
63 | 66 |
pid = fork(); |
... | ... | |
167 | 170 |
scenario *scen; |
168 | 171 |
device *inDev; |
169 | 172 |
int active = 0; |
170 |
float scenarioBuffer; |
|
171 | 173 |
//printf("My scen ID> %ld\n",pthread_self()); |
172 | 174 |
|
173 | 175 |
/*load scenario*/ |
... | ... | |
177 | 179 |
// TODO add pointer to this device (all of them actually) to scenario structure - problems with segfault |
178 | 180 |
//indev = scen->inDev; |
179 | 181 |
inDev = getDevice(hDevice, scen->inDevice_id); |
180 |
scen->buf=inDev->buf;
|
|
181 |
printf("Scenario %s buffer updated to %.2f!\n", scen->scen_id, inDev->buf);
|
|
182 |
scen->buf=inDev->buf/10; //TODO make sure buffer values make sense!
|
|
183 |
//printf("Scenario %s buffer updated to %.2f!\n", scen->scen_id, inDev->buf/10);
|
|
182 | 184 |
//set its value |
183 | 185 |
//* |
184 | 186 |
while(1) //TODO signal == true |
185 | 187 |
{ |
186 | 188 |
/// main scenario loop |
187 | 189 |
//printf("inDev->buf %.2f\n", 1.0f*inDev->buf); |
190 |
printf("scen->buf %.2f\n", 1.0f*scen->buf); |
|
188 | 191 |
if(active) |
189 | 192 |
sleep(scen->actvChkItv); |
190 | 193 |
else |
191 | 194 |
sleep(scen->idleChkItv); |
195 |
|
|
192 | 196 |
//checking primary condition |
193 |
if(scen->buf) // is not null |
|
197 |
scen->buf = scen->buf*scen->alpha+inDev->buf*(1-scen->alpha)/10; |
|
198 |
//printf("Scenario %s buffer updated to %.2f, alpha: %.2f!\n", scen->scen_id, scen->buf, scen->alpha); |
|
199 |
syslog(LOG_MAIL, "%s:%.2f", scen->inDevice_id, scen->buf); |
|
200 |
active = 1; |
|
201 |
|
|
202 |
if((scen->buf > scen->optval + scen->tolval) || |
|
203 |
(scen->buf < scen->optval - scen->tolval)) |
|
194 | 204 |
{ |
195 |
scen->buf = scen->buf*scen->alpha+inDev->buf*(1-scen->alpha); |
|
196 |
//printf("Scenario %s buffer updated to %f, alpha: %.2f!\n", scen->scen_id, scenarioBuffer, scen->alpha); |
|
197 |
syslog(LOG_MAIL, "%s:%.2f", scen->inDevice_id, scen->buf); |
|
198 |
active = 1; |
|
199 |
|
|
200 |
if((scen->buf > scen->optval + scen->tolval) || |
|
201 |
(scen->buf < scen->optval - scen->tolval)) |
|
205 |
if(evaluateAdditionalConditions(scen->cond_l, hDevice)) |
|
202 | 206 |
{ |
203 |
if(evaluateAdditionalConditions(scen->cond_l, hDevice)) |
|
204 |
{ |
|
205 |
// TODO syslog - "action:scen_ID:power_percentage" |
|
206 |
int power = getPowerPercentage(scen->minval, scen->maxval, scen->optval, &scen->buf, scen->func); |
|
207 |
// TODO syslog - "action:scen_ID:power_percentage" |
|
208 |
int power = getPowerPercentage(scen->minval, scen->maxval, scen->optval, &scen->buf, scen->func); |
|
207 | 209 |
|
208 |
/// Forking to execute action!
|
|
209 |
pid_t pid, sid;
|
|
210 |
/// Forking to execute action! |
|
211 |
pid_t pid;
|
|
210 | 212 |
|
211 |
pid = fork(); |
|
212 |
if (pid < 0) { |
|
213 |
exit(EXIT_FAILURE); |
|
214 |
} |
|
215 |
// ignore parent |
|
216 |
if (pid > 0) {} |
|
217 |
else |
|
218 |
{ |
|
219 |
/*TODO execute action with parameter(s)*/ |
|
220 |
syslog(LOG_MAIL, "%s:%s:%.2f", scen->action, scen->scen_id, power); |
|
213 |
pid = fork(); |
|
214 |
if (pid < 0) { |
|
215 |
exit(EXIT_FAILURE); |
|
216 |
} |
|
217 |
// ignore parent |
|
218 |
if (pid > 0) { |
|
219 |
} |
|
220 |
else |
|
221 |
{ |
|
222 |
/*TODO execute action with parameter(s)*/ |
|
223 |
syslog(LOG_MAIL, "%s:%s:%.2f", scen->action, scen->scen_id, power); |
|
221 | 224 |
|
222 |
execl(scen->action, power);
|
|
223 |
printf("Zaganjam napravo %s z mocjo %d\n", scen->scen_id, power);
|
|
225 |
execl(scen->action, power); |
|
226 |
printf("Zaganjam napravo %s z mocjo %d\n", scen->scen_id, power); |
|
224 | 227 |
|
225 |
shutDownLogic();
|
|
226 |
}
|
|
228 |
shutDownLogic(); |
|
229 |
} |
|
227 | 230 |
|
228 |
} |
|
229 |
else |
|
230 |
printf("Scenario %s not updated!\n", scen->scen_id); |
|
231 | 231 |
} |
232 | 232 |
else |
233 |
active = 0;
|
|
233 |
printf("Scenario %s not updated, additional conditions false!\n", scen->scen_id);
|
|
234 | 234 |
} |
235 |
else |
|
236 |
active = 0; |
|
235 | 237 |
/* |
236 | 238 |
if(active) |
237 | 239 |
printf("%s main buffer %.2f, sleeping %d\n",scen->scen_id, scen->buf, scen->actvChkItv); |
... | ... | |
254 | 256 |
//set its value |
255 | 257 |
while(1) //TODO signal == true |
256 | 258 |
{ |
257 |
dev->buf=random()%10+20;// random 20-30 |
|
259 |
dev->buf=get_device_value(dev1); |
|
260 |
//dev->buf=random()%10+20;// random 20-30 |
|
258 | 261 |
//printf("device %s buf = %d\n", dev->id, dev->buf); |
259 | 262 |
sleep(dev->readitv); |
260 | 263 |
} |
Also available in: Unified diff