added 802.15.4 frame packeter
This commit is contained in:
parent
3b2ad9cfc4
commit
9f2ff48fda
|
@ -1 +1 @@
|
||||||
CONTIKI_SOURCEFILES += xmac.c nullmac.c lpp.c #xmac2.c
|
CONTIKI_SOURCEFILES += xmac.c nullmac.c lpp.c frame802154.c sicslowmac.c
|
||||||
|
|
352
core/net/mac/frame802154.c
Normal file
352
core/net/mac/frame802154.c
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Additional fixes for MSP430 contributed by:
|
||||||
|
* Joakim Eriksson
|
||||||
|
* Niclas Finne
|
||||||
|
* Nicolas Tsiftes
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $Id: frame802154.c,v 1.1 2009/04/06 13:19:03 nifi Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* \brief This file is where the main functions that relate to frame
|
||||||
|
* manipulation will reside.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \addtogroup frame802154
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sys/cc.h"
|
||||||
|
#include "net/mac/frame802154.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Structure that contains the lengths of the various addressing and security fields
|
||||||
|
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
|
||||||
|
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
|
||||||
|
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
|
||||||
|
uint8_t src_addr_len; /**< Length (in bytes) of source address field */
|
||||||
|
uint8_t aux_sec_len; /**< Length (in bytes) of aux security header field */
|
||||||
|
} field_length_t;
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
CC_INLINE static uint8_t
|
||||||
|
addr_len(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case FRAME802154_SHORTADDRMODE: /* 16-bit address */
|
||||||
|
return 2;
|
||||||
|
case FRAME802154_LONGADDRMODE: /* 64-bit address */
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
field_len(frame802154_t *p, field_length_t *flen)
|
||||||
|
{
|
||||||
|
/* 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.dest_addr_mode) {
|
||||||
|
flen->dest_pid_len = 2;
|
||||||
|
}
|
||||||
|
if(p->fcf.src_addr_mode) {
|
||||||
|
flen->src_pid_len = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
||||||
|
if(p->fcf.dest_addr_mode && p->fcf.src_addr_mode && p->src_pid == p->dest_pid) {
|
||||||
|
p->fcf.panid_compression = 1;
|
||||||
|
|
||||||
|
/* compressed header, only do dest pid */
|
||||||
|
flen->src_pid_len = 0;
|
||||||
|
} else {
|
||||||
|
p->fcf.panid_compression = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine address lengths */
|
||||||
|
flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode);
|
||||||
|
flen->src_addr_len = addr_len(p->fcf.src_addr_mode);
|
||||||
|
|
||||||
|
/* Aux security header */
|
||||||
|
if(p->fcf.security_enabled) {
|
||||||
|
/* TODO Aux security header not yet implemented */
|
||||||
|
#if 0
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Calculates the length of the frame header. This function is
|
||||||
|
* meant to be called by a higher level function, that interfaces to a MAC.
|
||||||
|
*
|
||||||
|
* \param p Pointer to frame802154_t_t struct, which specifies the
|
||||||
|
* frame to send.
|
||||||
|
*
|
||||||
|
* \return The length of the frame header.
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
frame802154_hdrlen(frame802154_t *p)
|
||||||
|
{
|
||||||
|
field_length_t flen;
|
||||||
|
field_len(p, &flen);
|
||||||
|
return 3 + flen.dest_pid_len + flen.dest_addr_len +
|
||||||
|
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \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 frame802154_t struct, which specifies the
|
||||||
|
* frame to send.
|
||||||
|
*
|
||||||
|
* \param buf Pointer to the buffer to use for the frame.
|
||||||
|
*
|
||||||
|
* \param buf_len The length of the buffer to use for the frame.
|
||||||
|
*
|
||||||
|
* \return The length of the frame header or 0 if there was
|
||||||
|
* insufficient space in the buffer for the frame headers.
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
field_length_t flen;
|
||||||
|
uint8_t *tx_frame_buffer;
|
||||||
|
uint8_t pos;
|
||||||
|
|
||||||
|
field_len(p, &flen);
|
||||||
|
|
||||||
|
if(3 + flen.dest_pid_len + flen.dest_addr_len +
|
||||||
|
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len > buf_len) {
|
||||||
|
/* Too little space for headers. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, now we have field lengths. Time to actually construct */
|
||||||
|
/* the outgoing frame, and store it in tx_frame_buffer */
|
||||||
|
tx_frame_buffer = buf;
|
||||||
|
tx_frame_buffer[0] = (p->fcf.frame_type) |
|
||||||
|
(p->fcf.security_enabled << 3) | (p->fcf.frame_pending << 4) |
|
||||||
|
(p->fcf.ack_required << 5) | (p->fcf.panid_compression << 6);
|
||||||
|
tx_frame_buffer[1] = (p->fcf.dest_addr_mode << 2) |
|
||||||
|
(p->fcf.frame_version << 4) | (p->fcf.src_addr_mode << 6);
|
||||||
|
|
||||||
|
/* sequence number */
|
||||||
|
tx_frame_buffer[2] = p->seq;
|
||||||
|
pos = 3;
|
||||||
|
|
||||||
|
/* Destination PAN ID */
|
||||||
|
if(flen.dest_pid_len == 2) {
|
||||||
|
tx_frame_buffer[pos++] = p->dest_pid & 0xff;
|
||||||
|
tx_frame_buffer[pos++] = (p->dest_pid >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destination address */
|
||||||
|
for(c = flen.dest_addr_len; c > 0; c--) {
|
||||||
|
tx_frame_buffer[pos++] = p->dest_addr.u8[c - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Source PAN ID */
|
||||||
|
if(flen.src_pid_len == 2) {
|
||||||
|
tx_frame_buffer[pos++] = p->src_pid & 0xff;
|
||||||
|
tx_frame_buffer[pos++] = (p->src_pid >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Source address */
|
||||||
|
for(c = flen.src_addr_len; c > 0; c--) {
|
||||||
|
tx_frame_buffer[pos++] = p->src_addr.u8[c - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Aux header */
|
||||||
|
if(flen.aux_sec_len) {
|
||||||
|
/* TODO Aux security header not yet implemented */
|
||||||
|
/* pos += flen.aux_sec_len; */
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Parses an input frame. Scans the input frame to find each
|
||||||
|
* section, and stores the information of each section in a
|
||||||
|
* frame802154_t structure.
|
||||||
|
*
|
||||||
|
* \param data The input data from the radio chip.
|
||||||
|
* \param len The size of the input data
|
||||||
|
* \param pf The frame802154_t struct to store the parsed frame information.
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
frame802154_parse(uint8_t *data, uint8_t len, frame802154_t *pf)
|
||||||
|
{
|
||||||
|
uint8_t *p;
|
||||||
|
frame802154_fcf_t fcf;
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
if(len < 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = data;
|
||||||
|
|
||||||
|
/* decode the FCF */
|
||||||
|
fcf.frame_type = p[0] & 7;
|
||||||
|
fcf.security_enabled = (p[0] >> 3) & 1;
|
||||||
|
fcf.frame_pending = (p[0] >> 4) & 1;
|
||||||
|
fcf.ack_required = (p[0] >> 5) & 1;
|
||||||
|
fcf.panid_compression = (p[0] >> 6) & 1;
|
||||||
|
|
||||||
|
fcf.dest_addr_mode = (p[1] >> 2) & 3;
|
||||||
|
fcf.frame_version = (p[1] >> 4) & 3;
|
||||||
|
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
||||||
|
|
||||||
|
/* copy fcf and seqNum */
|
||||||
|
pf->fcf = fcf;
|
||||||
|
pf->seq = p[2];
|
||||||
|
p += 3; /* Skip first three bytes */
|
||||||
|
|
||||||
|
/* Destination address, if any */
|
||||||
|
if(fcf.dest_addr_mode) {
|
||||||
|
/* Destination PAN */
|
||||||
|
pf->dest_pid = p[0] + (p[1] << 8);
|
||||||
|
p += 2;
|
||||||
|
|
||||||
|
/* Destination address */
|
||||||
|
/* l = addr_len(fcf.dest_addr_mode); */
|
||||||
|
/* for(c = 0; c < l; c++) { */
|
||||||
|
/* pf->dest_addr.u8[c] = p[l - c - 1]; */
|
||||||
|
/* } */
|
||||||
|
/* p += l; */
|
||||||
|
if(fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||||
|
rimeaddr_copy(&(pf->dest_addr), &rimeaddr_null);
|
||||||
|
pf->dest_addr.u8[0] = p[1];
|
||||||
|
pf->dest_addr.u8[1] = p[0];
|
||||||
|
p += 2;
|
||||||
|
} else if(fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||||
|
for(c = 0; c < 8; c++) {
|
||||||
|
pf->dest_addr.u8[c] = p[7 - c];
|
||||||
|
}
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rimeaddr_copy(&(pf->dest_addr), &rimeaddr_null);
|
||||||
|
pf->dest_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Source address, if any */
|
||||||
|
if(fcf.src_addr_mode) {
|
||||||
|
/* Source PAN */
|
||||||
|
if(!fcf.panid_compression) {
|
||||||
|
pf->src_pid = p[0] + (p[1] << 8);
|
||||||
|
p += 2;
|
||||||
|
} else {
|
||||||
|
pf->src_pid = pf->dest_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Source address */
|
||||||
|
/* l = addr_len(fcf.src_addr_mode); */
|
||||||
|
/* for(c = 0; c < l; c++) { */
|
||||||
|
/* pf->src_addr.u8[c] = p[l - c - 1]; */
|
||||||
|
/* } */
|
||||||
|
/* p += l; */
|
||||||
|
if(fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
|
||||||
|
rimeaddr_copy(&(pf->src_addr), &rimeaddr_null);
|
||||||
|
pf->src_addr.u8[0] = p[1];
|
||||||
|
pf->src_addr.u8[1] = p[0];
|
||||||
|
p += 2;
|
||||||
|
} else if(fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
|
||||||
|
for(c = 0; c < 8; c++) {
|
||||||
|
pf->src_addr.u8[c] = p[7 - c];
|
||||||
|
}
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rimeaddr_copy(&(pf->src_addr), &rimeaddr_null);
|
||||||
|
pf->src_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fcf.security_enabled) {
|
||||||
|
/* TODO aux security header, not yet implemented */
|
||||||
|
/* return 0; */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header length */
|
||||||
|
c = p - data;
|
||||||
|
/* payload length */
|
||||||
|
pf->payload_len = len - c;
|
||||||
|
/* payload */
|
||||||
|
pf->payload = p;
|
||||||
|
|
||||||
|
/* return header length if successful */
|
||||||
|
return c > len ? 0 : c;
|
||||||
|
}
|
||||||
|
/** \} */
|
170
core/net/mac/frame802154.h
Normal file
170
core/net/mac/frame802154.h
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Additional fixes for MSP430 contributed by:
|
||||||
|
* Joakim Eriksson
|
||||||
|
* Niclas Finne
|
||||||
|
* Nicolas Tsiftes
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup frame802154
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \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.
|
||||||
|
*
|
||||||
|
* $Id: frame802154.h,v 1.1 2009/04/06 13:19:03 nifi Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Includes */
|
||||||
|
#ifndef FRAME_802154_H
|
||||||
|
#define FRAME_802154_H
|
||||||
|
|
||||||
|
#include "contiki-conf.h"
|
||||||
|
#include "net/rime/rimeaddr.h"
|
||||||
|
|
||||||
|
#ifdef IEEE802154_CONF_PANID
|
||||||
|
#define IEEE802154_PANID IEEE802154_CONF_PANID
|
||||||
|
#else
|
||||||
|
#define IEEE802154_PANID 0xABCD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Macros & Defines */
|
||||||
|
|
||||||
|
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
|
||||||
|
* \name FCF element values definitions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define FRAME802154_BEACONFRAME (0x00)
|
||||||
|
#define FRAME802154_DATAFRAME (0x01)
|
||||||
|
#define FRAME802154_ACKFRAME (0x02)
|
||||||
|
#define FRAME802154_CMDFRAME (0x03)
|
||||||
|
|
||||||
|
#define FRAME802154_BEACONREQ (0x07)
|
||||||
|
|
||||||
|
#define FRAME802154_IEEERESERVED (0x00)
|
||||||
|
#define FRAME802154_NOADDR (0x00) /**< Only valid for ACK or Beacon frames. */
|
||||||
|
#define FRAME802154_SHORTADDRMODE (0x02)
|
||||||
|
#define FRAME802154_LONGADDRMODE (0x03)
|
||||||
|
|
||||||
|
#define FRAME802154_NOBEACONS (0x0F)
|
||||||
|
|
||||||
|
#define FRAME802154_BROADCASTADDR (0xFFFF)
|
||||||
|
#define FRAME802154_BROADCASTPANDID (0xFFFF)
|
||||||
|
|
||||||
|
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||||
|
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||||
|
|
||||||
|
#define FRAME802154_SECURITY_LEVEL_NONE (0)
|
||||||
|
#define FRAME802154_SECURITY_LEVEL_128 (3)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The IEEE 802.15.4 frame has a number of constant/fixed fields that
|
||||||
|
* can be counted to make frame construction and max payload
|
||||||
|
* calculations easier.
|
||||||
|
*
|
||||||
|
* These include:
|
||||||
|
* 1. FCF - 2 bytes - Fixed
|
||||||
|
* 2. Sequence number - 1 byte - Fixed
|
||||||
|
* 3. Addressing fields - 4 - 20 bytes - Variable
|
||||||
|
* 4. Aux security header - 0 - 14 bytes - Variable
|
||||||
|
* 5. CRC - 2 bytes - Fixed
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Defines the bitfields of the frame control field (FCF).
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t frame_type : 3; /**< Frame type field, see 802.15.4 */
|
||||||
|
uint8_t security_enabled : 1; /**< True if security is used in this frame */
|
||||||
|
uint8_t frame_pending : 1; /**< True if sender has more data to send */
|
||||||
|
uint8_t ack_required : 1; /**< Is an ack frame required? */
|
||||||
|
uint8_t panid_compression : 1; /**< Is this a compressed header? */
|
||||||
|
uint8_t reserved : 3; /**< Unused bits */
|
||||||
|
uint8_t dest_addr_mode : 2; /**< Destination address mode, see 802.15.4 */
|
||||||
|
uint8_t frame_version : 2; /**< 802.15.4 frame version */
|
||||||
|
uint8_t src_addr_mode : 2; /**< Source address mode, see 802.15.4 */
|
||||||
|
} frame802154_fcf_t;
|
||||||
|
|
||||||
|
/** \brief 802.15.4 security control bitfield. See section 7.6.2.2.1 in 802.15.4 specification */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t security_level : 3; /**< security level */
|
||||||
|
uint8_t key_id_mode : 2; /**< Key identifier mode */
|
||||||
|
uint8_t reserved : 3; /**< Reserved bits */
|
||||||
|
} frame802154_scf_t;
|
||||||
|
|
||||||
|
/** \brief 802.15.4 Aux security header */
|
||||||
|
typedef struct {
|
||||||
|
frame802154_scf_t security_control; /**< Security control bitfield */
|
||||||
|
uint32_t frame_counter; /**< Frame counter, used for security */
|
||||||
|
uint8_t key[9]; /**< The key itself, or an index to the key */
|
||||||
|
} frame802154_aux_hdr_t;
|
||||||
|
|
||||||
|
/** \brief Parameters used by the frame802154_create() function. These
|
||||||
|
* parameters are used in the 802.15.4 frame header. See the 802.15.4
|
||||||
|
* specification for details.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
frame802154_fcf_t fcf; /**< Frame control field */
|
||||||
|
uint8_t seq; /**< Sequence number */
|
||||||
|
uint16_t dest_pid; /**< Destination PAN ID */
|
||||||
|
rimeaddr_t dest_addr; /**< Destination address */
|
||||||
|
uint16_t src_pid; /**< Source PAN ID */
|
||||||
|
rimeaddr_t src_addr; /**< Source address */
|
||||||
|
frame802154_aux_hdr_t aux_hdr; /**< Aux security header */
|
||||||
|
uint8_t *payload; /**< Pointer to 802.15.4 frame payload */
|
||||||
|
uint8_t payload_len; /**< Length of payload field */
|
||||||
|
} frame802154_t;
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
|
||||||
|
uint8_t frame802154_hdrlen(frame802154_t *p);
|
||||||
|
uint8_t frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len);
|
||||||
|
uint8_t frame802154_parse(uint8_t *data, uint8_t length, frame802154_t *pf);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
#endif /* FRAME_802154_H */
|
247
core/net/mac/sicslowmac.c
Normal file
247
core/net/mac/sicslowmac.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: sicslowmac.c,v 1.1 2009/04/06 13:19:03 nifi Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* MAC interface for packaging radio packets into 802.15.4 frames
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
* Eric Gnoske <egnoske@gmail.com>
|
||||||
|
* Blake Leverett <bleverett@gmail.com>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "net/mac/sicslowmac.h"
|
||||||
|
#include "net/mac/frame802154.h"
|
||||||
|
#include "net/rime/packetbuf.h"
|
||||||
|
#include "lib/random.h"
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#define PRINTADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7])
|
||||||
|
#else
|
||||||
|
#define PRINTF(...)
|
||||||
|
#define PRINTADDR(addr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \brief The sequence number (0x00 - 0xff) added to the transmitted
|
||||||
|
* data or MAC command frame. The default is a random value within
|
||||||
|
* the range.
|
||||||
|
*/
|
||||||
|
static uint8_t mac_dsn;
|
||||||
|
|
||||||
|
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||||
|
* sending to. If this value is 0xffff, the device is not
|
||||||
|
* associated.
|
||||||
|
*/
|
||||||
|
static uint16_t mac_dst_pan_id = IEEE802154_PANID;
|
||||||
|
|
||||||
|
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||||
|
* operating. If this value is 0xffff, the device is not
|
||||||
|
* associated.
|
||||||
|
*/
|
||||||
|
static uint16_t mac_src_pan_id = IEEE802154_PANID;
|
||||||
|
|
||||||
|
static const struct radio_driver *radio;
|
||||||
|
static void (* receiver_callback)(const struct mac_driver *);
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
||||||
|
{
|
||||||
|
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
|
||||||
|
while(i-- > 0) {
|
||||||
|
if(addr[i] != 0xff) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
send_packet(void)
|
||||||
|
{
|
||||||
|
frame802154_t params;
|
||||||
|
uint8_t len;
|
||||||
|
|
||||||
|
/* init to zeros */
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
/* Build the FCF. */
|
||||||
|
params.fcf.frame_type = FRAME802154_DATAFRAME;
|
||||||
|
params.fcf.security_enabled = 0;
|
||||||
|
params.fcf.frame_pending = 0;
|
||||||
|
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
|
||||||
|
params.fcf.panid_compression = 0;
|
||||||
|
|
||||||
|
/* Insert IEEE 802.15.4 (2003) version bit. */
|
||||||
|
params.fcf.frame_version = FRAME802154_IEEE802154_2003;
|
||||||
|
|
||||||
|
/* Increment and set the data sequence number. */
|
||||||
|
params.seq = mac_dsn++;
|
||||||
|
|
||||||
|
/* Complete the addressing fields. */
|
||||||
|
/**
|
||||||
|
\todo For phase 1 the addresses are all long. We'll need a mechanism
|
||||||
|
in the rime attributes to tell the mac to use long or short for phase 2.
|
||||||
|
*/
|
||||||
|
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
|
||||||
|
params.dest_pid = mac_dst_pan_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the output address is NULL in the Rime buf, then it is broadcast
|
||||||
|
* on the 802.15.4 network.
|
||||||
|
*/
|
||||||
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
|
||||||
|
/* Broadcast requires short address mode. */
|
||||||
|
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||||
|
params.dest_pid = FRAME802154_BROADCASTPANDID;
|
||||||
|
params.dest_addr.u8[0] = 0xFF;
|
||||||
|
params.dest_addr.u8[1] = 0xFF;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rimeaddr_copy(¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||||
|
params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the source PAN ID to the global variable. */
|
||||||
|
params.src_pid = mac_src_pan_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the source address using only the long address mode for
|
||||||
|
* phase 1.
|
||||||
|
*/
|
||||||
|
rimeaddr_copy(¶ms.src_addr, &rimeaddr_node_addr);
|
||||||
|
|
||||||
|
params.payload = packetbuf_dataptr();
|
||||||
|
params.payload_len = packetbuf_datalen();
|
||||||
|
len = frame802154_hdrlen(¶ms);
|
||||||
|
if(packetbuf_hdralloc(len)) {
|
||||||
|
frame802154_create(¶ms, packetbuf_hdrptr(), len);
|
||||||
|
|
||||||
|
PRINTF("6MAC-UT: %2X", params.fcf.frame_type);
|
||||||
|
PRINTADDR(params.dest_addr.u8);
|
||||||
|
PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen());
|
||||||
|
|
||||||
|
return radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||||
|
} else {
|
||||||
|
PRINTF("6MAC-UT: too large header: %u\n", len);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
input_packet(const struct radio_driver *d)
|
||||||
|
{
|
||||||
|
if(receiver_callback) {
|
||||||
|
receiver_callback(&sicslowmac_driver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
read_packet(void)
|
||||||
|
{
|
||||||
|
frame802154_t frame;
|
||||||
|
int len;
|
||||||
|
packetbuf_clear();
|
||||||
|
len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||||
|
if(len > 0) {
|
||||||
|
packetbuf_set_datalen(len);
|
||||||
|
if(frame802154_parse(packetbuf_dataptr(), len, &frame) &&
|
||||||
|
packetbuf_hdrreduce(len - frame.payload_len)) {
|
||||||
|
if(frame.fcf.dest_addr_mode &&
|
||||||
|
!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr.u8)) {
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &frame.dest_addr);
|
||||||
|
}
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &frame.src_addr);
|
||||||
|
|
||||||
|
PRINTF("6MAC-IN: %2X", frame.fcf.frame_type);
|
||||||
|
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||||
|
PRINTF("%u\n", packetbuf_datalen());
|
||||||
|
return packetbuf_datalen();
|
||||||
|
} else {
|
||||||
|
PRINTF("6MAC: failed to parse hdr\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
set_receive_function(void (* recv)(const struct mac_driver *))
|
||||||
|
{
|
||||||
|
receiver_callback = recv;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
on(void)
|
||||||
|
{
|
||||||
|
return radio->on();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
off(int keep_radio_on)
|
||||||
|
{
|
||||||
|
if(keep_radio_on) {
|
||||||
|
return radio->on();
|
||||||
|
} else {
|
||||||
|
return radio->off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
const struct mac_driver sicslowmac_driver = {
|
||||||
|
"sicslowmac",
|
||||||
|
send_packet,
|
||||||
|
read_packet,
|
||||||
|
set_receive_function,
|
||||||
|
on,
|
||||||
|
off,
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
const struct mac_driver *
|
||||||
|
sicslowmac_init(const struct radio_driver *d)
|
||||||
|
{
|
||||||
|
mac_dsn = random_rand() % 256;
|
||||||
|
|
||||||
|
radio = d;
|
||||||
|
radio->set_receive_function(input_packet);
|
||||||
|
radio->on();
|
||||||
|
return &sicslowmac_driver;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
56
core/net/mac/sicslowmac.h
Normal file
56
core/net/mac/sicslowmac.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: sicslowmac.h,v 1.1 2009/04/06 13:19:03 nifi Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* MAC interface for packaging radio packets into 802.15.4 frames
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
* Eric Gnoske <egnoske@gmail.com>
|
||||||
|
* Blake Leverett <bleverett@gmail.com>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SICSLOWMAC_H__
|
||||||
|
#define __SICSLOWMAC_H__
|
||||||
|
|
||||||
|
#include "net/mac/mac.h"
|
||||||
|
#include "dev/radio.h"
|
||||||
|
|
||||||
|
extern const struct mac_driver sicslowmac_driver;
|
||||||
|
|
||||||
|
const struct mac_driver *sicslowmac_init(const struct radio_driver *r);
|
||||||
|
|
||||||
|
#endif /* __SICSLOWMAC_H__ */
|
Loading…
Reference in a new issue