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 * Additional fixes for MSP430 contributed by: 00016 * Joakim Eriksson 00017 * Niclas Finne 00018 * Nicolas Tsiftes 00019 * 00020 * All rights reserved. 00021 * 00022 * Redistribution and use in source and binary forms, with or without 00023 * modification, are permitted provided that the following conditions are met: 00024 * 00025 * * Redistributions of source code must retain the above copyright 00026 * notice, this list of conditions and the following disclaimer. 00027 * * Redistributions in binary form must reproduce the above copyright 00028 * notice, this list of conditions and the following disclaimer in 00029 * the documentation and/or other materials provided with the 00030 * distribution. 00031 * * Neither the name of the copyright holders nor the names of 00032 * contributors may be used to endorse or promote products derived 00033 * from this software without specific prior written permission. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00036 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00037 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00038 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00039 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00040 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00041 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00042 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00043 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00044 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00045 * POSSIBILITY OF SUCH DAMAGE. 00046 * 00047 * $Id: frame802154.c,v 1.4 2010/02/18 21:00:28 adamdunkels Exp $ 00048 */ 00049 /* 00050 * \brief This file is where the main functions that relate to frame 00051 * manipulation will reside. 00052 */ 00053 /** 00054 * \addtogroup frame802154 00055 * @{ 00056 */ 00057 /** 00058 * \file 00059 * \brief 802.15.4 frame creation and parsing functions 00060 * 00061 * This file converts to and from a structure to a packed 802.15.4 00062 * frame. 00063 */ 00064 00065 #include "sys/cc.h" 00066 #include "net/mac/frame802154.h" 00067 #include <string.h> 00068 00069 /** 00070 * \brief Structure that contains the lengths of the various addressing and security fields 00071 * in the 802.15.4 header. This structure is used in \ref frame802154_create() 00072 */ 00073 typedef struct { 00074 uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */ 00075 uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */ 00076 uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */ 00077 uint8_t src_addr_len; /**< Length (in bytes) of source address field */ 00078 uint8_t aux_sec_len; /**< Length (in bytes) of aux security header field */ 00079 } field_length_t; 00080 00081 /*----------------------------------------------------------------------------*/ 00082 CC_INLINE static uint8_t 00083 addr_len(uint8_t mode) 00084 { 00085 switch(mode) { 00086 case FRAME802154_SHORTADDRMODE: /* 16-bit address */ 00087 return 2; 00088 case FRAME802154_LONGADDRMODE: /* 64-bit address */ 00089 return 8; 00090 default: 00091 return 0; 00092 } 00093 } 00094 /*----------------------------------------------------------------------------*/ 00095 static void 00096 field_len(frame802154_t *p, field_length_t *flen) 00097 { 00098 /* init flen to zeros */ 00099 memset(flen, 0, sizeof(field_length_t)); 00100 00101 /* Determine lengths of each field based on fcf and other args */ 00102 if(p->fcf.dest_addr_mode & 3) { 00103 flen->dest_pid_len = 2; 00104 } 00105 if(p->fcf.src_addr_mode & 3) { 00106 flen->src_pid_len = 2; 00107 } 00108 00109 /* Set PAN ID compression bit if src pan id matches dest pan id. */ 00110 if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 && 00111 p->src_pid == p->dest_pid) { 00112 p->fcf.panid_compression = 1; 00113 00114 /* compressed header, only do dest pid */ 00115 flen->src_pid_len = 0; 00116 } else { 00117 p->fcf.panid_compression = 0; 00118 } 00119 00120 /* determine address lengths */ 00121 flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3); 00122 flen->src_addr_len = addr_len(p->fcf.src_addr_mode & 3); 00123 00124 /* Aux security header */ 00125 if(p->fcf.security_enabled & 1) { 00126 /* TODO Aux security header not yet implemented */ 00127 #if 0 00128 switch(p->aux_hdr.security_control.key_id_mode) { 00129 case 0: 00130 flen->aux_sec_len = 5; /* minimum value */ 00131 break; 00132 case 1: 00133 flen->aux_sec_len = 6; 00134 break; 00135 case 2: 00136 flen->aux_sec_len = 10; 00137 break; 00138 case 3: 00139 flen->aux_sec_len = 14; 00140 break; 00141 default: 00142 break; 00143 } 00144 #endif 00145 } 00146 } 00147 /*----------------------------------------------------------------------------*/ 00148 /** 00149 * \brief Calculates the length of the frame header. This function is 00150 * meant to be called by a higher level function, that interfaces to a MAC. 00151 * 00152 * \param p Pointer to frame802154_t_t struct, which specifies the 00153 * frame to send. 00154 * 00155 * \return The length of the frame header. 00156 */ 00157 uint8_t 00158 frame802154_hdrlen(frame802154_t *p) 00159 { 00160 field_length_t flen; 00161 field_len(p, &flen); 00162 return 3 + flen.dest_pid_len + flen.dest_addr_len + 00163 flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len; 00164 } 00165 /*----------------------------------------------------------------------------*/ 00166 /** 00167 * \brief Creates a frame for transmission over the air. This function is 00168 * meant to be called by a higher level function, that interfaces to a MAC. 00169 * 00170 * \param p Pointer to frame802154_t struct, which specifies the 00171 * frame to send. 00172 * 00173 * \param buf Pointer to the buffer to use for the frame. 00174 * 00175 * \param buf_len The length of the buffer to use for the frame. 00176 * 00177 * \return The length of the frame header or 0 if there was 00178 * insufficient space in the buffer for the frame headers. 00179 */ 00180 uint8_t 00181 frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len) 00182 { 00183 int c; 00184 field_length_t flen; 00185 uint8_t *tx_frame_buffer; 00186 uint8_t pos; 00187 00188 field_len(p, &flen); 00189 00190 if(3 + flen.dest_pid_len + flen.dest_addr_len + 00191 flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len > buf_len) { 00192 /* Too little space for headers. */ 00193 return 0; 00194 } 00195 00196 /* OK, now we have field lengths. Time to actually construct */ 00197 /* the outgoing frame, and store it in tx_frame_buffer */ 00198 tx_frame_buffer = buf; 00199 tx_frame_buffer[0] = (p->fcf.frame_type & 7) | 00200 ((p->fcf.security_enabled & 1) << 3) | 00201 ((p->fcf.frame_pending & 1) << 4) | 00202 ((p->fcf.ack_required & 1) << 5) | 00203 ((p->fcf.panid_compression & 1) << 6); 00204 tx_frame_buffer[1] = ((p->fcf.dest_addr_mode & 3) << 2) | 00205 ((p->fcf.frame_version & 3) << 4) | 00206 ((p->fcf.src_addr_mode & 3) << 6); 00207 00208 /* sequence number */ 00209 tx_frame_buffer[2] = p->seq; 00210 pos = 3; 00211 00212 /* Destination PAN ID */ 00213 if(flen.dest_pid_len == 2) { 00214 tx_frame_buffer[pos++] = p->dest_pid & 0xff; 00215 tx_frame_buffer[pos++] = (p->dest_pid >> 8) & 0xff; 00216 } 00217 00218 /* Destination address */ 00219 for(c = flen.dest_addr_len; c > 0; c--) { 00220 tx_frame_buffer[pos++] = p->dest_addr[c - 1]; 00221 } 00222 00223 /* Source PAN ID */ 00224 if(flen.src_pid_len == 2) { 00225 tx_frame_buffer[pos++] = p->src_pid & 0xff; 00226 tx_frame_buffer[pos++] = (p->src_pid >> 8) & 0xff; 00227 } 00228 00229 /* Source address */ 00230 for(c = flen.src_addr_len; c > 0; c--) { 00231 tx_frame_buffer[pos++] = p->src_addr[c - 1]; 00232 } 00233 00234 /* Aux header */ 00235 if(flen.aux_sec_len) { 00236 /* TODO Aux security header not yet implemented */ 00237 /* pos += flen.aux_sec_len; */ 00238 } 00239 00240 return pos; 00241 } 00242 /*----------------------------------------------------------------------------*/ 00243 /** 00244 * \brief Parses an input frame. Scans the input frame to find each 00245 * section, and stores the information of each section in a 00246 * frame802154_t structure. 00247 * 00248 * \param data The input data from the radio chip. 00249 * \param len The size of the input data 00250 * \param pf The frame802154_t struct to store the parsed frame information. 00251 */ 00252 uint8_t 00253 frame802154_parse(uint8_t *data, uint8_t len, frame802154_t *pf) 00254 { 00255 uint8_t *p; 00256 frame802154_fcf_t fcf; 00257 uint8_t c; 00258 00259 if(len < 3) { 00260 return 0; 00261 } 00262 00263 p = data; 00264 00265 /* decode the FCF */ 00266 fcf.frame_type = p[0] & 7; 00267 fcf.security_enabled = (p[0] >> 3) & 1; 00268 fcf.frame_pending = (p[0] >> 4) & 1; 00269 fcf.ack_required = (p[0] >> 5) & 1; 00270 fcf.panid_compression = (p[0] >> 6) & 1; 00271 00272 fcf.dest_addr_mode = (p[1] >> 2) & 3; 00273 fcf.frame_version = (p[1] >> 4) & 3; 00274 fcf.src_addr_mode = (p[1] >> 6) & 3; 00275 00276 /* copy fcf and seqNum */ 00277 memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t)); 00278 pf->seq = p[2]; 00279 p += 3; /* Skip first three bytes */ 00280 00281 /* Destination address, if any */ 00282 if(fcf.dest_addr_mode) { 00283 /* Destination PAN */ 00284 pf->dest_pid = p[0] + (p[1] << 8); 00285 p += 2; 00286 00287 /* Destination address */ 00288 /* l = addr_len(fcf.dest_addr_mode); */ 00289 /* for(c = 0; c < l; c++) { */ 00290 /* pf->dest_addr.u8[c] = p[l - c - 1]; */ 00291 /* } */ 00292 /* p += l; */ 00293 if(fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) { 00294 rimeaddr_copy((rimeaddr_t *)&(pf->dest_addr), &rimeaddr_null); 00295 pf->dest_addr[0] = p[1]; 00296 pf->dest_addr[1] = p[0]; 00297 p += 2; 00298 } else if(fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) { 00299 for(c = 0; c < 8; c++) { 00300 pf->dest_addr[c] = p[7 - c]; 00301 } 00302 p += 8; 00303 } 00304 } else { 00305 rimeaddr_copy((rimeaddr_t *)&(pf->dest_addr), &rimeaddr_null); 00306 pf->dest_pid = 0; 00307 } 00308 00309 /* Source address, if any */ 00310 if(fcf.src_addr_mode) { 00311 /* Source PAN */ 00312 if(!fcf.panid_compression) { 00313 pf->src_pid = p[0] + (p[1] << 8); 00314 p += 2; 00315 } else { 00316 pf->src_pid = pf->dest_pid; 00317 } 00318 00319 /* Source address */ 00320 /* l = addr_len(fcf.src_addr_mode); */ 00321 /* for(c = 0; c < l; c++) { */ 00322 /* pf->src_addr.u8[c] = p[l - c - 1]; */ 00323 /* } */ 00324 /* p += l; */ 00325 if(fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) { 00326 rimeaddr_copy((rimeaddr_t *)&(pf->src_addr), &rimeaddr_null); 00327 pf->src_addr[0] = p[1]; 00328 pf->src_addr[1] = p[0]; 00329 p += 2; 00330 } else if(fcf.src_addr_mode == FRAME802154_LONGADDRMODE) { 00331 for(c = 0; c < 8; c++) { 00332 pf->src_addr[c] = p[7 - c]; 00333 } 00334 p += 8; 00335 } 00336 } else { 00337 rimeaddr_copy((rimeaddr_t *)&(pf->src_addr), &rimeaddr_null); 00338 pf->src_pid = 0; 00339 } 00340 00341 if(fcf.security_enabled) { 00342 /* TODO aux security header, not yet implemented */ 00343 /* return 0; */ 00344 } 00345 00346 /* header length */ 00347 c = p - data; 00348 /* payload length */ 00349 pf->payload_len = len - c; 00350 /* payload */ 00351 pf->payload = p; 00352 00353 /* return header length if successful */ 00354 return c > len ? 0 : c; 00355 } 00356 /** \} */