Skip to content

Commit

Permalink
Hacked in 1p and 4p variants of host
Browse files Browse the repository at this point in the history
  • Loading branch information
Tails86 committed Feb 5, 2024
1 parent 6ab8811 commit 4688cdd
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 87 deletions.
6 changes: 6 additions & 0 deletions inc/hal/Usb/client_usb_interface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <stdint.h>

extern "C" {
void set_usb_descriptor_number_of_gamepads(uint8_t num);
uint8_t get_usb_descriptor_number_of_gamepads();
}
7 changes: 6 additions & 1 deletion src/hal/Usb/Client/Hid/UsbGamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class UsbGamepad : public UsbControllerDevice
//! @param[in] reqlen The length of buffer
uint16_t getReport(uint8_t *buffer, uint16_t reqlen) final;

inline void setInterfaceId(uint8_t id)
{
interfaceId = id;
}

protected:
//! @returns the hat value based on current dpad state
uint8_t getHatValue();
Expand All @@ -128,7 +133,7 @@ class UsbGamepad : public UsbControllerDevice
static const int8_t ANALOG_PRESSED_TOL = 5;

private:
const uint8_t interfaceId;
uint8_t interfaceId;
//! The report ID to use when sending keys to host
const uint8_t reportId;
//! Current left analog states (x,y,z)
Expand Down
151 changes: 98 additions & 53 deletions src/hal/Usb/Client/Hid/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@
#include "configuration.h"
#include <string.h>

static uint8_t numberOfGamepads = NUMBER_OF_GAMEPADS;

void set_usb_descriptor_number_of_gamepads(uint8_t num)
{
if (num > NUMBER_OF_GAMEPADS)
{
num = NUMBER_OF_GAMEPADS;
}
numberOfGamepads = num;
}

uint8_t get_usb_descriptor_number_of_gamepads()
{
return numberOfGamepads;
}

#undef TUD_HID_REPORT_DESC_GAMEPAD

// Tweak the gamepad descriptor so that the minimum value on analog controls is -128 instead of -127
Expand Down Expand Up @@ -111,22 +127,7 @@ uint8_t const *tud_descriptor_device_cb(void) {
// HID Report Descriptor
//--------------------------------------------------------------------+

uint8_t const desc_hid_report1[] =
{
TUD_HID_REPORT_DESC_GAMEPAD()
};

uint8_t const desc_hid_report2[] =
{
TUD_HID_REPORT_DESC_GAMEPAD()
};

uint8_t const desc_hid_report3[] =
{
TUD_HID_REPORT_DESC_GAMEPAD()
};

uint8_t const desc_hid_report4[] =
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_GAMEPAD()
};
Expand All @@ -136,19 +137,15 @@ uint8_t const desc_hid_report4[] =
// Descriptor contents must exist long enough for transfer to complete
uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance)
{
switch (instance)
for (uint8_t i = 0; i < numberOfGamepads; ++i)
{
case ITF_NUM_GAMEPAD1:
return desc_hid_report1;
case ITF_NUM_GAMEPAD2:
return desc_hid_report2;
case ITF_NUM_GAMEPAD3:
return desc_hid_report3;
case ITF_NUM_GAMEPAD4:
return desc_hid_report4;
default:
return NULL;
if (instance == ITF_NUM_GAMEPAD(numberOfGamepads, i))
{
return desc_hid_report;
}
}

return NULL;
}

//--------------------------------------------------------------------+
Expand All @@ -161,7 +158,7 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance)
#define DEBUG_CONFIG_LEN 0
#endif

#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + (NUMBER_OF_GAMEPADS * TUD_HID_DESC_LEN) + DEBUG_CONFIG_LEN + TUD_MSC_DESC_LEN)
#define GET_CONFIG_LEN(numGamepads) (TUD_CONFIG_DESC_LEN + (numGamepads * TUD_HID_DESC_LEN) + DEBUG_CONFIG_LEN + TUD_MSC_DESC_LEN)

// Endpoint definitions (must all be unique)
#define EPIN_GAMEPAD1 (0x84)
Expand All @@ -174,49 +171,58 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance)
#define EPOUT_CDC (0x07)
#define EPIN_CDC (0x87)

#define PLAYER_TO_STR_IDX(player) (player + 4)

uint8_t player_to_epin(uint8_t player)
{
switch (player)
{
case 0: return EPIN_GAMEPAD1;
case 1: return EPIN_GAMEPAD2;
case 2: return EPIN_GAMEPAD3;
default:
case 3: return EPIN_GAMEPAD4;
}
}

#define GAMEPAD_REPORT_SIZE (1 + sizeof(hid_gamepad_report_t))

uint8_t const desc_configuration[] =
#define CONFIG_HEADER(numGamepads) \
TUD_CONFIG_DESCRIPTOR(1, ITF_COUNT(numGamepads), 0, GET_CONFIG_LEN(numGamepads), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 400)

