From c3d5e16ee1d7432b790673ceae5693787f098c98 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Sat, 25 Feb 2023 22:46:53 +0000 Subject: [PATCH 1/4] pico: start separating multiplayer code from device cdc --- 32blit-pico/usb_device.cpp | 53 ++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/32blit-pico/usb_device.cpp b/32blit-pico/usb_device.cpp index cc96ebbec..3b14e912b 100644 --- a/32blit-pico/usb_device.cpp +++ b/32blit-pico/usb_device.cpp @@ -98,32 +98,49 @@ bool tud_msc_is_writable_cb(uint8_t lun) { static bool multiplayer_enabled = false; static bool peer_connected = false; -static char cur_header[8]; +static uint8_t cur_header[8]; static int header_pos = 0; static uint16_t mp_buffer_len, mp_buffer_off; static uint8_t *mp_buffer = nullptr; -static void send_all(const void *buffer, uint32_t len) { - uint32_t done = tud_cdc_write(buffer, len); +bool usb_cdc_connected() { + // tud_cdc_connected returns false with STM32 USB host + return tud_ready(); //tud_cdc_connected(); +} + +uint16_t usb_cdc_read(uint8_t *data, uint16_t len) { + return tud_cdc_read(data, len); +} + +uint32_t usb_cdc_read_available() { + return tud_cdc_available(); +} + +void usb_cdc_write(const uint8_t *data, uint16_t len) { + uint32_t done = tud_cdc_write(data, len); while(done < len) { tud_task(); if(!tud_ready()) break; - done += tud_cdc_write((const char *)buffer + done, len - done); + done += tud_cdc_write(data + done, len - done); } } +void usb_cdc_flush_write() { + tud_cdc_write_flush(); +} + static void send_handshake(bool is_reply = false) { uint8_t val = 0; if(multiplayer_enabled) val = is_reply ? 2 : 1; uint8_t buf[]{'3', '2', 'B', 'L', 'M', 'L', 'T','I', val}; - send_all(buf, 9); - tud_cdc_write_flush(); + usb_cdc_write(buf, 9); + usb_cdc_flush_write(); } void init_usb() { @@ -133,14 +150,14 @@ void init_usb() { void update_usb() { tud_task(); - if(!tud_ready()) { // tud_cdc_connected returns false with STM USB host + if(!usb_cdc_connected()) { // tud_cdc_connected returns false with STM USB host peer_connected = false; } - while(tud_cdc_available()) { + while(usb_cdc_read_available()) { // match header if(header_pos < 8) { - cur_header[header_pos] = tud_cdc_read_char(); + usb_cdc_read(cur_header + header_pos, 1); const char *expected = "32BL"; if(header_pos >= 4 || cur_header[header_pos] == expected[header_pos]) @@ -151,7 +168,7 @@ void update_usb() { // get USER packet if(mp_buffer) { - mp_buffer_off += tud_cdc_read(mp_buffer + mp_buffer_off, mp_buffer_len - mp_buffer_off); + mp_buffer_off += usb_cdc_read(mp_buffer + mp_buffer_off, mp_buffer_len - mp_buffer_off); if(mp_buffer_off == mp_buffer_len) { if(blit::api.message_received) @@ -167,7 +184,9 @@ void update_usb() { // got header if(memcmp(cur_header + 4, "MLTI", 4) == 0) { // handshake packet - peer_connected = tud_cdc_read_char() != 0; + uint8_t b; + usb_cdc_read(&b, 1); + peer_connected = b != 0; if(peer_connected) send_handshake(true); @@ -175,10 +194,10 @@ void update_usb() { // done header_pos = 0; } else if(memcmp(cur_header + 4, "USER", 4) == 0) { - if(tud_cdc_available() < 2) + if(usb_cdc_read_available() < 2) break; - tud_cdc_read(&mp_buffer_len, 2); + usb_cdc_read((uint8_t *)&mp_buffer_len, 2); mp_buffer_off = 0; mp_buffer = new uint8_t[mp_buffer_len]; @@ -195,7 +214,7 @@ void usb_debug(const char *message) { return; auto len = strlen(message); - send_all(message, len); + usb_cdc_write((uint8_t *)message, len); } bool is_multiplayer_connected() { @@ -216,9 +235,9 @@ void send_multiplayer_message(const uint8_t *data, uint16_t len) { uint8_t buf[]{'3', '2', 'B', 'L', 'U', 'S', 'E','R', uint8_t(len & 0xFF), uint8_t(len >> 8) }; - send_all(buf, 10); + usb_cdc_write(buf, 10); - send_all((uint8_t *)data, len); + usb_cdc_write((uint8_t *)data, len); - tud_cdc_write_flush(); + usb_cdc_flush_write(); } From dba448a1c6e776d704fb299647786a30cef20478 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Sat, 25 Feb 2023 23:11:13 +0000 Subject: [PATCH 2/4] pico: split multiplayer from usb_device Replacing the multiplayer stubs in usb_host with cdc stubs --- 32blit-pico/CMakeLists.txt | 1 + 32blit-pico/main.cpp | 2 + 32blit-pico/multiplayer.cpp | 110 ++++++++++++++++++++++++++++++ 32blit-pico/multiplayer.hpp | 8 +++ 32blit-pico/usb.hpp | 9 +-- 32blit-pico/usb_device.cpp | 132 ++++-------------------------------- 32blit-pico/usb_host.cpp | 16 +++-- 7 files changed, 150 insertions(+), 128 deletions(-) create mode 100644 32blit-pico/multiplayer.cpp create mode 100644 32blit-pico/multiplayer.hpp diff --git a/32blit-pico/CMakeLists.txt b/32blit-pico/CMakeLists.txt index a6b6965fa..6aaf8bf64 100644 --- a/32blit-pico/CMakeLists.txt +++ b/32blit-pico/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources(BlitHalPico INTERFACE ${CMAKE_CURRENT_LIST_DIR}/led.cpp ${CMAKE_CURRENT_LIST_DIR}/main.cpp ${CMAKE_CURRENT_LIST_DIR}/storage.cpp + ${CMAKE_CURRENT_LIST_DIR}/multiplayer.cpp ${CMAKE_CURRENT_LIST_DIR}/st7789.cpp ${CMAKE_CURRENT_LIST_DIR}/usb_descriptors.c ) diff --git a/32blit-pico/main.cpp b/32blit-pico/main.cpp index 867302419..32b2eb1b6 100644 --- a/32blit-pico/main.cpp +++ b/32blit-pico/main.cpp @@ -14,6 +14,7 @@ #include "file.hpp" #include "input.hpp" #include "led.hpp" +#include "multiplayer.hpp" #include "usb.hpp" #include "engine/api_private.hpp" @@ -205,6 +206,7 @@ int main() { update_audio(now); update_led(); update_usb(); + update_multiplayer(); if(ms_to_next_update > 1 && !display_render_needed()) best_effort_wfe_or_timeout(make_timeout_time_ms(ms_to_next_update - 1)); diff --git a/32blit-pico/multiplayer.cpp b/32blit-pico/multiplayer.cpp new file mode 100644 index 000000000..57b559f0f --- /dev/null +++ b/32blit-pico/multiplayer.cpp @@ -0,0 +1,110 @@ +#include +#include "multiplayer.hpp" + +#include "usb.hpp" + +#include "engine/api_private.hpp" + +static bool multiplayer_enabled = false; +static bool peer_connected = false; + +static uint8_t cur_header[8]; +static int header_pos = 0; + +static uint16_t mp_buffer_len, mp_buffer_off; +static uint8_t *mp_buffer = nullptr; + +static void send_handshake(bool is_reply = false) { + uint8_t val = 0; + if(multiplayer_enabled) + val = is_reply ? 2 : 1; + + uint8_t buf[]{'3', '2', 'B', 'L', 'M', 'L', 'T','I', val}; + usb_cdc_write(buf, 9); + usb_cdc_flush_write(); +} + +void update_multiplayer() { + if(!usb_cdc_connected()) { + peer_connected = false; + } + + while(usb_cdc_read_available()) { + // match header + if(header_pos < 8) { + usb_cdc_read(cur_header + header_pos, 1); + + const char *expected = "32BL"; + if(header_pos >= 4 || cur_header[header_pos] == expected[header_pos]) + header_pos++; + else + header_pos = 0; + } else { + + // get USER packet + if(mp_buffer) { + mp_buffer_off += usb_cdc_read(mp_buffer + mp_buffer_off, mp_buffer_len - mp_buffer_off); + + if(mp_buffer_off == mp_buffer_len) { + if(blit::api.message_received) + blit::api.message_received(mp_buffer, mp_buffer_len); + + delete[] mp_buffer; + mp_buffer = nullptr; + header_pos = 0; + } + continue; + } + + // got header + if(memcmp(cur_header + 4, "MLTI", 4) == 0) { + // handshake packet + uint8_t b; + usb_cdc_read(&b, 1); + peer_connected = b != 0; + + if(peer_connected) + send_handshake(true); + + // done + header_pos = 0; + } else if(memcmp(cur_header + 4, "USER", 4) == 0) { + if(usb_cdc_read_available() < 2) + break; + + usb_cdc_read((uint8_t *)&mp_buffer_len, 2); + mp_buffer_off = 0; + mp_buffer = new uint8_t[mp_buffer_len]; + + } else { + printf("got: %c%c%c%c%c%c%c%c\n", cur_header[0], cur_header[1], cur_header[2], cur_header[3], cur_header[4], cur_header[5], cur_header[6], cur_header[7]); + header_pos = 0; + } + } + } +} + +bool is_multiplayer_connected() { + return multiplayer_enabled && peer_connected; +} + +void set_multiplayer_enabled(bool enabled) { + multiplayer_enabled = enabled; + + if(!enabled) + send_handshake(); +} + +void send_multiplayer_message(const uint8_t *data, uint16_t len) { + if(!peer_connected) + return; + + uint8_t buf[]{'3', '2', 'B', 'L', 'U', 'S', 'E','R', + uint8_t(len & 0xFF), uint8_t(len >> 8) + }; + usb_cdc_write(buf, 10); + + usb_cdc_write((uint8_t *)data, len); + + usb_cdc_flush_write(); +} diff --git a/32blit-pico/multiplayer.hpp b/32blit-pico/multiplayer.hpp new file mode 100644 index 000000000..90db7108b --- /dev/null +++ b/32blit-pico/multiplayer.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +void update_multiplayer(); + +bool is_multiplayer_connected(); +void set_multiplayer_enabled(bool enabled); +void send_multiplayer_message(const uint8_t *data, uint16_t len); diff --git a/32blit-pico/usb.hpp b/32blit-pico/usb.hpp index 477897204..59e7016ef 100644 --- a/32blit-pico/usb.hpp +++ b/32blit-pico/usb.hpp @@ -7,7 +7,8 @@ void update_usb(); void usb_debug(const char *message); -// TODO: separate multiplayer from usb -bool is_multiplayer_connected(); -void set_multiplayer_enabled(bool enabled); -void send_multiplayer_message(const uint8_t *data, uint16_t len); +bool usb_cdc_connected(); +uint16_t usb_cdc_read(uint8_t *data, uint16_t len); +uint32_t usb_cdc_read_available(); +void usb_cdc_write(const uint8_t *data, uint16_t len); +void usb_cdc_flush_write(); diff --git a/32blit-pico/usb_device.cpp b/32blit-pico/usb_device.cpp index 3b14e912b..1df405c5d 100644 --- a/32blit-pico/usb_device.cpp +++ b/32blit-pico/usb_device.cpp @@ -1,15 +1,11 @@ #include "usb.hpp" -#include - #include "tusb.h" #include "config.h" #include "file.hpp" #include "storage.hpp" -#include "engine/api_private.hpp" - // msc static bool storage_ejected = false; @@ -95,14 +91,21 @@ bool tud_msc_is_writable_cb(uint8_t lun) { } // cdc -static bool multiplayer_enabled = false; -static bool peer_connected = false; +void init_usb() { + tusb_init(); +} -static uint8_t cur_header[8]; -static int header_pos = 0; +void update_usb() { + tud_task(); +} -static uint16_t mp_buffer_len, mp_buffer_off; -static uint8_t *mp_buffer = nullptr; +void usb_debug(const char *message) { + if(!tud_cdc_connected()) + return; + + auto len = strlen(message); + usb_cdc_write((uint8_t *)message, len); +} bool usb_cdc_connected() { // tud_cdc_connected returns false with STM32 USB host @@ -132,112 +135,3 @@ void usb_cdc_write(const uint8_t *data, uint16_t len) { void usb_cdc_flush_write() { tud_cdc_write_flush(); } - -static void send_handshake(bool is_reply = false) { - uint8_t val = 0; - if(multiplayer_enabled) - val = is_reply ? 2 : 1; - - uint8_t buf[]{'3', '2', 'B', 'L', 'M', 'L', 'T','I', val}; - usb_cdc_write(buf, 9); - usb_cdc_flush_write(); -} - -void init_usb() { - tusb_init(); -} - -void update_usb() { - tud_task(); - - if(!usb_cdc_connected()) { // tud_cdc_connected returns false with STM USB host - peer_connected = false; - } - - while(usb_cdc_read_available()) { - // match header - if(header_pos < 8) { - usb_cdc_read(cur_header + header_pos, 1); - - const char *expected = "32BL"; - if(header_pos >= 4 || cur_header[header_pos] == expected[header_pos]) - header_pos++; - else - header_pos = 0; - } else { - - // get USER packet - if(mp_buffer) { - mp_buffer_off += usb_cdc_read(mp_buffer + mp_buffer_off, mp_buffer_len - mp_buffer_off); - - if(mp_buffer_off == mp_buffer_len) { - if(blit::api.message_received) - blit::api.message_received(mp_buffer, mp_buffer_len); - - delete[] mp_buffer; - mp_buffer = nullptr; - header_pos = 0; - } - continue; - } - - // got header - if(memcmp(cur_header + 4, "MLTI", 4) == 0) { - // handshake packet - uint8_t b; - usb_cdc_read(&b, 1); - peer_connected = b != 0; - - if(peer_connected) - send_handshake(true); - - // done - header_pos = 0; - } else if(memcmp(cur_header + 4, "USER", 4) == 0) { - if(usb_cdc_read_available() < 2) - break; - - usb_cdc_read((uint8_t *)&mp_buffer_len, 2); - mp_buffer_off = 0; - mp_buffer = new uint8_t[mp_buffer_len]; - - } else { - printf("got: %c%c%c%c%c%c%c%c\n", cur_header[0], cur_header[1], cur_header[2], cur_header[3], cur_header[4], cur_header[5], cur_header[6], cur_header[7]); - header_pos = 0; - } - } - } -} - -void usb_debug(const char *message) { - if(!tud_cdc_connected()) - return; - - auto len = strlen(message); - usb_cdc_write((uint8_t *)message, len); -} - -bool is_multiplayer_connected() { - return multiplayer_enabled && peer_connected; -} - -void set_multiplayer_enabled(bool enabled) { - multiplayer_enabled = enabled; - - if(!enabled) - send_handshake(); -} - -void send_multiplayer_message(const uint8_t *data, uint16_t len) { - if(!peer_connected) - return; - - uint8_t buf[]{'3', '2', 'B', 'L', 'U', 'S', 'E','R', - uint8_t(len & 0xFF), uint8_t(len >> 8) - }; - usb_cdc_write(buf, 10); - - usb_cdc_write((uint8_t *)data, len); - - usb_cdc_flush_write(); -} diff --git a/32blit-pico/usb_host.cpp b/32blit-pico/usb_host.cpp index 585d6d486..b115c451d 100644 --- a/32blit-pico/usb_host.cpp +++ b/32blit-pico/usb_host.cpp @@ -171,14 +171,20 @@ void usb_debug(const char *message) { } -// multiplayer could be supported with USB host, but we'd need a hub -// (host code is used for hid) -bool is_multiplayer_connected() { +bool usb_cdc_connected() { return false; } -void set_multiplayer_enabled(bool enabled) { +uint16_t usb_cdc_read(uint8_t *data, uint16_t len) { + return 0; } -void send_multiplayer_message(const uint8_t *data, uint16_t len) { +uint32_t usb_cdc_read_available() { + return 0; +} + +void usb_cdc_write(const uint8_t *data, uint16_t len) { +} + +void usb_cdc_flush_write() { } From f4059a0df213bf6103081569a971d4904003f9a5 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Sat, 25 Feb 2023 23:23:53 +0000 Subject: [PATCH 3/4] pico: export multiplayer send_handshake --- 32blit-pico/multiplayer.cpp | 6 +++--- 32blit-pico/multiplayer.hpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/32blit-pico/multiplayer.cpp b/32blit-pico/multiplayer.cpp index 57b559f0f..3def9e473 100644 --- a/32blit-pico/multiplayer.cpp +++ b/32blit-pico/multiplayer.cpp @@ -14,7 +14,7 @@ static int header_pos = 0; static uint16_t mp_buffer_len, mp_buffer_off; static uint8_t *mp_buffer = nullptr; -static void send_handshake(bool is_reply = false) { +void send_multiplayer_handshake(bool is_reply) { uint8_t val = 0; if(multiplayer_enabled) val = is_reply ? 2 : 1; @@ -64,7 +64,7 @@ void update_multiplayer() { peer_connected = b != 0; if(peer_connected) - send_handshake(true); + send_multiplayer_handshake(true); // done header_pos = 0; @@ -92,7 +92,7 @@ void set_multiplayer_enabled(bool enabled) { multiplayer_enabled = enabled; if(!enabled) - send_handshake(); + send_multiplayer_handshake(); } void send_multiplayer_message(const uint8_t *data, uint16_t len) { diff --git a/32blit-pico/multiplayer.hpp b/32blit-pico/multiplayer.hpp index 90db7108b..af6639ef6 100644 --- a/32blit-pico/multiplayer.hpp +++ b/32blit-pico/multiplayer.hpp @@ -2,6 +2,7 @@ #include void update_multiplayer(); +void send_multiplayer_handshake(bool is_reply = false); bool is_multiplayer_connected(); void set_multiplayer_enabled(bool enabled); From 9c844572308057788e7077b3552b333059640bdb Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Sat, 25 Feb 2023 23:24:40 +0000 Subject: [PATCH 4/4] pico: host cdc/multiplayer --- 32blit-pico/tusb_config.h | 2 +- 32blit-pico/usb_host.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/32blit-pico/tusb_config.h b/32blit-pico/tusb_config.h index 162717ffa..55d4f47a9 100644 --- a/32blit-pico/tusb_config.h +++ b/32blit-pico/tusb_config.h @@ -107,7 +107,7 @@ #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 0 -#define CFG_TUH_CDC 0 +#define CFG_TUH_CDC 1 #ifdef INPUT_USB_HID #define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces #else diff --git a/32blit-pico/usb_host.cpp b/32blit-pico/usb_host.cpp index b115c451d..1d78b62bd 100644 --- a/32blit-pico/usb_host.cpp +++ b/32blit-pico/usb_host.cpp @@ -1,6 +1,6 @@ #include "usb.hpp" -#include +#include "multiplayer.hpp" #include "tusb.h" @@ -159,12 +159,23 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons } #endif +// cdc +static uint8_t cdc_index = 0; // TODO: multiple devices? + +void tuh_cdc_mount_cb(uint8_t idx) { + cdc_index = idx; + + send_multiplayer_handshake(); +} + void init_usb() { tusb_init(); } void update_usb() { tuh_task(); + + // TODO: resend multiplayer handshake } void usb_debug(const char *message) { @@ -172,19 +183,29 @@ void usb_debug(const char *message) { } bool usb_cdc_connected() { - return false; + return tuh_cdc_mounted(cdc_index); } uint16_t usb_cdc_read(uint8_t *data, uint16_t len) { - return 0; + return tuh_cdc_read(cdc_index, data, len); } uint32_t usb_cdc_read_available() { - return 0; + return tuh_cdc_read_available(cdc_index); } void usb_cdc_write(const uint8_t *data, uint16_t len) { + uint32_t done = tuh_cdc_write(cdc_index,data, len); + + while(done < len) { + tuh_task(); + if(!tuh_cdc_mounted(cdc_index)) + break; + + done += tuh_cdc_write(cdc_index, data + done, len - done); + } } void usb_cdc_flush_write() { + tuh_cdc_write_flush(cdc_index); }