Skip to content

Commit

Permalink
Move USB data to its own module
Browse files Browse the repository at this point in the history
Also introduces an RAII version of the USB lock
  • Loading branch information
sapphire-arches committed Dec 26, 2024
1 parent b0da708 commit a559514
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 57 deletions.
8 changes: 3 additions & 5 deletions src/RZA1/usb/r_usb_basic/src/driver/r_usb_hlibusbip.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
#include "RZA1/usb/userdef/r_usb_hmidi_config.h"

#include "definitions.h"
#include "deluge/io/midi/midi_device_manager.h"

#include "deluge/drivers/uart/uart.h"
#include "deluge/io/midi/midi_device_manager.h"
#include "deluge/io/midi/midi_engine.h"
#include "deluge/io/usb/usb_state.h"

#if ((USB_CFG_DTC == USB_CFG_ENABLE) || (USB_CFG_DMA == USB_CFG_ENABLE))
#include "drivers/usb/r_usb_basic/src/hw/inc/r_usb_dmac.h"
Expand Down Expand Up @@ -954,7 +954,7 @@ void usb_hstd_receive_start(usb_utr_t* ptr, uint16_t pipe)
// I now just call the PSTD one instead of this - it does the same.
/***********************************************************************************************************************
Function Name : usb_hstd_read_data
Description : Request to read data from USB FIFO, and manage the size of
Description : Request to read data from USB FIFO, and manage the size of
: the data read.
Arguments : usb_utr_t *ptr : Pointer to usb_utr_t structure.
: uint16_t pipe : Pipe number.
Expand Down Expand Up @@ -1186,8 +1186,6 @@ void usb_hstd_data_end(usb_utr_t* ptr, uint16_t pipe, uint16_t status)
}
} /* End of function usb_hstd_data_end() */

extern usb_utr_t g_usb_midi_recv_utr[][MAX_NUM_USB_MIDI_DEVICES];

