Contiki 2.6

frame802154.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  *  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 /** \}   */