samples: net: remove wpanusb sample

Clean up before deprecating legacy device support.
The Linux kernel driver for this example has never been upstreamed or
implemented upstream. In general, 15.4 development does not seem to be a
big success, but if it comes up again, the protocol used by the example
will need to be redesigned anyway.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
Johann Fischer 2024-07-18 15:55:44 +02:00 committed by Carles Cufí
commit 6c779908fa
10 changed files with 5 additions and 736 deletions

View file

@ -159,8 +159,8 @@ externally connected SPI devices.
+-------------+------------------------------------------------------------------------------------------+ +-------------+------------------------------------------------------------------------------------------+
Zephyr provide several samples that can use this technology. You can check Zephyr provide several samples that can use this technology. You can check
:zephyr:code-sample:`wpan-usb` and :zephyr:code-sample:`wpan-serial` examples as starting :zephyr:code-sample:`wpan-serial` example as starting points.
points. Another good test can be done with IPv6 by using the server/client Another good test can be done with IPv6 by using the server/client
echo demo. More information at :zephyr:code-sample:`sockets-echo-server` and echo demo. More information at :zephyr:code-sample:`sockets-echo-server` and
:zephyr:code-sample:`sockets-echo-client`. :zephyr:code-sample:`sockets-echo-client`.

View file

@ -599,7 +599,7 @@ The following Product IDs are currently used:
+----------------------------------------------------+--------+ +----------------------------------------------------+--------+
| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | | :ref:`bluetooth-hci-usb-h4-sample` | 0x000C |
+----------------------------------------------------+--------+ +----------------------------------------------------+--------+
| :zephyr:code-sample:`wpan-usb` | 0x000D | | Reserved (previously: wpan-usb) | 0x000D |
+----------------------------------------------------+--------+ +----------------------------------------------------+--------+
| :zephyr:code-sample:`uac2-explicit-feedback` | 0x000E | | :zephyr:code-sample:`uac2-explicit-feedback` | 0x000E |
+----------------------------------------------------+--------+ +----------------------------------------------------+--------+

View file

@ -1,12 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(wpanusb)
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/l2)
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb/device)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -1,80 +0,0 @@
.. zephyr:code-sample:: wpan-usb
:name: 802.15.4 USB
:relevant-api: ieee802154 _usb_device_core_api
Implement a device that exposes an IEEE 802.15.4 radio over USB.
Overview
********
This application exports ieee802154 radio over USB to be used in
other OSes such as Linux. For Linux, the ieee802154 stack would be
implemented using the Linux SoftMAC driver.
This sample can be found under :zephyr_file:`samples/net/wpanusb` in the
Zephyr project tree.
Requirements
************
- a Zephyr board with supported 802.15.4 radio and supported USB driver
(such as the :ref:`nrf52840dk_nrf52840` or :ref:`samr21_xpro`)
connected via USB to a Linux host
- wpanusb Linux kernel driver (in the process of being open sourced)
- wpan-tools (available for all Linux distributions)
Building and Running
********************
There are configuration files for various setups in the
``samples/net/wpanusb`` directory:
- :file:`prj.conf`
This is the standard default config. This can be used by itself for
hardware which has native 802.15.4 support.
- :file:`overlay-cc2520.conf`
This overlay config enables support for CC2520
Build the wpanusb sample for a board:
.. zephyr-app-commands::
:zephyr-app: samples/net/wpanusb
:board: <board to use>
:gen-args: -DEXTRA_CONF_FILE=<overlay file to use>
:goals: build
:compact:
Example building for the Nordic nRF52840 Development Kit:
.. zephyr-app-commands::
:zephyr-app: samples/net/wpanusb
:board: nrf52840dk/nrf52840
:goals: build
:compact:
When connected to Linux with wpanusb kernel driver, it is recognized as:
.. code-block:: console
...
T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=ff(vend.) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=2fe3 ProdID=000d Rev=01.00
C: #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=00 Prot=00 Driver=wpanusb
...
The following script enables the network interface in Linux
(uses iwpan tool from above):
.. code-block:: console
#!/bin/sh
PHY=`iwpan phy | grep wpan_phy | cut -d' ' -f2`
echo 'Using phy' $PHY
iwpan dev wpan0 set pan_id 0xabcd
iwpan dev wpan0 set short_addr 0xbeef
iwpan phy $PHY set channel 0 26
ip link add link wpan0 name lowpan0 type lowpan
ip link set wpan0 up
ip link set lowpan0 up

View file

@ -1,22 +0,0 @@
CONFIG_GPIO=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PID=0x000D
CONFIG_USB_REQUEST_BUFFER_SIZE=300
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_PKT_TX_COUNT=4
CONFIG_NET_BUF_DATA_SIZE=128
CONFIG_IEEE802154=y
CONFIG_IEEE802154_RAW_MODE=y
CONFIG_SHELL=y
CONFIG_KERNEL_SHELL=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_AUTO_INIT=n
CONFIG_NET_LOG=y

View file

@ -1,16 +0,0 @@
sample:
description: Test wpanusb sample
name: wpanusb
common:
depends_on: usb_device
tags: net ieee802154 usb
harness: net
platform_exclude: pinnacle_100_dvk
tests:
sample.net.wpanusb:
filter: dt_chosen_enabled("zephyr,ieee802154")
platform_exclude: thingy53/nrf5340/cpuapp/ns raytac_mdbt53_db_40/nrf5340/cpuapp/ns
raytac_mdbt53_db_40/nrf5340/cpuapp
sample.net.wpanusb_frdm_cr20a:
extra_args: SHIELD=frdm_cr20a
platform_allow: frdm_k64f

View file

@ -1,453 +0,0 @@
/*
* Copyright (c) 2016-2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(wpanusb);
#include <zephyr/usb/usb_device.h>
#include <usb_descriptor.h>
#include <zephyr/net/buf.h>
#include <zephyr/net/ieee802154_radio.h>
#include <ieee802154/ieee802154_frame.h>
#include <net_private.h>
#include "wpanusb.h"
#if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
#else
#define THREAD_PRIORITY K_PRIO_PREEMPT(8)
#endif
#define WPANUSB_SUBCLASS 0
#define WPANUSB_PROTOCOL 0
/* Max packet size for endpoints */
#if defined(CONFIG_USB_DC_HAS_HS_SUPPORT)
#define WPANUSB_BULK_EP_MPS 512
#else
#define WPANUSB_BULK_EP_MPS 64
#endif
#define WPANUSB_IN_EP_IDX 0
static struct ieee802154_radio_api *radio_api;
static const struct device *const ieee802154_dev =
DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154));
static struct k_fifo tx_queue;
/* IEEE802.15.4 frame + 1 byte len + 1 byte LQI */
uint8_t tx_buf[IEEE802154_MAX_PHY_PACKET_SIZE + 1 + 1];
/**
* Stack for the tx thread.
*/
static K_THREAD_STACK_DEFINE(tx_stack, 1024);
static struct k_thread tx_thread_data;
#define INITIALIZER_IF(num_ep, iface_class) \
{ \
.bLength = sizeof(struct usb_if_descriptor), \
.bDescriptorType = USB_DESC_INTERFACE, \
.bInterfaceNumber = 0, \
.bAlternateSetting = 0, \
.bNumEndpoints = num_ep, \
.bInterfaceClass = iface_class, \
.bInterfaceSubClass = 0, \
.bInterfaceProtocol = 0, \
.iInterface = 0, \
}
#define INITIALIZER_IF_EP(addr, attr, mps, interval) \
{ \
.bLength = sizeof(struct usb_ep_descriptor), \
.bDescriptorType = USB_DESC_ENDPOINT, \
.bEndpointAddress = addr, \
.bmAttributes = attr, \
.wMaxPacketSize = sys_cpu_to_le16(mps), \
.bInterval = interval, \
}
USBD_CLASS_DESCR_DEFINE(primary, 0) struct {
struct usb_if_descriptor if0;
struct usb_ep_descriptor if0_in_ep;
} __packed wpanusb_desc = {
.if0 = INITIALIZER_IF(1, USB_BCC_VENDOR),
.if0_in_ep = INITIALIZER_IF_EP(AUTO_EP_IN, USB_DC_EP_BULK,
WPANUSB_BULK_EP_MPS, 0),
};
/* Describe EndPoints configuration */
static struct usb_ep_cfg_data wpanusb_ep[] = {
{
.ep_cb = usb_transfer_ep_callback,
.ep_addr = AUTO_EP_IN,
},
};
static void wpanusb_status_cb(struct usb_cfg_data *cfg,
enum usb_dc_status_code status,
const uint8_t *param)
{
ARG_UNUSED(param);
ARG_UNUSED(cfg);
/* Check the USB status and do needed action if required */
switch (status) {
case USB_DC_ERROR:
LOG_DBG("USB device error");
break;
case USB_DC_RESET:
LOG_DBG("USB device reset detected");
break;
case USB_DC_CONNECTED:
LOG_DBG("USB device connected");
break;
case USB_DC_CONFIGURED:
LOG_DBG("USB device configured");
break;
case USB_DC_DISCONNECTED:
LOG_DBG("USB device disconnected");
break;
case USB_DC_SUSPEND:
LOG_DBG("USB device suspended");
break;
case USB_DC_RESUME:
LOG_DBG("USB device resumed");
break;
case USB_DC_UNKNOWN:
default:
LOG_DBG("USB unknown state");
break;
}
}
/**
* Vendor handler is executed in the ISR context, queue data for
* later processing
*/
static int wpanusb_vendor_handler(struct usb_setup_packet *setup,
int32_t *len, uint8_t **data)
{
struct net_pkt *pkt;
if (usb_reqtype_is_to_host(setup)) {
return -ENOTSUP;
}
/* Maximum 2 bytes are added to the len */
pkt = net_pkt_alloc_with_buffer(NULL, *len + 2, AF_UNSPEC, 0,
K_NO_WAIT);
if (!pkt) {
return -ENOMEM;
}
net_pkt_write_u8(pkt, setup->bRequest);
/* Add seq to TX */
if (setup->bRequest == TX) {
net_pkt_write_u8(pkt, setup->wIndex);
}
net_pkt_write(pkt, *data, *len);
LOG_DBG("pkt %p len %u seq %u", pkt, *len, setup->wIndex);
k_fifo_put(&tx_queue, pkt);
return 0;
}
USBD_DEFINE_CFG_DATA(wpanusb_config) = {
.usb_device_description = NULL,
.interface_descriptor = &wpanusb_desc.if0,
.cb_usb_status = wpanusb_status_cb,
.interface = {
.vendor_handler = wpanusb_vendor_handler,
.class_handler = NULL,
.custom_handler = NULL,
},
.num_endpoints = ARRAY_SIZE(wpanusb_ep),
.endpoint = wpanusb_ep,
};
/* Decode wpanusb commands */
static int set_channel(void *data, int len)
{
struct set_channel *req = data;
LOG_DBG("page %u channel %u", req->page, req->channel);
return radio_api->set_channel(ieee802154_dev, req->channel);
}
static int set_ieee_addr(void *data, int len)
{
struct set_ieee_addr *req = data;
LOG_DBG("len %u", len);
if (IEEE802154_HW_FILTER &
radio_api->get_capabilities(ieee802154_dev)) {
struct ieee802154_filter filter;
filter.ieee_addr = (uint8_t *)&req->ieee_addr;
return radio_api->filter(ieee802154_dev, true,
IEEE802154_FILTER_TYPE_IEEE_ADDR,
&filter);
}
return 0;
}
static int set_short_addr(void *data, int len)
{
struct set_short_addr *req = data;
LOG_DBG("len %u", len);
if (IEEE802154_HW_FILTER &
radio_api->get_capabilities(ieee802154_dev)) {
struct ieee802154_filter filter;
filter.short_addr = req->short_addr;
return radio_api->filter(ieee802154_dev, true,
IEEE802154_FILTER_TYPE_SHORT_ADDR,
&filter);
}
return 0;
}
static int set_pan_id(void *data, int len)
{
struct set_pan_id *req = data;
LOG_DBG("len %u", len);
if (IEEE802154_HW_FILTER &
radio_api->get_capabilities(ieee802154_dev)) {
struct ieee802154_filter filter;
filter.pan_id = req->pan_id;
return radio_api->filter(ieee802154_dev, true,
IEEE802154_FILTER_TYPE_PAN_ID,
&filter);
}
return 0;
}
static int start(void)
{
LOG_INF("Start IEEE 802.15.4 device");
return radio_api->start(ieee802154_dev);
}
static int stop(void)
{
LOG_INF("Stop IEEE 802.15.4 device");
return radio_api->stop(ieee802154_dev);
}
static int tx(struct net_pkt *pkt)
{
uint8_t ep = wpanusb_config.endpoint[WPANUSB_IN_EP_IDX].ep_addr;
struct net_buf *buf = net_buf_frag_last(pkt->buffer);
uint8_t seq = net_buf_pull_u8(buf);
int retries = 3;
int ret;
LOG_DBG("len %d seq %u", buf->len, seq);
do {
ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT,
pkt, buf);
} while (ret && retries--);
if (ret) {
LOG_ERR("Error sending data, seq %u", seq);
/* Send seq = 0 for unsuccessful send */
seq = 0U;
}
ret = usb_transfer_sync(ep, &seq, sizeof(seq), USB_TRANS_WRITE);
if (ret != sizeof(seq)) {
LOG_ERR("Error sending seq");
ret = -EINVAL;
} else {
ret = 0;
}
return ret;
}
static void tx_thread(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p1);
ARG_UNUSED(p2);
ARG_UNUSED(p3);
LOG_DBG("Tx thread started");
while (1) {
uint8_t cmd;
struct net_pkt *pkt;
struct net_buf *buf;
pkt = k_fifo_get(&tx_queue, K_FOREVER);
buf = net_buf_frag_last(pkt->buffer);
cmd = net_buf_pull_u8(buf);
net_pkt_hexdump(pkt, ">");
switch (cmd) {
case RESET:
LOG_DBG("Reset device");
break;
case TX:
tx(pkt);
break;
case START:
start();
break;
case STOP:
stop();
break;
case SET_CHANNEL:
set_channel(buf->data, buf->len);
break;
case SET_IEEE_ADDR:
set_ieee_addr(buf->data, buf->len);
break;
case SET_SHORT_ADDR:
set_short_addr(buf->data, buf->len);
break;
case SET_PAN_ID:
set_pan_id(buf->data, buf->len);
break;
default:
LOG_ERR("%x: Not handled for now", cmd);
break;
}
net_pkt_unref(pkt);
k_yield();
}
}
static void init_tx_queue(void)
{
/* Transmit queue init */
k_fifo_init(&tx_queue);
k_thread_create(&tx_thread_data, tx_stack,
K_THREAD_STACK_SIZEOF(tx_stack),
tx_thread,
NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT);
}
/**
* Interface to the network stack, will be called when the packet is
* received
*/
int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
{
size_t len = net_pkt_get_len(pkt);
uint8_t *p = tx_buf;
int ret;
uint8_t ep;
LOG_DBG("Got data, pkt %p, len %d", pkt, len);
net_pkt_hexdump(pkt, "<");
if (len > (sizeof(tx_buf) - 2)) {
LOG_ERR("Too large packet");
ret = -ENOMEM;
goto out;
}
/**
* Add length 1 byte
*/
*p++ = (uint8_t)len;
/* This is needed to work with pkt */
net_pkt_cursor_init(pkt);
ret = net_pkt_read(pkt, p, len);
if (ret < 0) {
LOG_ERR("Cannot read pkt");
goto out;
}
p += len;
/**
* Add LQI at the end of the packet
*/
*p = net_pkt_ieee802154_lqi(pkt);
ep = wpanusb_config.endpoint[WPANUSB_IN_EP_IDX].ep_addr;
ret = usb_transfer_sync(ep, tx_buf, len + 2,
USB_TRANS_WRITE | USB_TRANS_NO_ZLP);
if (ret != len + 2) {
LOG_ERR("Transfer failure");
ret = -EINVAL;
}
out:
net_pkt_unref(pkt);
return ret;
}
enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt)
{
return NET_CONTINUE;
}
int main(void)
{
int ret;
LOG_INF("Starting wpanusb");
if (!device_is_ready(ieee802154_dev)) {
LOG_ERR("IEEE802.15.4 device not ready");
return 0;
}
/* Initialize net_pkt */
net_pkt_init();
/* Initialize transmit queue */
init_tx_queue();
radio_api = (struct ieee802154_radio_api *)ieee802154_dev->api;
ret = usb_enable(NULL);
if (ret != 0) {
LOG_ERR("Failed to enable USB");
return 0;
}
/* TODO: Initialize more */
LOG_DBG("radio_api %p initialized", radio_api);
return 0;
}