// For when data has been received, as host. Hub stuff is on PIPE9
void usb_hstd_brdy_pipe_process_rohan_midi_and_hub(usb_utr_t* ptr, uint16_t bitsts)
{
Expand Down
3 changes: 1 addition & 2 deletions src/RZA1/usb/r_usb_hmidi/src/r_usb_hmidi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "deluge/deluge.h"
#include "deluge/drivers/uart/uart.h"
#include "deluge/io/usb/usb_state.h"

/******************************************************************************
Exported global variables
Expand All @@ -61,8 +62,6 @@ static void usb_hmidi_check_result(usb_utr_t* ptr, uint16_t unused, uint16_t sta
static usb_er_t usb_hhid_data_trans(usb_utr_t* ptr, uint16_t pipe, uint32_t size, uint8_t* table, usb_cb_t complete);
static void usb_hmidi_enumeration_sequence(usb_utr_t* mess);

extern uint8_t currentDeviceNumWithSendPipe[];

/******************************************************************************
Exported global variables (to be accessed by other files)
******************************************************************************/
Expand Down
29 changes: 14 additions & 15 deletions src/deluge/deluge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "RZA1/sdhi/inc/sdif.h"
#include "definitions_cxx.hpp"
#include "deluge/io/usb//usb_state.h"
#include "drivers/pic/pic.h"
#include "gui/ui/audio_recorder.h"
#include "gui/ui/browser/browser.h"
Expand Down Expand Up @@ -549,8 +550,6 @@ void setupOLED() {
extern "C" void usb_pstd_pcd_task(void);
extern "C" void usb_cstd_usb_task(void);

extern "C" volatile uint32_t usbLock;

extern "C" void usb_main_host(void);

void registerTasks() {
Expand Down Expand Up @@ -843,21 +842,21 @@ extern "C" int32_t deluge_main(void) {
deluge::hid::display::swapDisplayType();
}

usbLock = 1;
openUSBHost();

// If nothing was plugged in to us as host, we'll go peripheral
// Ideally I'd like to repeatedly switch between host and peripheral mode anytime there's no USB connection.
// To do that, I'd really need to know at any point in time whether the user had just made a connection, just then,
// that hadn't fully initialized yet. I think I sorta have that for host, but not for peripheral yet.
if (!anythingInitiallyAttachedAsUSBHost) {
D_PRINTLN("switching from host to peripheral");
closeUSBHost();
openUSBPeripheral();
{
deluge::io::usb::USBAutoLock lock;
openUSBHost();

// If nothing was plugged in to us as host, we'll go peripheral
// Ideally I'd like to repeatedly switch between host and peripheral mode anytime there's no USB connection.
// To do that, I'd really need to know at any point in time whether the user had just made a connection, just
// then, that hadn't fully initialized yet. I think I sorta have that for host, but not for peripheral yet.
if (!anythingInitiallyAttachedAsUSBHost) {
D_PRINTLN("switching from host to peripheral");
closeUSBHost();
openUSBPeripheral();
}
}

usbLock = 0;

// Hopefully we can read these files now
runtimeFeatureSettings.readSettingsFromFile();
MIDIDeviceManager::readDevicesFromFile();
Expand Down
7 changes: 4 additions & 3 deletions src/deluge/io/midi/midi_device_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,18 @@
#include "io/midi/device_specific/specific_midi_device.h"
#include "io/midi/midi_device.h"
#include "io/midi/midi_engine.h"
#include "io/usb/usb_state.h"
#include "mem_functions.h"
#include "memory/general_memory_allocator.h"
#include "storage/storage_manager.h"
#include "util/container/vector/named_thing_vector.h"
#include "util/misc.h"

using namespace deluge::io::usb;

extern "C" {
#include "RZA1/usb/r_usb_basic/src/driver/inc/r_usb_basic_define.h"
#include "drivers/uart/uart.h"

extern uint8_t anyUSBSendingStillHappening[];
}
#pragma GCC diagnostic push
// This is supported by GCC and other compilers should error (not warn), so turn off for this file
Expand Down Expand Up @@ -636,7 +637,7 @@ void ConnectedUSBMIDIDevice::bufferMessage(uint32_t fullMessage) {
sendDataRingBuf[ringBufWriteIdx & MIDI_SEND_RING_MASK] = fullMessage;
ringBufWriteIdx++;

anythingInUSBOutputBuffer = true;
deluge::io::usb::anythingInUSBOutputBuffer = true;
}

bool ConnectedUSBMIDIDevice::hasBufferedSendData() {
Expand Down
41 changes: 10 additions & 31 deletions src/deluge/io/midi/midi_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "io/midi/midi_engine.h"
#include "definitions_cxx.hpp"
#include "deluge/io/usb/usb_state.h"
#include "gui/l10n/l10n.h"
#include "gui/ui/sound_editor.h"
#include "hid/display/display.h"
Expand All @@ -32,10 +33,11 @@
#include "storage/smsysex.h"
#include "version.h"

using namespace deluge::io::usb;

extern "C" {
#include "RZA1/uart/sio_char.h"

volatile uint32_t usbLock = 0;
void usb_cstd_usb_task();

#include "RZA1/system/iodefine.h"
Expand All @@ -46,19 +48,6 @@ void usb_cstd_usb_task();
#include "RZA1/usb/r_usb_hmidi/src/inc/r_usb_hmidi.h"
#include "RZA1/usb/userdef/r_usb_hmidi_config.h"

extern uint16_t g_usb_peri_connected;

uint8_t stopSendingAfterDeviceNum[USB_NUM_USBIP];
uint8_t usbDeviceNumBeingSentToNow[USB_NUM_USBIP];
uint8_t anyUSBSendingStillHappening[USB_NUM_USBIP];

usb_utr_t g_usb_midi_send_utr[USB_NUM_USBIP];
usb_utr_t g_usb_midi_recv_utr[USB_NUM_USBIP][MAX_NUM_USB_MIDI_DEVICES];

extern uint16_t g_usb_hmidi_tmp_ep_tbl[USB_NUM_USBIP][MAX_NUM_USB_MIDI_DEVICES][(USB_EPL * 2) + 1];

extern usb_utr_t* g_p_usb_pipe[USB_MAX_PIPE_NO + 1u];

usb_regadr_t usb_hstd_get_usb_ip_adr(uint16_t ipno);
void change_destination_of_send_pipe(usb_utr_t* ptr, uint16_t pipe, uint16_t* tbl, int32_t sq);
void usb_send_start_rohan(usb_utr_t* ptr, uint16_t pipe, uint8_t const* data, int32_t size);
Expand All @@ -70,9 +59,6 @@ uint16_t hw_usb_read_pipectr(usb_utr_t* ptr, uint16_t pipeno);

void flushUSBMIDIToHostedDevice(int32_t ip, int32_t d, bool resume = false);

uint8_t currentDeviceNumWithSendPipe[USB_NUM_USBIP][2] = {
MAX_NUM_USB_MIDI_DEVICES, MAX_NUM_USB_MIDI_DEVICES}; // One without, and one with, interrupt endpoints

// We now bypass calling this for successful as peripheral on A1 (see usb_pstd_bemp_pipe_process_rohan_midi())
void usbSendCompleteAsHost(int32_t ip) {

Expand Down Expand Up @@ -211,8 +197,6 @@ void brdyOccurred(int32_t ip) {

MidiEngine midiEngine{};

bool anythingInUSBOutputBuffer = false;

MidiEngine::MidiEngine() {
numSerialMidiInput = 0;
currentlyReceivingSysExSerial = false;
Expand Down Expand Up @@ -273,8 +257,8 @@ void flushUSBMIDIToHostedDevice(int32_t ip, int32_t d, bool resume) {

int32_t isInterrupt = (pipeNumber == USB_CFG_HMIDI_INT_SEND);

if (d != currentDeviceNumWithSendPipe[USB_CFG_USE_USBIP][isInterrupt]) {
currentDeviceNumWithSendPipe[USB_CFG_USE_USBIP][isInterrupt] = d;
if (d != currentDeviceNumWithSendPipe[isInterrupt]) {
currentDeviceNumWithSendPipe[isInterrupt] = d;
change_destination_of_send_pipe(&g_usb_midi_send_utr[USB_CFG_USE_USBIP], pipeNumber,
g_usb_hmidi_tmp_ep_tbl[USB_CFG_USE_USBIP][d], connectedDevice->sq);
}
Expand Down Expand Up @@ -305,7 +289,7 @@ void MidiEngine::flushUSBMIDIOutput() {
// is this still relevant? anyUSBSendingStillHappening[ip] acts as the lock between routine and interrupt
// on the sending side. all other uses of usbLock seems to be about _receiving_. Can there be a conflict
// between sending and receiving as well??
usbLock = 1;
USBAutoLock lock;

for (int32_t ip = 0; ip < USB_NUM_USBIP; ip++) {
if (anyUSBSendingStillHappening[ip]) {
Expand Down Expand Up @@ -342,7 +326,7 @@ void MidiEngine::flushUSBMIDIOutput() {
// This next bit was written with multiple devices on hubs in mind, but seems to work for a single MIDI
// device too

int32_t midiDeviceNumToSendTo = currentDeviceNumWithSendPipe[ip][0]; // This will do
int32_t midiDeviceNumToSendTo = currentDeviceNumWithSendPipe[0]; // This will do
if (midiDeviceNumToSendTo >= MAX_NUM_USB_MIDI_DEVICES) {
midiDeviceNumToSendTo = 0; // In case it was set to "none", I think
}
Expand Down Expand Up @@ -405,8 +389,6 @@ void MidiEngine::flushUSBMIDIOutput() {
}
getOut: {}
}

usbLock = 0;
}

bool MidiEngine::anythingInOutputBuffer() {
Expand Down Expand Up @@ -760,9 +742,8 @@ void MidiEngine::checkIncomingUsbMidi() {

if (!usbLockNow) {
// Have to call this regularly, to do "callbacks" that will grab out the received data
usbLock = 1;
USBAutoLock lock;
usb_cstd_usb_task();
usbLock = 0;
}

for (int32_t ip = 0; ip < USB_NUM_USBIP; ip++) {
Expand Down Expand Up @@ -827,10 +808,9 @@ void MidiEngine::checkIncomingUsbMidi() {

connectedUSBMIDIDevices[ip][0].currentlyWaitingToReceive = 1;

usbLock = 1;
USBAutoLock lock;
g_p_usb_pipe[USB_CFG_PMIDI_BULK_IN] = &g_usb_midi_recv_utr[ip][0];
usb_receive_start_rohan_midi(USB_CFG_PMIDI_BULK_IN);
usbLock = 0;
}

// Or as host
Expand All @@ -839,9 +819,8 @@ void MidiEngine::checkIncomingUsbMidi() {
// Only allowed to setup receive-transfer if not in the process of sending to various devices.
// (Wait, still? Was this just because of that insane bug that's now fixed?)
if (usbDeviceNumBeingSentToNow[ip] == stopSendingAfterDeviceNum[ip]) {
usbLock = 1;
USBAutoLock lock;
setupUSBHostReceiveTransfer(ip, d);
usbLock = 0;
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/deluge/io/midi/midi_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ class MidiEngine {
uint32_t setupUSBMessage(MIDIMessage message);

extern MidiEngine midiEngine;
extern bool anythingInUSBOutputBuffer;

extern "C" {
#endif
Expand Down
35 changes: 35 additions & 0 deletions src/deluge/io/usb/usb_state.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright © 2024 Synthstrom Audible Limited
*
* This file is part of The Synthstrom Audible Deluge Firmware.
*
* The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/

#include "usb_state.h"

namespace deluge::io::usb {
volatile bool usbLock;
bool anythingInUSBOutputBuffer;

uint8_t stopSendingAfterDeviceNum[USB_NUM_USBIP];
uint8_t usbDeviceNumBeingSentToNow[USB_NUM_USBIP];
uint8_t anyUSBSendingStillHappening[USB_NUM_USBIP];

} // namespace deluge::io::usb
extern "C" {

usb_utr_t g_usb_midi_send_utr[USB_NUM_USBIP];
usb_utr_t g_usb_midi_recv_utr[USB_NUM_USBIP][MAX_NUM_USB_MIDI_DEVICES];

uint8_t currentDeviceNumWithSendPipe[2] = {MAX_NUM_USB_MIDI_DEVICES, MAX_NUM_USB_MIDI_DEVICES};
}
76 changes: 76 additions & 0 deletions src/deluge/io/usb/usb_state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright © 2024 Synthstrom Audible Limited
*
* This file is part of The Synthstrom Audible Deluge Firmware.
*
* The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/

#include "RZA1/usb/r_usb_basic/r_usb_basic_if.h"
#include "definitions.h"

#ifdef __cplusplus

namespace deluge::io::usb {

/// When true, something is using the low-level USB structures.
///
/// XXX: this is super ill-defined and seems to mostly exist to avoid reentrant ISR problems
extern volatile bool usbLock;

/// RAII lock control for the USB lock
class USBAutoLock {
public:
USBAutoLock() { usbLock = true; }
~USBAutoLock() { usbLock = false; }

USBAutoLock(const USBAutoLock&) = delete;
USBAutoLock(USBAutoLock&&) = delete;
USBAutoLock& operator=(const USBAutoLock&) = delete;
USBAutoLock& operator=(USBAutoLock&&) = delete;
};

/// When true, some data is queued to the USB output buffer.
extern bool anythingInUSBOutputBuffer;

/// Last device to send to
extern uint8_t stopSendingAfterDeviceNum[USB_NUM_USBIP];

/// Current hosted device number, used in host send completion callback
extern uint8_t usbDeviceNumBeingSentToNow[USB_NUM_USBIP];

/// Flag to prevent reentrant sending
extern uint8_t anyUSBSendingStillHappening[USB_NUM_USBIP];

} // namespace deluge::io::usb

extern "C" {
#endif

// defined in r_usb_pdriver.c
extern uint16_t g_usb_peri_connected;

// defined in r_usb_cdataio.c
extern usb_utr_t* g_p_usb_pipe[USB_MAX_PIPE_NO + 1u];

extern usb_utr_t g_usb_midi_send_utr[USB_NUM_USBIP];
extern usb_utr_t g_usb_midi_recv_utr[USB_NUM_USBIP][MAX_NUM_USB_MIDI_DEVICES];

// defined in r_usb_hmidi_driver.c
extern uint16_t g_usb_hmidi_tmp_ep_tbl[USB_NUM_USBIP][MAX_NUM_USB_MIDI_DEVICES][(USB_EPL * 2) + 1];

// One without, and one with, interrupt endpoints
extern uint8_t currentDeviceNumWithSendPipe[2];

#ifdef __cplusplus
}
#endif

0 comments on commit a559514

Please sign in to comment.