Contiki 2.6
|
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 /** \} */