diff --git a/drivers/cc110x/cc110x_netdev.c b/drivers/cc110x/cc110x_netdev.c index 50ae5ddb2c..2f69dfa823 100644 --- a/drivers/cc110x/cc110x_netdev.c +++ b/drivers/cc110x/cc110x_netdev.c @@ -514,6 +514,27 @@ static int cc110x_get_iid(cc110x_t *dev, eui64_t *iid) return sizeof(eui64_t); } +/** + * @brief Checks if the CC110x's address filter is disabled + * @param dev Transceiver to check if in promiscuous mode + * @param dest Store the result here + * + * @return Returns the size of @ref netopt_enable_t to confirm with the API + * in @ref netdev_driver_t::get + */ +static int cc110x_get_promiscuous_mode(cc110x_t *dev, netopt_enable_t *dest) +{ + if (cc110x_acquire(dev) != SPI_OK) { + return -EIO; + } + + uint8_t pktctrl1; + cc110x_read(dev, CC110X_REG_PKTCTRL1, &pktctrl1); + *dest = ((pktctrl1 & CC110X_PKTCTRL1_GET_ADDR_MODE) == CC110X_PKTCTRL1_ADDR_ALL); + cc110x_release(dev); + return sizeof(netopt_enable_t); +} + static int cc110x_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) { @@ -555,6 +576,9 @@ static int cc110x_get(netdev_t *netdev, netopt_t opt, assert(max_len == sizeof(uint16_t)); *((uint16_t *)val) = dbm_from_tx_power[dev->tx_power]; return sizeof(uint16_t); + case NETOPT_PROMISCUOUSMODE: + assert(max_len == sizeof(netopt_enable_t)); + return cc110x_get_promiscuous_mode(dev, val); default: return -ENOTSUP; } @@ -578,6 +602,32 @@ static int cc110x_set_addr(cc110x_t *dev, uint8_t addr) return 1; } +/** + * @brief Enables/disables the CC110x's address filter + * @param dev Transceiver to turn promiscuous mode on/off + * @param enable Whether to enable or disable promiscuous mode + * + * @return Returns the size of @ref netopt_enable_t to confirm with the API + * in @ref netdev_driver_t::set + */ +static int cc110x_set_promiscuous_mode(cc110x_t *dev, netopt_enable_t enable) +{ + if (cc110x_acquire(dev) != SPI_OK) { + return -EIO; + } + + uint8_t pktctrl1 = CC110X_PKTCTRL1_VALUE; + if (enable == NETOPT_ENABLE) { + pktctrl1 |= CC110X_PKTCTRL1_ADDR_ALL; + } + else { + pktctrl1 |= CC110X_PKTCTRL1_ADDR_MATCH; + } + cc110x_write(dev, CC110X_REG_PKTCTRL1, pktctrl1); + cc110x_release(dev); + return sizeof(netopt_enable_t); +} + static int cc110x_set(netdev_t *netdev, netopt_t opt, const void *val, size_t len) { @@ -616,6 +666,9 @@ static int cc110x_set(netdev_t *netdev, netopt_t opt, } } return sizeof(uint16_t); + case NETOPT_PROMISCUOUSMODE: + assert(len == sizeof(netopt_enable_t)); + return cc110x_set_promiscuous_mode(dev, *((const netopt_enable_t *)val)); default: return -ENOTSUP; }