From 9f2ff48fda2369c778bd1a4b21778d6b4e343f82 Mon Sep 17 00:00:00 2001 From: nifi Date: Mon, 6 Apr 2009 13:19:03 +0000 Subject: [PATCH] added 802.15.4 frame packeter --- core/net/mac/Makefile.mac | 2 +- core/net/mac/frame802154.c | 352 +++++++++++++++++++++++++++++++++++++ core/net/mac/frame802154.h | 170 ++++++++++++++++++ core/net/mac/sicslowmac.c | 247 ++++++++++++++++++++++++++ core/net/mac/sicslowmac.h | 56 ++++++ 5 files changed, 826 insertions(+), 1 deletion(-) create mode 100644 core/net/mac/frame802154.c create mode 100644 core/net/mac/frame802154.h create mode 100644 core/net/mac/sicslowmac.c create mode 100644 core/net/mac/sicslowmac.h diff --git a/core/net/mac/Makefile.mac b/core/net/mac/Makefile.mac index 1fad82986..9f4a97085 100644 --- a/core/net/mac/Makefile.mac +++ b/core/net/mac/Makefile.mac @@ -1 +1 @@ -CONTIKI_SOURCEFILES += xmac.c nullmac.c lpp.c #xmac2.c +CONTIKI_SOURCEFILES += xmac.c nullmac.c lpp.c frame802154.c sicslowmac.c diff --git a/core/net/mac/frame802154.c b/core/net/mac/frame802154.c new file mode 100644 index 000000000..39e5f1b4b --- /dev/null +++ b/core/net/mac/frame802154.c @@ -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 + +/** + * \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; +} +/** \} */ diff --git a/core/net/mac/frame802154.h b/core/net/mac/frame802154.h new file mode 100644 index 000000000..783f95fdb --- /dev/null +++ b/core/net/mac/frame802154.h @@ -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 */ diff --git a/core/net/mac/sicslowmac.c b/core/net/mac/sicslowmac.c new file mode 100644 index 000000000..2ee70305e --- /dev/null +++ b/core/net/mac/sicslowmac.c @@ -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 + * Eric Gnoske + * Blake Leverett + * Niclas Finne + * Joakim Eriksson + */ + +#include +#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 +#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; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/sicslowmac.h b/core/net/mac/sicslowmac.h new file mode 100644 index 000000000..d5b52729c --- /dev/null +++ b/core/net/mac/sicslowmac.h @@ -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 + * Eric Gnoske + * Blake Leverett + * Niclas Finne + * Joakim Eriksson + */ + +#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__ */