Skip to content

Commit

Permalink
Add MQTT device through RNDIS example
Browse files Browse the repository at this point in the history
  • Loading branch information
scaprile committed Dec 13, 2023
1 parent ad90b0b commit ad57731
Show file tree
Hide file tree
Showing 17 changed files with 471 additions and 22 deletions.
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

0 comments on commit ad57731

Please sign in to comment.