Contiki 2.6

frame.c

Go to the documentation of this file.
00001 /*
00002  *
00003  *  Copyright (c) 2008, Swedish Institute of Computer Science
00004  *  All rights reserved. 
00005  *
00006  *  Additional fixes for AVR contributed by:
00007  *
00008  *      Colin O'Flynn coflynn@newae.com
00009  *      Eric Gnoske egnoske@gmail.com
00010  *      Blake Leverett bleverett@gmail.com
00011  *      Mike Vidales mavida404@gmail.com
00012  *      Kevin Brown kbrown3@uccs.edu
00013  *      Nate Bohlmann nate@elfwerks.com
00014  *
00015  *   All rights reserved.
00016  *
00017  *   Redistribution and use in source and binary forms, with or without
00018  *   modification, are permitted provided that the following conditions are met:
00019  *
00020  *   * Redistributions of source code must retain the above copyright
00021  *     notice, this list of conditions and the following disclaimer.
00022  *   * Redistributions in binary form must reproduce the above copyright
00023  *     notice, this list of conditions and the following disclaimer in
00024  *     the documentation and/or other materials provided with the
00025  *     distribution.
00026  *   * Neither the name of the copyright holders nor the names of
00027  *     contributors may be used to endorse or promote products derived
00028  *     from this software without specific prior written permission.
00029  *
00030  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00031  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00034  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00035  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00036  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00039  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040  *  POSSIBILITY OF SUCH DAMAGE.
00041  *
00042  *  $Id: frame.c,v 1.4 2008/12/10 21:26:05 c_oflynn Exp $
00043 */
00044 /*
00045  *  \brief This file is where the main functions that relate to frame
00046  *  manipulation will reside.
00047 */
00048 /**
00049  *   \addtogroup wireless
00050  *   @{
00051 */
00052 /**
00053  *  \defgroup frame RF230 Frame handling
00054  *  @{
00055  */
00056 /**
00057  *  \file
00058  *  \brief 802.15.4 frame creation and parsing functions
00059  *
00060  *  This file converts to and from a structure to a packed 802.15.4
00061  *  frame.
00062  */
00063 
00064 /* Includes */
00065 #if defined( __GNUC__ )
00066 #include <avr/io.h>
00067 #include <util/delay.h>
00068 #else /* IAR */
00069 #include <iom1284.h>
00070 #endif
00071 
00072 #include <stdlib.h>
00073 #include <string.h>
00074 #include <stdint.h>
00075 #include <stdbool.h>
00076 #include "at86rf230_registermap.h"
00077 #include "radio.h"
00078 #include "frame.h"
00079 //#include "mac_event.h"
00080 #include "zmac.h"
00081 #include "process.h"
00082 #include "sicslowmac.h"
00083 
00084 
00085 
00086 /* Macros & Defines */
00087 
00088 /* Some version of radio chip need this set to 2, so define it in Makefile */
00089 #ifndef AUTO_CRC_PADDING
00090 #define AUTO_CRC_PADDING 0
00091 #endif
00092 
00093 
00094 /* Protoypes */
00095 
00096 /* Globals */
00097 
00098 /*  Frame handling global variables. */
00099 //FRAME_t rx_frame;    /**< Structure that holds received frames. */
00100 static uint8_t tx_frame_buffer[130];
00101 
00102 /* Implementation */
00103 
00104 /*----------------------------------------------------------------------------*/
00105 /**
00106  *   \brief Creates a frame for transmission over the air.  This function is
00107  *   meant to be called by a higher level function, that interfaces to a MAC.
00108  *
00109  *   \param p Pointer to frame_create_params_t struct, which specifies the
00110  *   frame to send.
00111  *
00112  *   \param frame_result Pointer to frame_result_t struct, which will
00113  *   receive the results of this function, a pointer to the frame
00114  *   created, and the length of the frame.
00115  *
00116  *   \return Nothing directly, though the frame_result structure will be filled
00117  *   in with a pointer to the frame and the frame length.
00118 */
00119 void
00120 frame_tx_create(frame_create_params_t *p,frame_result_t *frame_result)
00121 {
00122     field_length_t flen;
00123     uint8_t index=0;
00124 
00125     /* init flen to zeros */
00126     memset(&flen, 0, sizeof(field_length_t));
00127 
00128     /* Determine lengths of each field based on fcf and other args */
00129     if (p->fcf.destAddrMode){
00130         flen.dest_pid_len = 2;
00131     }
00132     if (p->fcf.srcAddrMode){
00133         flen.src_pid_len = 2;
00134     }
00135     /* Set PAN ID compression bit it src pan if matches dest pan id. */
00136     if(p->fcf.destAddrMode == p->fcf.srcAddrMode){
00137         p->fcf.panIdCompression = 1;
00138     }
00139     if (p->fcf.panIdCompression){
00140         /* compressed header, only do dest pid */
00141         flen.src_pid_len = 0;
00142     }
00143     /* determine address lengths */
00144     switch (p->fcf.destAddrMode){
00145     case 2:  /* 16-bit address */
00146         flen.dest_addr_len = 2;
00147         break;
00148     case 3:  /* 64-bit address */
00149         flen.dest_addr_len = 8;
00150         break;
00151     default:
00152         break;
00153     }
00154     switch (p->fcf.srcAddrMode){
00155     case 2:  /* 16-bit address */
00156         flen.src_addr_len = 2;
00157         break;
00158     case 3:  /* 64-bit address */
00159         flen.src_addr_len = 8;
00160         break;
00161     default:
00162         break;
00163     }
00164     /* Aux security header */
00165     if (p->fcf.securityEnabled){
00166         switch (p->aux_hdr.security_control.key_id_mode){
00167         case 0:
00168             flen.aux_sec_len = 5; /* minimum value */
00169             break;
00170         case 1:
00171             flen.aux_sec_len = 6;
00172             break;
00173         case 2:
00174             flen.aux_sec_len = 10;
00175             break;
00176         case 3:
00177             flen.aux_sec_len = 14;
00178             break;
00179         default:
00180             break;
00181         }
00182     }
00183 
00184     /* OK, now we have field lengths.  Time to actually construct */
00185     /* the outgoing frame, and store it in tx_frame_buffer */
00186     *(uint16_t *)tx_frame_buffer  = p->fcf.word_val; /* FCF */
00187     index = 2;
00188     tx_frame_buffer[index++] = p->seq;           /* sequence number */
00189     /* Destination PAN ID */
00190     if (flen.dest_pid_len == 2){
00191         *(uint16_t *)&tx_frame_buffer[index] = p->dest_pid;
00192         index += 2;
00193     }
00194     /* Destination address */
00195     switch (flen.dest_addr_len){
00196     case 2:    /* two-byte address */
00197         *(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16;
00198         index += 2;
00199         break;
00200     case 8:    /* 8-byte address */
00201         *(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64;
00202         index += 8;
00203         break;
00204     case 0:
00205     default:
00206         break;
00207     }
00208     /* Source PAN ID */
00209     if (flen.src_pid_len == 2){
00210         *(uint16_t *)&tx_frame_buffer[index] = p->src_pid;
00211         index += 2;
00212     }
00213     /* Source address */
00214     switch (flen.src_addr_len){
00215     case 2:    /* two-byte address */
00216         *(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16;
00217         index += 2;
00218         break;
00219     case 8:    /* 8-byte address */
00220         *(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64;
00221         index += 8;
00222         break;
00223     case 0:
00224     default:
00225         break;
00226     }
00227     /* Aux header */
00228     if (flen.aux_sec_len){
00229         memcpy((char *)&tx_frame_buffer[index],
00230                 (char *)&p->aux_hdr,
00231                 flen.aux_sec_len);
00232         index += flen.aux_sec_len;
00233     }
00234     /* Frame payload */
00235     memcpy((char *)&tx_frame_buffer[index],
00236             (char *)p->payload,
00237             p->payload_len);
00238     index += p->payload_len;
00239 
00240     /* return results */
00241     frame_result->length = index + AUTO_CRC_PADDING;
00242     frame_result->frame = tx_frame_buffer;
00243     return;
00244 }
00245 
00246 /*----------------------------------------------------------------------------*/
00247 /**
00248  *   \brief Parses an input frame.  Scans the input frame to find each
00249  *   section, and stores the resulting addresses of each section in a
00250  *   parsed_frame_t structure.
00251  *
00252  *   \param rx_frame The input data from the radio chip.
00253  *   \param pf The parsed_frame_t struct that stores a pointer to each
00254  *   section of the frame payload.
00255  */
00256 void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
00257 {
00258     /* Pointer to start of AT86RF2xx frame */
00259     uint8_t *p = rx_frame->data;
00260     fcf_t *fcf = (fcf_t *)&rx_frame->data;
00261     static uint8_t frame_dropped = 0;
00262 
00263     /* Uh-oh... please don't overwrite me! */
00264     if (pf->in_use) {
00265         
00266         /* Only post this once when buffer is busy, otherwise you get many postings... */
00267         if (!frame_dropped) {
00268             event_object_t event;
00269             event.event = MAC_EVENT_DROPPED;
00270             event.data = NULL;
00271             mac_put_event(&event);
00272             process_post(&mac_process, event.event, event.data);
00273         }
00274         frame_dropped = 1;
00275         return;
00276     }
00277 
00278 
00279     pf->fcf = (fcf_t *)p;
00280     pf->seqNum = p+2;
00281     p += 3;                             /* Skip first three bytes */
00282         
00283         if (fcf->frameType == ACKFRAME) {       
00284                 //ACK frames have no addresses and no payload!
00285                 pf->payload_length = 0;
00286         
00287         } else {      
00288                 
00289                 /* Destination PID, if any */
00290                 if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */
00291                         pf->dest_pid = (uint16_t *)p;
00292                         p += 2;
00293                         /* Destination address */
00294                         pf->dest_addr = 0;
00295                         if (fcf->destAddrMode == SHORTADDRMODE ||
00296                                 fcf->destAddrMode == LONGADDRMODE){
00297                                 pf->dest_addr = (addr_t *)p;
00298                                 /* Update pointer to account for possible missing addr field */
00299                                 if (fcf->destAddrMode == SHORTADDRMODE){
00300                                         p += 2;
00301                                 }
00302                                 if (fcf->destAddrMode == LONGADDRMODE){
00303                                         p += 8;
00304                                 }
00305                         }
00306                 }
00307                 /* Source PANID */
00308                 pf->src_pid = 0;
00309                 if (!fcf->panIdCompression){
00310                         pf->src_pid = (uint16_t *)p;
00311                         p += 2;
00312                 } else {
00313                         pf->src_pid = pf->dest_pid;
00314                 }
00315                 /* Source address */
00316                 pf->src_addr = (addr_t *)p;
00317                 if (fcf->srcAddrMode == SHORTADDRMODE){
00318                         p += 2;
00319                 }
00320                 if (fcf->srcAddrMode == LONGADDRMODE){
00321                         p += 8;
00322                 }
00323                 /* aux security header, not yet implemented */
00324                 pf->aux_sec_hdr = 0;
00325                 /* payload length */
00326                 pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2;
00327                 /* payload */
00328                 pf->payload = p;
00329         }
00330 
00331     pf->lqi = rx_frame->lqi;
00332     pf->fcs = rx_frame->crc;
00333 
00334     /* pass frame to sicslowmac layer */
00335     event_object_t event;
00336     event.event = MAC_EVENT_RX;
00337     event.data = (uint8_t*)pf;
00338     pf->in_use = 1;
00339     mac_put_event(&event);
00340     process_poll(&mac_process);
00341 }
00342 
00343 /** \}   */
00344 /** \}   */