diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 42af6b5dfa..e983b1682b 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -26,23 +26,44 @@ #include /* maximum 802.15.4 header length */ -#define IEEE_802154_MAX_HDR_LEN 23 +#define IEEE_802154_MAX_HDR_LEN (23) /* ...and FCS*/ -#define IEEE_802154_FCS_LEN 2 +#define IEEE_802154_FCS_LEN (2) -#define IEEE_802154_BEACON_FRAME 0 -#define IEEE_802154_DATA_FRAME 1 -#define IEEE_802154_ACK_FRAME 2 -#define IEEE_802154_MAC_CMD_FRAME 3 +#define IEEE_802154_BEACON_FRAME (0) +#define IEEE_802154_DATA_FRAME (1) +#define IEEE_802154_ACK_FRAME (2) +#define IEEE_802154_MAC_CMD_FRAME (3) -#define IEEE_802154_SHORT_ADDR_M 2 -#define IEEE_802154_LONG_ADDR_M 3 +#define IEEE_802154_SHORT_ADDR_M (2) +#define IEEE_802154_LONG_ADDR_M (3) #define IEEE_802154_SHORT_MCAST_ADDR (0xffff) #define IEEE_802154_LONG_MCAST_ADDR {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff}} +/** + * @brief Transform 16-bit number from network order (big-endian) to + * little-endian byte order (as used by IEEE 802.15.4). + */ +#define NTOLES(a) (((a) >> 8) | (((a) & 0x00ff) << 8)) -#define IEEE_802154_PAN_ID 0x1234 +/** + * @brief Transform 16-bit number from little-endian byte order to network + * order (big-endian). + */ +#define LETONS(a) NTOLES(a) + +/** + * @brief Transform 16-bit number from host byte order to little-endian byte + * order (as used by IEEE 802.15.4). + */ +#define HTOLES(a) a + +/** + * @brief Transform 16-bit number from little-endian byte order to host byte + * order. + */ +#define LETOHS(a) HTOLES(a) typedef struct __attribute__((packed)) { uint8_t frame_type; @@ -84,6 +105,7 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf); uint8_t ieee802154_frame_get_hdr_len(ieee802154_frame_t *frame); uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len); void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame); +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len); /** @} */ #endif /* IEEE802154_IEEE802154_FRAME */ diff --git a/sys/net/link_layer/ieee802154/ieee802154_frame.c b/sys/net/link_layer/ieee802154/ieee802154_frame.c index 866cb457da..7a9e412a75 100644 --- a/sys/net/link_layer/ieee802154/ieee802154_frame.c +++ b/sys/net/link_layer/ieee802154/ieee802154_frame.c @@ -18,6 +18,13 @@ #include "ieee802154_frame.h" +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif +#include "debug.h" + +#define IEEE_802154_FCS_POLY (0x8408) /* x^16 + x^12 + x^5 + 1 for LSB first */ uint8_t ieee802154_hdr_ptr; uint8_t ieee802154_payload_ptr; @@ -28,16 +35,16 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Frame Control Field - 802.15.4 - 2006 - 7.2.1.1 */ uint8_t index = 0; - buf[index] = ((frame->fcf.frame_type) | - (frame->fcf.sec_enb << 3) | - (frame->fcf.frame_pend << 4) | - (frame->fcf.ack_req << 5) | - (frame->fcf.panid_comp << 6)); + buf[index] = (((frame->fcf.frame_type) & 0x07) | + ((frame->fcf.sec_enb << 3) & 0x08) | + ((frame->fcf.frame_pend << 4) & 0x10) | + ((frame->fcf.ack_req << 5) & 0x20) | + ((frame->fcf.panid_comp << 6) & 0x40)); index++; - buf[index] = ((frame->fcf.dest_addr_m << 2) | - (frame->fcf.frame_ver << 4) | - (frame->fcf.src_addr_m << 6)); + buf[index] = (((frame->fcf.dest_addr_m << 2) & 0x0c) | + ((frame->fcf.frame_ver << 4) & 0x30) | + ((frame->fcf.src_addr_m << 6) & 0xc0)); index++; @@ -55,49 +62,62 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Destination Address - 802.15.4 - 2006 - 7.2.1.4 */ if (frame->fcf.dest_addr_m == 0x02) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; + buf[index] = frame->dest_addr[1]; + buf[index + 1] = frame->dest_addr[0]; index += 2; } else if (frame->fcf.dest_addr_m == 0x03) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; - buf[index + 2] = frame->dest_addr[2]; - buf[index + 3] = frame->dest_addr[3]; - buf[index + 4] = frame->dest_addr[4]; - buf[index + 5] = frame->dest_addr[5]; - buf[index + 6] = frame->dest_addr[6]; - buf[index + 7] = frame->dest_addr[7]; + buf[index] = frame->dest_addr[7]; + buf[index + 1] = frame->dest_addr[6]; + buf[index + 2] = frame->dest_addr[5]; + buf[index + 3] = frame->dest_addr[4]; + buf[index + 4] = frame->dest_addr[3]; + buf[index + 5] = frame->dest_addr[2]; + buf[index + 6] = frame->dest_addr[1]; + buf[index + 7] = frame->dest_addr[0]; index += 8; } /* Source PAN Identifier - 802.15.4 - 2006 - 7.2.1.5 */ if (!(frame->fcf.panid_comp & 0x01)) { if (frame->fcf.src_addr_m == 0x02 || frame->fcf.src_addr_m == 0x03) { - buf[index] = ((frame->src_pan_id >> 8) & 0xff); - buf[index + 1] = (frame->src_pan_id & 0xff); + buf[index + 1] = ((frame->src_pan_id >> 8) & 0xff); + buf[index] = (frame->src_pan_id & 0xff); index += 2; } } /* Source Address field - 802.15.4 - 2006 - 7.2.1.6 */ if (frame->fcf.src_addr_m == 0x02) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; + buf[index] = frame->src_addr[1]; + buf[index + 1] = frame->src_addr[0]; index += 2; } else if (frame->fcf.src_addr_m == 0x03) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; - buf[index + 2] = frame->src_addr[2]; - buf[index + 3] = frame->src_addr[3]; - buf[index + 4] = frame->src_addr[4]; - buf[index + 5] = frame->src_addr[5]; - buf[index + 6] = frame->src_addr[6]; - buf[index + 7] = frame->src_addr[7]; + buf[index] = frame->src_addr[7]; + buf[index + 1] = frame->src_addr[6]; + buf[index + 2] = frame->src_addr[5]; + buf[index + 3] = frame->src_addr[4]; + buf[index + 4] = frame->src_addr[3]; + buf[index + 5] = frame->src_addr[2]; + buf[index + 6] = frame->src_addr[1]; + buf[index + 7] = frame->src_addr[0]; index += 8; } +#ifdef DEBUG_ENABLED + DEBUG("INFO: IEEE 802.15.4 header initialized:\n"); + + for (size_t i = 0; i < index; i++) { + printf("%02x ", buf[i]); + + if (!((i + 1) % 16) || i == index - 1) { + printf("\n"); + } + } + +#endif + return index; } @@ -170,13 +190,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; - switch(frame->fcf.dest_addr_m) { + switch (frame->fcf.dest_addr_m) { case (0): { - printf("fcf.dest_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.dest_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->dest_addr[0] = buf[index]; frame->dest_addr[1] = buf[index + 1]; index += 2; @@ -184,14 +205,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->dest_addr[0] = buf[index]; - frame->dest_addr[1] = buf[index + 1]; - frame->dest_addr[2] = buf[index + 2]; - frame->dest_addr[3] = buf[index + 3]; - frame->dest_addr[4] = buf[index + 4]; - frame->dest_addr[5] = buf[index + 5]; - frame->dest_addr[6] = buf[index + 6]; - frame->dest_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->dest_addr[7] = buf[index]; + frame->dest_addr[6] = buf[index + 1]; + frame->dest_addr[5] = buf[index + 2]; + frame->dest_addr[4] = buf[index + 3]; + frame->dest_addr[3] = buf[index + 4]; + frame->dest_addr[2] = buf[index + 5]; + frame->dest_addr[1] = buf[index + 6]; + frame->dest_addr[0] = buf[index + 7]; index += 8; break; } @@ -202,13 +224,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; } - switch(frame->fcf.src_addr_m) { + switch (frame->fcf.src_addr_m) { case (0): { - printf("fcf.src_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.src_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->src_addr[0] = buf[index]; frame->src_addr[1] = buf[index + 1]; index += 2; @@ -216,14 +239,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->src_addr[0] = buf[index]; - frame->src_addr[1] = buf[index + 1]; - frame->src_addr[2] = buf[index + 2]; - frame->src_addr[3] = buf[index + 3]; - frame->src_addr[4] = buf[index + 4]; - frame->src_addr[5] = buf[index + 5]; - frame->src_addr[6] = buf[index + 6]; - frame->src_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->src_addr[7] = buf[index]; + frame->src_addr[6] = buf[index + 1]; + frame->src_addr[5] = buf[index + 2]; + frame->src_addr[4] = buf[index + 3]; + frame->src_addr[3] = buf[index + 4]; + frame->src_addr[2] = buf[index + 5]; + frame->src_addr[1] = buf[index + 6]; + frame->src_addr[0] = buf[index + 7]; index += 8; break; } @@ -236,6 +260,27 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, return hdrlen; } +/* crc with lsb first */ +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len) +{ + uint16_t r = 0; + + for (uint8_t byte = 0; byte < frame_len; ++byte) { + r ^= frame[byte]; + + for (uint8_t bit = 8; bit > 0; --bit) { + if (r & 0x0001) { + r = (r >> 1) ^ IEEE_802154_FCS_POLY; + } + else { + r = (r >> 1); + } + } + } + + return r; +} + void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame) { printf("frame type: %02x\n"