mirror of
https://github.com/pumpitupdev/pumptools.git
synced 2026-09-29 10:18:14 +03:00
Use a similar code style to bemanitools though reduce indentation to 2 spaces. Also some other tweaks to be more similar to google style.
195 lines
5.9 KiB
C
195 lines
5.9 KiB
C
#define LOG_MODULE "usb-fix"
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "capnhook/hook/lib.h"
|
|
|
|
#include "util/log.h"
|
|
#include "util/mem.h"
|
|
#include "util/str.h"
|
|
|
|
typedef ssize_t (*readlink_t)(const char *path, char *buf, size_t len);
|
|
static readlink_t pro_usb_fix_real_readlink;
|
|
|
|
static const int16_t propatch_usb_fix_usb_static_ini_usb_bus[2] = {1, 1};
|
|
static const int16_t propatch_usb_fix_usb_static_ini_usb_port[2] = {2, 1};
|
|
|
|
static char propatch_usb_fix_device_thumb_drive_p1[128];
|
|
static char propatch_usb_fix_device_thumb_drive_p2[128];
|
|
|
|
static int propatch_usb_fix_usb_bus[2];
|
|
static int propatch_usb_fix_usb_port[2];
|
|
|
|
static bool propatch_usb_fix_enabled;
|
|
|
|
// Non static for testing
|
|
ssize_t propatch_usb_fix_readlink(const char *path, char *buf, size_t len)
|
|
{
|
|
if (!pro_usb_fix_real_readlink) {
|
|
pro_usb_fix_real_readlink = (readlink_t) cnh_lib_get_func_addr("readlink");
|
|
}
|
|
|
|
// pro is scanning the /sys/block directory where all usb thumb drives show up
|
|
// once connected The game iterates the directory and resolves the
|
|
// /sys/block/sdX/device symlink On current kernels, e.g. 5.6.14, it might
|
|
// look like this
|
|
// ../devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2:1.0/host7/target7:0:0/7:0:0:0/block/sdd
|
|
// However, when pro was developed, the symlink looked entirely different.
|
|
// In order to allow the game to detect and mount usb thumb drives on newer
|
|
// kernels, the path needs to be altered to match what the game is expecting
|
|
// which might be similar to this:
|
|
// ../devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2:1.0
|
|
// The game tokenizes this path by / and picks the second to last item, which
|
|
// is '2-2' here. This item gets further split into bus (2) and port (2). If
|
|
// that is successful, the game treats the detected device as valid allowing
|
|
// it to mount if the bus and port match what has been configured in the
|
|
// Static.ini file
|
|
if (propatch_usb_fix_enabled && util_str_starts_with(path, "/sys/block/") &&
|
|
util_str_ends_with(path, "/device")) {
|
|
log_debug("Trap %s", path);
|
|
|
|
// Remove the trailing "/device" part which is no longer valid on current
|
|
// kernels /sys/block/sdc/device -> /sys/block/sdc
|
|
char *tmp = util_str_dup(path);
|
|
size_t len_tmp = strlen(tmp);
|
|
tmp[len_tmp - 7] = '\0';
|
|
|
|
memset(buf, 0, len);
|
|
|
|
ssize_t res = pro_usb_fix_real_readlink(tmp, buf, len);
|
|
|
|
util_xfree((void **) &tmp);
|
|
|
|
if (strstr(buf, propatch_usb_fix_device_thumb_drive_p1) ||
|
|
strstr(buf, propatch_usb_fix_device_thumb_drive_p2)) {
|
|
log_debug("Detected assigned flash drive plugged in");
|
|
|
|
size_t count;
|
|
char **toks;
|
|
|
|
toks = util_str_split(buf, "/", &count);
|
|
|
|
// some sanity checks to ensure the format isn't different
|
|
if (count != 12 || strcmp(toks[0], "..") != 0 ||
|
|
strcmp(toks[1], "devices") != 0 || strcmp(toks[10], "block") != 0) {
|
|
log_error(
|
|
"/sys/block device readlink format changed, usb thumb drive "
|
|
"profiles will likely not work!: %s",
|
|
buf);
|
|
util_str_free_split(toks, count);
|
|
return 0;
|
|
}
|
|
|
|
int bus;
|
|
int port;
|
|
const char *device = toks[11];
|
|
|
|
if (sscanf(toks[5], "%d-%d", &bus, &port) != 2) {
|
|
log_error("Parsing bus-port of %s failed", buf);
|
|
util_str_free_split(toks, count);
|
|
return 0;
|
|
}
|
|
|
|
log_debug(
|
|
"Detected flash drive on bus %d, port %d, device %s",
|
|
bus,
|
|
port,
|
|
device);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (propatch_usb_fix_usb_bus[i] == bus &&
|
|
propatch_usb_fix_usb_port[i] == port) {
|
|
// The usb manager only cares about reading the second to last token
|
|
// in the correct format Copy-paste everything else
|
|
sprintf(
|
|
buf,
|
|
"%s/%s/%s/%s/%s/%d-%d/%d-%d:1.0",
|
|
toks[0],
|
|
toks[1],
|
|
toks[2],
|
|
toks[3],
|
|
toks[4],
|
|
propatch_usb_fix_usb_static_ini_usb_bus[i],
|
|
propatch_usb_fix_usb_static_ini_usb_port[i],
|
|
propatch_usb_fix_usb_static_ini_usb_bus[i],
|
|
propatch_usb_fix_usb_static_ini_usb_port[i]);
|
|
|
|
log_debug("Player %d usb thumb drive at path %s", i, buf);
|
|
|
|
util_str_free_split(toks, count);
|
|
|
|
return strlen(buf);
|
|
}
|
|
}
|
|
|
|
util_str_free_split(toks, count);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
return pro_usb_fix_real_readlink(path, buf, len);
|
|
}
|
|
|
|
ssize_t readlink(const char *path, char *buf, size_t len)
|
|
{
|
|
return propatch_usb_fix_readlink(path, buf, len);
|
|
}
|
|
|
|
void propatch_usb_fix_init(
|
|
const char *device_nodes, const char *p1_bus_port, const char *p2_bus_port)
|
|
{
|
|
size_t count;
|
|
char **toks;
|
|
|
|
if (!device_nodes || !p1_bus_port || !p2_bus_port) {
|
|
log_warn("Disabled, missing one or multiple option properties");
|
|
return;
|
|
}
|
|
|
|
toks = util_str_split(device_nodes, ",", &count);
|
|
|
|
if (count != 2) {
|
|
log_error("Invalid format for device nodes: %s", device_nodes);
|
|
util_str_free_split(toks, count);
|
|
return;
|
|
}
|
|
|
|
strcpy(propatch_usb_fix_device_thumb_drive_p1, toks[0]);
|
|
strcpy(propatch_usb_fix_device_thumb_drive_p2, toks[1]);
|
|
|
|
util_str_free_split(toks, count);
|
|
|
|
if (sscanf(
|
|
p1_bus_port,
|
|
"%d-%d",
|
|
&propatch_usb_fix_usb_bus[0],
|
|
&propatch_usb_fix_usb_port[0]) != 2) {
|
|
log_error("Invalid format for p1 bus-port: %s", p1_bus_port);
|
|
return;
|
|
}
|
|
|
|
if (sscanf(
|
|
p2_bus_port,
|
|
"%d-%d",
|
|
&propatch_usb_fix_usb_bus[1],
|
|
&propatch_usb_fix_usb_port[1]) != 2) {
|
|
log_error("Invalid format for p2 bus-port: %s", p2_bus_port);
|
|
return;
|
|
}
|
|
|
|
log_info(
|
|
"Initialized: device nodes %s,%s, p1 %d-%d, p2 %d-%d",
|
|
propatch_usb_fix_device_thumb_drive_p1,
|
|
propatch_usb_fix_device_thumb_drive_p2,
|
|
propatch_usb_fix_usb_bus[0],
|
|
propatch_usb_fix_usb_port[0],
|
|
propatch_usb_fix_usb_bus[1],
|
|
propatch_usb_fix_usb_port[1]);
|
|
|
|
propatch_usb_fix_enabled = true;
|
|
}
|
|
|
|
void propatch_usb_fix_shutdown()
|
|
{
|
|
} |