#define GAMEPAD_CONFIG_DESC(itfNum, strIdx, endpt) \
TUD_HID_DESCRIPTOR(itfNum, strIdx, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), endpt, GAMEPAD_REPORT_SIZE, 1)

// Only doing transfer at full speed since each file will only be about 128KB, max of 8 files
#define MSC_DESCRIPTOR(numGamepads) TUD_MSC_DESCRIPTOR(ITF_NUM_MSC(numGamepads), 8, EPOUT_MSC, EPIN_MSC, 64)

#define CDC_DESCRIPTOR(numGamepads) TUD_CDC_DESCRIPTOR(ITF_NUM_CDC(numGamepads), 9, EPIN_CDC_NOTIF, 8, EPOUT_CDC, EPIN_CDC, 64)

uint8_t desc_configuration[] =
{
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_COUNT, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 400),
CONFIG_HEADER(NUMBER_OF_GAMEPADS),

// *************************************************************************
// * Gamepad Descriptors *
// *************************************************************************

// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval ms
TUD_HID_DESCRIPTOR(ITF_NUM_GAMEPAD4, 7, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report4),
EPIN_GAMEPAD4, GAMEPAD_REPORT_SIZE, 1),

// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval ms
TUD_HID_DESCRIPTOR(ITF_NUM_GAMEPAD3, 6, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report3),
EPIN_GAMEPAD3, GAMEPAD_REPORT_SIZE, 1),

// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval ms
TUD_HID_DESCRIPTOR(ITF_NUM_GAMEPAD2, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report2),
EPIN_GAMEPAD2, GAMEPAD_REPORT_SIZE, 1),

// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval ms
TUD_HID_DESCRIPTOR(ITF_NUM_GAMEPAD1, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report1),
EPIN_GAMEPAD1, GAMEPAD_REPORT_SIZE, 1),
GAMEPAD_CONFIG_DESC(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 3), PLAYER_TO_STR_IDX(3), EPIN_GAMEPAD4),
GAMEPAD_CONFIG_DESC(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 2), PLAYER_TO_STR_IDX(2), EPIN_GAMEPAD3),
GAMEPAD_CONFIG_DESC(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 1), PLAYER_TO_STR_IDX(1), EPIN_GAMEPAD2),
GAMEPAD_CONFIG_DESC(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 0), PLAYER_TO_STR_IDX(0), EPIN_GAMEPAD1),

// *************************************************************************
// * Storage Device Descriptor *
// *************************************************************************

// Only doing transfer at full speed since each file will only be about 128KB, max of 8 files

// Interface number, string index, EP Out & EP In address, EP size
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 8, EPOUT_MSC, EPIN_MSC, 64),
MSC_DESCRIPTOR(NUMBER_OF_GAMEPADS),

// *************************************************************************
// * Communication Device Descriptor (for debug messaging) *
// *************************************************************************

#if USB_CDC_ENABLED
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 9, EPIN_CDC_NOTIF, 8, EPOUT_CDC, EPIN_CDC, 64),
CDC_DESCRIPTOR(NUMBER_OF_GAMEPADS),
#endif
};

Expand All @@ -225,6 +231,40 @@ uint8_t const desc_configuration[] =
// Descriptor contents must exist long enough for transfer to complete
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations

// Build the config based on number of players
uint32_t offset = 0;

uint8_t header[] = {
CONFIG_HEADER(numberOfGamepads)
};
memcpy(&desc_configuration[offset], header, sizeof(header));
offset += sizeof(header);

for (uint8_t i = 0; i < numberOfGamepads; ++i)
{
uint8_t idx = numberOfGamepads - i - 1;
uint8_t gpConfig[] = {
GAMEPAD_CONFIG_DESC(ITF_NUM_GAMEPAD(numberOfGamepads, idx), PLAYER_TO_STR_IDX(idx), player_to_epin(idx))
};
memcpy(&desc_configuration[offset], gpConfig, sizeof(gpConfig));
offset += sizeof(gpConfig);
}

uint8_t mscConfig[] = {
MSC_DESCRIPTOR(numberOfGamepads)
};
memcpy(&desc_configuration[offset], mscConfig, sizeof(mscConfig));
offset += sizeof(mscConfig);

#if USB_CDC_ENABLED
uint8_t cdcConfig[] = {
CDC_DESCRIPTOR(numberOfGamepads)
};
memcpy(&desc_configuration[offset], cdcConfig, sizeof(cdcConfig));
offset += sizeof(cdcConfig);
#endif

return desc_configuration;
}

