-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcom.c
147 lines (119 loc) · 2.57 KB
/
com.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <linux/module.h>
#include <linux/init.h>
#include <linux/in.h>
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/inet.h>
#include <linux/uio.h>
#include <linux/version.h>
#include "msg.h"
#include "com.h"
#include "com_udp.h"
#include "debug.h"
#define MAX_SIZE_MSG 16000
typedef struct internal_com_t {
com_init_fn init;
com_close_fn close;
com_send_fn send;
com_recv_fn recv;
} internal_com_t;
/* Default operations */
static internal_com_t conf_com = {
(com_init_fn)udp_com_init,
(com_close_fn)udp_com_close,
(com_send_fn)udp_com_send,
(com_recv_fn)udp_com_recv
};
typedef struct {
struct work_struct work;
void *com;
} recv_wq_t;
/*
Function executed by workqueue
*/
static void
com_recv(struct work_struct *data)
{
recv_wq_t *work = (recv_wq_t *)data;
com_t *com = (com_t*)work->com;
ssize_t sz;
sz = conf_com.recv(com->state,com->msg);
if (sz < 0) {
com_log(com->id,ERR,"Unable to receive data from userland (err:%d)",sz);
return;
} else if (!check_msg(com->msg)) {
com_log(com->id,ERR,"Invalid structure of message");
return;
} else if (sz == 0) {
return;
} else {
com->cb_recv(com->msg);
}
}
/*
Called when a message arrives
*/
static void
wq_recv(com_t *com)
{
recv_wq_t *work;
work = kmalloc(sizeof *work, GFP_KERNEL);
if(!work) {
com_log("COM",ERR,"Unable to allocate memory");
return;
}
work->com = com;
INIT_WORK(&work->work, &com_recv);
queue_work(com->wq, (struct work_struct *)work);
}
int
com_send(com_t *com,msg_t *msg)
{
if (!check_msg(msg)) {
com_log(com->id,ERR,"Invalid structure of message, not sending");
return -EINVAL;
}
return conf_com.send(com->state,msg);
}
/*
Init communication
*/
com_t*
com_init(void *opt, int (cb_recv)(msg_t*), const char *name)
{
com_t *com;
com = kmalloc(sizeof *com, GFP_KERNEL);
if (!com) {
goto fail1;
}
com->msg = alloc_msg(MAX_SIZE_MSG,DATA);
if (!com->msg) {
goto fail2;
}
com->cb_recv = cb_recv;
com->state = conf_com.init(com,opt,wq_recv);
if (com->state < 0) {
goto fail3;
}
strncpy(com->id,name,MAX_SIZE_ID);
com->send = com_send;
com->wq = create_workqueue("recv");
return com;
fail3:
free_msg(com->msg);
fail2:
kfree(com);
fail1:
com_log(com->id,ERR,"Unable to allocate memory");
return NULL;
}
void
com_close(com_t *com)
{
flush_workqueue(com->wq);
destroy_workqueue(com->wq);
conf_com.close(com->state);
free_msg(com->msg);
kfree(com);
}