2013-06-22 05:11:53 +02:00
|
|
|
/*
|
|
|
|
* 6LoWPAN MAC - layer 2 implementations
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 INRIA.
|
|
|
|
*
|
|
|
|
* This file subject to the terms and conditions of the GNU Lesser General
|
|
|
|
* Public License. See the file LICENSE in the top level directory for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* @ingroup sixlowpan
|
|
|
|
* @{
|
2013-08-08 13:39:00 +02:00
|
|
|
* @file sixlowmac.c
|
|
|
|
* @brief 6lowpan link layer functions
|
2013-06-22 05:11:53 +02:00
|
|
|
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
|
|
|
|
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
|
|
|
|
* @author Eric Engel <eric.engel@fu-berlin.de>
|
|
|
|
* @author Oliver Gesch <oliver.gesch@googlemail.com>
|
2013-07-30 15:07:35 +02:00
|
|
|
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
2013-06-22 05:11:53 +02:00
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
2013-08-08 13:39:00 +02:00
|
|
|
#include <stdint.h>
|
2012-11-05 22:29:11 +01:00
|
|
|
#include <string.h>
|
2013-06-24 14:11:30 +02:00
|
|
|
|
2013-08-08 13:39:00 +02:00
|
|
|
#include "ltc4150.h"
|
|
|
|
#include "hwtimer.h"
|
2012-11-05 22:29:11 +01:00
|
|
|
#include "thread.h"
|
|
|
|
#include "msg.h"
|
|
|
|
#include "radio/radio.h"
|
|
|
|
#include "transceiver.h"
|
|
|
|
#include "vtimer.h"
|
2013-08-08 16:22:37 +02:00
|
|
|
#include "sixlowpan/mac.h"
|
2013-08-08 13:39:00 +02:00
|
|
|
|
|
|
|
#include "ip.h"
|
|
|
|
#include "icmp.h"
|
|
|
|
#include "lowpan.h"
|
2013-08-05 16:10:54 +02:00
|
|
|
#include "sys/net/ieee802154/ieee802154_frame.h"
|
|
|
|
#include "sys/net/net_help/net_help.h"
|
2012-11-05 22:29:11 +01:00
|
|
|
|
2013-07-30 15:07:35 +02:00
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#include "debug.h"
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
#define RADIO_STACK_SIZE (MINIMUM_STACK_SIZE + 256)
|
|
|
|
#define RADIO_RCV_BUF_SIZE (64)
|
|
|
|
#define RADIO_SENDING_DELAY (1000)
|
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
char radio_stack_buffer[RADIO_STACK_SIZE];
|
|
|
|
msg_t msg_q[RADIO_RCV_BUF_SIZE];
|
|
|
|
|
|
|
|
static uint8_t r_src_addr;
|
|
|
|
uint8_t buf[PAYLOAD_SIZE];
|
|
|
|
static uint8_t macdsn;
|
|
|
|
|
|
|
|
static radio_packet_t p;
|
|
|
|
static msg_t mesg;
|
|
|
|
int transceiver_type;
|
|
|
|
static transceiver_command_t tcmd;
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
uint8_t sixlowpan_mac_get_radio_address(void)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
int16_t address;
|
|
|
|
|
|
|
|
tcmd.transceivers = transceiver_type;
|
|
|
|
tcmd.data = &address;
|
2013-06-22 05:11:53 +02:00
|
|
|
mesg.content.ptr = (char *)&tcmd;
|
2012-11-05 22:29:11 +01:00
|
|
|
mesg.type = GET_ADDRESS;
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_send_receive(&mesg, &mesg, transceiver_pid);
|
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
return (uint8_t)address;
|
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
void sixlowpan_mac_set_radio_address(uint8_t addr)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
int16_t address = (int16_t)addr;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
tcmd.transceivers = transceiver_type;
|
|
|
|
tcmd.data = &address;
|
2013-06-22 05:11:53 +02:00
|
|
|
mesg.content.ptr = (char *)&tcmd;
|
2012-11-05 22:29:11 +01:00
|
|
|
mesg.type = SET_ADDRESS;
|
|
|
|
msg_send_receive(&mesg, &mesg, transceiver_pid);
|
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void set_radio_channel(uint8_t channel)
|
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
int16_t chan = (int16_t)channel;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
tcmd.transceivers = transceiver_type;
|
|
|
|
tcmd.data = &chan;
|
2013-06-22 05:11:53 +02:00
|
|
|
mesg.content.ptr = (char *)&tcmd;
|
2012-11-05 22:29:11 +01:00
|
|
|
mesg.type = SET_CHANNEL;
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_send_receive(&mesg, &mesg, transceiver_pid);
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void switch_to_rx(void)
|
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
mesg.type = SWITCH_RX;
|
2013-06-22 05:11:53 +02:00
|
|
|
mesg.content.ptr = (char *) &tcmd;
|
2012-11-05 22:29:11 +01:00
|
|
|
tcmd.transceivers = TRANSCEIVER_CC1100;
|
|
|
|
msg_send(&mesg, transceiver_pid, 1);
|
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
saddr->uint8[0] = 0;
|
2013-08-08 16:22:37 +02:00
|
|
|
saddr->uint8[1] = sixlowpan_mac_get_radio_address();
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2013-08-15 11:27:30 +02:00
|
|
|
return ((ieee_802154_long_t *) &ipaddr->uint8[8]);
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
// 16bit Pan-ID:16-zero-bits:16-bit-short-addr = 48bit
|
|
|
|
laddr->uint16[0] = IEEE_802154_PAN_ID;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
/* RFC 4944 Section 6 / RFC 2464 Section 4 */
|
|
|
|
laddr->uint8[0] ^= 0x02;
|
|
|
|
laddr->uint8[2] = 0;
|
|
|
|
laddr->uint8[3] = 0xFF;
|
|
|
|
laddr->uint8[4] = 0xFE;
|
|
|
|
laddr->uint8[5] = 0;
|
|
|
|
laddr->uint8[6] = 0;
|
2013-08-08 16:22:37 +02:00
|
|
|
laddr->uint8[7] = sixlowpan_mac_get_radio_address();
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void recv_ieee802154_frame(void)
|
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
msg_t m;
|
|
|
|
radio_packet_t *p;
|
|
|
|
uint8_t hdrlen, length;
|
|
|
|
ieee802154_frame_t frame;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
msg_init_queue(msg_q, RADIO_RCV_BUF_SIZE);
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
while (1) {
|
2012-11-05 22:29:11 +01:00
|
|
|
msg_receive(&m);
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (m.type == PKT_PENDING) {
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
p = (radio_packet_t *) m.content.ptr;
|
2012-11-05 22:29:11 +01:00
|
|
|
hdrlen = read_802154_frame(p->data, &frame, p->length);
|
|
|
|
length = p->length - hdrlen;
|
|
|
|
|
|
|
|
/* deliver packet to network(6lowpan)-layer */
|
2013-06-22 05:11:53 +02:00
|
|
|
lowpan_read(frame.payload, length, (ieee_802154_long_t *)&frame.src_addr,
|
|
|
|
(ieee_802154_long_t *)&frame.dest_addr);
|
2012-11-05 22:29:11 +01:00
|
|
|
|
|
|
|
p->processing--;
|
|
|
|
}
|
2013-06-24 22:37:35 +02:00
|
|
|
else if (m.type == ENOBUFFER) {
|
2012-11-05 22:29:11 +01:00
|
|
|
puts("Transceiver buffer full");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
puts("Unknown packet received");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_ieee802154_fcf_values(ieee802154_frame_t *frame, uint8_t dest_mode,
|
2013-06-22 05:11:53 +02:00
|
|
|
uint8_t src_mode)
|
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
frame->fcf.frame_type = IEEE_802154_DATA_FRAME;
|
|
|
|
frame->fcf.sec_enb = 0;
|
|
|
|
frame->fcf.frame_pend = 0;
|
|
|
|
frame->fcf.ack_req = 0;
|
|
|
|
frame->fcf.panid_comp = 0;
|
|
|
|
frame->fcf.frame_ver = 0;
|
|
|
|
frame->fcf.src_addr_m = src_mode;
|
|
|
|
frame->fcf.dest_addr_m = dest_mode;
|
2013-09-23 15:09:16 +02:00
|
|
|
#if ENABLE_DEBUG
|
2013-07-30 15:07:35 +02:00
|
|
|
print_802154_fcf_frame(frame);
|
2013-09-23 15:09:16 +02:00
|
|
|
#endif
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void set_ieee802154_frame_values(ieee802154_frame_t *frame)
|
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
// TODO: addresse aus ip paket auslesen und in frame einfuegen
|
|
|
|
frame->dest_pan_id = IEEE_802154_PAN_ID;
|
|
|
|
frame->src_pan_id = IEEE_802154_PAN_ID;
|
|
|
|
frame->seq_nr = macdsn;
|
|
|
|
macdsn++;
|
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr,
|
2013-08-13 06:41:05 +02:00
|
|
|
const uint8_t *payload,
|
|
|
|
uint8_t length, uint8_t mcast)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2012-11-05 22:29:11 +01:00
|
|
|
uint16_t daddr;
|
|
|
|
/* TODO: check if dedicated response struct is necessary */
|
|
|
|
msg_t transceiver_rsp;
|
|
|
|
r_src_addr = local_address;
|
|
|
|
mesg.type = SND_PKT;
|
2013-06-22 05:11:53 +02:00
|
|
|
mesg.content.ptr = (char *) &tcmd;
|
2012-11-05 22:29:11 +01:00
|
|
|
|
|
|
|
tcmd.transceivers = transceiver_type;
|
|
|
|
tcmd.data = &p;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
ieee802154_frame_t frame;
|
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
memset(&frame, 0, sizeof(frame));
|
2013-06-22 05:11:53 +02:00
|
|
|
set_ieee802154_fcf_values(&frame, IEEE_802154_LONG_ADDR_M,
|
2012-11-05 22:29:11 +01:00
|
|
|
IEEE_802154_LONG_ADDR_M);
|
2013-06-22 05:11:53 +02:00
|
|
|
set_ieee802154_frame_values(&frame);
|
|
|
|
|
2012-11-05 22:29:11 +01:00
|
|
|
memcpy(&(frame.dest_addr[0]), &(addr->uint8[0]), 8);
|
|
|
|
memcpy(&(frame.src_addr[0]), &(iface.laddr.uint8[0]), 8);
|
|
|
|
|
|
|
|
daddr = HTONS(addr->uint16[3]);
|
2013-08-08 16:22:37 +02:00
|
|
|
frame.payload = (uint8_t *)payload; // payload won't be changed so cast is legal.
|
2012-11-05 22:29:11 +01:00
|
|
|
frame.payload_len = length;
|
|
|
|
uint8_t hdrlen = get_802154_hdr_len(&frame);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
memset(&buf, 0, PAYLOAD_SIZE);
|
|
|
|
init_802154_frame(&frame, (uint8_t *)&buf);
|
|
|
|
memcpy(&buf[hdrlen], frame.payload, frame.payload_len);
|
2013-08-15 20:25:20 +02:00
|
|
|
/* set FCS */
|
|
|
|
/* RSSI = 0 */
|
|
|
|
buf[frame.payload_len+hdrlen] = 0;
|
|
|
|
/* FCS Valid = 1 / LQI Correlation Value = 0 */
|
|
|
|
buf[frame.payload_len+hdrlen+1] = 0x80;
|
2013-07-30 15:07:35 +02:00
|
|
|
DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame->dest_pan_id, frame->src_pan_id, frame->seq_nr);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-08-15 20:25:20 +02:00
|
|
|
p.length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (mcast == 0) {
|
2012-11-05 22:29:11 +01:00
|
|
|
p.dst = daddr;
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
else {
|
2012-11-05 22:29:11 +01:00
|
|
|
p.dst = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
p.data = buf;
|
|
|
|
msg_send_receive(&mesg, &transceiver_rsp, transceiver_pid);
|
|
|
|
|
|
|
|
hwtimer_wait(5000);
|
|
|
|
}
|
|
|
|
|
2013-08-08 16:22:37 +02:00
|
|
|
void sixlowpan_mac_init(transceiver_type_t type)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
|
|
|
int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE,
|
|
|
|
PRIORITY_MAIN - 2, CREATE_STACKTEST, recv_ieee802154_frame , "radio");
|
2012-11-05 22:29:11 +01:00
|
|
|
transceiver_type = type;
|
|
|
|
transceiver_init(transceiver_type);
|
|
|
|
transceiver_start();
|
|
|
|
transceiver_register(type, recv_pid);
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
macdsn = rand() % 256;
|
2012-11-05 22:29:11 +01:00
|
|
|
}
|