Expand Down Expand Up @@ -267,7 +307,12 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {

const char *str = string_desc_arr[index];

if (str == NULL)
if (index == PLAYER_TO_STR_IDX(0) && numberOfGamepads == 1)
{
// Special case - if there is only 1 controller, change the label
str = "Dreamcast Controller";
}
else if (str == NULL)
{
if (index == 3)
{
Expand Down
22 changes: 7 additions & 15 deletions src/hal/Usb/Client/Hid/usb_descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,15 @@
#include "configuration.h"

// Going in reverse order because the host seems to usually enumerate the highest value first
enum {
// Gamepads
ITF_NUM_GAMEPAD4 = 0,
ITF_NUM_GAMEPAD3,
ITF_NUM_GAMEPAD2,
ITF_NUM_GAMEPAD1,
// For mass storage device
ITF_NUM_MSC,
#define ITF_NUM_GAMEPAD(numGamepads, idx) (numGamepads - idx - 1)

#if USB_CDC_ENABLED
ITF_NUM_CDC,
ITF_NUM_CDC_DATA,
#endif
#define NUMBER_OF_GAMEPADS (4)

ITF_COUNT
};
// For mass storage device
#define ITF_NUM_MSC(numGamepads) (numGamepads)

#define NUMBER_OF_GAMEPADS (ITF_NUM_GAMEPAD1 + 1)
#define ITF_NUM_CDC(numGamepads) (numGamepads + 1)
#define ITF_NUM_CDC_DATA(numGamepads) (numGamepads + 2)
#define ITF_COUNT(numGamepads) (numGamepads + 3)

#endif // __USB_DESCRITORS_H__
35 changes: 29 additions & 6 deletions src/hal/Usb/Client/Hid/usb_execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "UsbGamepadDreamcastControllerObserver.hpp"
#include "UsbGamepad.h"
#include "configuration.h"
#include "hal/Usb/client_usb_interface.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Expand All @@ -16,10 +17,10 @@
#include "cdc.hpp"

UsbGamepad usbGamepads[NUMBER_OF_GAMEPADS] = {
UsbGamepad(ITF_NUM_GAMEPAD1),
UsbGamepad(ITF_NUM_GAMEPAD2),
UsbGamepad(ITF_NUM_GAMEPAD3),
UsbGamepad(ITF_NUM_GAMEPAD4)
UsbGamepad(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 0)),
UsbGamepad(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 1)),
UsbGamepad(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 2)),
UsbGamepad(ITF_NUM_GAMEPAD(NUMBER_OF_GAMEPADS, 3))
};

UsbGamepadDreamcastControllerObserver usbGamepadDreamcastControllerObservers[NUMBER_OF_GAMEPADS] = {
Expand Down Expand Up @@ -50,7 +51,16 @@ DreamcastControllerObserver** get_usb_controller_observers()

uint32_t get_num_usb_controllers()
{
return NUMBER_OF_GAMEPADS;
uint8_t installedGamepads = get_usb_descriptor_number_of_gamepads();

if (installedGamepads <= NUMBER_OF_GAMEPADS)
{
return installedGamepads;
}
else
{
return NUMBER_OF_GAMEPADS;
}
}

bool usbEnabled = false;
Expand Down Expand Up @@ -129,7 +139,20 @@ void usb_init(
MutexInterface* mscMutex,
MutexInterface* cdcStdioMutex)
{
set_usb_devices(devices, sizeof(devices) / sizeof(devices[1]));
uint32_t numDevices = get_num_usb_controllers();

for (uint32_t i = 0; i < numDevices; ++i)
{
usbGamepads[i].setInterfaceId(ITF_NUM_GAMEPAD(numDevices, i));
}

uint32_t max = sizeof(devices) / sizeof(devices[1]);
if (numDevices > max)
{
numDevices = max;
}
set_usb_devices(devices, numDevices);

board_init();
tusb_init();
msc_init(mscMutex);
Expand Down
12 changes: 6 additions & 6 deletions src/main/Client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ set(CMAKE_VERBOSE_MAKEFILE ON)

file(GLOB COMMON_SRC "${CMAKE_CURRENT_SOURCE_DIR}/common/*.c*")

add_executable(client-usb-host "${CMAKE_CURRENT_SOURCE_DIR}/client_usb_host.cpp" "${COMMON_SRC}")
pico_add_extra_outputs(client-usb-host)
pico_set_binary_type(client-usb-host copy_to_ram)
target_link_libraries(client-usb-host
add_executable(client-with-usb-host "${CMAKE_CURRENT_SOURCE_DIR}/client_usb_host.cpp" "${COMMON_SRC}")
pico_add_extra_outputs(client-with-usb-host)
pico_set_binary_type(client-with-usb-host copy_to_ram)
target_link_libraries(client-with-usb-host
PRIVATE
pico_multicore
hal-MapleBus
Expand All @@ -16,13 +16,13 @@ target_link_libraries(client-usb-host
clientLib
pico_stdlib
)
target_compile_options(client-usb-host PRIVATE
target_compile_options(client-with-usb-host PRIVATE
-Wall
#-Werror
-O3
)

target_include_directories(client-usb-host
target_include_directories(client-with-usb-host
PRIVATE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/client>"
Expand Down
Loading

0 comments on commit 4688cdd

Please sign in to comment.