nrfmin_gnrc.c
6.09 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_nrf5x_nrfmin_gnrc
* @{
*
* @file
* @brief GNRC adapter for the nrfmin radio driver
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "net/gnrc.h"
#include "thread.h"
#ifdef MODULE_GNRC_NETIF2
#include "net/gnrc/netif2.h"
#else
#include "net/gnrc/netdev.h"
#endif
#include "nrfmin_gnrc.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Definition of default thread priority and stacksize
* @{
*/
#ifndef NRFMIN_GNRC_THREAD_PRIO
#ifdef MODULE_GNRC_NETIF2
#define NRFMIN_GNRC_THREAD_PRIO GNRC_NETIF2_PRIO
#else
#define NRFMIN_GNRC_THREAD_PRIO GNRC_NETDEV_MAC_PRIO
#endif
#endif
#ifndef NRFMIN_GNRC_STACKSIZE
#define NRFMIN_GNRC_STACKSIZE THREAD_STACKSIZE_DEFAULT
#endif
/** @} */
/**
* @brief
*/
#define BCAST (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)
/**
* @brief Allocate the stack for the GNRC netdev thread to run in
*/
static char stack[NRFMIN_GNRC_STACKSIZE];
#ifndef MODULE_GNRC_NETIF2
/**
* @brief Allocate the GNRC netdev data structure.
*/
static gnrc_netdev_t plug;
#endif
static int hdr_netif_to_nrfmin(nrfmin_hdr_t *nrfmin, gnrc_pktsnip_t *pkt)
{
gnrc_netif_hdr_t *netif = (gnrc_netif_hdr_t *)pkt->data;
if (!(netif->flags & BCAST) && (netif->dst_l2addr_len != 2)) {
return -EINVAL;
}
nrfmin->len = gnrc_pkt_len(pkt->next) + NRFMIN_HDR_LEN;
if (netif->flags & BCAST) {
nrfmin->dst_addr = NRFMIN_ADDR_BCAST;
}
else {
memcpy(&nrfmin->dst_addr, gnrc_netif_hdr_get_dst_addr(netif), 2);
}
nrfmin->src_addr = nrfmin_get_addr();
if (pkt->next) {
nrfmin->proto = (uint8_t)pkt->next->type;
}
else {
nrfmin->proto = 0;
}
return 0;
}
#ifdef MODULE_GNRC_NETIF2
static int gnrc_nrfmin_send(gnrc_netif2_t *dev, gnrc_pktsnip_t *pkt)
#else
static int gnrc_nrfmin_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt)
#endif
{
int res;
struct iovec *vec;
size_t vec_len;
gnrc_pktsnip_t *vec_snip;
nrfmin_hdr_t nrfmin_hdr;
assert(pkt);
if (pkt->type != GNRC_NETTYPE_NETIF) {
DEBUG("[nrfmin_gnrc] send: first header is not generic netif header\n");
return -EBADMSG;
}
/* build the nrfmin header from the generic netif header */
res = hdr_netif_to_nrfmin(&nrfmin_hdr, pkt);
if (res < 0) {
DEBUG("[nrfmin_gnrc] send: failed to build nrfmin header\n");
gnrc_pktbuf_release(pkt);
return res;
}
/* create iovec of data */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &vec_len);
if (vec_snip == NULL) {
DEBUG("[nrfmin_gnrc] send: failed to create IO vector\n");
gnrc_pktbuf_release(pkt);
return -ENOBUFS;
}
/* link first entry of the vector to the nrfmin header */
vec = (struct iovec *)vec_snip->data;
vec[0].iov_base = &nrfmin_hdr;
vec[0].iov_len = NRFMIN_HDR_LEN;
/* and finally send out the data and release the packet */
res = dev->dev->driver->send(dev->dev, vec, vec_len);
gnrc_pktbuf_release(vec_snip);
return res;
}
#ifdef MODULE_GNRC_NETIF2
static gnrc_pktsnip_t *gnrc_nrfmin_recv(gnrc_netif2_t *dev)
#else
static gnrc_pktsnip_t *gnrc_nrfmin_recv(gnrc_netdev_t *dev)
#endif
{
int pktsize;
nrfmin_hdr_t *nrfmin;
gnrc_netif_hdr_t *netif;
gnrc_pktsnip_t *pkt_snip;
gnrc_pktsnip_t *hdr_snip;
gnrc_pktsnip_t *netif_snip;
/* get the size of the new packet */
pktsize = nrfmin_dev.driver->recv(NULL, NULL, 0, NULL);
if (pktsize <= 0) {
DEBUG("[nrfmin_gnrc] recv: error: tried to read empty packet\n");
return NULL;
}
/* allocate space in the packet buffer */
pkt_snip = gnrc_pktbuf_add(NULL, NULL, pktsize, GNRC_NETTYPE_UNDEF);
if (pkt_snip == NULL) {
DEBUG("[nrfmin_gnrc] recv: unable to allocate pktsnip\n");
return NULL;
}
/* read the incoming data into the packet buffer */
nrfmin_dev.driver->recv(NULL, pkt_snip->data, pktsize, NULL);
/* now we mark the nrfmin header */
hdr_snip = gnrc_pktbuf_mark(pkt_snip, NRFMIN_HDR_LEN, GNRC_NETTYPE_UNDEF);
if (hdr_snip == NULL) {
DEBUG("[nrfmin_gnrc] recv: unable to mark the nrfmin header\n");
gnrc_pktbuf_release(pkt_snip);
return NULL;
}
/* allocate the generic netif header and populate it with data from the
nrfmin header */
nrfmin = (nrfmin_hdr_t *)hdr_snip->data;
netif_snip = gnrc_netif_hdr_build((uint8_t *)&nrfmin->src_addr, 2,
(uint8_t *)&nrfmin->dst_addr, 2);
if (netif_snip == NULL) {
DEBUG("[nrfmin_gnrc] recv: unable to allocate netif header\n");
gnrc_pktbuf_release(pkt_snip);
return NULL;
}
netif = (gnrc_netif_hdr_t *)netif_snip->data;
if (nrfmin->dst_addr == NRFMIN_ADDR_BCAST) {
netif->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST;
}
netif->lqi = 0;
netif->rssi = 0;
netif->if_pid = dev->pid;
pkt_snip->type = nrfmin->proto;
/* finally: remove the nrfmin header and append the netif header */
gnrc_pktbuf_remove_snip(pkt_snip, hdr_snip);
LL_APPEND(pkt_snip, netif_snip);
return pkt_snip;
}
#ifdef MODULE_GNRC_NETIF2
static const gnrc_netif2_ops_t gnrc_nrfmin_ops = {
.send = gnrc_nrfmin_send,
.recv = gnrc_nrfmin_recv,
.get = gnrc_netif2_get_from_netdev,
.set = gnrc_netif2_set_from_netdev,
};
#endif
void gnrc_nrfmin_init(void)
{
/* setup the NRFMIN driver */
nrfmin_setup();
#ifdef MODULE_GNRC_NETIF2
gnrc_netif2_create(stack, sizeof(stack), NRFMIN_GNRC_THREAD_PRIO, "nrfmin",
(netdev_t *)&nrfmin_dev, &gnrc_nrfmin_ops);
#else
/* initialize the GNRC plug struct */
plug.send = gnrc_nrfmin_send;
plug.recv = gnrc_nrfmin_recv;
plug.dev = &nrfmin_dev;
gnrc_netdev_init(stack, sizeof(stack),
NRFMIN_GNRC_THREAD_PRIO,
"nrfmin", &plug);
#endif
}