Contiki 2.5
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  * $Id: frame.c,v 1.4 2008/12/10 21:26:05 c_oflynn Exp $
43 */
44 /*
45  * \brief This file is where the main functions that relate to frame
46  * manipulation will reside.
47 */
48 /**
49  * \addtogroup wireless
50  * @{
51 */
52 /**
53  * \defgroup frame RF230 Frame handling
54  * @{
55  */
56 /**
57  * \file
58  * \brief 802.15.4 frame creation and parsing functions
59  *
60  * This file converts to and from a structure to a packed 802.15.4
61  * frame.
62  */
63 
64 /* Includes */
65 #if defined( __GNUC__ )
66 #include <avr/io.h>
67 #include <util/delay.h>
68 #else /* IAR */
69 #include <iom1284.h>
70 #endif
71 
72 #include <stdlib.h>
73 #include <string.h>
74 #include <stdint.h>
75 #include <stdbool.h>
76 #include "at86rf230_registermap.h"
77 #include "radio.h"
78 #include "frame.h"
79 //#include "mac_event.h"
80 #include "zmac.h"
81 #include "process.h"
82 #include "sicslowmac.h"
83 
84 
85 
86 /* Macros & Defines */
87 
88 /* Some version of radio chip need this set to 2, so define it in Makefile */
89 #ifndef AUTO_CRC_PADDING
90 #define AUTO_CRC_PADDING 0
91 #endif
92 
93 
94 /* Protoypes */
95 
96 /* Globals */
97 
98 /* Frame handling global variables. */
99 //FRAME_t rx_frame; /**< Structure that holds received frames. */
100 static uint8_t tx_frame_buffer[130];
101 
102 /* Implementation */
103 
104 /*----------------------------------------------------------------------------*/
105 /**
106  * \brief Creates a frame for transmission over the air. This function is
107  * meant to be called by a higher level function, that interfaces to a MAC.
108  *
109  * \param p Pointer to frame_create_params_t struct, which specifies the
110  * frame to send.
111  *
112  * \param frame_result Pointer to frame_result_t struct, which will
113  * receive the results of this function, a pointer to the frame
114  * created, and the length of the frame.
115  *
116  * \return Nothing directly, though the frame_result structure will be filled
117  * in with a pointer to the frame and the frame length.
118 */
119 void
121 {
122  field_length_t flen;
123  uint8_t index=0;
124 
125  /* init flen to zeros */
126  memset(&flen, 0, sizeof(field_length_t));
127 
128  /* Determine lengths of each field based on fcf and other args */
129  if (p->fcf.destAddrMode){
130  flen.dest_pid_len = 2;
131  }
132  if (p->fcf.srcAddrMode){
133  flen.src_pid_len = 2;
134  }
135  /* Set PAN ID compression bit it src pan if matches dest pan id. */
136  if(p->fcf.destAddrMode == p->fcf.srcAddrMode){
137  p->fcf.panIdCompression = 1;
138  }
139  if (p->fcf.panIdCompression){
140  /* compressed header, only do dest pid */
141  flen.src_pid_len = 0;
142  }
143  /* determine address lengths */
144  switch (p->fcf.destAddrMode){
145  case 2: /* 16-bit address */
146  flen.dest_addr_len = 2;
147  break;
148  case 3: /* 64-bit address */
149  flen.dest_addr_len = 8;
150  break;
151  default:
152  break;
153  }
154  switch (p->fcf.srcAddrMode){
155  case 2: /* 16-bit address */
156  flen.src_addr_len = 2;
157  break;
158  case 3: /* 64-bit address */
159  flen.src_addr_len = 8;
160  break;
161  default:
162  break;
163  }
164  /* Aux security header */
165  if (p->fcf.securityEnabled){
167  case 0:
168  flen.aux_sec_len = 5; /* minimum value */
169  break;
170  case 1:
171  flen.aux_sec_len = 6;
172  break;
173  case 2:
174  flen.aux_sec_len = 10;
175  break;
176  case 3:
177  flen.aux_sec_len = 14;
178  break;
179  default:
180  break;
181  }
182  }
183 
184  /* OK, now we have field lengths. Time to actually construct */
185  /* the outgoing frame, and store it in tx_frame_buffer */
186  *(uint16_t *)tx_frame_buffer = p->fcf.word_val; /* FCF */
187  index = 2;
188  tx_frame_buffer[index++] = p->seq; /* sequence number */
189  /* Destination PAN ID */
190  if (flen.dest_pid_len == 2){
191  *(uint16_t *)&tx_frame_buffer[index] = p->dest_pid;
192  index += 2;
193  }
194  /* Destination address */
195  switch (flen.dest_addr_len){
196  case 2: /* two-byte address */
197  *(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16;
198  index += 2;
199  break;
200  case 8: /* 8-byte address */
201  *(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64;
202  index += 8;
203  break;
204  case 0:
205  default:
206  break;
207  }
208  /* Source PAN ID */
209  if (flen.src_pid_len == 2){
210  *(uint16_t *)&tx_frame_buffer[index] = p->src_pid;
211  index += 2;
212  }
213  /* Source address */
214  switch (flen.src_addr_len){
215  case 2: /* two-byte address */
216  *(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16;
217  index += 2;
218  break;
219  case 8: /* 8-byte address */
220  *(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64;
221  index += 8;
222  break;
223  case 0:
224  default:
225  break;
226  }
227  /* Aux header */
228  if (flen.aux_sec_len){
229  memcpy((char *)&tx_frame_buffer[index],
230  (char *)&p->aux_hdr,
231  flen.aux_sec_len);
232  index += flen.aux_sec_len;
233  }
234  /* Frame payload */
235  memcpy((char *)&tx_frame_buffer[index],
236  (char *)p->payload,
237  p->payload_len);
238  index += p->payload_len;
239 
240  /* return results */
241  frame_result->length = index + AUTO_CRC_PADDING;
242  frame_result->frame = tx_frame_buffer;
243  return;
244 }
245 
246 /*----------------------------------------------------------------------------*/
247 /**
248  * \brief Parses an input frame. Scans the input frame to find each
249  * section, and stores the resulting addresses of each section in a
250  * parsed_frame_t structure.
251  *
252  * \param rx_frame The input data from the radio chip.
253  * \param pf The parsed_frame_t struct that stores a pointer to each
254  * section of the frame payload.
255  */
256 void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
257 {
258  /* Pointer to start of AT86RF2xx frame */
259  uint8_t *p = rx_frame->data;
260  fcf_t *fcf = (fcf_t *)&rx_frame->data;
261  static uint8_t frame_dropped = 0;
262 
263  /* Uh-oh... please don't overwrite me! */
264  if (pf->in_use) {
265 
266  /* Only post this once when buffer is busy, otherwise you get many postings... */
267  if (!frame_dropped) {
268  event_object_t event;
269  event.event = MAC_EVENT_DROPPED;
270  event.data = NULL;
271  mac_put_event(&event);
272  process_post(&mac_process, event.event, event.data);
273  }
274  frame_dropped = 1;
275  return;
276  }
277 
278 
279  pf->fcf = (fcf_t *)p;
280  pf->seqNum = p+2;
281  p += 3; /* Skip first three bytes */
282 
283  if (fcf->frameType == ACKFRAME) {
284  //ACK frames have no addresses and no payload!
285  pf->payload_length = 0;
286 
287  } else {
288 
289  /* Destination PID, if any */
290  if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */
291  pf->dest_pid = (uint16_t *)p;
292  p += 2;
293  /* Destination address */
294  pf->dest_addr = 0;
295  if (fcf->destAddrMode == SHORTADDRMODE ||
296  fcf->destAddrMode == LONGADDRMODE){
297  pf->dest_addr = (addr_t *)p;
298  /* Update pointer to account for possible missing addr field */
299  if (fcf->destAddrMode == SHORTADDRMODE){
300  p += 2;
301  }
302  if (fcf->destAddrMode == LONGADDRMODE){
303  p += 8;
304  }
305  }
306  }
307  /* Source PANID */
308  pf->src_pid = 0;
309  if (!fcf->panIdCompression){
310  pf->src_pid = (uint16_t *)p;
311  p += 2;
312  } else {
313  pf->src_pid = pf->dest_pid;
314  }
315  /* Source address */
316  pf->src_addr = (addr_t *)p;
317  if (fcf->srcAddrMode == SHORTADDRMODE){
318  p += 2;
319  }
320  if (fcf->srcAddrMode == LONGADDRMODE){
321  p += 8;
322  }
323  /* aux security header, not yet implemented */
324  pf->aux_sec_hdr = 0;
325  /* payload length */
326  pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2;
327  /* payload */
328  pf->payload = p;
329  }
330 
331  pf->lqi = rx_frame->lqi;
332  pf->fcs = rx_frame->crc;
333 
334  /* pass frame to sicslowmac layer */
335  event_object_t event;
336  event.event = MAC_EVENT_RX;
337  event.data = (uint8_t*)pf;
338  pf->in_use = 1;
339  mac_put_event(&event);
340  process_poll(&mac_process);
341 }
342 
343 /** \} */
344 /** \} */