wip: implement portalIO

TODO : Fix the write IO timing issue
This commit is contained in:
Lucas Peter 2024-09-20 14:29:13 +02:00 committed by LUCASTUCIOUS
parent 2360897978
commit ed7b37b4fe
2 changed files with 101 additions and 26 deletions

View file

@ -14,6 +14,7 @@ void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Initialized")); UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Initialized"));
// Initialize HIDAPI // Initialize HIDAPI
/*May be not needed
int res = hid_init(); int res = hid_init();
if (res == 0) if (res == 0)
{ {
@ -26,6 +27,7 @@ void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
HidError = hid_error(NULL); HidError = hid_error(NULL);
UE_LOG(LogHIDApi, Error, TEXT("%s"), *HidError); UE_LOG(LogHIDApi, Error, TEXT("%s"), *HidError);
} }
*/
} }
@ -42,6 +44,34 @@ void USkyPortalSubsystem::Deinitialize()
Super::Deinitialize(); Super::Deinitialize();
} }
// Antenna up / activate
void USkyPortalSubsystem::ActivatePortal(int active)
{
RWBlock req, res;
memset(req.buf, 0, rw_buf_size);
req.buf[1] = 'A';
req.buf[2] = active;
do { Write(&req); } while (CheckResponse(&res, 'A'));
}
// Start portal
void USkyPortalSubsystem::RestartPortal()
{
RWBlock req, res;
memset(req.buf, 0, rw_buf_size);
req.buf[1] = 'R';
// Wait until the device is ready
while (PortalStatus() == 0) {
FPlatformProcess::Sleep(0.05f); // Sleep for 50ms and try again
}
do { Write(&req); } while (CheckResponse(&res, 'R'));
}
/* /*
@ -49,7 +79,13 @@ Number of endpoints : 2
found an IN End Point 0 with attributes interrupt and address 0x1 found an IN End Point 0 with attributes interrupt and address 0x1
found an OUT End Point 1 with attributes interrupt and address 0x1 found an OUT End Point 1 with attributes interrupt and address 0x1
*/ */
bool USkyPortalSubsystem::ConnectPortal() { bool USkyPortalSubsystem::OpenPortalHandle() {
//reset
if (PortalDevice) {
hid_close(PortalDevice);
}
/* /*
Declare two pointers to hold information about HID devices. Declare two pointers to hold information about HID devices.
"list" will point to the head of the linked list of devices, "list" will point to the head of the linked list of devices,
@ -90,7 +126,7 @@ bool USkyPortalSubsystem::ConnectPortal() {
// Free the device list // Free the device list
hid_free_enumeration(list); hid_free_enumeration(list);
bPortalConnected = true; //bPortalConnected = true;
return true; return true;
} }
@ -128,27 +164,28 @@ void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color)
Write(&req); Write(&req);
} }
void USkyPortalSubsystem::Write(RWBlock* pb) { void USkyPortalSubsystem::Write(RWBlock *pb) {
// TODO: Need to make this function async
if (!ensure(PortalDevice)) {
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
return;
}
pb->buf[0] = 0; // Use report 0 if (!ensure(PortalDevice)) {
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
/*
for (int attempt = 0; attempt < 10; attempt++) {
if (hid_write(PortalDevice, pb->buf, 0x21) == -1) {
Sleep(100);
}
else {
return; return;
} }
}
*/ pb->buf[0] = 0; // Use report 0
ensureMsgf(hid_write(PortalDevice, pb->buf, 0x21) != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice));
UE_LOG(LogSkyportalIO, Verbose, TEXT("Writed"));
for (int attempt = 0; attempt < 10; attempt++) {
if (hid_write(PortalDevice, pb->buf, 0x21) == -1) {
UE_LOG(LogSkyportalIO, Warning, TEXT("Attempt %d: Failed to write to Portal, retrying..."), attempt + 1);
FPlatformProcess::Sleep(0.1f);
}
else {
UE_LOG(LogSkyportalIO, Verbose, TEXT("Successfully wrote to the Portal on attempt %d."), attempt + 1);
return;
}
}
//ensureMsgf(hid_write(PortalDevice, pb->buf, 0x21) != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice));
UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write to Portal after multiple attempts. error:\n %s"), hid_error(PortalDevice));
} }
@ -157,7 +194,7 @@ void USkyPortalSubsystem::Sleep(int sleepMs) {
} }
bool USkyPortalSubsystem::CheckResponse(RWBlock* res, char expect) bool USkyPortalSubsystem::CheckResponse(RWBlock *res, char expect)
{ {
if (!PortalDevice) { if (!PortalDevice) {
return false; return false;
@ -284,4 +321,31 @@ bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10]
UE_LOG(LogSkyportalIO, Fatal, TEXT("PortalIO:ReadBlock failed after retries")); UE_LOG(LogSkyportalIO, Fatal, TEXT("PortalIO:ReadBlock failed after retries"));
ensureMsgf(false, TEXT("PortalIO: Failed to read block after multiple retries")); ensureMsgf(false, TEXT("PortalIO: Failed to read block after multiple retries"));
return false; return false;
}
bool USkyPortalSubsystem::ConnectPortal()
{
bPortalConnected = OpenPortalHandle();
if (bPortalConnected) {
RestartPortal();
ActivatePortal(1);
ChangePortalColor(FLinearColor(0xC8, 0xC8, 0xC8));
UE_LOG(LogSkyportalIO, Log, TEXT("Portal Status: %d\n"), PortalStatus());
}
return bPortalConnected;
}
unsigned char USkyPortalSubsystem::PortalStatus()
{
RWBlock req, res;
memset(req.buf, 0, rw_buf_size);
req.buf[1] = 'S';
do { Write(&req); } while (CheckResponse(&res, 'S'));
return res.buf[1];
} }

View file

@ -22,15 +22,22 @@ class SKYPORTAL_API USkyPortalSubsystem : public UEngineSubsystem
{ {
GENERATED_BODY() GENERATED_BODY()
//Portal ref used in the subsystem
hid_device* PortalDevice;
public: public:
// Override initialization and deinitialization methods // Override initialization and deinitialization methods
virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override; virtual void Deinitialize() override;
// Connect to Portal, return false if portal is not found // Connect to Portal, return false if portal is not found
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal")) UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal"))
bool ConnectPortal(); bool ConnectPortal();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
bool bPortalConnected = false; bool bPortalConnected = false;
@ -42,14 +49,13 @@ public:
unsigned char PortalStatus();
private: private:
//Portal ref used in the subsystem
hid_device* PortalDevice;
typedef struct { typedef struct {
unsigned char buf[rw_buf_size]; int BytesTransferred; unsigned char buf[rw_buf_size]; int BytesTransferred;
@ -58,12 +64,17 @@ private:
static void Sleep(int sleepMs); static void Sleep(int sleepMs);
void ActivatePortal(int active);
void RestartPortal();
// Block/byte related data write/read functions // Block/byte related data write/read functions
bool OpenPortalHandle();
bool ReadBlock(unsigned int block, unsigned char data[0x10], int skylander); bool ReadBlock(unsigned int block, unsigned char data[0x10], int skylander);
bool WriteBlock(unsigned int, unsigned char[0x10], int); bool WriteBlock(unsigned int, unsigned char[0x10], int);
bool CheckResponse(RWBlock* res, char expect); bool CheckResponse(RWBlock *, char);
void Write(RWBlock* pb); void Write(RWBlock *);
protected: protected: