net: ieee802154: Add a shell module named 'ieee15_4'

This one exposes IEEE 802.15.4 net mgmt requests through the shell. User
has then the ability to directly make relevant requests like raising a
scan, associating, etc...

For now, it assumes the 15.4 interface is the only one on the system and
thus will rely on net_if_get_default().

Change-Id: I8eb20565b8231e6cfcba6c1479179cc85ff1d8e5
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-01-05 18:32:47 +01:00
commit 336e3f8721
4 changed files with 309 additions and 0 deletions

View file

@ -69,6 +69,15 @@ config NET_L2_IEEE802154_RFD
thus it is not set as the default level
endchoice
config NET_L2_IEEE802154_SHELL
bool "Enable IEEE 802.15.4 shell module"
default n
select CONSOLE_SHELL
depends on NET_L2_IEEE802154_RFD
help
This can be used for testing 15.4 through the console via exposing
a shell module named "ieee15_4".
config NET_L2_IEEE802154_ACK_SET
bool "Expose ACK request setting"
default n

View file

@ -4,6 +4,7 @@ obj-$(CONFIG_NET_L2_IEEE802154) += ieee802154.o \
ieee802154_frame.o
obj-$(CONFIG_NET_L2_IEEE802154_MGMT) += ieee802154_mgmt.o
obj-$(CONFIG_NET_L2_IEEE802154_SHELL) += ieee802154_shell.o
obj-$(CONFIG_NET_L2_IEEE802154_RADIO_ALOHA) += ieee802154_radio_aloha.o
obj-$(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) += ieee802154_radio_csma_ca.o

View file

