Version 1.08 with public source code release.

This commit is contained in:
icex2
2020-10-03 20:56:55 +02:00
parent 656148121d
commit 762bf140c0
555 changed files with 55502 additions and 3 deletions
+177
View File
@@ -0,0 +1,177 @@
#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()
{
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
void propatch_usb_fix_init(const char* device_nodes, const char* p1_bus_port, const char* p2_bus_port);
void propatch_usb_fix_shutdown();