/* * * Copyright (c) 2008, Swedish Institute of Computer Science * All rights reserved. * * Additional fixes for AVR contributed by: * * Colin O'Flynn coflynn@newae.com * Eric Gnoske egnoske@gmail.com * Blake Leverett bleverett@gmail.com * Mike Vidales mavida404@gmail.com * Kevin Brown kbrown3@uccs.edu * Nate Bohlmann nate@elfwerks.com * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /* * \brief This file is where the main functions that relate to frame * manipulation will reside. */ /** * \addtogroup wireless * @{ */ /** * \defgroup frame RF230 Frame handling * @{ */ /** * \file * \brief 802.15.4 frame creation and parsing functions * * This file converts to and from a structure to a packed 802.15.4 * frame. */ /* Includes */ #if defined( __GNUC__ ) #include #include #else /* IAR */ #include #endif #include #include #include #include #include "at86rf230_registermap.h" #include "radio.h" #include "frame.h" //#include "mac_event.h" #include "zmac.h" #include "process.h" #include "sicslowmac.h" /* Macros & Defines */ /* Some version of radio chip need this set to 2, so define it in Makefile */ #ifndef AUTO_CRC_PADDING #define AUTO_CRC_PADDING 0 #endif /* Protoypes */ /* Globals */ /* Frame handling global variables. */ //FRAME_t rx_frame; /**< Structure that holds received frames. */ static uint8_t tx_frame_buffer[130]; /* Implementation */ /*----------------------------------------------------------------------------*/ /** * \brief Creates a frame for transmission over the air. This function is * meant to be called by a higher level function, that interfaces to a MAC. * * \param p Pointer to frame_create_params_t struct, which specifies the * frame to send. * * \param frame_result Pointer to frame_result_t struct, which will * receive the results of this function, a pointer to the frame * created, and the length of the frame. * * \return Nothing directly, though the frame_result structure will be filled * in with a pointer to the frame and the frame length. */ void frame_tx_create(frame_create_params_t *p,frame_result_t *frame_result) { field_length_t flen; uint8_t index=0; /* init flen to zeros */ memset(&flen, 0, sizeof(field_length_t)); /* Determine lengths of each field based on fcf and other args */ if (p->fcf.destAddrMode){ flen.dest_pid_len = 2; } if (p->fcf.srcAddrMode){ flen.src_pid_len = 2; } /* Set PAN ID compression bit it src pan if matches dest pan id. */ if(p->fcf.destAddrMode == p->fcf.srcAddrMode){ p->fcf.panIdCompression = 1; } if (p->fcf.panIdCompression){ /* compressed header, only do dest pid */ flen.src_pid_len = 0; } /* determine address lengths */ switch (p->fcf.destAddrMode){ case 2: /* 16-bit address */ flen.dest_addr_len = 2; break; case 3: /* 64-bit address */ flen.dest_addr_len = 8; break; default: break; } switch (p->fcf.srcAddrMode){ case 2: /* 16-bit address */ flen.src_addr_len = 2; break; case 3: /* 64-bit address */ flen.src_addr_len = 8; break; default: break; } /* Aux security header */ if (p->fcf.securityEnabled){ switch (p->aux_hdr.security_control.key_id_mode){ case 0: flen.aux_sec_len = 5; /* minimum value */ break; case 1: flen.aux_sec_len = 6; break; case 2: flen.aux_sec_len = 10; break; case 3: flen.aux_sec_len = 14; break; default: break; } } /* OK, now we have field lengths. Time to actually construct */ /* the outgoing frame, and store it in tx_frame_buffer */ *(uint16_t *)tx_frame_buffer = p->fcf.word_val; /* FCF */ index = 2; tx_frame_buffer[index++] = p->seq; /* sequence number */ /* Destination PAN ID */ if (flen.dest_pid_len == 2){ *(uint16_t *)&tx_frame_buffer[index] = p->dest_pid; index += 2; } /* Destination address */ switch (flen.dest_addr_len){ case 2: /* two-byte address */ *(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16; index += 2; break; case 8: /* 8-byte address */ *(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64; index += 8; break; case 0: default: break; } /* Source PAN ID */ if (flen.src_pid_len == 2){ *(uint16_t *)&tx_frame_buffer[index] = p->src_pid; index += 2; } /* Source address */ switch (flen.src_addr_len){ case 2: /* two-byte address */ *(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16; index += 2; break; case 8: /* 8-byte address */ *(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64; index += 8; break; case 0: default: break; } /* Aux header */ if (flen.aux_sec_len){ memcpy((char *)&tx_frame_buffer[index], (char *)&p->aux_hdr, flen.aux_sec_len); index += flen.aux_sec_len; } /* Frame payload */ memcpy((char *)&tx_frame_buffer[index], (char *)p->payload, p->payload_len); index += p->payload_len; /* return results */ frame_result->length = index + AUTO_CRC_PADDING; frame_result->frame = tx_frame_buffer; return; } /*----------------------------------------------------------------------------*/ /** * \brief Parses an input frame. Scans the input frame to find each * section, and stores the resulting addresses of each section in a * parsed_frame_t structure. * * \param rx_frame The input data from the radio chip. * \param pf The parsed_frame_t struct that stores a pointer to each * section of the frame payload. */ void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf) { /* Pointer to start of AT86RF2xx frame */ uint8_t *p = rx_frame->data; fcf_t *fcf = (fcf_t *)&rx_frame->data; static uint8_t frame_dropped = 0; /* Uh-oh... please don't overwrite me! */ if (pf->in_use) { /* Only post this once when buffer is busy, otherwise you get many postings... */ if (!frame_dropped) { event_object_t event; event.event = MAC_EVENT_DROPPED; event.data = NULL; mac_put_event(&event); process_post(&mac_process, event.event, event.data); } frame_dropped = 1; return; } pf->fcf = (fcf_t *)p; pf->seqNum = p+2; p += 3; /* Skip first three bytes */ if (fcf->frameType == ACKFRAME) { //ACK frames have no addresses and no payload! pf->payload_length = 0; } else { /* Destination PID, if any */ if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */ pf->dest_pid = (uint16_t *)p; p += 2; /* Destination address */ pf->dest_addr = 0; if (fcf->destAddrMode == SHORTADDRMODE || fcf->destAddrMode == LONGADDRMODE){ pf->dest_addr = (addr_t *)p; /* Update pointer to account for possible missing addr field */ if (fcf->destAddrMode == SHORTADDRMODE){ p += 2; } if (fcf->destAddrMode == LONGADDRMODE){ p += 8; } } } /* Source PANID */ pf->src_pid = 0; if (!fcf->panIdCompression){ pf->src_pid = (uint16_t *)p; p += 2; } else { pf->src_pid = pf->dest_pid; } /* Source address */ pf->src_addr = (addr_t *)p; if (fcf->srcAddrMode == SHORTADDRMODE){ p += 2; } if (fcf->srcAddrMode == LONGADDRMODE){ p += 8; } /* aux security header, not yet implemented */ pf->aux_sec_hdr = 0; /* payload length */ pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2; /* payload */ pf->payload = p; } pf->lqi = rx_frame->lqi; pf->fcs = rx_frame->crc; /* pass frame to sicslowmac layer */ event_object_t event; event.event = MAC_EVENT_RX; event.data = (uint8_t*)pf; pf->in_use = 1; mac_put_event(&event); process_poll(&mac_process); } /** \} */ /** \} */