void ng_ndp_state_timeout(ng_ipv6_nc_t *nc_entry) { switch (ng_ipv6_nc_get_state(nc_entry)) { case NG_IPV6_NC_STATE_REACHABLE: _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); break; case NG_IPV6_NC_STATE_DELAY: _set_state(nc_entry, NG_IPV6_NC_STATE_PROBE); break; default: break; } }
static bool _handle_sl2a_opt(kernel_pid_t iface, ng_pktsnip_t *pkt, ng_ipv6_hdr_t *ipv6, uint8_t icmpv6_type, ng_ndp_opt_t *sl2a_opt) { ng_ipv6_nc_t *nc_entry = NULL; uint8_t sl2a_len = 0; uint8_t *sl2a = (uint8_t *)(sl2a_opt + 1); if ((sl2a_opt->len == 0) || ng_ipv6_addr_is_unspecified(&ipv6->src)) { DEBUG("ndp: invalid source link-layer address option received\n"); return false; } while (pkt) { if (pkt->type == NG_NETTYPE_NETIF) { ng_netif_hdr_t *hdr = pkt->data; sl2a_len = hdr->src_l2addr_len; break; } pkt = pkt->next; } if (sl2a_len == 0) { /* in case there was no source address in l2 */ sl2a_len = (sl2a_opt->len / 8) - sizeof(ng_ndp_opt_t); /* ignore all zeroes at the end for length */ for (; sl2a[sl2a_len - 1] == 0x00; sl2a_len--); } DEBUG("ndp: received SL2A (link-layer address: %s)\n", ng_netif_addr_to_str(addr_str, sizeof(addr_str), sl2a, sl2a_len)); switch (icmpv6_type) { case NG_ICMPV6_NBR_SOL: nc_entry = ng_ipv6_nc_get(iface, &ipv6->src); if (nc_entry != NULL) { if ((sl2a_len != nc_entry->l2_addr_len) || (memcmp(sl2a, nc_entry->l2_addr, sl2a_len) != 0)) { /* if entry exists but l2 address differs: set */ nc_entry->l2_addr_len = sl2a_len; memcpy(nc_entry->l2_addr, sl2a, sl2a_len); _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } } else { ng_ipv6_nc_add(iface, &ipv6->src, sl2a, sl2a_len, NG_IPV6_NC_STATE_STALE); } return true; default: /* wrong encapsulating message: silently discard */ DEBUG("ndp: silently discard sl2a_opt for ICMPv6 message type %" PRIu8 "\n", icmpv6_type); return true; } }
void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) { uint8_t old_state = at86rf2xx_get_status(dev); /* make sure there is no ongoing transmission, or state transition already * in progress */ while (old_state == AT86RF2XX_STATE_BUSY_RX_AACK || old_state == AT86RF2XX_STATE_BUSY_TX_ARET || old_state == AT86RF2XX_STATE_IN_PROGRESS) { old_state = at86rf2xx_get_status(dev); } if (state == old_state) { return; } /* we need to go via PLL_ON if we are moving between RX_AACK_ON <-> TX_ARET_ON */ if ((old_state == AT86RF2XX_STATE_RX_AACK_ON && state == AT86RF2XX_STATE_TX_ARET_ON) || (old_state == AT86RF2XX_STATE_TX_ARET_ON && state == AT86RF2XX_STATE_RX_AACK_ON)) { _set_state(dev, AT86RF2XX_STATE_PLL_ON); } /* check if we need to wake up from sleep mode */ else if (old_state == AT86RF2XX_STATE_SLEEP) { DEBUG("at86rf2xx: waking up from sleep mode\n"); at86rf2xx_assert_awake(dev); } if (state == AT86RF2XX_STATE_SLEEP) { /* First go to TRX_OFF */ at86rf2xx_force_trx_off(dev); /* Discard all IRQ flags, framebuffer is lost anyway */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); /* Go to SLEEP mode from TRX_OFF */ gpio_set(dev->params.sleep_pin); dev->state = state; } else { _set_state(dev, state); } }
int _set(ng_netdev_t *dev, netopt_t opt, void *value, size_t value_len) { (void)dev; switch (opt) { case NETOPT_ADDRESS: return _set_address(value, value_len); case NETOPT_CHANNEL: return _set_channel(value, value_len); case NETOPT_NID: return _set_pan(value, value_len); case NETOPT_TX_POWER: return _set_txpower(value, value_len); case NETOPT_STATE: return _set_state(value, value_len); default: return -ENOTSUP; } }
void Machine::process() { std::unique_lock<std::mutex> lock( _mutexQueueEvents ); auto queue = _eventsQueue; while( _eventsQueue.empty() == false ) _eventsQueue.pop(); lock.unlock(); while( queue.size() > 0 ) { Event& event = *queue.front(); Tag nextState = _currentState->process( event ); auto iState = _state( nextState ); if( _isvalid( iState ) ) { _set_state( *iState ); } queue.pop(); } }
static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len) { at86rf2xx_t *dev = (at86rf2xx_t *) netdev; uint8_t old_state = at86rf2xx_get_status(dev); int res = -ENOTSUP; if (dev == NULL) { return -ENODEV; } /* temporarily wake up if sleeping */ if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_assert_awake(dev); } switch (opt) { case NETOPT_ADDRESS: if (len > sizeof(uint16_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_addr_short(dev, *((uint16_t *)val)); /* don't set res to set netdev2_ieee802154_t::short_addr */ } break; case NETOPT_ADDRESS_LONG: if (len > sizeof(uint64_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_addr_long(dev, *((uint64_t *)val)); /* don't set res to set netdev2_ieee802154_t::long_addr */ } break; case NETOPT_NID: if (len > sizeof(uint16_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_pan(dev, *((uint16_t *)val)); /* don't set res to set netdev2_ieee802154_t::pan */ } break; case NETOPT_CHANNEL: if (len != sizeof(uint16_t)) { res = -EINVAL; } else { uint8_t chan = ((uint8_t *)val)[0]; if (chan < AT86RF2XX_MIN_CHANNEL || chan > AT86RF2XX_MAX_CHANNEL) { res = -EINVAL; break; } at86rf2xx_set_chan(dev, chan); /* don't set res to set netdev2_ieee802154_t::chan */ } break; case NETOPT_CHANNEL_PAGE: if (len != sizeof(uint16_t)) { res = -EINVAL; } else { uint8_t page = ((uint8_t *)val)[0]; #ifdef MODULE_AT86RF212B if ((page != 0) && (page != 2)) { res = -EINVAL; } else { at86rf2xx_set_page(dev, page); res = sizeof(uint16_t); } #else /* rf23x only supports page 0, no need to configure anything in the driver. */ if (page != 0) { res = -EINVAL; } else { res = sizeof(uint16_t); } #endif } break; case NETOPT_TX_POWER: if (len > sizeof(int16_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_txpower(dev, *((int16_t *)val)); res = sizeof(uint16_t); } break; case NETOPT_STATE: if (len > sizeof(netopt_state_t)) { res = -EOVERFLOW; } else { res = _set_state(dev, *((netopt_state_t *)val)); } break; case NETOPT_AUTOACK: at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, ((bool *)val)[0]); /* don't set res to set netdev2_ieee802154_t::flags */ break; case NETOPT_RETRANS: if (len > sizeof(uint8_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_max_retries(dev, *((uint8_t *)val)); res = sizeof(uint8_t); } break; case NETOPT_PRELOADING: at86rf2xx_set_option(dev, AT86RF2XX_OPT_PRELOADING, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_PROMISCUOUSMODE: at86rf2xx_set_option(dev, AT86RF2XX_OPT_PROMISCUOUS, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_RX_START_IRQ: at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_RX_END_IRQ: at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_TX_START_IRQ: at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_START, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_TX_END_IRQ: at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_CSMA: at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_CSMA_RETRIES: if ((len > sizeof(uint8_t)) || (*((uint8_t *)val) > 5)) { res = -EOVERFLOW; } else if (dev->netdev.flags & AT86RF2XX_OPT_CSMA) { /* only set if CSMA is enabled */ at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val)); res = sizeof(uint8_t); } break; case NETOPT_CCA_THRESHOLD: if (len > sizeof(int8_t)) { res = -EOVERFLOW; } else { at86rf2xx_set_cca_threshold(dev, *((int8_t *)val)); res = sizeof(int8_t); } break; default: break; } /* go back to sleep if were sleeping and state hasn't been changed */ if ((old_state == AT86RF2XX_STATE_SLEEP) && (opt != NETOPT_STATE)) { at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP); } if (res == -ENOTSUP) { res = netdev2_ieee802154_set((netdev2_ieee802154_t *)netdev, opt, val, len); } return res; }
kernel_pid_t ng_ndp_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len, kernel_pid_t iface, ng_ipv6_addr_t *dst, ng_pktsnip_t *pkt) { ng_ipv6_addr_t *next_hop_ip = NULL, *prefix = NULL; #ifdef MODULE_NG_IPV6_EXT_RH next_hop_ip = ng_ipv6_ext_rh_next_hop(hdr); #endif #ifdef MODULE_FIB size_t next_hop_size = sizeof(ng_ipv6_addr_t); uint32_t next_hop_flags = 0; ng_ipv6_addr_t next_hop_actual; /* FIB copies address into this variable */ if ((next_hop_ip == NULL) && (fib_get_next_hop(&iface, next_hop_actual.u8, &next_hop_size, &next_hop_flags, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0) >= 0) && (next_hop_size == sizeof(ng_ipv6_addr_t))) { next_hop_ip = &next_hop_actual; } #endif if (next_hop_ip == NULL) { /* no route to host */ if (iface == KERNEL_PID_UNDEF) { /* ng_ipv6_netif_t doubles as prefix list */ iface = ng_ipv6_netif_find_by_prefix(&prefix, dst); } else { /* ng_ipv6_netif_t doubles as prefix list */ prefix = ng_ipv6_netif_match_prefix(iface, dst); } if ((prefix != NULL) && /* prefix is on-link */ (ng_ipv6_netif_addr_get(prefix)->flags & NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK)) { next_hop_ip = dst; #ifdef MODULE_FIB /* We don't care if FIB is full, this is just for efficiency * for later sends */ fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0, (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0, FIB_LIFETIME_NO_EXPIRE); #endif } } if (next_hop_ip == NULL) { next_hop_ip = _default_router(); #ifdef MODULE_FIB /* We don't care if FIB is full, this is just for efficiency for later * sends */ fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0, (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0, FIB_LIFETIME_NO_EXPIRE); #endif } if (next_hop_ip != NULL) { ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, next_hop_ip); if ((nc_entry != NULL) && ng_ipv6_nc_is_reachable(nc_entry)) { DEBUG("ndp: found reachable neighbor (%s => ", ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str))); DEBUG("%s)\n", ng_netif_addr_to_str(addr_str, sizeof(addr_str), nc_entry->l2_addr, nc_entry->l2_addr_len)); if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_STALE) { _set_state(nc_entry, NG_IPV6_NC_STATE_DELAY); } memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len); *l2addr_len = nc_entry->l2_addr_len; /* TODO: unreachability check */ return nc_entry->iface; } else if (nc_entry == NULL) { ng_pktqueue_t *pkt_node; ng_ipv6_addr_t dst_sol; nc_entry = ng_ipv6_nc_add(iface, next_hop_ip, NULL, 0, NG_IPV6_NC_STATE_INCOMPLETE << NG_IPV6_NC_STATE_POS); if (nc_entry == NULL) { DEBUG("ndp: could not create neighbor cache entry\n"); return KERNEL_PID_UNDEF; } pkt_node = _alloc_pkt_node(pkt); if (pkt_node == NULL) { DEBUG("ndp: could not add packet to packet queue\n"); } else { /* prevent packet from being released by IPv6 */ ng_pktbuf_hold(pkt_node->pkt, 1); ng_pktqueue_add(&nc_entry->pkts, pkt_node); } /* address resolution */ ng_ipv6_addr_set_solicited_nodes(&dst_sol, next_hop_ip); if (iface == KERNEL_PID_UNDEF) { timex_t t = { 0, NG_NDP_RETRANS_TIMER }; kernel_pid_t ifs[NG_NETIF_NUMOF]; size_t ifnum = ng_netif_get(ifs); for (size_t i = 0; i < ifnum; i++) { _send_nbr_sol(ifs[i], next_hop_ip, &dst_sol); } vtimer_remove(&nc_entry->nbr_sol_timer); vtimer_set_msg(&nc_entry->nbr_sol_timer, t, ng_ipv6_pid, NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry); } else { ng_ipv6_netif_t *ipv6_iface = ng_ipv6_netif_get(iface); _send_nbr_sol(iface, next_hop_ip, &dst_sol); mutex_lock(&ipv6_iface->mutex); vtimer_remove(&nc_entry->nbr_sol_timer); vtimer_set_msg(&nc_entry->nbr_sol_timer, ipv6_iface->retrans_timer, ng_ipv6_pid, NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry); mutex_unlock(&ipv6_iface->mutex); } } } return KERNEL_PID_UNDEF; }
void ng_ndp_nbr_adv_handle(kernel_pid_t iface, ng_pktsnip_t *pkt, ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_adv_t *nbr_adv, size_t icmpv6_size) { uint16_t opt_offset = 0; uint8_t *buf = ((uint8_t *)nbr_adv) + sizeof(ng_ndp_nbr_adv_t); int l2tgt_len = 0; uint8_t l2tgt[NG_IPV6_NC_L2_ADDR_MAX]; int sicmpv6_size = (int)icmpv6_size; ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, &nbr_adv->tgt); ng_pktsnip_t *netif; ng_netif_hdr_t *netif_hdr = NULL; DEBUG("ndp: received neighbor advertisement (src: %s, ", ng_ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); DEBUG("dst: %s, ", ng_ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); DEBUG("tgt: %s)\n", ng_ipv6_addr_to_str(addr_str, &nbr_adv->tgt, sizeof(addr_str))); /* check validity */ if ((ipv6->hl != 255) || (nbr_adv->code != 0) || (icmpv6_size < sizeof(ng_ndp_nbr_adv_t)) || ng_ipv6_addr_is_multicast(&nbr_adv->tgt)) { DEBUG("ndp: neighbor advertisement was invalid.\n"); /* ipv6 releases */ return; } if (nc_entry == NULL) { /* see https://tools.ietf.org/html/rfc4861#section-7.2.5 */ DEBUG("ndp: no neighbor cache entry found for advertisement's target\n"); /* ipv6 releases */ return; } sicmpv6_size -= sizeof(ng_ndp_nbr_adv_t); while (sicmpv6_size > 0) { ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset); switch (opt->type) { case NG_NDP_OPT_TL2A: if ((l2tgt_len = _handle_tl2a_opt(pkt, ipv6, nbr_adv->type, opt, l2tgt)) < 0) { /* invalid target link-layer address option */ return; } break; default: /* silently discard all other options */ break; } opt_offset += (opt->len * 8); sicmpv6_size -= (opt->len * 8); } LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF); if (netif != NULL) { netif_hdr = netif->data; } if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) { ng_pktqueue_t *queued_pkt; if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) { /* link-layer has addresses, but no TLLAO supplied: discard silently * (see https://tools.ietf.org/html/rfc4861#section-7.2.5) */ return; } nc_entry->iface = iface; nc_entry->l2_addr_len = l2tgt_len; memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len); if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) { _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE); } else { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) { nc_entry->flags |= NG_IPV6_NC_IS_ROUTER; } else { nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER; /* TODO: update FIB */ } while ((queued_pkt = ng_pktqueue_remove_head(&nc_entry->pkts)) != NULL) { ng_netapi_send(ng_ipv6_pid, queued_pkt->pkt); queued_pkt->pkt = NULL; } } else { /* first or-term: no link-layer, but nc_entry has l2addr, * second or-term: different l2addr cached */ bool l2tgt_changed = false; if ((!_pkt_has_l2addr(netif_hdr)) && (l2tgt_len == 0)) { /* there was previously a L2 address registered */ l2tgt_changed = (nc_entry->l2_addr_len != 0); } /* link-layer has addresses and TLLAO with different address */ else if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len != 0)) { l2tgt_changed = (!(l2tgt_len == nc_entry->l2_addr_len)) && (memcmp(nc_entry->l2_addr, l2tgt, l2tgt_len) == 0); } if ((nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_O) || !l2tgt_changed || (l2tgt_len == 0)) { if (l2tgt_len != 0) { nc_entry->iface = iface; nc_entry->l2_addr_len = l2tgt_len; memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) { _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE); } else if (l2tgt_changed && (l2tgt_len != 0)) { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) { nc_entry->flags |= NG_IPV6_NC_IS_ROUTER; } else { nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER; /* TODO: update FIB */ } } else if (l2tgt_changed) { if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_REACHABLE) { _set_state(nc_entry, NG_IPV6_NC_STATE_STALE); } } } return; }
void Machine::start( const Tag & nameState ) { _set_state( &state( nameState ) ); }
static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t len) { kw2xrf_t *dev = (kw2xrf_t *)netdev; int res = -ENOTSUP; if (dev == NULL) { return -ENODEV; } switch (opt) { case NETOPT_ADDRESS: if (len > sizeof(uint16_t)) { res = -EOVERFLOW; } else { kw2xrf_set_addr_short(dev, *((uint16_t *)value)); /* don't set res to set netdev_ieee802154_t::short_addr */ } break; case NETOPT_ADDRESS_LONG: if (len > sizeof(uint64_t)) { return -EOVERFLOW; } else { kw2xrf_set_addr_long(dev, *((uint64_t *)value)); /* don't set res to set netdev_ieee802154_t::short_addr */ } break; case NETOPT_NID: if (len > sizeof(uint16_t)) { return -EOVERFLOW; } else { kw2xrf_set_pan(dev, *((uint16_t *)value)); /* don't set res to set netdev_ieee802154_t::pan */ } break; case NETOPT_CHANNEL: if (len != sizeof(uint16_t)) { res = -EINVAL; } else { uint8_t chan = ((uint8_t *)value)[0]; if (kw2xrf_set_channel(dev, chan)) { res = -EINVAL; break; } dev->netdev.chan = chan; /* don't set res to set netdev_ieee802154_t::chan */ } break; case NETOPT_CHANNEL_PAGE: res = -EINVAL; break; case NETOPT_TX_POWER: if (len < sizeof(uint16_t)) { res = -EOVERFLOW; } else { kw2xrf_set_tx_power(dev, *(int16_t *)value); res = sizeof(uint16_t); } break; case NETOPT_STATE: if (len > sizeof(netopt_state_t)) { res = -EOVERFLOW; } else { res = _set_state(dev, *((netopt_state_t *)value)); } break; case NETOPT_AUTOACK: /* Set up HW generated automatic ACK after Receive */ kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK, ((bool *)value)[0]); break; case NETOPT_ACK_REQ: kw2xrf_set_option(dev, KW2XRF_OPT_ACK_REQ, ((bool *)value)[0]); break; case NETOPT_PRELOADING: kw2xrf_set_option(dev, KW2XRF_OPT_PRELOADING, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_PROMISCUOUSMODE: kw2xrf_set_option(dev, KW2XRF_OPT_PROMISCUOUS, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_RX_START_IRQ: kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_START, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_RX_END_IRQ: kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_END, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_TX_START_IRQ: kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_START, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_TX_END_IRQ: kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_END, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_AUTOCCA: kw2xrf_set_option(dev, KW2XRF_OPT_AUTOCCA, ((bool *)value)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_CCA_THRESHOLD: if (len < sizeof(uint8_t)) { res = -EOVERFLOW; } else { kw2xrf_set_cca_threshold(dev, *((int8_t*)value)); res = sizeof(uint8_t); } break; case NETOPT_CCA_MODE: if (len < sizeof(uint8_t)) { res = -EOVERFLOW; } else { switch (*((int8_t*)value)) { case NETDEV_IEEE802154_CCA_MODE_1: case NETDEV_IEEE802154_CCA_MODE_2: case NETDEV_IEEE802154_CCA_MODE_3: kw2xrf_set_cca_mode(dev, *((int8_t*)value)); res = sizeof(uint8_t); break; case NETDEV_IEEE802154_CCA_MODE_4: case NETDEV_IEEE802154_CCA_MODE_5: case NETDEV_IEEE802154_CCA_MODE_6: default: break; } } break; case NETOPT_RF_TESTMODE: #ifdef KW2XRF_TESTMODE if (len < sizeof(uint8_t)) { res = -EOVERFLOW; } else { kw2xrf_set_test_mode(dev, *((uint8_t *)value)); res = sizeof(uint8_t); } #endif break; default: break; } if (res == -ENOTSUP) { res = netdev_ieee802154_set((netdev_ieee802154_t *)netdev, opt, value, len); } return res; }