/*---------------------------------------------------------------------------*/ static void handle_beacon_send_timer(struct net_buf *buf, void *p) { struct net_buf *mbuf; frame802154_t params; uint8_t len; mbuf = l2_buf_get_reserve(0); if(!mbuf) { return; } /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* use packetbuf for sending ?? */ packetbuf_clear(mbuf); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_BEACONFRAME; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; /* assume long for now */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); /* Set the source PAN ID to the global variable. */ params.src_pid = panid; params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; params.dest_pid = 0xffff; params.seq = framer_802154_next_seqno(); /* Calculate beacon length and copy it to packetbuf */ beacon_payload_len = handler_802154_calculate_beacon_payload_length(beacon_payload, BEACON_PAYLOAD_BUFFER_SIZE); packetbuf_copyfrom(mbuf, beacon_payload, beacon_payload_len); /* Set payload and payload length */ params.payload = packetbuf_dataptr(mbuf); params.payload_len = packetbuf_datalen(mbuf); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(mbuf, len)) { frame802154_create(¶ms, packetbuf_hdrptr(mbuf), len); if(NETSTACK_RADIO.send(mbuf, packetbuf_hdrptr(mbuf), packetbuf_totlen(mbuf)) != RADIO_TX_OK) { l2_buf_unref(mbuf); return; } HANDLER_802154_STAT(handler_802154_stats.beacons_sent++); } }
/* * active scan - will scan all 16 channels in the 802.15.4 network * NOTE: this assumes 16 channels, starting from 11. Needs to be changed * if running on other than 2.4 GHz */ int handler_802154_active_scan(scan_callback_t cb) { /* if no scan is active - start one */ if(!scan) { callback = cb; current_channel = 0; #if (DISABLE_NETSELECT_RANDOM_CHANNEL == 0) channel_index = 0; #endif /* (DISABLE_NETSELECT_RANDOM_CHANNEL == 0) */ scan = 1; chseqno = framer_802154_next_seqno(); NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, 0); ctimer_set(NULL, &scan_timer, (CLOCK_SECOND * 6) / 10, &handle_scan_timer, callback); return 1; } return 0; }
/*---------------------------------------------------------------------------*/ static int create_frame(struct net_buf *buf, int do_create) { frame802154_t params; int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* Build the FCF. */ params.fcf.frame_type = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(buf, PACKETBUF_ATTR_PENDING); if(packetbuf_holds_broadcast(buf)) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(buf, PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; #if LLSEC802154_SECURITY_LEVEL if(packetbuf_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } /* Setting security-related attributes */ params.aux_hdr.security_control.security_level = packetbuf_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); #if LLSEC802154_USES_EXPLICIT_KEYS params.aux_hdr.security_control.key_id_mode = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.key_index = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_SECURITY_LEVEL */ /* Increment and set the data sequence number. */ if(!do_create) { /* Only length calculation - no sequence number is needed and should not be consumed. */ } else if(packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO); } else { params.seq = framer_802154_next_seqno(); packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* 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. */ if(LINKADDR_SIZE == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast(buf)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(LINKADDR_SIZE == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { 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. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); params.payload = packetbuf_dataptr(buf); params.payload_len = packetbuf_datalen(buf); hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ return hdr_len; } else if(packetbuf_hdralloc(buf, hdr_len)) { frame802154_create(¶ms, packetbuf_hdrptr(buf), hdr_len); PRINTF("15.4-OUT: %2X ", params.fcf.frame_type); PRINTLLADDR((const uip_lladdr_t *)params.dest_addr); PRINTF(" %d %u (%u)\n", hdr_len, packetbuf_datalen(buf), packetbuf_totlen(buf)); return hdr_len; } else { PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } }