kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/usb_device/ncm' into 'master'
usb: Add NCM device example See merge request espressif/esp-idf!22232pull/11637/head
commit
9f9bd8c033
|
@ -0,0 +1,6 @@
|
|||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(tusb_ncm)
|
|
@ -0,0 +1,103 @@
|
|||
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
# TinyUSB Network Control Model Device Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
Network Control Model (NCM) is a sub-class of Communication Device Class (CDC) USB Device for Ethernet-over-USB applications.
|
||||
|
||||
In this example, we implemented the ESP development board to transmit WiFi data to the Linux or Windows host via USB, so that the host could access the Internet.
|
||||
|
||||
As a USB stack, a TinyUSB component is used.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
Any ESP board that have USB-OTG supported.
|
||||
|
||||
#### Pin Assignment
|
||||
|
||||
_Note:_ In case your board doesn't have micro-USB connector connected to USB-OTG peripheral, you may have to DIY a cable and connect **D+** and **D-** to the pins listed below.
|
||||
|
||||
See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).
|
||||
|
||||
### Configure the project
|
||||
|
||||
Open the project configuration menu (`idf.py menuconfig`).
|
||||
|
||||
In the `Example Configuration` menu:
|
||||
|
||||
* Set the Wi-Fi configuration.
|
||||
* Set `WiFi SSID`.
|
||||
* Set `WiFi Password`.
|
||||
|
||||
### Build, Flash, and Run
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT build flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
After the flashing you should see the output at idf monitor:
|
||||
|
||||
```
|
||||
I (399) main_task: Calling app_main()
|
||||
I (429) USB_NCM: USB NCM device initialization
|
||||
W (429) TinyUSB: The device's configuration descriptor is not provided by user, using default.
|
||||
W (429) TinyUSB: The device's string descriptor is not provided by user, using default.
|
||||
W (439) TinyUSB: The device's device descriptor is not provided by user, using default.
|
||||
I (449) tusb_desc:
|
||||
┌─────────────────────────────────┐
|
||||
│ USB Device Descriptor Summary │
|
||||
├───────────────────┬─────────────┤
|
||||
│bDeviceClass │ 239 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bDeviceSubClass │ 2 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bDeviceProtocol │ 1 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bMaxPacketSize0 │ 64 │
|
||||
├───────────────────┼─────────────┤
|
||||
│idVendor │ 0x303a │
|
||||
├───────────────────┼─────────────┤
|
||||
│idProduct │ 0x4001 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bcdDevice │ 0x100 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iManufacturer │ 0x1 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iProduct │ 0x2 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iSerialNumber │ 0x3 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bNumConfigurations │ 0x1 │
|
||||
└───────────────────┴─────────────┘
|
||||
I (619) TinyUSB: TinyUSB Driver installed
|
||||
I (619) USB_NCM: WiFi initialization
|
||||
I (619) pp: pp rom version: e7ae62f
|
||||
I (629) net80211: net80211 rom version: e7ae62f
|
||||
I (689) wifi_init: rx ba win: 6
|
||||
I (699) wifi_init: tcpip mbox: 32
|
||||
I (699) wifi_init: udp mbox: 6
|
||||
I (699) wifi_init: tcp mbox: 6
|
||||
I (709) wifi_init: tcp tx win: 5744
|
||||
I (709) wifi_init: tcp rx win: 5744
|
||||
I (719) wifi_init: tcp mss: 1440
|
||||
I (719) wifi_init: WiFi IRAM OP enabled
|
||||
I (719) wifi_init: WiFi RX IRAM OP enabled
|
||||
I (729) phy_init: phy_version 600,8dd0147,Mar 31 2023,16:34:12
|
||||
I (779) USB_NCM: USB NCM and WiFi initialized and started
|
||||
I (779) main_task: Returned from app_main()
|
||||
I (849) USB_NCM: WiFi STA connected
|
||||
```
|
|
@ -0,0 +1,2 @@
|
|||
idf_component_register(SRCS "tusb_ncm_main.c"
|
||||
INCLUDE_DIRS "")
|
|
@ -0,0 +1,15 @@
|
|||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,5 @@
|
|||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb:
|
||||
version: "^1.3.0"
|
||||
idf: "^5.0"
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/* DESCRIPTION:
|
||||
* This example demonstrates using ESP32-S2/S3 as a USB network device. It initializes WiFi in station mode,
|
||||
* connects and bridges the WiFi and USB networks, so the USB device acts as a standard network interface that
|
||||
* acquires an IP address from the AP/router which the WiFi station connects to.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_check.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_mac.h"
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_private/wifi.h"
|
||||
|
||||
#include "tinyusb.h"
|
||||
#include "tinyusb_net.h"
|
||||
|
||||
|
||||
static const char *TAG = "USB_NCM";
|
||||
|
||||
static esp_err_t usb_recv_callback(void *buffer, uint16_t len, void *ctx)
|
||||
{
|
||||
bool *is_wifi_connected = ctx;
|
||||
if (*is_wifi_connected) {
|
||||
esp_wifi_internal_tx(ESP_IF_WIFI_STA, buffer, len);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_pkt_free(void *eb, void *ctx)
|
||||
{
|
||||
esp_wifi_internal_free_rx_buffer(eb);
|
||||
}
|
||||
|
||||
static esp_err_t pkt_wifi2usb(void *buffer, uint16_t len, void *eb)
|
||||
{
|
||||
if (tinyusb_net_send_sync(buffer, len, eb, portMAX_DELAY) != ESP_OK) {
|
||||
esp_wifi_internal_free_rx_buffer(eb);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
bool *is_connected = arg;
|
||||
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "WiFi STA disconnected");
|
||||
*is_connected = false;
|
||||
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL);
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
|
||||
ESP_LOGI(TAG, "WiFi STA connected");
|
||||
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, pkt_wifi2usb);
|
||||
*is_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t start_wifi(bool *is_connected)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(esp_event_loop_create_default(), TAG, "Cannot initialize event loop");
|
||||
|
||||
wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_init(&wifi_cfg), TAG, "Failed to initialize WiFi library");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, is_connected),
|
||||
TAG, "Failed to register handler for wifi events");
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_STA), TAG, "Failed to set WiFi station mode");
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_start(), TAG, "Failed to start WiFi library");
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||
.password = CONFIG_ESP_WIFI_PASSWORD,
|
||||
},
|
||||
};
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_config(WIFI_IF_STA, &wifi_config), TAG, "Failed to set WiFi config");
|
||||
return esp_wifi_connect();
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
static bool s_is_wifi_connected = false; // needs to be static as it's used after we exit app_main()
|
||||
|
||||
/* Initialize NVS — it is used to store PHY calibration data */
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
ESP_LOGI(TAG, "USB NCM device initialization");
|
||||
const tinyusb_config_t tusb_cfg = {
|
||||
.external_phy = false,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(tinyusb_driver_install(&tusb_cfg), err, TAG, "Failed to install TinyUSB driver");
|
||||
|
||||
tinyusb_net_config_t net_config = {
|
||||
.on_recv_callback = usb_recv_callback,
|
||||
.free_tx_buffer = wifi_pkt_free,
|
||||
.user_context = &s_is_wifi_connected
|
||||
};
|
||||
esp_read_mac(net_config.mac_addr, ESP_MAC_WIFI_STA);
|
||||
uint8_t *mac = net_config.mac_addr;
|
||||
ESP_LOGI(TAG, "Network interface HW address: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
ESP_GOTO_ON_ERROR(tinyusb_net_init(TINYUSB_USBDEV_0, &net_config), err, TAG, "Failed to initialize TinyUSB NCM device class");
|
||||
|
||||
ESP_LOGI(TAG, "WiFi initialization");
|
||||
ESP_GOTO_ON_ERROR(start_wifi(&s_is_wifi_connected), err, TAG, "Failed to init and start WiFi");
|
||||
|
||||
ESP_LOGI(TAG, "USB NCM and WiFi initialized and started");
|
||||
return;
|
||||
|
||||
err:
|
||||
ESP_LOGE(TAG, "USB-WiFi bridge example failed!");
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.usb_device
|
||||
def test_usb_device_ncm_example(dut: Dut) -> None:
|
||||
netif_mac = dut.expect(r'Network interface HW address: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})')
|
||||
netif_mac = netif_mac.group(1).decode('utf-8')
|
||||
dut.expect_exact('USB NCM and WiFi initialized and started')
|
||||
dut.expect_exact('Returned from app_main()')
|
||||
time.sleep(1) # Wait 1s for the network interface to appear
|
||||
out_bytes = subprocess.check_output('ifconfig', shell=True, timeout=5)
|
||||
out_str = out_bytes.decode('utf-8')
|
||||
print('expected network interface HW address: ', netif_mac)
|
||||
print('ifconfig command output:\n', out_str)
|
||||
if netif_mac in out_str:
|
||||
print("NCM device's MAC address {} was found in system network interfaces".format(netif_mac))
|
||||
else:
|
||||
raise AssertionError('NCM device not found in network interface list')
|
|
@ -0,0 +1 @@
|
|||
CONFIG_TINYUSB_NET_MODE_NCM=y
|
|
@ -0,0 +1,3 @@
|
|||
CONFIG_TINYUSB_TASK_AFFINITY_CPU0=y
|
||||
CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK=y
|
||||
CONFIG_TINYUSB_NET_MODE_NCM=y
|
Ładowanie…
Reference in New Issue