@ -22,6 +22,14 @@
#ifndef __IEEE802154_MGMT_H__
#define __IEEE802154_MGMT_H__
#include "ieee802154_frame.h"
#ifdef CONFIG_NET_L2_IEEE802154_SHELL
void ieee802154_shell_init(void);
#else
#define ieee802154_shell_init(...)
#endif /* CONFIG_NET_L2_IEEE802154_SHELL */
#ifdef CONFIG_NET_MGMT
static inline bool ieee802154_is_scanning(struct net_if *iface)
@ -36,6 +44,8 @@ static inline void ieee802154_mgmt_init(struct net_if *iface)
struct ieee802154_context *ctx = net_if_l2_data(iface);
k_sem_init(&ctx->res_lock, 1, 1);
ieee802154_shell_init();
}
enum net_verdict ieee802154_handle_beacon(struct net_if *iface,

View file

@ -0,0 +1,289 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** @file
* @brief IEEE 802.15.4 shell module
*/
#include <zephyr.h>
#include <stdio.h>
#include <stdlib.h>
#include <shell/shell.h>
#include <misc/printk.h>
#include <net/net_if.h>
#include <net/ieee802154.h>
#include "ieee802154_mgmt.h"
#include "ieee802154_frame.h"
#define IEEE802154_SHELL_MODULE "ieee15_4"
struct ieee802154_req_params params;
static struct net_mgmt_event_callback scan_cb;
static int shell_cmd_ack(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
if (!strcmp(argv[1], "set") || !strcmp(argv[1], "1")) {
net_mgmt(NET_REQUEST_IEEE802154_SET_ACK, iface, NULL, 0);
printk("ACK flag set on outgoing packets\n");
return 0;
}
if (!strcmp(argv[1], "unset") || !strcmp(argv[1], "0")) {
net_mgmt(NET_REQUEST_IEEE802154_SET_ACK, iface, NULL, 0);
printk("ACK flag unset on outgoing packets\n");
return 0;
}
return -EINVAL;
}
static inline void parse_extended_address(char *addr, uint8_t *ext_addr)
{
char *p, *n;
int i = 0;
p = addr;
do {
n = strchr(p, ':');
if (n) {
*n = '\0';
}
ext_addr[i] = strtol(p, NULL, 16);
p = n ? n + 1 : n;
} while (n);
}
static int shell_cmd_associate(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
params.pan_id = atoi(argv[1]);
if (strlen(argv[2]) == 23) {
parse_extended_address(argv[2], params.addr);
params.len = IEEE802154_EXT_ADDR_LENGTH;
} else {
params.short_addr = (uint16_t) atoi(argv[2]);
params.len = IEEE802154_SHORT_ADDR_LENGTH;
}
if (net_mgmt(NET_REQUEST_IEEE802154_ASSOCIATE, iface,
&params, sizeof(struct ieee802154_req_params))) {
printk("Could not associate to %s on PAN ID %u",
argv[2], params.pan_id);
} else {
printk("Associated to PAN ID %u", params.pan_id);
}
return 0;
}
static int shell_cmd_disassociate(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
int ret;
ret = net_mgmt(NET_REQUEST_IEEE802154_DISASSOCIATE, iface, NULL, 0);
if (ret == -EALREADY) {
printk("Interface is not associated\n");
} else if (ret) {
printk("Could not disassociate? (status: %i)\n", ret);
} else {
printk("Interface is now disassociated\n");
}
return 0;
}
static inline uint32_t parse_channel_set(char *str_set)
{
uint32_t channel_set = 0;
char *p, *n;
p = str_set;
do {
uint32_t chan;
n = strchr(p, ':');
if (n) {
*n = '\0';
}
chan = atoi(p);
channel_set |= BIT(chan - 1);
p = n ? n + 1 : n;
} while (n);
return channel_set;
}
static inline void print_coordinator_address(void)
{
if (params.len == IEEE802154_EXT_ADDR_LENGTH) {
int i;
printk("(extended) ");
for (i = 0; i < IEEE802154_EXT_ADDR_LENGTH; i++) {
printk("%02X", params.addr[i]);
if (i < (IEEE802154_EXT_ADDR_LENGTH - 1)) {
printk(":");
}
}
} else {
printk("(short) %u", params.short_addr);
}
}
static void scan_result_cb(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
{
printk("\nChannel: %u\tPAN ID: %u\tCoordinator Address: ",
params.channel, params.pan_id);
print_coordinator_address();
printk("LQI: %u\n", params.lqi);
}
static int shell_cmd_scan(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
uint32_t scan_type;
int ret;
memset(&params, 0, sizeof(struct ieee802154_req_params));
net_mgmt_init_event_callback(&scan_cb, scan_result_cb,
NET_EVENT_IEEE802154_SCAN_RESULT);
if (!strcmp(argv[1], "active")) {
scan_type = NET_REQUEST_IEEE802154_ACTIVE_SCAN;
} else if (!strcmp(argv[1], "passive")) {
scan_type = NET_REQUEST_IEEE802154_PASSIVE_SCAN;
} else {
return -EINVAL;
}
if (!strcmp(argv[2], "all")) {
params.channel_set = IEEE802154_ALL_CHANNELS;
} else {
params.channel_set = parse_channel_set(argv[2]);
}
if (!params.channel_set) {
return -EINVAL;
}
params.duration = atoi(argv[3]);
printk("%s Scanning (channel set: 0x%08x, duration %u ms)...",
scan_type == NET_REQUEST_IEEE802154_ACTIVE_SCAN ?
"Active" : "Passive", params.channel_set, params.duration);
if (scan_type == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
ret = net_mgmt(NET_REQUEST_IEEE802154_ACTIVE_SCAN, iface,
&params, sizeof(struct ieee802154_req_params));
} else {
ret = net_mgmt(NET_REQUEST_IEEE802154_PASSIVE_SCAN, iface,
&params, sizeof(struct ieee802154_req_params));
}
if (ret) {
printk("Could not raise a scan (status: %i)\n", ret);
} else {
printk("Done\n");
}
return 0;
}
static int shell_cmd_set_chan(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
uint16_t channel = (uint16_t) atoi(argv[1]);
if (net_mgmt(NET_REQUEST_IEEE802154_SET_CHAN, iface,
&channel, sizeof(uint16_t))) {
printk("Could not set channel %u\n", channel);
} else {
printk("Channel %u set\n", channel);
}
return 0;
}
static int shell_cmd_set_pan_id(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
uint16_t pan_id = (uint16_t) atoi(argv[1]);
if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID, iface,
&pan_id, sizeof(uint16_t))) {
printk("Could not set PAN ID %u\n", pan_id);
} else {
printk("PAN ID %u set\n", pan_id);
}
return 0;
}
static int shell_cmd_set_short_addr(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
uint16_t short_addr = (uint16_t) atoi(argv[1]);
if (net_mgmt(NET_REQUEST_IEEE802154_SET_SHORT_ADDR, iface,
&short_addr, sizeof(uint16_t))) {
printk("Could not set short address %u\n", short_addr);
} else {
printk("Short address %u set\n", short_addr);
}
return 0;
}
static struct shell_cmd ieee802154_commands[] = {
{ "ack", shell_cmd_ack,
"<set/1 | unset/0>" },
{ "associate", shell_cmd_associate,
"<pan_id> <PAN coordinator short or long address>" },
{ "disassociate", shell_cmd_disassociate,
NULL },
{ "scan", shell_cmd_scan,
"<passive|active> <channels set n[:m:...]:x|all>"
" <per-channel duration in ms>" },
{ "set_chan", shell_cmd_set_chan,
"<channel>" },
{ "set_pan_id", shell_cmd_set_pan_id,
"<pan_id>" },
{ "set_short_addr", shell_cmd_set_short_addr,
"<short address>" },
{ NULL, NULL, NULL },
};
void ieee802154_shell_init(void)
{
SHELL_REGISTER(IEEE802154_SHELL_MODULE, ieee802154_commands);
}