Merge branch 'rework'
This commit is contained in:
commit
65652d3a2a
25 changed files with 1945 additions and 15 deletions
BIN
Content/icons/sky-portal-icon-black.png
Normal file
BIN
Content/icons/sky-portal-icon-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
18
Content/icons/sky-portal-icon-black.svg
Normal file
18
Content/icons/sky-portal-icon-black.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 404 404" width="404" height="404">
|
||||
<title>sky-portal-icon</title>
|
||||
<style>
|
||||
.s0 { fill: #000000 }
|
||||
</style>
|
||||
<g>
|
||||
<path id="Circle" class="s0" d="m168.6 0l23 46h20.8l23-46zm-9.5 21.1q-5 1.2-9.9 2.7-4.9 1.4-9.7 3.2-4.8 1.7-9.6 3.7-4.7 2.1-9.2 4.3l7.2 30.2q5.2-2.9 10.7-5.4 5.5-2.5 11.1-4.6 5.7-2 11.5-3.6 5.8-1.7 11.7-2.8zm86.1 0l-13.9 27.7q5.9 1.2 11.7 2.8 5.8 1.6 11.5 3.6 5.6 2.1 11.1 4.6 5.5 2.5 10.7 5.4l7.3-30.2q-4.6-2.2-9.3-4.2-4.7-2.1-9.6-3.8-4.8-1.8-9.7-3.2-4.9-1.5-9.8-2.7zm59.2 4l-11.9 50 16 13.4 47.2-20.5c0 0-51.3-42.9-51.3-42.9zm-204.6 0l-51.2 43 47.2 20.4 16-13.4c0 0-12-50-12-50zm249.7 65.3l-28.5 12.3q3.7 4.7 7.2 9.6 3.4 5 6.4 10.2 3 5.2 5.6 10.7 2.6 5.4 4.8 11l24.9-18.5q-2.1-4.7-4.4-9.2-2.3-4.6-4.8-9-2.6-4.5-5.4-8.7-2.8-4.3-5.8-8.4zm-294.7 0q-3 4.1-5.8 8.4-2.9 4.3-5.4 8.7-2.6 4.4-4.9 9-2.3 4.6-4.3 9.3l24.9 18.4q2.1-5.6 4.7-11 2.6-5.5 5.6-10.7 3.1-5.2 6.5-10.1 3.4-5 7.2-9.7zm337.5 41.2l-41.3 30.6 3.7 20.6 49.2 14.6c0 0-11.6-65.8-11.6-65.8zm-380.3 0l-11.6 65.9 49.3-14.7 3.6-20.5c0 0-41.3-30.7-41.3-30.7zm343.1 70.1c-0.3 16.5-3.2 32.4-8.3 47.2l30.9 1.9q1.5-5 2.6-9.9 1.2-5 2.1-10.1 0.9-5 1.5-10.1 0.6-5.1 0.9-10.2zm-306 0.1l-29.6 8.8q0.3 5.1 0.9 10.2 0.6 5.1 1.5 10.1 0.8 5 2 10 1.2 5 2.6 9.9l31-1.8c-5.2-14.9-8.1-30.7-8.4-47.2zm290.8 64.7l-10.5 18.1 28.4 42.9 33.4-57.9zm-275.4 0.1l-51.4 3.1 33.5 57.9 28.3-43zm253.2 32.8q-3 3.5-6.2 6.7-3.2 3.3-6.6 6.4-3.4 3-7 5.9-3.5 2.9-7.2 5.5l14.7 26.5q4-2.8 7.8-5.7 3.8-2.9 7.5-6.1 3.7-3.1 7.2-6.4 3.5-3.4 6.9-6.9zm-230.9 0.1l-17.2 25.9q3.4 3.5 6.9 6.8 3.5 3.4 7.2 6.5 3.6 3.1 7.5 6 3.8 3 7.8 5.7l14.7-26.5q-3.7-2.6-7.3-5.5-3.5-2.8-6.9-5.9-3.4-3-6.6-6.3-3.1-3.2-6.1-6.7zm13.3 79.7l62.9 22.9-5.9-51.1-19.6-7.1c0 0-37.4 35.3-37.4 35.3zm79.1 6.4q5.1 0.6 10.2 0.8 5.1 0.3 10.2 0.3 5.1 0 10.2-0.2 5.1-0.3 10.2-0.9l3.6-30.8q-6 0.9-12 1.4-6 0.5-12 0.4-6 0-12-0.4-6-0.5-12-1.5zm57.1 16.5l62.8-22.9-37.3-35.3-19.6 7.1c0 0-5.9 51.1-5.9 51.1z"/>
|
||||
<g id="Vortex">
|
||||
<path id="Vortex7" class="s0" d="m182.3 194.1c-2.1 3.5-19.8 50.8 46.8 73.2 50.6 11.2 85.3-32.6 85.3-32.6 0 0-14.6 66.8-95.6 54.5-73.9-23.5-54.9-83.4-36.5-95.1z"/>
|
||||
<path id="Vortex6" class="s0" d="m197.4 181.2c-4.1 0.4-52.2 15.8-28.5 82 22.5 46.7 78.3 46.9 78.3 46.9 0 0-61.5 29.8-101.9-41.5-27.3-72.5 31.5-94.6 52.1-87.4z"/>
|
||||
<path id="Vortex5" class="s0" d="m217.4 185.2c-2.8-3-44.2-32-82.6 26.9-23.5 46.1 10.1 90.7 10.1 90.7 0 0-61-30.9-28.7-106.2 41.3-65.6 94.5-32.2 101.2-11.4z"/>
|
||||
<path id="Vortex4" class="s0" d="m182.4 212.2c1.1 3.9 23.5 49.2 85.4 15.9 42.8-29.2 34.6-84.5 34.6-84.5 0 0 38.7 56.4-25.7 107-67.7 37.9-98.3-17-94.3-38.4z"/>
|
||||
<path id="Vortex3" class="s0" d="m197 225.2c3.7 1.6 52.8 13.2 66.6-55.7 4.7-51.6-43.1-80.5-43.1-80.5 0 0 68.1 6.1 66.1 88-13.9 76.2-75.7 64.9-89.6 48.2z"/>
|
||||
<path id="Vortex2" class="s0" d="m218 220.7c3.5-2.1 40.5-36.4-9-86.3-40.1-32.8-90.8-9.3-90.8-9.3 0 0 43.1-53.1 109.9-5.6 55.5 54.1 11.6 99.1-10.1 101.2z"/>
|
||||
<path id="Vortex1" class="s0" d="m226.2 203.4c0.6-4.1-1.6-54.5-71.7-49.1-50.9 9.4-65.8 63.3-65.8 63.3 0 0-12.6-67.2 66.8-87.5 77.2-7.2 83.1 55.3 70.7 73.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
BIN
Content/icons/sky-portal-icon-white.png
Normal file
BIN
Content/icons/sky-portal-icon-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
18
Content/icons/sky-portal-icon-white.svg
Normal file
18
Content/icons/sky-portal-icon-white.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 404 404" width="404" height="404">
|
||||
<title>sky-portal-icon</title>
|
||||
<style>
|
||||
.s0 { fill: #ffffff }
|
||||
</style>
|
||||
<g>
|
||||
<path id="Circle" class="s0" d="m168.6 0l23 46h20.8l23-46zm-9.5 21.1q-5 1.2-9.9 2.7-4.9 1.4-9.7 3.2-4.8 1.7-9.6 3.7-4.7 2.1-9.2 4.3l7.2 30.2q5.2-2.9 10.7-5.4 5.5-2.5 11.1-4.6 5.7-2 11.5-3.6 5.8-1.7 11.7-2.8zm86.1 0l-13.9 27.7q5.9 1.2 11.7 2.8 5.8 1.6 11.5 3.6 5.6 2.1 11.1 4.6 5.5 2.5 10.7 5.4l7.3-30.2q-4.6-2.2-9.3-4.2-4.7-2.1-9.6-3.8-4.8-1.8-9.7-3.2-4.9-1.5-9.8-2.7zm59.2 4l-11.9 50 16 13.4 47.2-20.5c0 0-51.3-42.9-51.3-42.9zm-204.6 0l-51.2 43 47.2 20.4 16-13.4c0 0-12-50-12-50zm249.7 65.3l-28.5 12.3q3.7 4.7 7.2 9.6 3.4 5 6.4 10.2 3 5.2 5.6 10.7 2.6 5.4 4.8 11l24.9-18.5q-2.1-4.7-4.4-9.2-2.3-4.6-4.8-9-2.6-4.5-5.4-8.7-2.8-4.3-5.8-8.4zm-294.7 0q-3 4.1-5.8 8.4-2.9 4.3-5.4 8.7-2.6 4.4-4.9 9-2.3 4.6-4.3 9.3l24.9 18.4q2.1-5.6 4.7-11 2.6-5.5 5.6-10.7 3.1-5.2 6.5-10.1 3.4-5 7.2-9.7zm337.5 41.2l-41.3 30.6 3.7 20.6 49.2 14.6c0 0-11.6-65.8-11.6-65.8zm-380.3 0l-11.6 65.9 49.3-14.7 3.6-20.5c0 0-41.3-30.7-41.3-30.7zm343.1 70.1c-0.3 16.5-3.2 32.4-8.3 47.2l30.9 1.9q1.5-5 2.6-9.9 1.2-5 2.1-10.1 0.9-5 1.5-10.1 0.6-5.1 0.9-10.2zm-306 0.1l-29.6 8.8q0.3 5.1 0.9 10.2 0.6 5.1 1.5 10.1 0.8 5 2 10 1.2 5 2.6 9.9l31-1.8c-5.2-14.9-8.1-30.7-8.4-47.2zm290.8 64.7l-10.5 18.1 28.4 42.9 33.4-57.9zm-275.4 0.1l-51.4 3.1 33.5 57.9 28.3-43zm253.2 32.8q-3 3.5-6.2 6.7-3.2 3.3-6.6 6.4-3.4 3-7 5.9-3.5 2.9-7.2 5.5l14.7 26.5q4-2.8 7.8-5.7 3.8-2.9 7.5-6.1 3.7-3.1 7.2-6.4 3.5-3.4 6.9-6.9zm-230.9 0.1l-17.2 25.9q3.4 3.5 6.9 6.8 3.5 3.4 7.2 6.5 3.6 3.1 7.5 6 3.8 3 7.8 5.7l14.7-26.5q-3.7-2.6-7.3-5.5-3.5-2.8-6.9-5.9-3.4-3-6.6-6.3-3.1-3.2-6.1-6.7zm13.3 79.7l62.9 22.9-5.9-51.1-19.6-7.1c0 0-37.4 35.3-37.4 35.3zm79.1 6.4q5.1 0.6 10.2 0.8 5.1 0.3 10.2 0.3 5.1 0 10.2-0.2 5.1-0.3 10.2-0.9l3.6-30.8q-6 0.9-12 1.4-6 0.5-12 0.4-6 0-12-0.4-6-0.5-12-1.5zm57.1 16.5l62.8-22.9-37.3-35.3-19.6 7.1c0 0-5.9 51.1-5.9 51.1z"/>
|
||||
<g id="Vortex">
|
||||
<path id="Vortex7" class="s0" d="m182.3 194.1c-2.1 3.5-19.8 50.8 46.8 73.2 50.6 11.2 85.3-32.6 85.3-32.6 0 0-14.6 66.8-95.6 54.5-73.9-23.5-54.9-83.4-36.5-95.1z"/>
|
||||
<path id="Vortex6" class="s0" d="m197.4 181.2c-4.1 0.4-52.2 15.8-28.5 82 22.5 46.7 78.3 46.9 78.3 46.9 0 0-61.5 29.8-101.9-41.5-27.3-72.5 31.5-94.6 52.1-87.4z"/>
|
||||
<path id="Vortex5" class="s0" d="m217.4 185.2c-2.8-3-44.2-32-82.6 26.9-23.5 46.1 10.1 90.7 10.1 90.7 0 0-61-30.9-28.7-106.2 41.3-65.6 94.5-32.2 101.2-11.4z"/>
|
||||
<path id="Vortex4" class="s0" d="m182.4 212.2c1.1 3.9 23.5 49.2 85.4 15.9 42.8-29.2 34.6-84.5 34.6-84.5 0 0 38.7 56.4-25.7 107-67.7 37.9-98.3-17-94.3-38.4z"/>
|
||||
<path id="Vortex3" class="s0" d="m197 225.2c3.7 1.6 52.8 13.2 66.6-55.7 4.7-51.6-43.1-80.5-43.1-80.5 0 0 68.1 6.1 66.1 88-13.9 76.2-75.7 64.9-89.6 48.2z"/>
|
||||
<path id="Vortex2" class="s0" d="m218 220.7c3.5-2.1 40.5-36.4-9-86.3-40.1-32.8-90.8-9.3-90.8-9.3 0 0 43.1-53.1 109.9-5.6 55.5 54.1 11.6 99.1-10.1 101.2z"/>
|
||||
<path id="Vortex1" class="s0" d="m226.2 203.4c0.6-4.1-1.6-54.5-71.7-49.1-50.9 9.4-65.8 63.3-65.8 63.3 0 0-12.6-67.2 66.8-87.5 77.2-7.2 83.1 55.3 70.7 73.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
|
@ -21,6 +21,5 @@
|
|||
"LoadingPhase": "PostDefault"
|
||||
}
|
||||
],
|
||||
"IsExperimentalVersion": false,
|
||||
"Sealed": true
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "SkyPortal.h"
|
||||
#include "SkyPortalSubsystem.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FSkyPortalModule"
|
||||
|
||||
|
|
88
Source/SkyPortal/Private/SkyPortalFigure.cpp
Normal file
88
Source/SkyPortal/Private/SkyPortalFigure.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#pragma once
|
||||
|
||||
#include "SkyPortalFigure.h"
|
||||
|
||||
|
||||
uint32 FigureData::GetFigureID()
|
||||
{
|
||||
if (ID == 0) {
|
||||
int16_t OutFigureID = 0;
|
||||
|
||||
// The figure ID is stored in Block 1 of Sector 0 (i.e., data[1]), bytes 0 and 1 (16-bit integer, little-endian)
|
||||
OutFigureID = data[1][0] | // Least significant byte
|
||||
(data[1][1] << 8); // Most significant byte, shifted left by 8 bits
|
||||
|
||||
ID = OutFigureID;// Return the 16-bit figure ID
|
||||
return OutFigureID;
|
||||
}
|
||||
else { return ID; }
|
||||
/*
|
||||
// Variant ID is stored in Block 0, bytes 4 to 5 (16-bit integer, little-endian)
|
||||
OutVariantID = (DataBlock.blockdata[0][5] << 8) |
|
||||
DataBlock.blockdata[0][4];
|
||||
*/
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
void FigureData::ReadData(uint8 index)
|
||||
{
|
||||
ClearData();
|
||||
for (uint8 i = 0; i < 64; i++)
|
||||
{
|
||||
GEngine->GetEngineSubsystem<USkyPortalSubsystem>();
|
||||
TArray<uint8> output = SkySubsystem->QueryBlock(index, i);
|
||||
|
||||
uint8[] blockData = new uint8[0x10];
|
||||
Array.Copy(output, 3, blockData, 0, 16);
|
||||
|
||||
// block 1 is sometimes a duplicate of block 0
|
||||
if (i == 1)
|
||||
{
|
||||
if (blockData.SequenceEqual(data[0]))
|
||||
{
|
||||
i -= 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Array.Copy(blockData, 0, data[i], 0, 16);
|
||||
|
||||
if (((i + 1) % 4 == 0) || i < 8)
|
||||
{
|
||||
Array.Copy(data[i], 0, decryptedData[i], 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8[] hashIn = new byte[0x56];
|
||||
data[0].CopyTo(hashIn, 0);
|
||||
data[1].CopyTo(hashIn, 0x10);
|
||||
hashIn[0x20] = i;
|
||||
HASH_CONST.CopyTo(hashIn, 0x21);
|
||||
|
||||
uint8[] key = MD5.Create().ComputeHash(hashIn);
|
||||
|
||||
uint8[] decrypted = new byte[0x10];
|
||||
|
||||
using (Aes aesAlg = Aes.Create())
|
||||
{
|
||||
aesAlg.Key = key;
|
||||
aesAlg.Mode = CipherMode.ECB;
|
||||
aesAlg.Padding = PaddingMode.Zeros;
|
||||
|
||||
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
|
||||
|
||||
decrypted = decryptor.TransformFinalBlock(data[i], 0, data[i].Length);
|
||||
|
||||
}
|
||||
|
||||
Array.Copy(decrypted, 0, decryptedData[i], 0, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void FigureData::ClearData()
|
||||
{
|
||||
}
|
320
Source/SkyPortal/Private/SkyPortalIO.cpp
Normal file
320
Source/SkyPortal/Private/SkyPortalIO.cpp
Normal file
|
@ -0,0 +1,320 @@
|
|||
#include "SkyPortalIO.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogHIDApi);
|
||||
DEFINE_LOG_CATEGORY(LogSkyportalIO);
|
||||
|
||||
|
||||
//Constructor
|
||||
USkyPortalIO::USkyPortalIO()
|
||||
{
|
||||
bPortalReady = OpenPortalHandle();
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool USkyPortalIO::OpenPortalHandle() {
|
||||
//reset
|
||||
if (PortalDevice) {
|
||||
hid_close(PortalDevice);
|
||||
bPortalReady = false;
|
||||
}
|
||||
/*
|
||||
Declare two pointers to hold information about HID devices.
|
||||
"list" will point to the head of the linked list of devices,
|
||||
"attributes" will be used to iterate through the list.
|
||||
*/
|
||||
struct hid_device_info* list, * attributes;
|
||||
|
||||
list = hid_enumerate(0x0, 0x0);
|
||||
// If `list` is NULL, that means no devices were found or there was an error.
|
||||
// In this case, print an error message and terminate the program.
|
||||
if (!list) {
|
||||
UE_LOG(LogHIDApi, Error, TEXT("No devices found"));
|
||||
// Get the error message from the HIDAPI
|
||||
HidError = hid_error(NULL);
|
||||
UE_LOG(LogHIDApi, Error, TEXT("%s"), *HidError);
|
||||
return false;
|
||||
}
|
||||
attributes = list;
|
||||
|
||||
|
||||
|
||||
|
||||
// Iterate through the linked list of devices
|
||||
int vendorCount = sizeof(VendorIds) / sizeof(VendorIds[0]);
|
||||
int productCount = sizeof(ProductIds) / sizeof(ProductIds[0]);
|
||||
|
||||
while (attributes) {
|
||||
// Check if the devices match any of vendor_id and product_id
|
||||
for (int i = 0; i < vendorCount; i++) {
|
||||
for (int j = 0; j < productCount; j++) {
|
||||
if (attributes->vendor_id == VendorIds[i] && attributes->product_id == ProductIds[j]) {
|
||||
UE_LOG(LogHIDApi, Display, TEXT("Portal found"));
|
||||
UE_LOG(LogHIDApi, Log, TEXT("Vendor ID: 0x%x, Product ID: 0x%x"), attributes->vendor_id, attributes->product_id);
|
||||
|
||||
PortalDevice = hid_open(attributes->vendor_id, attributes->product_id, NULL);
|
||||
if (PortalDevice) {
|
||||
UE_LOG(LogHIDApi, Display, TEXT("Successful connection to Portal."));
|
||||
|
||||
// Free the device list
|
||||
hid_free_enumeration(list);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next device in the list
|
||||
attributes = attributes->next;
|
||||
}
|
||||
|
||||
// Free the device list
|
||||
hid_free_enumeration(list);
|
||||
UE_LOG(LogHIDApi, Error, TEXT("No Portals found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// write function need to be different on windows, as hid_write doesn't work with the way windows handle I/O
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#define HID_CTL_CODE(id) \
|
||||
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define HID_IN_CTL_CODE(id) \
|
||||
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
|
||||
|
||||
struct hid_device_ {
|
||||
HANDLE device_handle;
|
||||
BOOL blocking;
|
||||
USHORT output_report_length;
|
||||
unsigned char* write_buf;
|
||||
size_t input_report_length;
|
||||
USHORT feature_report_length;
|
||||
unsigned char* feature_buf;
|
||||
wchar_t* last_error_str;
|
||||
BOOL read_pending;
|
||||
char* read_buf;
|
||||
OVERLAPPED ol;
|
||||
OVERLAPPED write_ol;
|
||||
struct hid_device_info* device_info;
|
||||
};
|
||||
|
||||
|
||||
void USkyPortalIO::Write(FWriteBlock* pb)
|
||||
{
|
||||
if (!ensure(PortalDevice)) {
|
||||
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
|
||||
return;
|
||||
}
|
||||
BOOL res;
|
||||
|
||||
OVERLAPPED ol;
|
||||
memset(&ol, 0, sizeof(ol));
|
||||
|
||||
DWORD bytes_returned;
|
||||
|
||||
res = DeviceIoControl(PortalDevice->device_handle,
|
||||
IOCTL_HID_SET_OUTPUT_REPORT,
|
||||
(unsigned char*)pb->data, write_buf_size,
|
||||
(unsigned char*)pb->data, write_buf_size,
|
||||
&bytes_returned, &ol);
|
||||
ensureMsgf(res, TEXT("Unable to write to Portal"));
|
||||
pb->BytesTransferred = bytes_returned;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
void USkyPortalIO::Write(FWriteBlock* pb) {
|
||||
|
||||
if (!ensure(PortalDevice)) {
|
||||
UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found"));
|
||||
return;
|
||||
}
|
||||
|
||||
pb->data[0] = 0; // Use report 0
|
||||
|
||||
res = hid_write(PortalDevice, pb->data, write_buf_size);
|
||||
ensureMsgf(res != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice));
|
||||
pb->BytesTransferred = res;
|
||||
}
|
||||
#endif
|
||||
|
||||
void USkyPortalIO::WriteRaw(const TArray<uint8>* block)
|
||||
{
|
||||
;
|
||||
int res = hid_write(PortalDevice, block->GetData(), block->GetAllocatedSize()); //return the number of byte written
|
||||
if (res == -1)
|
||||
{
|
||||
UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write raw data to Portal. error:\n %s"), hid_error(PortalDevice));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8* USkyPortalIO::Read()
|
||||
{
|
||||
uint8* output = new byte[0x20];
|
||||
hid_read(PortalDevice, output, 0x20);
|
||||
return output;
|
||||
}
|
||||
|
||||
TArray<uint8> USkyPortalIO::QueryBlock(uint8 characterIndex, uint8 block)
|
||||
{
|
||||
return TArray<uint8>();
|
||||
}
|
||||
|
||||
void USkyPortalIO::Close() {
|
||||
if (PortalDevice) {
|
||||
hid_close(PortalDevice);
|
||||
}
|
||||
bPortalReady = false;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Should not be here
|
||||
bool USkyPortalIO::IsFalsePositive() const
|
||||
{
|
||||
int dif = FMath::Abs(CurrentStatusData.Counter - OldStatusData.Counter);
|
||||
return (dif <= 2 || dif >= 254);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
EPortalCommand GetPortalCommandFromChar(unsigned char Char)
|
||||
{
|
||||
switch (Char)
|
||||
{
|
||||
case 'A':
|
||||
return EPortalCommand::A;
|
||||
case 'C':
|
||||
return EPortalCommand::C;
|
||||
case 'J':
|
||||
return EPortalCommand::J;
|
||||
case 'L':
|
||||
return EPortalCommand::L;
|
||||
case 'M':
|
||||
return EPortalCommand::M;
|
||||
case 'Q':
|
||||
return EPortalCommand::Q;
|
||||
case 'R':
|
||||
return EPortalCommand::R;
|
||||
case 'S':
|
||||
return EPortalCommand::S;
|
||||
default:
|
||||
// Handle the case when the character doesn't match any enum
|
||||
// Return a default or invalid value, or handle the error
|
||||
UE_LOG(LogSkyportalIO, Warning, TEXT("Invalid character for Portal Command: %c"), TCHAR(Char));
|
||||
return EPortalCommand::S; // 'S' for Status as a default
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FPortalStatusData ParsePortalStatus(const uint8* StatusResponse)
|
||||
{
|
||||
FPortalStatusData result;
|
||||
result.Counter = StatusResponse[5];
|
||||
result.bIsReady = (StatusResponse[6] == 0x01);
|
||||
|
||||
// Parse the figure status array (little-endian 32-bit integer)
|
||||
uint32 FigureStatusArray = 0;
|
||||
// Reading the 32-bit integer (character status array) from the buffer
|
||||
FigureStatusArray |= StatusResponse[1]; // 1st byte
|
||||
FigureStatusArray |= (StatusResponse[2] << 8); // 2nd byte
|
||||
FigureStatusArray |= (StatusResponse[3] << 16); // 3rd byte
|
||||
FigureStatusArray |= (StatusResponse[4] << 24); // 4th byte
|
||||
|
||||
bool bChangeBitsSet = false;
|
||||
|
||||
TStaticArray<EFigureStatus, 16> tempArray;
|
||||
// For each of the 16 entries, extract the 2-bit status and map it to EFigureStatus
|
||||
for (int32 i = 0; i < 16; ++i)
|
||||
{
|
||||
uint8 StatusBits = (FigureStatusArray >> (i * 2)) & 0b11; // Extract 2 bits
|
||||
EFigureStatus FigureStatus;
|
||||
|
||||
switch (StatusBits)
|
||||
{
|
||||
case 0b00:
|
||||
FigureStatus = EFigureStatus::NOT_PRESENT;
|
||||
break;
|
||||
case 0b01:
|
||||
FigureStatus = EFigureStatus::PRESENT;
|
||||
break;
|
||||
case 0b11:
|
||||
FigureStatus = EFigureStatus::ADDED; // When it's a new NUID detected
|
||||
break;
|
||||
case 0b10:
|
||||
FigureStatus = EFigureStatus::REMOVED; // New NUID removed
|
||||
break;
|
||||
default:
|
||||
FigureStatus = EFigureStatus::NOT_PRESENT; // Default case
|
||||
break;
|
||||
}
|
||||
|
||||
// Add to the array of figure statuses
|
||||
//PortalStatusData.StatusArray.Insert(FigureStatus, i);
|
||||
tempArray[i] = FigureStatus;
|
||||
}
|
||||
result.StatusArray.SetNum(0);
|
||||
result.StatusArray.Append(tempArray);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
||||
{
|
||||
|
||||
FigureData FigureData;
|
||||
FigureData.dataError = false; // Initialize error flag
|
||||
|
||||
FWriteBlock command;
|
||||
|
||||
// Loop over all 64 blocks
|
||||
for (uint8 BlockIndex = 0; BlockIndex < FIGURE_TOTAL_BLOCKS; ++BlockIndex)
|
||||
{
|
||||
memset(command.data, 0, write_buf_size); //maybe not needed here
|
||||
command.data[1] = 'Q';
|
||||
command.data[2] = FigureIndex; // Figure index (0x00-0x0F)
|
||||
command.data[3] = BlockIndex;
|
||||
uint8* output;
|
||||
do {
|
||||
Write(&command);
|
||||
output = Read();
|
||||
} while (output[0] != 'Q');
|
||||
|
||||
if (output[1] == (0x10 + 'Q')) // Successful query
|
||||
{
|
||||
// Extract the 16 bytes of block data
|
||||
for (int i = 3; i < 19; i++)
|
||||
{
|
||||
FigureData.data[BlockIndex][i] = output[i];
|
||||
}
|
||||
}
|
||||
else if (output[0] == 0x01) {
|
||||
FigureData.dataError = true;
|
||||
UE_LOG(LogSkyportalIO, Warning, TEXT("Error querying block %d from figure %d"), BlockIndex, FigureIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
// Verify that the block index matches the requested block
|
||||
uint8 ReturnedBlockIndex = output[3];
|
||||
if (ReturnedBlockIndex != BlockIndex)
|
||||
{
|
||||
FigureData.dataError = true;
|
||||
UE_LOG(LogSkyportalIO, Warning, TEXT("Mismatched block index. Expected %d, got %d"), BlockIndex, ReturnedBlockIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy block data into FigureData
|
||||
//memcpy(FigureData.blockdata[BlockIndex], &res.buf[4], FIGURE_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Some verifications should happen. Like if dataError is set.
|
||||
|
||||
return FigureData; // Return the complete figure data
|
||||
}
|
105
Source/SkyPortal/Private/SkyPortalRunner.cpp
Normal file
105
Source/SkyPortal/Private/SkyPortalRunner.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include "SkyPortalRunner.h"
|
||||
#include "SkyPortalFigure.h"
|
||||
#include "SkyPortalSubsystem.h"
|
||||
|
||||
FPortalStatusChecker::FPortalStatusChecker(UEngineSubsystem* InSubsystem, float InCheckInterval)
|
||||
: SkyPortalSubsystemRef(InSubsystem), CheckInterval(InCheckInterval), bShouldRun(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool FPortalStatusChecker::Init()
|
||||
{
|
||||
// Initialization logic, if necessary (e.g., logging)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 FPortalStatusChecker::Run()
|
||||
{
|
||||
// Main loop of the thread, runs until Stop() is called
|
||||
while (bShouldRun)
|
||||
{
|
||||
// Check the portal status
|
||||
CheckPortalStatus();
|
||||
|
||||
// Sleep for the specified interval
|
||||
FPlatformProcess::Sleep(CheckInterval);
|
||||
}
|
||||
|
||||
return 0; // Exit code for the thread
|
||||
}
|
||||
|
||||
void FPortalStatusChecker::Stop()
|
||||
{
|
||||
// Signal the thread to stop running
|
||||
bShouldRun = false;
|
||||
}
|
||||
|
||||
void FPortalStatusChecker::Exit()
|
||||
{
|
||||
// Cleanup after the thread has stopped
|
||||
}
|
||||
|
||||
void FPortalStatusChecker::CheckPortalStatus()
|
||||
{
|
||||
// Ensure the subsystem is valid
|
||||
if (SkyPortalSubsystemRef && Cast<USkyPortalSubsystem>(SkyPortalSubsystemRef))
|
||||
{
|
||||
USkyPortalSubsystem* subref = Cast<USkyPortalSubsystem>(SkyPortalSubsystemRef);
|
||||
USkyPortalIO* PortalHandleRef = subref->PortalHandle;
|
||||
UE_LOG(LogSkyportalIO, Verbose, TEXT("Check portal"));
|
||||
if (PortalHandleRef && PortalHandleRef->bPortalReady)
|
||||
{
|
||||
// Call the subsystem function to get portal status
|
||||
uint8* output = PortalHandleRef->Read();
|
||||
EPortalCommand CommandResponse = GetPortalCommandFromChar(output[0]);
|
||||
FigureData figData;
|
||||
switch (CommandResponse)
|
||||
{
|
||||
case S:
|
||||
CurrentStatusData = ParsePortalStatus(output);
|
||||
UE_LOG(LogSkyportalIO, Verbose, TEXT("Output Data: %s"), *BytesToHex(output, sizeof(output)));
|
||||
|
||||
//Send delegate when new informations are received
|
||||
if (OldStatusData != CurrentStatusData) {
|
||||
|
||||
|
||||
for (int i = 0; i < CurrentStatusData.StatusArray.Num(); i++) {
|
||||
if (CurrentStatusData.StatusArray[i] != OldStatusData.StatusArray[i]) {
|
||||
if (
|
||||
//!FalsePositive() //filter conflicting infos
|
||||
true) {
|
||||
//FigureDataBlock FigureData;
|
||||
switch (CurrentStatusData.StatusArray[i])
|
||||
{
|
||||
case EFigureStatus::NOT_PRESENT:
|
||||
|
||||
break;
|
||||
case EFigureStatus::PRESENT:
|
||||
//FigureData = ReadFigureBlocks(i);
|
||||
//subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i);
|
||||
break;
|
||||
case EFigureStatus::ADDED:
|
||||
figData = PortalHandleRef->ReadFigureBlocks(i);
|
||||
subref->OnSkylanderAdded.Broadcast(figData.GetFigureID(), i);
|
||||
break;
|
||||
case EFigureStatus::REMOVED:
|
||||
subref->OnSkylanderRemoved.Broadcast(00, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OldStatusData = CurrentStatusData;
|
||||
subref->StatusData = CurrentStatusData;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Do something with the status (log, notify, etc.)
|
||||
UE_LOG(LogSkyportalIO, Verbose, TEXT("Portal Status:"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,16 +1,239 @@
|
|||
// A lot of this code is made because of the work of https://github.com/capull0/SkyDumper and https://github.com/silicontrip/SkyReader
|
||||
|
||||
#include "SkyPortalSubsystem.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "SkyPortal.h"
|
||||
|
||||
#include "HAL/RunnableThread.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
|
||||
|
||||
void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
|
||||
Super::Initialize(Collection);
|
||||
// Custom initialization logic
|
||||
UE_LOG(LogTemp, Warning, TEXT("SkyPortalSubsystem Initialized"));
|
||||
// Start the status checker thread
|
||||
StatusChecker = new FPortalStatusChecker(this, RunnerInterval);
|
||||
StatusCheckerThread = FRunnableThread::Create(StatusChecker, TEXT("PortalStatusCheckerThread"), 0, TPri_AboveNormal);
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Initialized"));
|
||||
|
||||
}
|
||||
|
||||
void USkyPortalSubsystem::Deinitialize()
|
||||
{
|
||||
// Custom cleanup logic
|
||||
UE_LOG(LogTemp, Warning, TEXT("SkyPortalSubsystem Deinitialized"));
|
||||
// Stop the thread when the subsystem is deinitialized
|
||||
if (StatusChecker)
|
||||
{
|
||||
StatusChecker->Stop();
|
||||
StatusCheckerThread->WaitForCompletion();
|
||||
|
||||
delete StatusCheckerThread;
|
||||
delete StatusChecker;
|
||||
StatusChecker = nullptr;
|
||||
StatusCheckerThread = nullptr;
|
||||
}
|
||||
|
||||
// Disconnect portal
|
||||
if (PortalHandle) {
|
||||
PortalHandle->Close();
|
||||
}
|
||||
hid_exit();
|
||||
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Deinitialized"));
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
|
||||
void USkyPortalSubsystem::PortalActivate(const bool bShouldActivate)
|
||||
{
|
||||
FWriteBlock command;
|
||||
|
||||
memset(command.data, 0, write_buf_size);
|
||||
command.data[1] = 'A';
|
||||
command.data[2] = bShouldActivate;
|
||||
uint8* output;
|
||||
do {
|
||||
PortalHandle->Write(&command);
|
||||
output = PortalHandle->Read();
|
||||
} while (output[0] != 'A');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void USkyPortalSubsystem::PortalReady()
|
||||
{
|
||||
FWriteBlock command;
|
||||
|
||||
memset(command.data, 0, write_buf_size); //maybe not needed here
|
||||
command.data[1] = 'R';
|
||||
unsigned char* output;
|
||||
do {
|
||||
PortalHandle->Write(&command);
|
||||
output = PortalHandle->Read();
|
||||
} while (output[0] != 'R');
|
||||
|
||||
unsigned char _PortalId[2] = { output[1],output[2] };
|
||||
uint16_t BE_PortalId = (_PortalId[0] << 8) | _PortalId[1]; // Big-endian format
|
||||
uint32 BEU_PortalId = (_PortalId[0] << 8) | _PortalId[1]; // Big-endian format unsigned
|
||||
uint16_t LE_PortalId = (_PortalId[1] << 8) | _PortalId[0]; //little endian
|
||||
//uint32 LEU_PortalId = (_PortalId[1] << 8) | _PortalId[0]; //little endian unsigned
|
||||
PortalId = BEU_PortalId; //Need a conversion as uint16 is not supported in BP
|
||||
|
||||
}
|
||||
|
||||
FPortalStatusData USkyPortalSubsystem::PortalStatus() {
|
||||
FWriteBlock command;
|
||||
|
||||
memset(command.data, 0, write_buf_size); //maybe not needed here
|
||||
command.data[1] = 'S';
|
||||
uint8* output;
|
||||
|
||||
do {
|
||||
PortalHandle->Write(&command);
|
||||
output = PortalHandle->Read();
|
||||
} while (output[0] != 'S');
|
||||
|
||||
|
||||
|
||||
return ParsePortalStatus(output);
|
||||
}
|
||||
|
||||
SKYPORTAL_API bool USkyPortalSubsystem::RestartRunner()
|
||||
{
|
||||
if (StatusChecker)
|
||||
{
|
||||
StatusChecker->Stop();
|
||||
StatusCheckerThread->WaitForCompletion();
|
||||
|
||||
delete StatusCheckerThread;
|
||||
delete StatusChecker;
|
||||
StatusChecker = nullptr;
|
||||
StatusCheckerThread = nullptr;
|
||||
}
|
||||
|
||||
StatusChecker = new FPortalStatusChecker(this, RunnerInterval); // Check every 10 milliseconds
|
||||
StatusCheckerThread = FRunnableThread::Create(StatusChecker, TEXT("PortalStatusCheckerThread"), 0, TPri_AboveNormal);
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Initialized"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma region Color functions
|
||||
|
||||
void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color)
|
||||
{
|
||||
|
||||
unsigned char r = FMath::Clamp(Color.R * 100, 0.0f, 255.0f);
|
||||
unsigned char g = FMath::Clamp(Color.G * 100, 0.0f, 255.0f);
|
||||
unsigned char b = FMath::Clamp(Color.B * 100, 0.0f, 255.0f);
|
||||
|
||||
FWriteBlock command;
|
||||
|
||||
memset(command.data, 0, write_buf_size);
|
||||
|
||||
command.data[1] = 'C';
|
||||
command.data[2] = r; // R
|
||||
command.data[3] = g; // G
|
||||
command.data[4] = b; // B
|
||||
|
||||
// no response for this one.
|
||||
PortalHandle->Write(&command);
|
||||
}
|
||||
|
||||
void USkyPortalSubsystem::ChangePortalColorSide(const FLinearColor& Color, const EPortalSide PortalSide, const float BlendTime)
|
||||
{
|
||||
|
||||
unsigned char r = FMath::Clamp(Color.R * 100, 0, 255);
|
||||
unsigned char g = FMath::Clamp(Color.G * 100, 0, 255);
|
||||
unsigned char b = FMath::Clamp(Color.B * 100, 0, 255);
|
||||
EPortalSide _portalside;
|
||||
FWriteBlock command;
|
||||
|
||||
memset(command.data, 0, write_buf_size);
|
||||
|
||||
if (PortalSide == EPortalSide::BOTH) {
|
||||
_portalside = EPortalSide::LEFT;
|
||||
}
|
||||
else {
|
||||
_portalside = PortalSide;
|
||||
}
|
||||
|
||||
switch (_portalside) {
|
||||
case EPortalSide::LEFT:
|
||||
command.data[1] = 'J';
|
||||
command.data[2] = 0x00;
|
||||
case EPortalSide::RIGHT:
|
||||
command.data[1] = 'J';
|
||||
command.data[2] = 0x02;
|
||||
case EPortalSide::TRAP:
|
||||
command.data[1] = 'L';
|
||||
command.data[2] = 0x01;
|
||||
command.data[3] = FMath::Max3(r, g, b); // calculate brightness
|
||||
PortalHandle->Write(&command); //since it's a color command for trap, only 3 bytes are needed, no response.
|
||||
return;
|
||||
}
|
||||
|
||||
command.data[3] = r; // R
|
||||
command.data[4] = g; // G
|
||||
command.data[5] = b; // B
|
||||
|
||||
//Convert the time in millisecond into two bytes
|
||||
uint16_t _time = BlendTime;
|
||||
uint8_t _time_low = _time & 0xFF; // Get the low byte by masking the least significant 8 bits
|
||||
uint8_t _time_high = (_time >> 8) & 0xFF; // Get the high byte extracted by shifting the bits 8 positions to the right and masking the result
|
||||
command.data[6] = _time_low;
|
||||
command.data[7] = _time_high;
|
||||
|
||||
uint8* output;
|
||||
do {
|
||||
PortalHandle->Write(&command);
|
||||
output = PortalHandle->Read();
|
||||
} while (output[0] != 'J');
|
||||
|
||||
if (PortalSide == EPortalSide::BOTH) {
|
||||
ChangePortalColorSide(Color, EPortalSide::RIGHT, BlendTime); // send a second command for the right side
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
|
||||
void USkyPortalSubsystem::Sleep(int sleepMs) {
|
||||
FPlatformProcess::Sleep(sleepMs * 0.0001);
|
||||
}
|
||||
|
||||
|
||||
bool USkyPortalSubsystem::PortalConnect()
|
||||
{
|
||||
PortalHandle = NewObject<USkyPortalIO>();
|
||||
if (IsValid(PortalHandle)) {
|
||||
UE_LOG(LogSkyportalIO, Log, TEXT("Portal connected: "));
|
||||
PortalReady();
|
||||
PortalActivate(1);
|
||||
|
||||
Sleep(500);
|
||||
ChangePortalColor(FLinearColor(0.5, 0.5, 0.5));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USkyPortalSubsystem::IsPortalReady()
|
||||
{
|
||||
if (PortalHandle) {
|
||||
return PortalHandle->bPortalReady;
|
||||
}
|
||||
//maybe should send a status request ?
|
||||
return false;
|
||||
}
|
||||
|
||||
SKYPORTAL_API void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "SkyPortalSubsystem.h"
|
||||
|
||||
class FSkyPortalModule : public IModuleInterface
|
||||
{
|
||||
|
|
83
Source/SkyPortal/Public/SkyPortalDefinitions.h
Normal file
83
Source/SkyPortal/Public/SkyPortalDefinitions.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "SkyPortalDefinitions.generated.h"
|
||||
|
||||
// This file is not supposed to have a c++ counterpart. Use it as a library
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EFigureStatus : uint8
|
||||
{
|
||||
NOT_PRESENT = 0b00 UMETA(DisplayName = "Not Present"),
|
||||
PRESENT = 0b01 UMETA(DisplayName = "Present"),
|
||||
ADDED = 0b11 UMETA(DisplayName = "Added"),
|
||||
REMOVED = 0b10 UMETA(DisplayName = "Removed")
|
||||
};
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum EPortalSide {
|
||||
LEFT UMETA(DisplayName = "Left side"),
|
||||
RIGHT UMETA(DisplayName = "Right side"),
|
||||
BOTH UMETA(DisplayName = "Both left and right"),
|
||||
TRAP UMETA(DisplayName = "Trap")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum EPortalCommand {
|
||||
A UMETA(DisplayName = "Activate"),
|
||||
C UMETA(DisplayName = "Color"),
|
||||
J UMETA(DisplayName = "Advanced color"),
|
||||
L UMETA(DisplayName = "Trap color"),
|
||||
M UMETA(DisplayName = "Music"),
|
||||
Q UMETA(DisplayName = "Query"),
|
||||
R UMETA(DisplayName = "Ready"),
|
||||
S UMETA(DisplayName = "Status")
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FPortalStatusData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Array of statuses
|
||||
UPROPERTY(BlueprintReadOnly, EditFixedSize, Category = "SkyPortal|Figure", meta = (EditFixedOrder))
|
||||
TArray<EFigureStatus> StatusArray;
|
||||
|
||||
// timestamp.
|
||||
// only one byte long. This means that after the value 0xFF, it overflows back to 0x00.
|
||||
// Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF.
|
||||
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
||||
uint8 Counter;
|
||||
|
||||
// Should always be true
|
||||
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
||||
bool bIsReady;
|
||||
|
||||
explicit FPortalStatusData(uint8 ArraySize = 16, EFigureStatus DefaultStatus = EFigureStatus::NOT_PRESENT) :
|
||||
Counter(0),
|
||||
bIsReady(true)
|
||||
{
|
||||
// Initialisation du tableau StatusArray avec 16 éléments par défaut
|
||||
StatusArray.Init(DefaultStatus, ArraySize);
|
||||
}
|
||||
|
||||
// Overload the == operator
|
||||
// Different only between
|
||||
bool operator==(const FPortalStatusData& Other) const
|
||||
{
|
||||
if (bIsReady == Other.bIsReady && Counter == Other.Counter) {
|
||||
if (StatusArray == Other.StatusArray) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Overload the != operator
|
||||
bool operator!=(const FPortalStatusData& Other) const
|
||||
{
|
||||
return !(*this == Other);
|
||||
}
|
||||
};
|
68
Source/SkyPortal/Public/SkyPortalFigure.h
Normal file
68
Source/SkyPortal/Public/SkyPortalFigure.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
//#include "SkyPortalFigure.generated.h"
|
||||
|
||||
|
||||
#define FIGURE_TOTAL_BLOCKS 64
|
||||
#define FIGURE_BLOCK_SIZE 16
|
||||
|
||||
typedef struct {
|
||||
unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error;
|
||||
} FigureDataBlock;
|
||||
|
||||
|
||||
|
||||
class FigureData {
|
||||
public:
|
||||
// Data Arrays
|
||||
uint8 data[64][16];
|
||||
uint8 decryptedData[64][16];
|
||||
bool dataError;
|
||||
|
||||
// Properties
|
||||
#pragma region manufacturer
|
||||
uint32 NUID; // should under no circumstances be corrupted. 4-byte
|
||||
uint8 BCC; //Block Check Character. When this BCC does not match the NUID of the tag, the tag ceases to function. stored in block 0 at offset 0x4
|
||||
uint8 SAK = 0x81; //needs to be set to allow for the tag to be read correctly
|
||||
uint16 ATQA; //always set to 0x01 0x0F
|
||||
FString ProductionYear; //last 2 digits of the year that the tag was manufactured as Binary-coded decimal
|
||||
#pragma endregion
|
||||
#pragma region Toy code
|
||||
uint32 ToyCodeNumber1, ToyCodeNumber2;
|
||||
uint64 FullToyCodeNumber;
|
||||
FString ToyCode;
|
||||
#pragma endregion
|
||||
int16 ID;
|
||||
int16 VariantID;
|
||||
#pragma region counters
|
||||
uint8 counter1;
|
||||
uint8 couter2;
|
||||
#pragma endregion
|
||||
FString Nickname;
|
||||
|
||||
FigureData()
|
||||
{
|
||||
ClearData();
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
|
||||
uint32 GetFigureID();
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
|
||||
uint32 GetFigureIdByIndex(uint32 index);
|
||||
|
||||
UFUNCTION()
|
||||
TArray<uint8> QueryBlock(uint8 characterIndex, uint8 block = 0x00);
|
||||
|
||||
void ReadData(uint8 index);
|
||||
void ClearData();
|
||||
uint8 GetByte(int block, int offset);
|
||||
void SetByte(int block, int offset, uint8 value);
|
||||
uint16 GetShort(int block, int offset);
|
||||
uint32 GetUInt(int block, int offset);
|
||||
void Dump(bool decrypted, FString filePath);
|
||||
};
|
||||
|
||||
|
94
Source/SkyPortal/Public/SkyPortalIO.h
Normal file
94
Source/SkyPortal/Public/SkyPortalIO.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
/*
|
||||
* This is the bridge between hidapi and unreal and contains all the rawdata of the portal
|
||||
*/
|
||||
#include "CoreMinimal.h"
|
||||
#include "hidapi.h"
|
||||
#include "SkyPortalDefinitions.h"
|
||||
#include "SkyPortalFigure.h"
|
||||
#include "SkyPortalIO.generated.h"
|
||||
|
||||
#pragma region Definitions
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All);
|
||||
|
||||
constexpr auto write_buf_size = 0x21; //buffer size for all the write command on portal. Should always be 0x21 - 33
|
||||
constexpr auto TIMEOUT = 30000; //milliseconds
|
||||
|
||||
/* Portal physicial device IDs */
|
||||
const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 };
|
||||
const int ProductIds[4] = { 0x150, 0x967, 0x1f17 };
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
FPortalStatusData ParsePortalStatus(const uint8* StatusResponse);
|
||||
EPortalCommand GetPortalCommandFromChar(unsigned char Char);
|
||||
|
||||
/* Contain all the data that pass inside hidapi write + the number of bytes in case of successful write
|
||||
*
|
||||
* @param data all the block data, should be 0x21 sized
|
||||
* @param BytesTransferred In case of successful write, print the number of byte transfered. Could be used for verifications
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FWriteBlock {
|
||||
GENERATED_BODY()
|
||||
unsigned char data[write_buf_size];
|
||||
int BytesTransferred;
|
||||
};
|
||||
|
||||
/* This class will contain and handle all the low-lewel functions
|
||||
* Should be able to be called anywhere
|
||||
*/
|
||||
UCLASS()
|
||||
class USkyPortalIO : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
USkyPortalIO();
|
||||
|
||||
/* hidapi will write error message in here*/
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FString HidError;
|
||||
|
||||
/*Portal ready to be listened or to receive commands*/
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
bool bPortalReady = false;
|
||||
|
||||
/* Connect to Portal - will write the PortalDevice var if success */
|
||||
bool OpenPortalHandle();
|
||||
|
||||
/* Send block to portal. In windows, don't use the hidapi */
|
||||
void Write(FWriteBlock* Block);
|
||||
|
||||
/* Send raw command to portal */
|
||||
void WriteRaw(const TArray<uint8>* block);
|
||||
|
||||
/* Listen to portal
|
||||
* @return The data sended by the portal device
|
||||
*/
|
||||
uint8* Read();
|
||||
|
||||
UFUNCTION()
|
||||
TArray<uint8> QueryBlock(uint8 characterIndex, uint8 block = 0x00);
|
||||
|
||||
FigureData ReadFigureBlocks(uint8 FigureIndex);
|
||||
|
||||
/* Close connection to Portal*/
|
||||
void Close();
|
||||
|
||||
private:
|
||||
|
||||
/*TODO: Should not be here
|
||||
bool IsFalsePositive() const;
|
||||
*/
|
||||
|
||||
|
||||
/* Portal device ref, useful for hidapi commands */
|
||||
hid_device* PortalDevice;
|
||||
|
||||
};
|
||||
|
41
Source/SkyPortal/Public/SkyPortalRunner.h
Normal file
41
Source/SkyPortal/Public/SkyPortalRunner.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "HAL/Runnable.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class FPortalStatusChecker : public FRunnable {
|
||||
public:
|
||||
/* Constructor : pass the subsystem and desired check interval(in seconds)
|
||||
*
|
||||
* @param InSubsystem Should always be the SkyPortalSubsystem
|
||||
*/
|
||||
FPortalStatusChecker(UEngineSubsystem* InSubsystem, float InCheckInterval);
|
||||
|
||||
// FRunnable interface
|
||||
virtual bool Init() override;
|
||||
virtual uint32 Run() override;
|
||||
virtual void Stop() override;
|
||||
virtual void Exit() override;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FPortalStatusData CurrentStatusData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FPortalStatusData OldStatusData;
|
||||
|
||||
private:
|
||||
// Pointer to the subsystem that contains PortalStatus()
|
||||
UEngineSubsystem* SkyPortalSubsystemRef;
|
||||
|
||||
// Time interval (in seconds) for status checking
|
||||
float CheckInterval;
|
||||
|
||||
// Thread control variables
|
||||
FThreadSafeBool bShouldRun;
|
||||
|
||||
// Helper function to check portal status
|
||||
void CheckPortalStatus();
|
||||
};
|
||||
|
|
@ -1,16 +1,152 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/EngineSubsystem.h"
|
||||
#include "SkyPortalRunner.h"
|
||||
#include "SkyPortalIO.h"
|
||||
#include "SkyPortalSubsystem.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class SKYPORTAL_API USkyPortalSubsystem : public UEngineSubsystem
|
||||
#pragma region Definitions
|
||||
|
||||
//// Delegates
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Handle all the blueprints functions and game logic.
|
||||
*
|
||||
*/
|
||||
UCLASS(MinimalAPI)
|
||||
class USkyPortalSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Override initialization and deinitialization methods
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
|
||||
/***********************************************************/
|
||||
/********************* Portal Actions *********************/
|
||||
/***********************************************************/
|
||||
|
||||
/* The first function to run, before anything else.
|
||||
* It will re-init and prepare the portal for receiving/sending inputs
|
||||
*
|
||||
* @return false if portal is not found
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal"))
|
||||
SKYPORTAL_API bool PortalConnect();
|
||||
|
||||
/* Make sure that the connection to the portal works and that the device that is connected is actually a portal.
|
||||
*
|
||||
* In case of success, will update the PortalId, wich is different for each portal model.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
|
||||
SKYPORTAL_API void PortalReady();
|
||||
|
||||
/* Activate all the main functions of the portal, like figure detection or wireless signal.
|
||||
* This command should be used before any other commands with the exception of the Ready command
|
||||
*
|
||||
* When the portal is activated, it will periodically send out Status responses even when no Status request has been sent. If the portal has not been activated, or if it has been deactivated again, Status responses will still be sent when requested.
|
||||
* If a Deactivate request is received by a portal, all LEDs will turn off. They can be turned on again by their respective commands.
|
||||
*
|
||||
* @param bShouldActivate Optional : If false, send a Deactivate command.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
|
||||
SKYPORTAL_API void PortalActivate(const bool bShouldActivate = true);
|
||||
|
||||
|
||||
/* Change portal color, ideally should be called just at the start. For gameplay usage, use ChangePortalColorSide()
|
||||
*
|
||||
* @param NextColor New color
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel))
|
||||
SKYPORTAL_API void ChangePortalColor(const FLinearColor& NextColor = FLinearColor::Green);
|
||||
|
||||
/*Send a **Status** command, to see if the portal is ready to receive new commands*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal"))
|
||||
SKYPORTAL_API bool IsPortalReady();
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING"))
|
||||
SKYPORTAL_API void PortalMusic(const USoundWave* Sound);
|
||||
|
||||
/**/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
|
||||
SKYPORTAL_API FPortalStatusData PortalStatus();
|
||||
|
||||
/**/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal"))
|
||||
SKYPORTAL_API bool RestartRunner();
|
||||
|
||||
|
||||
/* Change the color of the portal, can separate side and even trap ligth
|
||||
* @param NextColor New color
|
||||
* @param PortalSide The actors to record
|
||||
* @param BlendTime Blend between current color and NextColor, in milliseconds
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel))
|
||||
SKYPORTAL_API void ChangePortalColorSide(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f);
|
||||
|
||||
|
||||
|
||||
// Blueprint-assignable event property
|
||||
UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander")
|
||||
FOnSkylanderAddedDelegate OnSkylanderAdded;
|
||||
|
||||
// Blueprint-assignable event property
|
||||
UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander")
|
||||
FOnSkylanderRemovedDelegate OnSkylanderRemoved;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FPortalStatusData StatusData;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
float RunnerInterval = 0.01f; //In seconds
|
||||
|
||||
/* Different for each portal model.
|
||||
*
|
||||
* SSA :
|
||||
* GIANTS :
|
||||
* SWAP FORCE : 0000547 ? , 515
|
||||
* TRAP TEAM :
|
||||
* SUPERCHARGERS :
|
||||
* IMAGINATORS :
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
int PortalId;
|
||||
|
||||
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
USkyPortalIO* PortalHandle;
|
||||
|
||||
/**/
|
||||
UPROPERTY()
|
||||
bool bPortalConnected_DEPRECATED = PortalHandle ? PortalHandle->bPortalReady : false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/* Sleep the system
|
||||
*
|
||||
* @param sleepMs Sleep time (in milliseconds)
|
||||
*/
|
||||
static void Sleep(int sleepMs);
|
||||
|
||||
// Pointer to the status checker thread
|
||||
FPortalStatusChecker* StatusChecker;
|
||||
FRunnableThread* StatusCheckerThread;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,51 @@
|
|||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class SkyPortal : ModuleRules
|
||||
{
|
||||
public SkyPortal(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
bPrecompile = true;
|
||||
// Add the path to the hidapi include directory
|
||||
PublicIncludePaths.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "include"));
|
||||
|
||||
// Check platform-specific settings
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
// Add the path to the library (for Windows platform)
|
||||
PublicSystemLibraryPaths.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "lib", "Windows"));
|
||||
|
||||
// Link against the hidapi.lib (static library)
|
||||
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "lib", "Windows", "hidapi.lib"));
|
||||
|
||||
// Add runtime library path for the .dll (dynamic library)
|
||||
PublicRuntimeLibraryPaths.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "bin", "Windows"));
|
||||
|
||||
// Copy the DLL to the output folder, if using dynamic linking
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/hidapi.dll", Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "bin", "Windows", "hidapi.dll"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
PublicSystemLibraryPaths.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "lib", "Mac"));
|
||||
PublicAdditionalLibraries.Add("hidapi.a");
|
||||
|
||||
// Handle Mac-specific dynamic linking
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/hidapi.dylib", Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "bin", "Mac", "hidapi.dylib"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PublicSystemLibraryPaths.Add(Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "lib", "Linux"));
|
||||
PublicAdditionalLibraries.Add("hidapi.a");
|
||||
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/hidapi.so", Path.Combine(PluginDirectory, "ThirdParty", "hidapi", "bin", "Linux", "hidapi.so"));
|
||||
}
|
||||
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
|
BIN
ThirdParty/hidapi/bin/Windows/hidapi.dll
vendored
Normal file
BIN
ThirdParty/hidapi/bin/Windows/hidapi.dll
vendored
Normal file
Binary file not shown.
BIN
ThirdParty/hidapi/bin/Windows/hidapi.lib
vendored
Normal file
BIN
ThirdParty/hidapi/bin/Windows/hidapi.lib
vendored
Normal file
Binary file not shown.
BIN
ThirdParty/hidapi/bin/Windows/hidapi.pdb
vendored
Normal file
BIN
ThirdParty/hidapi/bin/Windows/hidapi.pdb
vendored
Normal file
Binary file not shown.
628
ThirdParty/hidapi/include/hidapi.h
vendored
Normal file
628
ThirdParty/hidapi/include/hidapi.h
vendored
Normal file
|
@ -0,0 +1,628 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2023, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU General Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/** @file
|
||||
* @defgroup API hidapi API
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_H__
|
||||
#define HIDAPI_H__
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
/* #480: this is to be refactored properly for v1.0 */
|
||||
#ifdef _WIN32
|
||||
#ifndef HID_API_NO_EXPORT_DEFINE
|
||||
#define HID_API_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HID_API_EXPORT
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#endif
|
||||
/* To be removed in v1.0 */
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
|
||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||
|
||||
/** @brief Static/compile-time major version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_MAJOR 0
|
||||
/** @brief Static/compile-time minor version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_MINOR 14
|
||||
/** @brief Static/compile-time patch version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_PATCH 0
|
||||
|
||||
/* Helper macros */
|
||||
#define HID_API_AS_STR_IMPL(x) #x
|
||||
#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x)
|
||||
#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3)
|
||||
|
||||
/** @brief Coverts a version as Major/Minor/Patch into a number:
|
||||
<8 bit major><16 bit minor><8 bit patch>.
|
||||
|
||||
This macro was added in version 0.12.0.
|
||||
|
||||
Convenient function to be used for compile-time checks, like:
|
||||
@code{.c}
|
||||
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
@endcode
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p))
|
||||
|
||||
/** @brief Static/compile-time version of the library.
|
||||
|
||||
This macro was added in version 0.12.0.
|
||||
|
||||
@see @ref HID_API_MAKE_VERSION.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||
|
||||
/** @brief Static/compile-time string version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||
|
||||
/** @brief Maximum expected HID Report descriptor size in bytes.
|
||||
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE 4096
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/** A structure to hold the version numbers. */
|
||||
struct hid_api_version {
|
||||
int major; /**< major version number */
|
||||
int minor; /**< minor version number */
|
||||
int patch; /**< patch version number */
|
||||
};
|
||||
|
||||
struct hid_device_;
|
||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
||||
|
||||
/** @brief HID underlying bus types.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
typedef enum {
|
||||
/** Unknown bus type */
|
||||
HID_API_BUS_UNKNOWN = 0x00,
|
||||
|
||||
/** USB bus
|
||||
Specifications:
|
||||
https://usb.org/hid */
|
||||
HID_API_BUS_USB = 0x01,
|
||||
|
||||
/** Bluetooth or Bluetooth LE bus
|
||||
Specifications:
|
||||
https://www.bluetooth.com/specifications/specs/human-interface-device-profile-1-1-1/
|
||||
https://www.bluetooth.com/specifications/specs/hid-service-1-0/
|
||||
https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/ */
|
||||
HID_API_BUS_BLUETOOTH = 0x02,
|
||||
|
||||
/** I2C bus
|
||||
Specifications:
|
||||
https://docs.microsoft.com/previous-versions/windows/hardware/design/dn642101(v=vs.85) */
|
||||
HID_API_BUS_I2C = 0x03,
|
||||
|
||||
/** SPI bus
|
||||
Specifications:
|
||||
https://www.microsoft.com/download/details.aspx?id=103325 */
|
||||
HID_API_BUS_SPI = 0x04,
|
||||
} hid_bus_type;
|
||||
|
||||
/** hidapi info structure */
|
||||
struct hid_device_info {
|
||||
/** Platform-specific device path */
|
||||
char *path;
|
||||
/** Device Vendor ID */
|
||||
unsigned short vendor_id;
|
||||
/** Device Product ID */
|
||||
unsigned short product_id;
|
||||
/** Serial Number */
|
||||
wchar_t *serial_number;
|
||||
/** Device Release Number in binary-coded decimal,
|
||||
also known as Device Version Number */
|
||||
unsigned short release_number;
|
||||
/** Manufacturer String */
|
||||
wchar_t *manufacturer_string;
|
||||
/** Product string */
|
||||
wchar_t *product_string;
|
||||
/** Usage Page for this Device/Interface
|
||||
(Windows/Mac/hidraw only) */
|
||||
unsigned short usage_page;
|
||||
/** Usage for this Device/Interface
|
||||
(Windows/Mac/hidraw only) */
|
||||
unsigned short usage;
|
||||
/** The USB interface which this logical device
|
||||
represents.
|
||||
|
||||
Valid only if the device is a USB HID device.
|
||||
Set to -1 in all other cases.
|
||||
*/
|
||||
int interface_number;
|
||||
|
||||
/** Pointer to the next device */
|
||||
struct hid_device_info *next;
|
||||
|
||||
/** Underlying bus type
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
*/
|
||||
hid_bus_type bus_type;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Initialize the HIDAPI library.
|
||||
|
||||
This function initializes the HIDAPI library. Calling it is not
|
||||
strictly necessary, as it will be called automatically by
|
||||
hid_enumerate() and any of the hid_open_*() functions if it is
|
||||
needed. This function should be called at the beginning of
|
||||
execution however, if there is a chance of HIDAPI handles
|
||||
being opened by different threads simultaneously.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
||||
|
||||
/** @brief Finalize the HIDAPI library.
|
||||
|
||||
This function frees all of the static data associated with
|
||||
HIDAPI. It should be called at the end of execution to avoid
|
||||
memory leaks.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
||||
|
||||
/** @brief Enumerate the HID Devices.
|
||||
|
||||
This function returns a linked list of all the HID devices
|
||||
attached to the system which match vendor_id and product_id.
|
||||
If @p vendor_id is set to 0 then any vendor matches.
|
||||
If @p product_id is set to 0 then any product matches.
|
||||
If @p vendor_id and @p product_id are both set to 0, then
|
||||
all HID devices will be returned.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the types of device
|
||||
to open.
|
||||
@param product_id The Product ID (PID) of the types of
|
||||
device to open.
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device_info, containing information about the HID devices
|
||||
attached to the system,
|
||||
or NULL in the case of failure or if no HID devices present in the system.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned value by this function must to be freed by calling hid_free_enumeration(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
||||
|
||||
/** @brief Free an enumeration Linked List
|
||||
|
||||
This function frees a linked list created by hid_enumerate().
|
||||
|
||||
@ingroup API
|
||||
@param devs Pointer to a list of struct_device returned from
|
||||
hid_enumerate().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
||||
|
||||
/** @brief Open a HID device using a Vendor ID (VID), Product ID
|
||||
(PID) and optionally a serial number.
|
||||
|
||||
If @p serial_number is NULL, the first device with the
|
||||
specified VID and PID is opened.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the device to open.
|
||||
@param product_id The Product ID (PID) of the device to open.
|
||||
@param serial_number The Serial Number of the device to open
|
||||
(Optionally NULL).
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned object must be freed by calling hid_close(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
||||
|
||||
/** @brief Open a HID device by its path name.
|
||||
|
||||
The path name be determined by calling hid_enumerate(), or a
|
||||
platform-specific path name can be used (eg: /dev/hidraw0 on
|
||||
Linux).
|
||||
|
||||
@ingroup API
|
||||
@param path The path name of the device to open
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned object must be freed by calling hid_close(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
||||
|
||||
/** @brief Write an Output report to a HID device.
|
||||
|
||||
The first byte of @p data[] must contain the Report ID. For
|
||||
devices which only support a single report, this must be set
|
||||
to 0x0. The remaining bytes contain the report data. Since
|
||||
the Report ID is mandatory, calls to hid_write() will always
|
||||
contain one more byte than the report contains. For example,
|
||||
if a hid report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_write(), the Report ID (or 0x0, for devices with a
|
||||
single report), followed by the report data (16 bytes). In
|
||||
this example, the length passed in would be 17.
|
||||
|
||||
hid_write() will send the data on the first OUT endpoint, if
|
||||
one exists. If it does not, it will send the data through
|
||||
the Control Endpoint (Endpoint 0).
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Read an Input report from a HID device with timeout.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
@param milliseconds timeout in milliseconds or -1 for blocking wait.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
If no packet was available to be read within
|
||||
the timeout period, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
||||
|
||||
/** @brief Read an Input report from a HID device.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
If no packet was available to be read and
|
||||
the handle is in non-blocking mode, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Set the device handle to be non-blocking.
|
||||
|
||||
In non-blocking mode calls to hid_read() will return
|
||||
immediately with a value of 0 if there is no data to be
|
||||
read. In blocking mode, hid_read() will wait (block) until
|
||||
there is data to read before returning.
|
||||
|
||||
Nonblocking can be turned on and off at any time.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param nonblock enable or not the nonblocking reads
|
||||
- 1 to enable nonblocking
|
||||
- 0 to disable nonblocking.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);
|
||||
|
||||
/** @brief Send a Feature report to the device.
|
||||
|
||||
Feature reports are sent over the Control endpoint as a
|
||||
Set_Report transfer. The first byte of @p data[] must
|
||||
contain the Report ID. For devices which only support a
|
||||
single report, this must be set to 0x0. The remaining bytes
|
||||
contain the report data. Since the Report ID is mandatory,
|
||||
calls to hid_send_feature_report() will always contain one
|
||||
more byte than the report contains. For example, if a hid
|
||||
report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_send_feature_report(): the Report ID (or 0x0, for
|
||||
devices which do not use numbered reports), followed by the
|
||||
report data (16 bytes). In this example, the length passed
|
||||
in would be 17.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send, including
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_output_report(hid_device* device, const unsigned char* data, size_t length);
|
||||
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a feature report from a HID device.
|
||||
|
||||
Set the first byte of @p data[] to the Report ID of the
|
||||
report to be read. Make sure to allow space for this
|
||||
extra byte in @p data[]. Upon return, the first byte will
|
||||
still contain the Report ID, and the report data will
|
||||
start in data[1].
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read, or set it to zero
|
||||
if your device does not use numbered reports.
|
||||
@param length The number of bytes to read, including an
|
||||
extra byte for the report ID. The buffer can be longer
|
||||
than the actual report.
|
||||
|
||||
@returns
|
||||
This function returns the number of bytes read plus
|
||||
one for the report ID (which is still in the first
|
||||
byte), or -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a input report from a HID device.
|
||||
|
||||
Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0)
|
||||
|
||||
Set the first byte of @p data[] to the Report ID of the
|
||||
report to be read. Make sure to allow space for this
|
||||
extra byte in @p data[]. Upon return, the first byte will
|
||||
still contain the Report ID, and the report data will
|
||||
start in data[1].
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read, or set it to zero
|
||||
if your device does not use numbered reports.
|
||||
@param length The number of bytes to read, including an
|
||||
extra byte for the report ID. The buffer can be longer
|
||||
than the actual report.
|
||||
|
||||
@returns
|
||||
This function returns the number of bytes read plus
|
||||
one for the report ID (which is still in the first
|
||||
byte), or -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Close a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev);
|
||||
|
||||
/** @brief Get The Manufacturer String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Product String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Serial Number String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The struct #hid_device_info from a HID device.
|
||||
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
|
||||
@returns
|
||||
This function returns a pointer to the struct #hid_device_info
|
||||
for this hid_device, or NULL in the case of failure.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
This struct is valid until the device is closed with hid_close().
|
||||
|
||||
@note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user.
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev);
|
||||
|
||||
/** @brief Get a string from a HID device, based on its string index.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string_index The index of the string to get.
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a report descriptor from a HID device.
|
||||
|
||||
Since version 0.14.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0)
|
||||
|
||||
User has to provide a preallocated buffer where descriptor will be copied to.
|
||||
The recommended size for preallocated buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param buf The buffer to copy descriptor into.
|
||||
@param buf_size The size of the buffer in bytes.
|
||||
|
||||
@returns
|
||||
This function returns non-negative number of bytes actually copied, or -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
|
||||
This function is intended for logging/debugging purposes.
|
||||
|
||||
This function guarantees to never return NULL.
|
||||
If there was no error in the last function call -
|
||||
the returned string clearly indicates that.
|
||||
|
||||
Any HIDAPI function that can explicitly indicate an execution failure
|
||||
(e.g. by an error code, or by returning NULL) - may set the error string,
|
||||
to be returned by this function.
|
||||
|
||||
Strings returned from hid_error() must not be freed by the user,
|
||||
i.e. owned by HIDAPI library.
|
||||
Device-specific error string may remain allocated at most until hid_close() is called.
|
||||
Global error string may remain allocated at most until hid_exit() is called.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open(),
|
||||
or NULL to get the last non-device-specific error
|
||||
(e.g. for errors in hid_open() or hid_enumerate()).
|
||||
|
||||
@returns
|
||||
A string describing the last error (if any).
|
||||
*/
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev);
|
||||
|
||||
/** @brief Get a runtime version of the library.
|
||||
|
||||
This function is thread-safe.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
Pointer to statically allocated struct, that contains version.
|
||||
*/
|
||||
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void);
|
||||
|
||||
|
||||
/** @brief Get a runtime version string of the library.
|
||||
|
||||
This function is thread-safe.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
Pointer to statically allocated string, that contains version string.
|
||||
*/
|
||||
HID_API_EXPORT const char* HID_API_CALL hid_version_str(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
74
ThirdParty/hidapi/include/hidapi_winapi.h
vendored
Normal file
74
ThirdParty/hidapi/include/hidapi_winapi.h
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU General Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/** @file
|
||||
* @defgroup API hidapi API
|
||||
*
|
||||
* Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_WINAPI_H__
|
||||
#define HIDAPI_WINAPI_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <guiddef.h>
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Get the container ID for a HID device.
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
This function returns the `DEVPKEY_Device_ContainerId` property of
|
||||
the given device. This can be used to correlate different
|
||||
interfaces/ports on the same hardware device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param container_id The device's container ID on return.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id);
|
||||
|
||||
/**
|
||||
* @brief Reconstructs a HID Report Descriptor from a Win32 HIDP_PREPARSED_DATA structure.
|
||||
* This reconstructed report descriptor is logical identical to the real report descriptor,
|
||||
* but not byte wise identical.
|
||||
*
|
||||
* @param[in] hidp_preparsed_data Pointer to the HIDP_PREPARSED_DATA to read, i.e.: the value of PHIDP_PREPARSED_DATA,
|
||||
* as returned by HidD_GetPreparsedData WinAPI function.
|
||||
* @param buf Pointer to the buffer where the report descriptor should be stored.
|
||||
* @param[in] buf_size Size of the buffer. The recommended size for the buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||
*
|
||||
* @return Returns size of reconstructed report descriptor if successful, -1 for error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_winapi_descriptor_reconstruct_pp_data(void *hidp_preparsed_data, unsigned char *buf, size_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
BIN
ThirdParty/hidapi/lib/Windows/hidapi.dll
vendored
Normal file
BIN
ThirdParty/hidapi/lib/Windows/hidapi.dll
vendored
Normal file
Binary file not shown.
BIN
ThirdParty/hidapi/lib/Windows/hidapi.lib
vendored
Normal file
BIN
ThirdParty/hidapi/lib/Windows/hidapi.lib
vendored
Normal file
Binary file not shown.
BIN
ThirdParty/hidapi/lib/Windows/hidapi.pdb
vendored
Normal file
BIN
ThirdParty/hidapi/lib/Windows/hidapi.pdb
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue