Contiki 3.x
frame.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2008, Swedish Institute of Computer Science
4  * All rights reserved.
5  *
6  * Additional fixes for AVR contributed by:
7  *
8  * Colin O'Flynn coflynn@newae.com
9  * Eric Gnoske egnoske@gmail.com
10  * Blake Leverett bleverett@gmail.com
11  * Mike Vidales mavida404@gmail.com
12  * Kevin Brown kbrown3@uccs.edu
13  * Nate Bohlmann nate@elfwerks.com
14  *
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are met:
19  *
20  * * Redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer.
22  * * Redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in
24  * the documentation and/or other materials provided with the
25  * distribution.
26  * * Neither the name of the copyright holders nor the names of
27  * contributors may be used to endorse or promote products derived
28  * from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  * POSSIBILITY OF SUCH DAMAGE.
41  *
42 */
43 /*
44  * \brief This file is where the main functions that relate to frame
45  * manipulation will reside.
46 */
47 /**
48  * \addtogroup wireless
49  * @{
50 */
51 /**
52  * \defgroup frame RF230 Frame handling
53  * @{
54  */
55 /**
56  * \file
57  * \brief 802.15.4 frame creation and parsing functions
58  *
59  * This file converts to and from a structure to a packed 802.15.4
60  * frame.
61  */
62 
63 /* Includes */
64 #if defined( __GNUC__ )
65 #include <avr/io.h>
66 #include <util/delay.h>
67 #else /* IAR */
68 #include <iom1284.h>
69 #endif
70 
71 #include <stdlib.h>
72 #include <string.h>
73 #include <stdint.h>
74 #include <stdbool.h>
75 #include "at86rf230_registermap.h"
76 #include "radio.h"
77 #include "frame.h"
78 //#include "mac_event.h"
79 #include "zmac.h"
80 #include "process.h"
81 #include "sicslowmac.h"
82 
83 
84 
85 /* Macros & Defines */
86 
87 /* Some version of radio chip need this set to 2, so define it in Makefile */
88 #ifndef AUTO_CRC_PADDING
89 #define AUTO_CRC_PADDING 0
90 #endif
91 
92 
93 /* Protoypes */
94 
95 /* Globals */
96 
97 /* Frame handling global variables. */
98 //FRAME_t rx_frame; /**< Structure that holds received frames. */
99 static uint8_t tx_frame_buffer[130];
100 
101 /* Implementation */
102 
103 /*----------------------------------------------------------------------------*/
104 /**
105  * \brief Creates a frame for transmission over the air. This function is
106  * meant to be called by a higher level function, that interfaces to a MAC.
107  *
108  * \param p Pointer to frame_create_params_t struct, which specifies the
109  * frame to send.
110  *
111  * \param frame_result Pointer to frame_result_t struct, which will
112  * receive the results of this function, a pointer to the frame
113  * created, and the length of the frame.
114  *
115  * \return Nothing directly, though the frame_result structure will be filled
116  * in with a pointer to the frame and the frame length.
117 */
118 void
120 {
121  field_length_t flen;
122  uint8_t index=0;
123 
124  /* init flen to zeros */
125  memset(&flen, 0, sizeof(field_length_t));
126 
127  /* Determine lengths of each field based on fcf and other args */
128  if (p->fcf.destAddrMode){
129  flen.dest_pid_len = 2;
130  }
131  if (p->fcf.srcAddrMode){
132  flen.src_pid_len = 2;
133  }
134  /* Set PAN ID compression bit it src pan if matches dest pan id. */
135  if(p->fcf.destAddrMode == p->fcf.srcAddrMode){
136  p->fcf.panIdCompression = 1;
137  }
138  if (p->fcf.panIdCompression){
139  /* compressed header, only do dest pid */
140  flen.src_pid_len = 0;
141  }
142  /* determine address lengths */
143  switch (p->fcf.destAddrMode){
144  case 2: /* 16-bit address */
145  flen.dest_addr_len = 2;
146  break;
147  case 3: /* 64-bit address */
148  flen.dest_addr_len = 8;
149  break;
150  default:
151  break;
152  }
153  switch (p->fcf.srcAddrMode){
154  case 2: /* 16-bit address */
155  flen.src_addr_len = 2;
156  break;
157  case 3: /* 64-bit address */
158  flen.src_addr_len = 8;
159  break;
160  default:
161  break;
162  }
163  /* Aux security header */
164  if (p->fcf.securityEnabled){
166  case 0:
167  flen.aux_sec_len = 5; /* minimum value */
168  break;
169  case 1:
170  flen.aux_sec_len = 6;
171  break;
172  case 2:
173  flen.aux_sec_len = 10;
174  break;
175  case 3:
176  flen.aux_sec_len = 14;
177  break;
178  default:
179  break;
180  }
181  }
182 
183  /* OK, now we have field lengths. Time to actually construct */
184  /* the outgoing frame, and store it in tx_frame_buffer */
185  *(uint16_t *)tx_frame_buffer = p->fcf.word_val; /* FCF */
186  index = 2;
187  tx_frame_buffer[index++] = p->seq; /* sequence number */
188  /* Destination PAN ID */
189  if (flen.dest_pid_len == 2){
190  *(uint16_t *)&tx_frame_buffer[index] = p->dest_pid;
191  index += 2;
192  }
193  /* Destination address */
194  switch (flen.dest_addr_len){
195  case 2: /* two-byte address */
196  *(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16;
197  index += 2;
198  break;
199  case 8: /* 8-byte address */
200  *(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64;
201  index += 8;
202  break;
203  case 0:
204  default:
205  break;
206  }
207  /* Source PAN ID */
208  if (flen.src_pid_len == 2){
209  *(uint16_t *)&tx_frame_buffer[index] = p->src_pid;
210  index += 2;
211  }
212  /* Source address */
213  switch (flen.src_addr_len){
214  case 2: /* two-byte address */
215  *(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16;
216  index += 2;
217  break;
218  case 8: /* 8-byte address */
219  *(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64;
220  index += 8;
221  break;
222  case 0:
223  default:
224  break;
225  }
226  /* Aux header */
227  if (flen.aux_sec_len){
228  memcpy((char *)&tx_frame_buffer[index],
229  (char *)&p->aux_hdr,
230  flen.aux_sec_len);
231  index += flen.aux_sec_len;
232  }
233  /* Frame payload */
234  memcpy((char *)&tx_frame_buffer[index],
235  (char *)p->payload,
236  p->payload_len);
237  index += p->payload_len;
238 
239  /* return results */
240  frame_result->length = index + AUTO_CRC_PADDING;
241  frame_result->frame = tx_frame_buffer;
242  return;
243 }
244 
245 /*----------------------------------------------------------------------------*/
246 /**
247  * \brief Parses an input frame. Scans the input frame to find each
248  * section, and stores the resulting addresses of each section in a
249  * parsed_frame_t structure.
250  *
251  * \param rx_frame The input data from the radio chip.
252  * \param pf The parsed_frame_t struct that stores a pointer to each
253  * section of the frame payload.
254  */
255 void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
256 {
257  /* Pointer to start of AT86RF2xx frame */
258  uint8_t *p = rx_frame->data;
259  fcf_t *fcf = (fcf_t *)&rx_frame->data;
260  static uint8_t frame_dropped = 0;
261 
262  /* Uh-oh... please don't overwrite me! */
263  if (pf->in_use) {
264 
265  /* Only post this once when buffer is busy, otherwise you get many postings... */
266  if (!frame_dropped) {
267  event_object_t event;
268  event.event = MAC_EVENT_DROPPED;
269  event.data = NULL;
270  mac_put_event(&event);
271  process_post(&mac_process, event.event, event.data);
272  }
273  frame_dropped = 1;
274  return;
275  }
276 
277 
278  pf->fcf = (fcf_t *)p;
279  pf->seqNum = p+2;
280  p += 3; /* Skip first three bytes */
281 
282  if (fcf->frameType == ACKFRAME) {
283  //ACK frames have no addresses and no payload!
284  pf->payload_length = 0;
285 
286  } else {
287 
288  /* Destination PID, if any */
289  if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */
290  pf->dest_pid = (uint16_t *)p;
291  p += 2;
292  /* Destination address */
293  pf->dest_addr = 0;
294  if (fcf->destAddrMode == SHORTADDRMODE ||
295  fcf->destAddrMode == LONGADDRMODE){
296  pf->dest_addr = (addr_t *)p;
297  /* Update pointer to account for possible missing addr field */
298  if (fcf->destAddrMode == SHORTADDRMODE){
299  p += 2;
300  }
301  if (fcf->destAddrMode == LONGADDRMODE){
302  p += 8;
303  }
304  }
305  }
306  /* Source PANID */
307  pf->src_pid = 0;
308  if (!fcf->panIdCompression){
309  pf->src_pid = (uint16_t *)p;
310  p += 2;
311  } else {
312  pf->src_pid = pf->dest_pid;
313  }
314  /* Source address */
315  pf->src_addr = (addr_t *)p;
316  if (fcf->srcAddrMode == SHORTADDRMODE){
317  p += 2;
318  }
319  if (fcf->srcAddrMode == LONGADDRMODE){
320  p += 8;
321  }
322  /* aux security header, not yet implemented */
323  pf->aux_sec_hdr = 0;
324  /* payload length */
325  pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2;
326  /* payload */
327  pf->payload = p;
328  }
329 
330  pf->lqi = rx_frame->lqi;
331  pf->fcs = rx_frame->crc;
332 
333  /* pass frame to sicslowmac layer */
334  event_object_t event;
335  event.event = MAC_EVENT_RX;
336  event.data = (uint8_t*)pf;
337  pf->in_use = 1;
338  mac_put_event(&event);
339  process_poll(&mac_process);
340 }
341 
342 /** \} */
343 /** \} */
bool securityEnabled
True if security is used in this frame.
Definition: frame.h:72
uint8_t lqi
LQI value for received frame.
Definition: hal.h:354
uint8_t length
Length (in bytes) of created frame.
Definition: frame.h:155
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
uint16_t src_pid
Source PAN ID.
Definition: frame.h:167
uint8_t seq
Sequence number.
Definition: frame.h:164
uint8_t payload_len
Length of payload field.
Definition: frame.h:171
uint8_t destAddrMode
Destination address mode, see 802.15.4.
Definition: frame.h:77
void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
Parses an input frame.
Definition: frame.c:255
bool panIdCompression
Is this a compressed header?
Definition: frame.h:75
scf_t security_control
Security control bitfield.
Definition: frame.h:105
uint8_t length
Length of frame.
Definition: hal.h:352
void frame_tx_create(frame_create_params_t *p, frame_result_t *frame_result)
Creates a frame for transmission over the air.
Definition: frame.c:119
#define NULL
The null pointer.
This struct defines the rx data container.
Definition: hal.h:351
uint8_t data[HAL_MAX_FRAME_LENGTH]
Actual frame data.
Definition: hal.h:353
bool crc
Flag - did CRC pass for received frame?
Definition: hal.h:355
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
uint8_t * frame
Pointer to created frame.
Definition: frame.h:154
Strucure used to return that status of the frame create process.
Definition: frame.h:153
This file contains the register definitions for the AT86RF230.
aux_hdr_t aux_hdr
Aux security header.
Definition: frame.h:169
addr_t src_addr
Source address.
Definition: frame.h:168
uint64_t addr64
Long address.
Definition: frame.h:148
uint8_t srcAddrMode
Source address mode, see 802.15.4.
Definition: frame.h:79
uint16_t dest_pid
Destination PAN ID.
Definition: frame.h:165
uint8_t frameType
Frame type field, see 802.15.4.
Definition: frame.h:71
uint16_t addr16
Short address.
Definition: frame.h:147
addr_t dest_addr
Destination address.
Definition: frame.h:166
Union of both short and long addresses.
Definition: frame.h:146
Parameters used by the frame_tx_create() function.
Definition: frame.h:162
void mac_put_event(event_object_t *object)
Puts an event into the queue of events.
Definition: sicslowmac.c:133
uint16_t word_val
A word-wide value for the entire FCF.
Definition: frame.h:81
uint8_t key_id_mode
Key identifier mode.
Definition: frame.h:99
The IEEE 802.15.4 (2003/2006) MAC utility functions.
fcf_t fcf
Frame control field.
Definition: frame.h:163
802.15.4 frame creation and parsing functions
Header file for the Contiki process interface.
uint8_t * payload
Pointer to 802.15.4 frame payload.
Definition: frame.h:170
This file contains radio driver code.
Defines the bitfields of the frame control field (FCF).
Definition: frame.h:68