Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MQTT device through RNDIS example #2531

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -557,26 +557,26 @@ jobs:
- if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build

# mqtt_dashboard_examples:
# runs-on: ubuntu-latest
# strategy:
# fail-fast: false
# matrix:
# example:
# - path:
# name: ${{ matrix.example.path }}
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v3
# with: { fetch-depth: 2 }
# - run: |
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# run: make -C examples/${{ matrix.example.path }} build
mqtt_dashboard_examples:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example:
- path: rp2040/pico-rndis-device
name: ${{ matrix.example.path }}
env:
GO: 0
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: |
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build

dual_examples:
runs-on: ubuntu-latest
Expand Down
28 changes: 28 additions & 0 deletions examples/rp2040/pico-rndis-device/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)

project(firmware)
pico_sdk_init()

add_executable(firmware
main.c
usb_descriptors.c
mongoose.c
net.c
pico-sdk/lib/tinyusb/lib/networking/rndis_reports.c)

target_include_directories(firmware PUBLIC
.
pico-sdk/lib/tinyusb/lib/networking)

target_link_libraries(firmware pico_stdlib hardware_spi tinyusb_device)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.

pico_enable_stdio_usb(firmware 0) # Route stdio
pico_enable_stdio_uart(firmware 1) # to the UART

# Mongoose build flags
add_definitions(-DMG_ENABLE_TCPIP=1)
add_definitions(-DMG_ENABLE_FILE=0)

# Example build options
20 changes: 20 additions & 0 deletions examples/rp2040/pico-rndis-device/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
RM = rm -rf
MKBUILD = test -d build || mkdir build
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F /S
MKBUILD = if not exist build mkdir build
endif

all example:
true

build: pico-sdk
$(MKBUILD)
cd build && cmake -G "Unix Makefiles" .. && make

pico-sdk:
git clone --depth 1 -b 1.4.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init

clean:
$(RM) pico-sdk build
30 changes: 30 additions & 0 deletions examples/rp2040/pico-rndis-device/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Remote MQTT Device on an RP2040

Your headless Raspberry Pi Pico-based hardware can also be a remote gadget when you connect it to your computer via USB

For the USB specifics, see this related tutorial at https://mongoose.ws/tutorials/rp2040/pico-rndis-dashboard/

See this tutorial to control your device: https://mongoose.ws/tutorials/mqtt-dashboard/

For this to work, you need your computer to act as a router (gateway) and NAT for your device.

## Linux setup

Enable "masquerading"; the quick and simple options are:

``` bash
sudo iptables --flush
sudo iptables --table nat --flush
sudo iptables --delete-chain
sudo iptables --table nat --delete-chain

# Do masquerading
sudo iptables -t nat -A POSTROUTING -o yourifc -j MASQUERADE
# enable routing
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
```

Where `yourifc` is the interface that is connected to your network

## MacOS setup

11 changes: 11 additions & 0 deletions examples/rp2040/pico-rndis-device/hal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved

#define LED PICO_DEFAULT_LED_PIN

static inline int gpio_read(uint16_t pin) {
return gpio_get_out_level(pin);
}
static inline void gpio_write(uint16_t pin, bool val) {
gpio_put(pin, val);
}
89 changes: 89 additions & 0 deletions examples/rp2040/pico-rndis-device/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved

#include "mongoose.h"
#include "net.h"
#include "pico/stdlib.h"
#include "tusb.h"

bool hal_gpio_read(int pin) {
return (pin >= 0 && pin <= 29) ? gpio_get_out_level((uint) pin) : false;
}

void hal_gpio_write(int pin, bool val) {
if (pin >= 0 && pin <= 29) gpio_put((uint) pin, val);
}

int hal_led_pin(void) {
return PICO_DEFAULT_LED_PIN;
}

static struct mg_tcpip_if *s_ifp;

const uint8_t tud_network_mac_address[6] = {2, 2, 0x84, 0x6A, 0x96, 0};

bool tud_network_recv_cb(const uint8_t *buf, uint16_t len) {
mg_tcpip_qwrite((void *) buf, len, s_ifp);
// MG_INFO(("RECV %hu", len));
// mg_hexdump(buf, len);
tud_network_recv_renew();
return true;
}

void tud_network_init_cb(void) {
}

uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
// MG_INFO(("SEND %hu", arg));
memcpy(dst, ref, arg);
return arg;
}

static size_t usb_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
if (!tud_ready()) return 0;
while (!tud_network_can_xmit(len)) tud_task();
tud_network_xmit((void *) buf, len);
(void) ifp;
return len;
}

static bool usb_up(struct mg_tcpip_if *ifp) {
(void) ifp;
return tud_inited() && tud_ready() && tud_connected();
}

static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_dta) {
if (ev == MG_EV_HTTP_MSG) return mg_http_reply(c, 200, "", "ok\n");
}

int main(void) {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
stdio_init_all();

struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface

struct mg_tcpip_driver driver = {.tx = usb_tx, .up = usb_up};
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 0x77},
.ip = mg_htonl(MG_U32(192, 168, 3, 1)),
.mask = mg_htonl(MG_U32(255, 255, 255, 0)),
.enable_dhcp_server = true,
.enable_get_gateway = true,
.driver = &driver,
.recv_queue.size = 4096};
s_ifp = &mif;
mg_tcpip_init(&mgr, &mif);
tusb_init();

MG_INFO(("Initialising application..."));
web_init(&mgr);

MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
tud_task();
}

return 0;
}
1 change: 1 addition & 0 deletions examples/rp2040/pico-rndis-device/mongoose.c
1 change: 1 addition & 0 deletions examples/rp2040/pico-rndis-device/mongoose.h
1 change: 1 addition & 0 deletions examples/rp2040/pico-rndis-device/net.c
1 change: 1 addition & 0 deletions examples/rp2040/pico-rndis-device/net.h
2 changes: 2 additions & 0 deletions examples/rp2040/pico-rndis-device/netif/ethernet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#define SIZEOF_ETH_HDR 14
9 changes: 9 additions & 0 deletions examples/rp2040/pico-rndis-device/tusb_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

// Windows only supports RNDIS
// Mac only supports CDC-ECM
// Linux supports either RNDIS, CDC-ECM or CDC-NCM
#define CFG_TUD_ECM_RNDIS 1
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
Loading
Loading