View file

@ -1,40 +0,0 @@
/*
* Copyright (c) 2016-2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
enum wpanusb_requests {
RESET,
TX,
XMIT_ASYNC,
ED,
SET_CHANNEL,
START,
STOP,
SET_SHORT_ADDR,
SET_PAN_ID,
SET_IEEE_ADDR,
SET_TXPOWER,
SET_CCA_MODE,
SET_CCA_ED_LEVEL,
SET_CSMA_PARAMS,
SET_PROMISCUOUS_MODE,
};
struct set_channel {
uint8_t page;
uint8_t channel;
} __packed;
struct set_short_addr {
uint16_t short_addr; /* in CPU byte order */
} __packed;
struct set_pan_id {
uint16_t pan_id; /* in CPU byte order */
} __packed;
struct set_ieee_addr {
uint64_t ieee_addr; /* big endian */
} __packed;

View file

@ -1,107 +0,0 @@
ieee802154 wpan radio protocol over USB
Overview
========
The document describes protocol between 802.15.4 physical radio and Linux
kernel driver over USB. Protocol is based on atusb Linux driver protocol
found inside Linux kernel: drivers/net/ieee802154/atusb.h
Packet structure
================
Command opcodes are inside bRequest field. bRequest and wIndex are one octet
long.
Commands from Host to Device
============================
USB Control endpoint, Vendor commands
Opcode 0x00 - Reset bRequest
Reset the Radio
Opcode 0x01 - Transmit bRequest
Sequence number wIndex
Data length wLength
Transmit data from Host to Device
Opcode 0x02 - Transmit Async bRequest
TBD
Opcode 0x03 - ED bRequest
TBD
Opcode 0x04 - Set Channel bRequest
Set ieee802154 channel
Page 1 octet
Channel 1 octet
Opcode 0x05 - Start bRequest
Start ieee802154 device
Opcode 0x06 - Stop bRequest
Stop ieee802154 device
Opcode 0x07 - Set Short address bRequest
Set ieee802154 Short address
Short address 2 octets
Opcode 0x08 - Set PAN ID bRequest
Set ieee802154 PAN ID
PAN ID 2 octets
Opcode 0x09 - Set address bRequest
Set ieee802154 address
address 8 octets
Opcode 0x0A - Set TX Power bRequest
TBD
Opcode 0x0B - Set CCA Mode bRequest
TBD
Opcode 0x0C - Set CCA ED level bRequest
TBD
Opcode 0x0D - Set CSMA Params bRequest
TBD
Opcode 0x0E - Set Promisc mode bRequest
TBD
Data from Device to Host
========================
USB BULK IN endpoint
Transmit ACK
Length 1 octet
Data Sequence number
Data
Length 1 octet
Data Data
LQI 1 octet

View file

@ -204,10 +204,9 @@ Step 4.3: Build for IEEE 802.15.4 [experimental]
For IEEE 802.15.4 needs add ``overlay-802154.conf``. This requires two nodes: For IEEE 802.15.4 needs add ``overlay-802154.conf``. This requires two nodes:
one will be the host and the second one will be the device under test. The one will be the host and the second one will be the device under test. The
validation needs a Linux kernel >= 4.9 with all 6loWPAN support. The start validation needs a Linux kernel >= 4.9 with all 6loWPAN support. It is out of scope
point is try reproduce the Zephyr :zephyr:code-sample:`wpan-usb`. It is out of scope
at this moment provide support since it is experimental. The gateway was at this moment provide support since it is experimental. The gateway was
tested with both native linux driver and ``atusb`` and with ``wpanusb`` sample. tested with both native linux driver and ``atusb``.
.. zephyr-app-commands:: .. zephyr-app-commands::
:zephyr-app: zephyr/samples/subsys/mgmt/updatehub :zephyr-app: zephyr/samples/subsys/mgmt/updatehub