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"));
// Initialize HIDAPI
/*May be not needed
int res = hid_init();
if (res == 0)
{
@ -26,6 +27,7 @@ void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
HidError = hid_error(NULL);
UE_LOG(LogHIDApi, Error, TEXT("%s"), *HidError);
}
*/
}
@ -42,6 +44,34 @@ void USkyPortalSubsystem::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 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.
"list" will point to the head of the linked list of devices,
@ -90,7 +126,7 @@ bool USkyPortalSubsystem::ConnectPortal() {
// Free the device list
hid_free_enumeration(list);
bPortalConnected = true;
//bPortalConnected = true;
return true;
}
@ -128,27 +164,28 @@ void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color)
Write(&req);
}
void USkyPortalSubsystem::Write(RWBlock* pb) {
// TODO: Need to make this function async
if (!ensure(PortalDevice)) {
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
return;
}
void USkyPortalSubsystem::Write(RWBlock *pb) {
pb->buf[0] = 0; // Use report 0
/*
for (int attempt = 0; attempt < 10; attempt++) {
if (hid_write(PortalDevice, pb->buf, 0x21) == -1) {
Sleep(100);
}
else {
if (!ensure(PortalDevice)) {
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
return;
}
}
*/
ensureMsgf(hid_write(PortalDevice, pb->buf, 0x21) != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice));
UE_LOG(LogSkyportalIO, Verbose, TEXT("Writed"));
pb->buf[0] = 0; // Use report 0
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) {
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"));
ensureMsgf(false, TEXT("PortalIO: Failed to read block after multiple retries"));
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()
//Portal ref used in the subsystem
hid_device* PortalDevice;
public:
// Override initialization and deinitialization methods
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// Connect to Portal, return false if portal is not found
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal"))
bool ConnectPortal();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
bool bPortalConnected = false;
@ -42,14 +49,13 @@ public:
unsigned char PortalStatus();
private:
//Portal ref used in the subsystem
hid_device* PortalDevice;
typedef struct {
unsigned char buf[rw_buf_size]; int BytesTransferred;
@ -58,12 +64,17 @@ private:
static void Sleep(int sleepMs);
void ActivatePortal(int active);
void RestartPortal();
// Block/byte related data write/read functions
bool OpenPortalHandle();
bool ReadBlock(unsigned int block, unsigned char data[0x10], int skylander);
bool WriteBlock(unsigned int, unsigned char[0x10], int);
bool CheckResponse(RWBlock* res, char expect);
void Write(RWBlock* pb);
bool CheckResponse(RWBlock *, char);
void Write(RWBlock *);
protected: