Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2a5d97dae | |||
| 94895fd2fe | |||
| f2d98ef4f1 | |||
| 8edf8c2d4f | |||
| c961499239 | |||
| 0d41f63533 | |||
| 394628b8da | |||
| bee0fa3aef | |||
| ff9f9a5c1f | |||
| af308b5aac |
@@ -2,10 +2,9 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
|
|
||||||
using handler_fn = std::vector<std::vector<uint8_t>> (*)(uint32_t message_id, std::span<const uint8_t> payload);
|
using handler_fn = size_t (*)(uint32_t message_id, std::span<const uint8_t> payload, span_writer &out);
|
||||||
|
|
||||||
struct handler_entry {
|
struct handler_entry {
|
||||||
int8_t type_id;
|
int8_t type_id;
|
||||||
@@ -13,16 +12,16 @@ struct handler_entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Req, auto Fn>
|
template <typename Req, auto Fn>
|
||||||
std::vector<std::vector<uint8_t>> typed_handler(uint32_t message_id, std::span<const uint8_t> payload) {
|
size_t typed_handler(uint32_t message_id, std::span<const uint8_t> payload, span_writer &out) {
|
||||||
msgpack::parser p(payload.data(), static_cast<int>(payload.size()));
|
msgpack::parser p(payload.data(), static_cast<int>(payload.size()));
|
||||||
Req req;
|
Req req;
|
||||||
auto tup = req.as_tuple();
|
auto tup = req.as_tuple();
|
||||||
auto r = msgpack::unpack(p, tup);
|
auto r = msgpack::unpack(p, tup);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return {encode_response(message_id, DeviceError{1, "decode request ext_id=" +
|
return encode_response_into(out, message_id, DeviceError{1, "decode request ext_id=" +
|
||||||
std::to_string(Req::ext_id) + ": msgpack error " + std::to_string(static_cast<int>(r.error()))})};
|
std::to_string(Req::ext_id) + ": msgpack error " + std::to_string(static_cast<int>(r.error()))});
|
||||||
}
|
}
|
||||||
return Fn(message_id, req);
|
return Fn(message_id, req, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_init();
|
void dispatch_init();
|
||||||
|
|||||||
@@ -2,11 +2,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
|
|
||||||
extern std::string_view firmware_name;
|
extern std::string_view firmware_name;
|
||||||
|
|
||||||
std::vector<std::vector<uint8_t>> handle_picoboot(uint32_t message_id, std::span<const uint8_t> payload);
|
size_t handle_picoboot(uint32_t message_id, std::span<const uint8_t> payload, span_writer &out);
|
||||||
std::vector<std::vector<uint8_t>> handle_info(uint32_t message_id, std::span<const uint8_t> payload);
|
size_t handle_info(uint32_t message_id, std::span<const uint8_t> payload, span_writer &out);
|
||||||
std::vector<std::vector<uint8_t>> handle_log(uint32_t message_id, std::span<const uint8_t> payload);
|
size_t handle_log(uint32_t message_id, std::span<const uint8_t> payload, span_writer &out);
|
||||||
|
|||||||
+51
-53
@@ -6,11 +6,11 @@
|
|||||||
#include <expected>
|
#include <expected>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "span_writer.h"
|
||||||
|
|
||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
@@ -163,26 +163,23 @@ inline result<body_info> get_body_info(const uint8_t *p, int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class packer {
|
class packer {
|
||||||
public:
|
|
||||||
using buffer = std::vector<std::uint8_t>;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<buffer> m_buffer;
|
span_writer m_buf;
|
||||||
|
|
||||||
template <typename T> void push_big_endian(T n) {
|
template <typename T> void push_big_endian(T n) {
|
||||||
auto p = reinterpret_cast<std::uint8_t *>(&n) + (sizeof(T) - 1);
|
auto p = reinterpret_cast<std::uint8_t *>(&n) + (sizeof(T) - 1);
|
||||||
for (size_t i = 0; i < sizeof(T); ++i, --p) {
|
for (size_t i = 0; i < sizeof(T); ++i, --p) {
|
||||||
m_buffer->push_back(*p);
|
m_buf.push_back(*p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Range> void push(const Range &r) {
|
template <class Range> void push(const Range &r) {
|
||||||
m_buffer->insert(m_buffer->end(), std::begin(r), std::end(r));
|
m_buf.insert(m_buf.end(), std::begin(r), std::end(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
packer() : m_buffer(std::make_shared<buffer>()) {}
|
packer(uint8_t *data, size_t capacity) : m_buf(data, capacity) {}
|
||||||
packer(const std::shared_ptr<buffer> &buf) : m_buffer(buf) {}
|
packer(span_writer buf) : m_buf(buf) {}
|
||||||
|
|
||||||
packer(const packer &) = delete;
|
packer(const packer &) = delete;
|
||||||
packer &operator=(const packer &) = delete;
|
packer &operator=(const packer &) = delete;
|
||||||
@@ -190,12 +187,12 @@ public:
|
|||||||
using pack_result = result<std::reference_wrapper<packer>>;
|
using pack_result = result<std::reference_wrapper<packer>>;
|
||||||
|
|
||||||
pack_result pack_nil() {
|
pack_result pack_nil() {
|
||||||
m_buffer->push_back(format::NIL);
|
m_buf.push_back(format::NIL);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_result pack_bool(bool v) {
|
pack_result pack_bool(bool v) {
|
||||||
m_buffer->push_back(v ? format::TRUE : format::FALSE);
|
m_buf.push_back(v ? format::TRUE : format::FALSE);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,36 +200,36 @@ public:
|
|||||||
pack_result pack_integer(T n) {
|
pack_result pack_integer(T n) {
|
||||||
if constexpr (std::is_signed_v<T>) {
|
if constexpr (std::is_signed_v<T>) {
|
||||||
if (n >= 0 && n <= 0x7F) {
|
if (n >= 0 && n <= 0x7F) {
|
||||||
m_buffer->push_back(static_cast<uint8_t>(n));
|
m_buf.push_back(static_cast<uint8_t>(n));
|
||||||
} else if (n >= -32 && n < 0) {
|
} else if (n >= -32 && n < 0) {
|
||||||
m_buffer->push_back(static_cast<uint8_t>(n)); // negative fixint
|
m_buf.push_back(static_cast<uint8_t>(n)); // negative fixint
|
||||||
} else if (n >= std::numeric_limits<int8_t>::min() && n <= std::numeric_limits<int8_t>::max()) {
|
} else if (n >= std::numeric_limits<int8_t>::min() && n <= std::numeric_limits<int8_t>::max()) {
|
||||||
m_buffer->push_back(format::INT8);
|
m_buf.push_back(format::INT8);
|
||||||
m_buffer->push_back(static_cast<uint8_t>(n));
|
m_buf.push_back(static_cast<uint8_t>(n));
|
||||||
} else if (n >= std::numeric_limits<int16_t>::min() && n <= std::numeric_limits<int16_t>::max()) {
|
} else if (n >= std::numeric_limits<int16_t>::min() && n <= std::numeric_limits<int16_t>::max()) {
|
||||||
m_buffer->push_back(format::INT16);
|
m_buf.push_back(format::INT16);
|
||||||
push_big_endian(static_cast<int16_t>(n));
|
push_big_endian(static_cast<int16_t>(n));
|
||||||
} else if (n >= std::numeric_limits<int32_t>::min() && n <= std::numeric_limits<int32_t>::max()) {
|
} else if (n >= std::numeric_limits<int32_t>::min() && n <= std::numeric_limits<int32_t>::max()) {
|
||||||
m_buffer->push_back(format::INT32);
|
m_buf.push_back(format::INT32);
|
||||||
push_big_endian(static_cast<int32_t>(n));
|
push_big_endian(static_cast<int32_t>(n));
|
||||||
} else {
|
} else {
|
||||||
m_buffer->push_back(format::INT64);
|
m_buf.push_back(format::INT64);
|
||||||
push_big_endian(static_cast<int64_t>(n));
|
push_big_endian(static_cast<int64_t>(n));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (n <= 0x7F) {
|
if (n <= 0x7F) {
|
||||||
m_buffer->push_back(static_cast<uint8_t>(n));
|
m_buf.push_back(static_cast<uint8_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint8_t>::max()) {
|
} else if (n <= std::numeric_limits<uint8_t>::max()) {
|
||||||
m_buffer->push_back(format::UINT8);
|
m_buf.push_back(format::UINT8);
|
||||||
m_buffer->push_back(static_cast<uint8_t>(n));
|
m_buf.push_back(static_cast<uint8_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::UINT16);
|
m_buf.push_back(format::UINT16);
|
||||||
push_big_endian(static_cast<uint16_t>(n));
|
push_big_endian(static_cast<uint16_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::UINT32);
|
m_buf.push_back(format::UINT32);
|
||||||
push_big_endian(static_cast<uint32_t>(n));
|
push_big_endian(static_cast<uint32_t>(n));
|
||||||
} else {
|
} else {
|
||||||
m_buffer->push_back(format::UINT64);
|
m_buf.push_back(format::UINT64);
|
||||||
push_big_endian(static_cast<uint64_t>(n));
|
push_big_endian(static_cast<uint64_t>(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,13 +237,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
pack_result pack_float(float n) {
|
pack_result pack_float(float n) {
|
||||||
m_buffer->push_back(format::FLOAT32);
|
m_buf.push_back(format::FLOAT32);
|
||||||
push_big_endian(n);
|
push_big_endian(n);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_result pack_double(double n) {
|
pack_result pack_double(double n) {
|
||||||
m_buffer->push_back(format::FLOAT64);
|
m_buf.push_back(format::FLOAT64);
|
||||||
push_big_endian(n);
|
push_big_endian(n);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -255,15 +252,15 @@ public:
|
|||||||
pack_result pack_str(const Range &r) {
|
pack_result pack_str(const Range &r) {
|
||||||
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
||||||
if (sz < 32) {
|
if (sz < 32) {
|
||||||
m_buffer->push_back(format::FIXSTR_MIN | static_cast<uint8_t>(sz));
|
m_buf.push_back(format::FIXSTR_MIN | static_cast<uint8_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint8_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint8_t>::max()) {
|
||||||
m_buffer->push_back(format::STR8);
|
m_buf.push_back(format::STR8);
|
||||||
m_buffer->push_back(static_cast<uint8_t>(sz));
|
m_buf.push_back(static_cast<uint8_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::STR16);
|
m_buf.push_back(format::STR16);
|
||||||
push_big_endian(static_cast<uint16_t>(sz));
|
push_big_endian(static_cast<uint16_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::STR32);
|
m_buf.push_back(format::STR32);
|
||||||
push_big_endian(static_cast<uint32_t>(sz));
|
push_big_endian(static_cast<uint32_t>(sz));
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected(error_code::overflow);
|
return std::unexpected(error_code::overflow);
|
||||||
@@ -280,13 +277,13 @@ public:
|
|||||||
pack_result pack_bin(const Range &r) {
|
pack_result pack_bin(const Range &r) {
|
||||||
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
||||||
if (sz <= std::numeric_limits<uint8_t>::max()) {
|
if (sz <= std::numeric_limits<uint8_t>::max()) {
|
||||||
m_buffer->push_back(format::BIN8);
|
m_buf.push_back(format::BIN8);
|
||||||
m_buffer->push_back(static_cast<uint8_t>(sz));
|
m_buf.push_back(static_cast<uint8_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::BIN16);
|
m_buf.push_back(format::BIN16);
|
||||||
push_big_endian(static_cast<uint16_t>(sz));
|
push_big_endian(static_cast<uint16_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::BIN32);
|
m_buf.push_back(format::BIN32);
|
||||||
push_big_endian(static_cast<uint32_t>(sz));
|
push_big_endian(static_cast<uint32_t>(sz));
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected(error_code::overflow);
|
return std::unexpected(error_code::overflow);
|
||||||
@@ -297,12 +294,12 @@ public:
|
|||||||
|
|
||||||
pack_result pack_array(size_t n) {
|
pack_result pack_array(size_t n) {
|
||||||
if (n <= 15) {
|
if (n <= 15) {
|
||||||
m_buffer->push_back(format::FIXARRAY_MIN | static_cast<uint8_t>(n));
|
m_buf.push_back(format::FIXARRAY_MIN | static_cast<uint8_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::ARRAY16);
|
m_buf.push_back(format::ARRAY16);
|
||||||
push_big_endian(static_cast<uint16_t>(n));
|
push_big_endian(static_cast<uint16_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::ARRAY32);
|
m_buf.push_back(format::ARRAY32);
|
||||||
push_big_endian(static_cast<uint32_t>(n));
|
push_big_endian(static_cast<uint32_t>(n));
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected(error_code::overflow);
|
return std::unexpected(error_code::overflow);
|
||||||
@@ -312,12 +309,12 @@ public:
|
|||||||
|
|
||||||
pack_result pack_map(size_t n) {
|
pack_result pack_map(size_t n) {
|
||||||
if (n <= 15) {
|
if (n <= 15) {
|
||||||
m_buffer->push_back(format::FIXMAP_MIN | static_cast<uint8_t>(n));
|
m_buf.push_back(format::FIXMAP_MIN | static_cast<uint8_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
} else if (n <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::MAP16);
|
m_buf.push_back(format::MAP16);
|
||||||
push_big_endian(static_cast<uint16_t>(n));
|
push_big_endian(static_cast<uint16_t>(n));
|
||||||
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
} else if (n <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::MAP32);
|
m_buf.push_back(format::MAP32);
|
||||||
push_big_endian(static_cast<uint32_t>(n));
|
push_big_endian(static_cast<uint32_t>(n));
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected(error_code::overflow);
|
return std::unexpected(error_code::overflow);
|
||||||
@@ -330,26 +327,26 @@ public:
|
|||||||
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
auto sz = static_cast<size_t>(std::distance(std::begin(r), std::end(r)));
|
||||||
|
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 1: m_buffer->push_back(format::FIXEXT1); break;
|
case 1: m_buf.push_back(format::FIXEXT1); break;
|
||||||
case 2: m_buffer->push_back(format::FIXEXT2); break;
|
case 2: m_buf.push_back(format::FIXEXT2); break;
|
||||||
case 4: m_buffer->push_back(format::FIXEXT4); break;
|
case 4: m_buf.push_back(format::FIXEXT4); break;
|
||||||
case 8: m_buffer->push_back(format::FIXEXT8); break;
|
case 8: m_buf.push_back(format::FIXEXT8); break;
|
||||||
case 16: m_buffer->push_back(format::FIXEXT16); break;
|
case 16: m_buf.push_back(format::FIXEXT16); break;
|
||||||
default:
|
default:
|
||||||
if (sz <= std::numeric_limits<uint8_t>::max()) {
|
if (sz <= std::numeric_limits<uint8_t>::max()) {
|
||||||
m_buffer->push_back(format::EXT8);
|
m_buf.push_back(format::EXT8);
|
||||||
m_buffer->push_back(static_cast<uint8_t>(sz));
|
m_buf.push_back(static_cast<uint8_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint16_t>::max()) {
|
||||||
m_buffer->push_back(format::EXT16);
|
m_buf.push_back(format::EXT16);
|
||||||
push_big_endian(static_cast<uint16_t>(sz));
|
push_big_endian(static_cast<uint16_t>(sz));
|
||||||
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
} else if (sz <= std::numeric_limits<uint32_t>::max()) {
|
||||||
m_buffer->push_back(format::EXT32);
|
m_buf.push_back(format::EXT32);
|
||||||
push_big_endian(static_cast<uint32_t>(sz));
|
push_big_endian(static_cast<uint32_t>(sz));
|
||||||
} else {
|
} else {
|
||||||
return std::unexpected(error_code::overflow);
|
return std::unexpected(error_code::overflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_buffer->push_back(static_cast<uint8_t>(type));
|
m_buf.push_back(static_cast<uint8_t>(type));
|
||||||
push(r);
|
push(r);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -392,7 +389,8 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
requires requires(const T &v) { { T::ext_id } -> std::convertible_to<int8_t>; v.as_tuple(); }
|
requires requires(const T &v) { { T::ext_id } -> std::convertible_to<int8_t>; v.as_tuple(); }
|
||||||
pack_result pack(const T &v) {
|
pack_result pack(const T &v) {
|
||||||
packer inner;
|
uint8_t ext_buf[256];
|
||||||
|
packer inner(ext_buf, sizeof(ext_buf));
|
||||||
auto r = inner.pack(v.as_tuple());
|
auto r = inner.pack(v.as_tuple());
|
||||||
if (!r) return r;
|
if (!r) return r;
|
||||||
return pack_ext(T::ext_id, inner.get_payload());
|
return pack_ext(T::ext_id, inner.get_payload());
|
||||||
@@ -413,7 +411,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const buffer &get_payload() const { return *m_buffer; }
|
const span_writer &get_payload() const { return m_buf; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class parser {
|
class parser {
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include "span_writer.h"
|
||||||
|
|
||||||
struct net_state {
|
struct net_state {
|
||||||
std::array<uint8_t, 6> mac;
|
std::array<uint8_t, 6> mac;
|
||||||
std::array<uint8_t, 4> ip;
|
std::array<uint8_t, 4> ip;
|
||||||
};
|
};
|
||||||
|
|
||||||
using net_handler = std::function<std::vector<std::vector<uint8_t>>(std::span<const uint8_t> payload)>;
|
using net_handler = std::function<size_t(std::span<const uint8_t> payload, span_writer &out)>;
|
||||||
|
|
||||||
bool net_init();
|
bool net_init();
|
||||||
const net_state& net_get_state();
|
const net_state& net_get_state();
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
class span_writer {
|
||||||
|
uint8_t *m_data;
|
||||||
|
size_t m_capacity;
|
||||||
|
size_t m_size = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
span_writer(uint8_t *data, size_t capacity) : m_data(data), m_capacity(capacity) {}
|
||||||
|
|
||||||
|
void push_back(uint8_t v) {
|
||||||
|
if (m_size < m_capacity) m_data[m_size++] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class It>
|
||||||
|
void insert(uint8_t *, It first, It last) {
|
||||||
|
while (first != last && m_size < m_capacity)
|
||||||
|
m_data[m_size++] = *first++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
size_t capacity() const { return m_capacity; }
|
||||||
|
bool full() const { return m_size >= m_capacity; }
|
||||||
|
|
||||||
|
uint8_t *data() { return m_data; }
|
||||||
|
const uint8_t *data() const { return m_data; }
|
||||||
|
|
||||||
|
uint8_t *begin() { return m_data; }
|
||||||
|
uint8_t *end() { return m_data + m_size; }
|
||||||
|
const uint8_t *begin() const { return m_data; }
|
||||||
|
const uint8_t *end() const { return m_data + m_size; }
|
||||||
|
};
|
||||||
@@ -15,6 +15,7 @@ inline bool operator<(const timer_entry& a, const timer_entry& b) {
|
|||||||
struct timer_queue {
|
struct timer_queue {
|
||||||
sorted_list<timer_entry, 16> queue;
|
sorted_list<timer_entry, 16> queue;
|
||||||
alarm_id_t alarm = -1;
|
alarm_id_t alarm = -1;
|
||||||
|
volatile bool irq_pending = false;
|
||||||
|
|
||||||
void schedule(absolute_time_t when, std::function<void()> fn) {
|
void schedule(absolute_time_t when, std::function<void()> fn) {
|
||||||
queue.insert({when, std::move(fn)});
|
queue.insert({when, std::move(fn)});
|
||||||
@@ -26,6 +27,8 @@ struct timer_queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
|
if (!irq_pending) return;
|
||||||
|
irq_pending = false;
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
auto& front = queue.front();
|
auto& front = queue.front();
|
||||||
if (absolute_time_diff_us(get_absolute_time(), front.when) > 0) break;
|
if (absolute_time_diff_us(get_absolute_time(), front.when) > 0) break;
|
||||||
@@ -39,12 +42,15 @@ struct timer_queue {
|
|||||||
bool empty() const { return queue.empty(); }
|
bool empty() const { return queue.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int64_t alarm_cb(alarm_id_t, void*) { return 0; }
|
static int64_t alarm_cb(alarm_id_t, void* user_data) {
|
||||||
|
static_cast<timer_queue*>(user_data)->irq_pending = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void arm() {
|
void arm() {
|
||||||
if (alarm >= 0) cancel_alarm(alarm);
|
if (alarm >= 0) cancel_alarm(alarm);
|
||||||
alarm = -1;
|
alarm = -1;
|
||||||
if (!queue.empty())
|
if (!queue.empty())
|
||||||
alarm = add_alarm_at(queue.front().when, alarm_cb, nullptr, false);
|
alarm = add_alarm_at(queue.front().when, alarm_cb, this, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-12
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -96,18 +97,27 @@ struct DecodedMessage {
|
|||||||
std::vector<uint8_t> payload;
|
std::vector<uint8_t> payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::vector<uint8_t> pack_envelope(uint32_t message_id, const std::vector<uint8_t> &payload) {
|
inline size_t pack_envelope_into(span_writer &out, uint32_t message_id, const uint8_t *payload, size_t payload_len) {
|
||||||
uint32_t checksum = halfsiphash::hash32(payload.data(), payload.size(), hash_key);
|
uint32_t checksum = halfsiphash::hash32(payload, payload_len, hash_key);
|
||||||
msgpack::packer p;
|
uint8_t env_buf[512];
|
||||||
p.pack(Envelope{message_id, checksum, payload});
|
span_writer env_body(env_buf, sizeof(env_buf));
|
||||||
return p.get_payload();
|
msgpack::packer env_p(env_body);
|
||||||
|
env_p.pack_array(3);
|
||||||
|
env_p.pack(message_id);
|
||||||
|
env_p.pack(checksum);
|
||||||
|
env_p.pack_bin(std::span<const uint8_t>{payload, payload_len});
|
||||||
|
msgpack::packer outer(out);
|
||||||
|
outer.pack_ext(Envelope::ext_id, env_body);
|
||||||
|
return out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::vector<uint8_t> encode_response(uint32_t message_id, const T &msg) {
|
inline size_t encode_response_into(span_writer &out, uint32_t message_id, const T &msg) {
|
||||||
msgpack::packer inner;
|
uint8_t inner_buf[256];
|
||||||
|
msgpack::packer inner(inner_buf, sizeof(inner_buf));
|
||||||
inner.pack(msg);
|
inner.pack(msg);
|
||||||
return pack_envelope(message_id, inner.get_payload());
|
auto &pl = inner.get_payload();
|
||||||
|
return pack_envelope_into(out, message_id, pl.data(), pl.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline msgpack::result<DecodedMessage> try_decode(const uint8_t *data, size_t len) {
|
inline msgpack::result<DecodedMessage> try_decode(const uint8_t *data, size_t len) {
|
||||||
@@ -154,8 +164,6 @@ inline msgpack::result<T> decode_response(const uint8_t *data, size_t len) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector<uint8_t> encode_request(uint32_t message_id, const auto &msg) {
|
inline size_t encode_request_into(span_writer &out, uint32_t message_id, const auto &msg) {
|
||||||
msgpack::packer inner;
|
return encode_response_into(out, message_id, msg);
|
||||||
inner.pack(msg);
|
|
||||||
return pack_envelope(message_id, inner.get_payload());
|
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-16
@@ -1,7 +1,6 @@
|
|||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pico/bootrom.h"
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
@@ -23,20 +22,21 @@ void dispatch_schedule_ms(uint32_t ms, std::function<void()> fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void dispatch_run(std::span<const handler_entry> handlers) {
|
[[noreturn]] void dispatch_run(std::span<const handler_entry> handlers) {
|
||||||
std::unordered_map<int8_t, std::vector<std::vector<uint8_t>> (*)(uint32_t, std::span<const uint8_t>)> handler_map;
|
std::unordered_map<int8_t, handler_fn> handler_map;
|
||||||
for (auto& entry : handlers) {
|
for (auto& entry : handlers) {
|
||||||
handler_map[entry.type_id] = entry.handle;
|
handler_map[entry.type_id] = entry.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static usb_cdc usb;
|
static usb_cdc usb;
|
||||||
static static_vector<uint8_t, 256> usb_rx_buf;
|
static static_vector<uint8_t, 256> usb_rx_buf;
|
||||||
|
static uint8_t tx_buf[1514];
|
||||||
|
|
||||||
net_set_handler([&](std::span<const uint8_t> payload) -> std::vector<std::vector<uint8_t>> {
|
net_set_handler([&](std::span<const uint8_t> payload, span_writer &out) -> size_t {
|
||||||
auto msg = try_decode(payload.data(), payload.size());
|
auto msg = try_decode(payload.data(), payload.size());
|
||||||
if (!msg) return {};
|
if (!msg) return 0;
|
||||||
auto it = handler_map.find(msg->type_id);
|
auto it = handler_map.find(msg->type_id);
|
||||||
if (it == handler_map.end()) return {};
|
if (it == handler_map.end()) return 0;
|
||||||
return it->second(msg->message_id, msg->payload);
|
return it->second(msg->message_id, msg->payload, out);
|
||||||
});
|
});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -63,19 +63,18 @@ void dispatch_schedule_ms(uint32_t ms, std::function<void()> fn) {
|
|||||||
|
|
||||||
auto it = handler_map.find(msg->type_id);
|
auto it = handler_map.find(msg->type_id);
|
||||||
if (it != handler_map.end()) {
|
if (it != handler_map.end()) {
|
||||||
for (auto& response : it->second(msg->message_id, msg->payload)) {
|
span_writer out(tx_buf, sizeof(tx_buf));
|
||||||
if (response.size() > usb.tx.free()) {
|
size_t resp_len = it->second(msg->message_id, msg->payload, out);
|
||||||
auto err = encode_response(msg->message_id,
|
if (resp_len > 0) {
|
||||||
DeviceError{2, "response too large: " + std::to_string(response.size())});
|
if (resp_len > usb.tx.free()) {
|
||||||
usb.send(err);
|
span_writer err_out(tx_buf, sizeof(tx_buf));
|
||||||
|
size_t err_len = encode_response_into(err_out, msg->message_id,
|
||||||
|
DeviceError{2, "response too large: " + std::to_string(resp_len)});
|
||||||
|
usb.send(std::span<const uint8_t>{tx_buf, err_len});
|
||||||
} else {
|
} else {
|
||||||
usb.send(response);
|
usb.send(std::span<const uint8_t>{tx_buf, resp_len});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg->type_id == RequestPICOBOOT::ext_id) {
|
|
||||||
sleep_ms(100);
|
|
||||||
reset_usb_boot(0, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "pico/unique_id.h"
|
#include "pico/unique_id.h"
|
||||||
|
#include "pico/bootrom.h"
|
||||||
|
#include "dispatch.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "debug_log.h"
|
#include "debug_log.h"
|
||||||
|
|
||||||
std::vector<std::vector<uint8_t>> handle_picoboot(uint32_t message_id, std::span<const uint8_t>) {
|
size_t handle_picoboot(uint32_t message_id, std::span<const uint8_t>, span_writer &out) {
|
||||||
return {encode_response(message_id, ResponsePICOBOOT{})};
|
dispatch_schedule_ms(100, []{ reset_usb_boot(0, 1); });
|
||||||
|
return encode_response_into(out, message_id, ResponsePICOBOOT{});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<uint8_t>> handle_info(uint32_t message_id, std::span<const uint8_t>) {
|
size_t handle_info(uint32_t message_id, std::span<const uint8_t>, span_writer &out) {
|
||||||
ResponseInfo resp;
|
ResponseInfo resp;
|
||||||
pico_unique_board_id_t uid;
|
pico_unique_board_id_t uid;
|
||||||
pico_get_unique_board_id(&uid);
|
pico_get_unique_board_id(&uid);
|
||||||
@@ -16,12 +19,12 @@ std::vector<std::vector<uint8_t>> handle_info(uint32_t message_id, std::span<con
|
|||||||
resp.mac = ns.mac;
|
resp.mac = ns.mac;
|
||||||
resp.ip = ns.ip;
|
resp.ip = ns.ip;
|
||||||
resp.firmware_name = firmware_name;
|
resp.firmware_name = firmware_name;
|
||||||
return {encode_response(message_id, resp)};
|
return encode_response_into(out, message_id, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<uint8_t>> handle_log(uint32_t message_id, std::span<const uint8_t>) {
|
size_t handle_log(uint32_t message_id, std::span<const uint8_t>, span_writer &out) {
|
||||||
ResponseLog resp;
|
ResponseLog resp;
|
||||||
for (auto& e : dlog_drain())
|
for (auto& e : dlog_drain())
|
||||||
resp.entries.push_back(LogEntry{e.timestamp_us, std::move(e.message)});
|
resp.entries.push_back(LogEntry{e.timestamp_us, std::move(e.message)});
|
||||||
return {encode_response(message_id, resp)};
|
return encode_response_into(out, message_id, resp);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-22
@@ -108,9 +108,7 @@ static bool ip_match_or_broadcast(const ip4_addr& dst) {
|
|||||||
|
|
||||||
static void send_raw(const void* data, size_t len) {
|
static void send_raw(const void* data, size_t len) {
|
||||||
dlog_if_slow("send_raw", 1000, [&]{
|
dlog_if_slow("send_raw", 1000, [&]{
|
||||||
w6300::ip_address dummy = {};
|
w6300::send(raw_socket, std::span<const uint8_t>{static_cast<const uint8_t*>(data), len});
|
||||||
w6300::sendto(raw_socket, std::span<const uint8_t>{static_cast<const uint8_t*>(data), len},
|
|
||||||
dummy, w6300::port_num{0});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +139,8 @@ static void handle_arp(const uint8_t* frame, size_t len) {
|
|||||||
send_raw(&reply, sizeof(reply));
|
send_raw(&reply, sizeof(reply));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t tx_buf[1514];
|
||||||
|
|
||||||
static void handle_udp(const uint8_t* frame, size_t len) {
|
static void handle_udp(const uint8_t* frame, size_t len) {
|
||||||
if (len < sizeof(udp_header)) return;
|
if (len < sizeof(udp_header)) return;
|
||||||
auto& pkt = *reinterpret_cast<const udp_header*>(frame);
|
auto& pkt = *reinterpret_cast<const udp_header*>(frame);
|
||||||
@@ -156,16 +156,14 @@ static void handle_udp(const uint8_t* frame, size_t len) {
|
|||||||
auto* payload = frame + sizeof(udp_header);
|
auto* payload = frame + sizeof(udp_header);
|
||||||
size_t payload_len = udp_len - 8;
|
size_t payload_len = udp_len - 8;
|
||||||
|
|
||||||
auto responses = msg_handler(std::span<const uint8_t>{payload, payload_len});
|
span_writer resp(tx_buf + sizeof(udp_header), sizeof(tx_buf) - sizeof(udp_header));
|
||||||
|
size_t resp_len = msg_handler(std::span<const uint8_t>{payload, payload_len}, resp);
|
||||||
|
if (resp_len == 0) return;
|
||||||
|
|
||||||
for (auto& resp : responses) {
|
size_t ip_total = 20 + 8 + resp_len;
|
||||||
uint8_t reply_buf[1514];
|
|
||||||
size_t udp_data_len = resp.size();
|
|
||||||
size_t ip_total = 20 + 8 + udp_data_len;
|
|
||||||
size_t reply_len = sizeof(eth_header) + ip_total;
|
size_t reply_len = sizeof(eth_header) + ip_total;
|
||||||
if (reply_len > sizeof(reply_buf)) continue;
|
|
||||||
|
|
||||||
auto& rip = *reinterpret_cast<ipv4_header*>(reply_buf);
|
auto& rip = *reinterpret_cast<ipv4_header*>(tx_buf);
|
||||||
rip.eth.dst = pkt.ip.eth.src;
|
rip.eth.dst = pkt.ip.eth.src;
|
||||||
rip.eth.src = state.mac;
|
rip.eth.src = state.mac;
|
||||||
rip.eth.ethertype = ETH_IPV4;
|
rip.eth.ethertype = ETH_IPV4;
|
||||||
@@ -181,16 +179,13 @@ static void handle_udp(const uint8_t* frame, size_t len) {
|
|||||||
rip.dst = pkt.ip.src;
|
rip.dst = pkt.ip.src;
|
||||||
rip.checksum = ip_checksum(rip.ip_start(), 20);
|
rip.checksum = ip_checksum(rip.ip_start(), 20);
|
||||||
|
|
||||||
auto& rudp = *reinterpret_cast<udp_header*>(reply_buf);
|
auto& rudp = *reinterpret_cast<udp_header*>(tx_buf);
|
||||||
rudp.src_port = PICOMAP_PORT;
|
rudp.src_port = PICOMAP_PORT;
|
||||||
rudp.dst_port = pkt.src_port;
|
rudp.dst_port = pkt.src_port;
|
||||||
rudp.length = __builtin_bswap16(8 + udp_data_len);
|
rudp.length = __builtin_bswap16(8 + resp_len);
|
||||||
rudp.checksum = 0;
|
rudp.checksum = 0;
|
||||||
|
|
||||||
memcpy(reply_buf + sizeof(udp_header), resp.data(), udp_data_len);
|
send_raw(tx_buf, reply_len);
|
||||||
|
|
||||||
send_raw(reply_buf, reply_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_icmp(const uint8_t* frame, size_t len) {
|
static void handle_icmp(const uint8_t* frame, size_t len) {
|
||||||
@@ -262,7 +257,6 @@ static void process_frame(const uint8_t* frame, size_t len) {
|
|||||||
|
|
||||||
bool net_init() {
|
bool net_init() {
|
||||||
w6300::init_spi();
|
w6300::init_spi();
|
||||||
w6300::init_critical_section();
|
|
||||||
w6300::reset();
|
w6300::reset();
|
||||||
w6300::init();
|
w6300::init();
|
||||||
if (!w6300::check()) return false;
|
if (!w6300::check()) return false;
|
||||||
@@ -281,8 +275,7 @@ bool net_init() {
|
|||||||
state.ip[2] = state.mac[4];
|
state.ip[2] = state.mac[4];
|
||||||
state.ip[3] = state.mac[5];
|
state.ip[3] = state.mac[5];
|
||||||
|
|
||||||
w6300::open_socket(raw_socket, w6300::protocol::macraw, w6300::port_num{0}, w6300::sock_flag::none);
|
w6300::open_socket(raw_socket, w6300::protocol::macraw, w6300::sock_flag::none);
|
||||||
w6300::set_socket_io_mode(raw_socket, w6300::sock_io_mode::nonblock);
|
|
||||||
w6300::set_interrupt_mask(w6300::ik_sock_0);
|
w6300::set_interrupt_mask(w6300::ik_sock_0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -297,12 +290,12 @@ void net_set_handler(net_handler handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void net_poll() {
|
void net_poll() {
|
||||||
|
if (!w6300::irq_pending) return;
|
||||||
|
w6300::irq_pending = false;
|
||||||
w6300::clear_interrupt(w6300::ik_int_all);
|
w6300::clear_interrupt(w6300::ik_int_all);
|
||||||
if (w6300::get_socket_recv_buf(raw_socket) == 0) return;
|
if (w6300::get_socket_recv_buf(raw_socket) == 0) return;
|
||||||
static uint8_t rx_buf[1518];
|
static uint8_t rx_buf[1518];
|
||||||
w6300::ip_address dummy_addr = {};
|
auto result = w6300::recv(raw_socket, std::span{rx_buf});
|
||||||
w6300::port_num dummy_port{0};
|
|
||||||
auto result = w6300::recvfrom(raw_socket, std::span{rx_buf}, dummy_addr, dummy_port);
|
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
process_frame(rx_buf, *result);
|
process_frame(rx_buf, *result);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-23
@@ -29,44 +29,36 @@ static ResponseTest test_discovery() {
|
|||||||
ResponseTest resp;
|
ResponseTest resp;
|
||||||
resp.pass = true;
|
resp.pass = true;
|
||||||
|
|
||||||
w6300::ip_address dest = {};
|
uint8_t req_buf[256];
|
||||||
std::copy(picomap_discovery_ip.begin(), picomap_discovery_ip.end(), dest.ip.begin());
|
span_writer req_out(req_buf, sizeof(req_buf));
|
||||||
dest.len = 4;
|
size_t req_len = encode_request_into(req_out, 0, RequestInfo{});
|
||||||
|
auto send_result = w6300::send(test_socket, std::span<const uint8_t>{req_buf, req_len});
|
||||||
w6300::set_socket_dest_mac(test_socket, picomap_discovery_mac);
|
|
||||||
|
|
||||||
auto req = encode_request(0, RequestInfo{});
|
|
||||||
auto send_result = w6300::sendto(test_socket, std::span<const uint8_t>{req}, dest,
|
|
||||||
w6300::port_num{PICOMAP_DISCOVERY_PORT});
|
|
||||||
if (!send_result) {
|
if (!send_result) {
|
||||||
resp.pass = false;
|
resp.pass = false;
|
||||||
resp.messages.push_back("sendto: error " + std::to_string(static_cast<int>(send_result.error())));
|
resp.messages.push_back("send: error " + std::to_string(static_cast<int>(send_result.error())));
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t rx_buf[512];
|
uint8_t rx_buf[512];
|
||||||
w6300::ip_address src_addr = {};
|
|
||||||
w6300::port_num src_port{0};
|
|
||||||
|
|
||||||
auto deadline = make_timeout_time_ms(5000);
|
auto deadline = make_timeout_time_ms(5000);
|
||||||
std::expected<uint16_t, w6300::sock_error> recv_result = std::unexpected(w6300::sock_error::busy);
|
std::expected<uint16_t, w6300::sock_error> recv_result = std::unexpected(w6300::sock_error::busy);
|
||||||
while (get_absolute_time() < deadline) {
|
while (get_absolute_time() < deadline) {
|
||||||
recv_result = w6300::recvfrom(test_socket, std::span{rx_buf}, src_addr, src_port);
|
recv_result = w6300::recv(test_socket, std::span{rx_buf});
|
||||||
if (recv_result || recv_result.error() != w6300::sock_error::busy) break;
|
if (recv_result || recv_result.error() != w6300::sock_error::busy) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recv_result) {
|
if (!recv_result) {
|
||||||
resp.pass = false;
|
resp.pass = false;
|
||||||
if (recv_result.error() == w6300::sock_error::busy) {
|
if (recv_result.error() == w6300::sock_error::busy) {
|
||||||
resp.messages.push_back("recvfrom: timed out after 5s");
|
resp.messages.push_back("recv: timed out after 5s");
|
||||||
} else {
|
} else {
|
||||||
resp.messages.push_back("recvfrom: error " + std::to_string(static_cast<int>(recv_result.error())));
|
resp.messages.push_back("recv: error " + std::to_string(static_cast<int>(recv_result.error())));
|
||||||
}
|
}
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.messages.push_back("received " + std::to_string(*recv_result) + " bytes from port " +
|
resp.messages.push_back("received " + std::to_string(*recv_result) + " bytes");
|
||||||
std::to_string(static_cast<uint16_t>(src_port)));
|
|
||||||
|
|
||||||
auto info = decode_response<ResponseInfo>(rx_buf, *recv_result);
|
auto info = decode_response<ResponseInfo>(rx_buf, *recv_result);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
@@ -105,13 +97,11 @@ static const std::unordered_map<std::string_view, test_fn> tests = {
|
|||||||
{"discovery", test_discovery},
|
{"discovery", test_discovery},
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<std::vector<uint8_t>> handle_test(uint32_t message_id, const RequestTest& req) {
|
static size_t handle_test(uint32_t message_id, const RequestTest& req, span_writer &out) {
|
||||||
auto it = tests.find(req.name);
|
auto it = tests.find(req.name);
|
||||||
if (it == tests.end()) {
|
if (it == tests.end())
|
||||||
return {encode_response(message_id, ResponseTest{false, {"unknown test: " + req.name}})};
|
return encode_response_into(out, message_id, ResponseTest{false, {"unknown test: " + req.name}});
|
||||||
}
|
return encode_response_into(out, message_id, it->second());
|
||||||
|
|
||||||
return {encode_response(message_id, it->second())};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr handler_entry handlers[] = {
|
static constexpr handler_entry handlers[] = {
|
||||||
|
|||||||
+88
-1262
File diff suppressed because it is too large
Load Diff
+4
-221
@@ -2,267 +2,50 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
#include <optional>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
namespace w6300 {
|
namespace w6300 {
|
||||||
|
|
||||||
constexpr int sock_count = 8;
|
|
||||||
|
|
||||||
enum class socket_id : uint8_t {};
|
enum class socket_id : uint8_t {};
|
||||||
enum class port_num : uint16_t {};
|
|
||||||
|
|
||||||
enum class sock_error : int16_t {
|
enum class sock_error : int16_t {
|
||||||
busy = 0,
|
busy = 0,
|
||||||
sock_num = -1,
|
sock_num = -1,
|
||||||
sock_opt = -2,
|
|
||||||
sock_init = -3,
|
|
||||||
sock_closed = -4,
|
sock_closed = -4,
|
||||||
sock_mode = -5,
|
sock_mode = -5,
|
||||||
sock_flag = -6,
|
|
||||||
sock_status = -7,
|
|
||||||
arg = -10,
|
arg = -10,
|
||||||
port_zero = -11,
|
|
||||||
ip_invalid = -12,
|
|
||||||
timeout = -13,
|
timeout = -13,
|
||||||
data_len = -14,
|
data_len = -14,
|
||||||
buffer = -15,
|
|
||||||
fatal_packlen = -1001,
|
fatal_packlen = -1001,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class protocol : uint8_t {
|
enum class protocol : uint8_t {
|
||||||
tcp = 0x01,
|
|
||||||
udp = 0x02,
|
|
||||||
ipraw = 0x03,
|
|
||||||
macraw = 0x07,
|
macraw = 0x07,
|
||||||
tcp6 = 0x09,
|
|
||||||
udp6 = 0x0A,
|
|
||||||
ipraw6 = 0x0B,
|
|
||||||
tcp_dual = 0x0D,
|
|
||||||
udp_dual = 0x0E,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class sock_flag : uint8_t {
|
enum class sock_flag : uint8_t {
|
||||||
none = 0,
|
none = 0,
|
||||||
multi_enable = 1 << 7,
|
|
||||||
ether_own = 1 << 7,
|
|
||||||
broad_block = 1 << 6,
|
|
||||||
tcp_fpsh = 1 << 6,
|
|
||||||
tcp_nodelay = 1 << 5,
|
|
||||||
igmp_ver2 = 1 << 5,
|
|
||||||
solicit_block = 1 << 5,
|
|
||||||
ether_multi4b = 1 << 5,
|
|
||||||
uni_block = 1 << 4,
|
|
||||||
ether_multi6b = 1 << 4,
|
|
||||||
force_arp = 1 << 0,
|
|
||||||
dha_manual = 1 << 1,
|
|
||||||
io_nonblock = 1 << 3,
|
|
||||||
};
|
|
||||||
constexpr sock_flag operator|(sock_flag a, sock_flag b) {
|
|
||||||
return static_cast<sock_flag>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
|
||||||
}
|
|
||||||
constexpr uint8_t operator&(sock_flag a, sock_flag b) {
|
|
||||||
return static_cast<uint8_t>(a) & static_cast<uint8_t>(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class pack_info : uint8_t {
|
|
||||||
none = 0x00,
|
|
||||||
first = 1 << 1,
|
|
||||||
remained = 1 << 2,
|
|
||||||
completed = 1 << 3,
|
|
||||||
ipv6_lla = (1 << 7) | (1 << 4),
|
|
||||||
ipv6_multi = (1 << 7) | (1 << 5),
|
|
||||||
ipv6_allnode = (1 << 7) | (1 << 6),
|
|
||||||
ipv6 = 1 << 7,
|
|
||||||
};
|
|
||||||
constexpr pack_info operator|(pack_info a, pack_info b) {
|
|
||||||
return static_cast<pack_info>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
|
||||||
}
|
|
||||||
constexpr uint8_t operator&(pack_info a, pack_info b) {
|
|
||||||
return static_cast<uint8_t>(a) & static_cast<uint8_t>(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class srcv6_prefer : uint8_t {
|
|
||||||
auto_select = 0x00,
|
|
||||||
lla = 0x02,
|
|
||||||
gua = 0x03,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class tcp_sock_info : uint8_t {
|
|
||||||
mode = 1 << 2,
|
|
||||||
op = 1 << 1,
|
|
||||||
sip = 1 << 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class sock_io_mode : uint8_t {
|
|
||||||
block = 0,
|
|
||||||
nonblock = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum intr_kind : uint32_t {
|
enum intr_kind : uint32_t {
|
||||||
ik_pppoe_terminated = (1 << 0), ik_dest_unreach = (1 << 1), ik_ip_conflict = (1 << 2),
|
ik_sock_0 = (1 << 8),
|
||||||
ik_dest_unreach6 = (1 << 4), ik_wol = (1 << 7), ik_net_all = 0x97,
|
|
||||||
ik_sock_0 = (1 << 8), ik_sock_1 = (1 << 9), ik_sock_2 = (1 << 10), ik_sock_3 = (1 << 11),
|
|
||||||
ik_sock_4 = (1 << 12), ik_sock_5 = (1 << 13), ik_sock_6 = (1 << 14), ik_sock_7 = (1 << 15),
|
|
||||||
ik_sock_all = (0xFF << 8),
|
|
||||||
ik_sockl_tout = (1 << 16), ik_sockl_arp4 = (1 << 17), ik_sockl_ping4 = (1 << 18),
|
|
||||||
ik_sockl_arp6 = (1 << 19), ik_sockl_ping6 = (1 << 20), ik_sockl_ns = (1 << 21),
|
|
||||||
ik_sockl_rs = (1 << 22), ik_sockl_ra = (1 << 23), ik_sockl_all = (0xFF << 16),
|
|
||||||
ik_int_all = 0x00FFFF97
|
ik_int_all = 0x00FFFF97
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phy_conf {
|
|
||||||
uint8_t by;
|
|
||||||
uint8_t mode;
|
|
||||||
uint8_t speed;
|
|
||||||
uint8_t duplex;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ipconf_mode : uint8_t {
|
|
||||||
ipconf_none = 0x00, ipconf_static_v4 = 0x01, ipconf_static_v6 = 0x02,
|
|
||||||
ipconf_static_all = 0x03, ipconf_slaac_v6 = 0x04,
|
|
||||||
ipconf_dhcp_v4 = 0x10, ipconf_dhcp_v6 = 0x20, ipconf_dhcp_all = 0x30
|
|
||||||
};
|
|
||||||
|
|
||||||
enum dhcp_mode : uint8_t { dhcp_static = 1, dhcp_dynamic };
|
|
||||||
|
|
||||||
struct net_info {
|
|
||||||
std::array<uint8_t, 6> mac;
|
|
||||||
std::array<uint8_t, 4> ip;
|
|
||||||
std::array<uint8_t, 4> sn;
|
|
||||||
std::array<uint8_t, 4> gw;
|
|
||||||
std::array<uint8_t, 16> lla;
|
|
||||||
std::array<uint8_t, 16> gua;
|
|
||||||
std::array<uint8_t, 16> sn6;
|
|
||||||
std::array<uint8_t, 16> gw6;
|
|
||||||
std::array<uint8_t, 4> dns;
|
|
||||||
std::array<uint8_t, 16> dns6;
|
|
||||||
ipconf_mode ipmode;
|
|
||||||
dhcp_mode dhcp;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum netmode_type : uint32_t {
|
|
||||||
nm_ipb_v4 = (1 << 0), nm_ipb_v6 = (1 << 1), nm_wol = (1 << 2),
|
|
||||||
nm_pb6_multi = (1 << 4), nm_pb6_allnode = (1 << 5), nm_mr_mask = 0x37,
|
|
||||||
nm_pppoe = (1 << 8), nm_dha_select = (1 << 15), nm_mr2_mask = (0x09 << 8),
|
|
||||||
nm_pb4_all = (1 << 16), nm_trstb_v4 = (1 << 17), nm_parp_v4 = (1 << 18),
|
|
||||||
nm_unrb_v4 = (1 << 19), nm_net4_mask = (0x0F << 16),
|
|
||||||
nm_pb6_all = (1 << 24), nm_trstb_v6 = (1 << 25), nm_parp_v6 = (1 << 26),
|
|
||||||
nm_unrb_v6 = (1 << 27), nm_net6_mask = (0x0F << 24),
|
|
||||||
nm_mask_all = 0x0F0F0937
|
|
||||||
};
|
|
||||||
|
|
||||||
struct net_timeout {
|
|
||||||
uint8_t s_retry_cnt;
|
|
||||||
uint16_t s_time_100us;
|
|
||||||
uint8_t sl_retry_cnt;
|
|
||||||
uint16_t sl_time_100us;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ip_address {
|
|
||||||
std::array<uint8_t, 16> ip;
|
|
||||||
uint8_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix {
|
|
||||||
uint8_t len;
|
|
||||||
uint8_t flag;
|
|
||||||
uint32_t valid_lifetime;
|
|
||||||
uint32_t preferred_lifetime;
|
|
||||||
std::array<uint8_t, 16> prefix;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct arp_request {
|
|
||||||
ip_address destinfo;
|
|
||||||
std::array<uint8_t, 6> dha;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ping_request {
|
|
||||||
uint16_t id;
|
|
||||||
uint16_t seq;
|
|
||||||
ip_address destinfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_spi();
|
void init_spi();
|
||||||
void init_critical_section();
|
|
||||||
void reset();
|
void reset();
|
||||||
void init();
|
void init();
|
||||||
bool check();
|
bool check();
|
||||||
void init_net(const net_info& info);
|
|
||||||
|
|
||||||
void soft_reset();
|
extern volatile bool irq_pending;
|
||||||
int8_t init_buffers(std::span<const uint8_t> txsize, std::span<const uint8_t> rxsize);
|
|
||||||
void clear_interrupt(intr_kind intr);
|
void clear_interrupt(intr_kind intr);
|
||||||
intr_kind get_interrupt();
|
|
||||||
void set_interrupt_mask(intr_kind intr);
|
void set_interrupt_mask(intr_kind intr);
|
||||||
intr_kind get_interrupt_mask();
|
|
||||||
|
|
||||||
int8_t get_phy_link();
|
std::expected<socket_id, sock_error> open_socket(socket_id sn, protocol proto, sock_flag flag);
|
||||||
int8_t get_phy_power_mode();
|
|
||||||
void reset_phy();
|
|
||||||
void set_phy_conf(const phy_conf& conf);
|
|
||||||
phy_conf get_phy_conf();
|
|
||||||
phy_conf get_phy_status();
|
|
||||||
void set_phy_power_mode(uint8_t pmode);
|
|
||||||
|
|
||||||
void set_net_info(const net_info& info);
|
|
||||||
net_info get_net_info();
|
|
||||||
void set_net_mode(netmode_type mode);
|
|
||||||
netmode_type get_net_mode();
|
|
||||||
void set_timeout(const net_timeout& timeout);
|
|
||||||
net_timeout get_timeout();
|
|
||||||
|
|
||||||
int8_t send_arp(arp_request& arp);
|
|
||||||
int8_t send_ping(const ping_request& ping);
|
|
||||||
int8_t send_dad(std::span<const uint8_t, 16> ipv6);
|
|
||||||
int8_t send_slaac(prefix& pfx);
|
|
||||||
int8_t send_unsolicited();
|
|
||||||
int8_t get_prefix(prefix& pfx);
|
|
||||||
|
|
||||||
std::expected<socket_id, sock_error> open_socket(socket_id sn, protocol proto, port_num port, sock_flag flag);
|
|
||||||
std::expected<void, sock_error> close(socket_id sn);
|
|
||||||
std::expected<void, sock_error> listen(socket_id sn);
|
|
||||||
std::expected<void, sock_error> disconnect(socket_id sn);
|
|
||||||
std::expected<uint16_t, sock_error> send(socket_id sn, std::span<const uint8_t> buf);
|
std::expected<uint16_t, sock_error> send(socket_id sn, std::span<const uint8_t> buf);
|
||||||
std::expected<uint16_t, sock_error> recv(socket_id sn, std::span<uint8_t> buf);
|
std::expected<uint16_t, sock_error> recv(socket_id sn, std::span<uint8_t> buf);
|
||||||
|
|
||||||
std::expected<void, sock_error> connect(socket_id sn, const ip_address& addr, port_num port);
|
|
||||||
std::expected<uint16_t, sock_error> sendto(socket_id sn, std::span<const uint8_t> buf, const ip_address& addr, port_num port);
|
|
||||||
std::expected<uint16_t, sock_error> recvfrom(socket_id sn, std::span<uint8_t> buf, ip_address& addr, port_num& port);
|
|
||||||
|
|
||||||
std::expected<void, sock_error> set_socket_io_mode(socket_id sn, sock_io_mode mode);
|
|
||||||
sock_io_mode get_socket_io_mode(socket_id sn);
|
|
||||||
uint16_t get_socket_max_tx(socket_id sn);
|
|
||||||
uint16_t get_socket_max_rx(socket_id sn);
|
|
||||||
std::expected<void, sock_error> clear_socket_interrupt(socket_id sn, uint8_t flags);
|
|
||||||
uint8_t get_socket_interrupt(socket_id sn);
|
|
||||||
std::expected<void, sock_error> set_socket_interrupt_mask(socket_id sn, uint8_t mask);
|
|
||||||
uint8_t get_socket_interrupt_mask(socket_id sn);
|
|
||||||
std::expected<void, sock_error> set_socket_prefer(socket_id sn, srcv6_prefer pref);
|
|
||||||
srcv6_prefer get_socket_prefer(socket_id sn);
|
|
||||||
|
|
||||||
void set_socket_ttl(socket_id sn, uint8_t ttl);
|
|
||||||
uint8_t get_socket_ttl(socket_id sn);
|
|
||||||
void set_socket_tos(socket_id sn, uint8_t tos);
|
|
||||||
uint8_t get_socket_tos(socket_id sn);
|
|
||||||
void set_socket_mss(socket_id sn, uint16_t mss);
|
|
||||||
uint16_t get_socket_mss(socket_id sn);
|
|
||||||
void set_socket_dest_mac(socket_id sn, const std::array<uint8_t, 6>& mac);
|
|
||||||
void set_socket_dest_ip(socket_id sn, const ip_address& addr);
|
|
||||||
ip_address get_socket_dest_ip(socket_id sn);
|
|
||||||
void set_socket_dest_port(socket_id sn, port_num port);
|
|
||||||
port_num get_socket_dest_port(socket_id sn);
|
|
||||||
std::expected<void, sock_error> send_keepalive(socket_id sn);
|
|
||||||
void set_socket_keepalive_auto(socket_id sn, uint8_t interval);
|
|
||||||
uint8_t get_socket_keepalive_auto(socket_id sn);
|
|
||||||
uint16_t get_socket_send_buf(socket_id sn);
|
|
||||||
uint16_t get_socket_recv_buf(socket_id sn);
|
uint16_t get_socket_recv_buf(socket_id sn);
|
||||||
uint8_t get_socket_status(socket_id sn);
|
|
||||||
uint8_t get_socket_ext_status(socket_id sn);
|
|
||||||
uint8_t get_socket_mode(socket_id sn);
|
|
||||||
uint16_t get_socket_remain_size(socket_id sn);
|
|
||||||
pack_info get_socket_pack_info(socket_id sn);
|
|
||||||
|
|
||||||
std::optional<uint16_t> peek_socket_msg(socket_id sn, std::span<const uint8_t> submsg);
|
|
||||||
|
|
||||||
} // namespace w6300
|
} // namespace w6300
|
||||||
|
|||||||
Reference in New Issue
Block a user