Initial re-upload of spice2x-24-08-24

This commit is contained in:
2024-08-28 11:10:34 -04:00
commit caa9e02285
1181 changed files with 380065 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
# SpiceAPI C++ Library
This library is still a bit experimental and might contain bugs.
To include it into your project, it's recommended to just copy the
files into your source directory.
To use the wrappers, RapidJSON is required and you might need to
adjust the include paths for your project's build.

View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View File

@@ -0,0 +1,181 @@
#include <iostream>
#include <ws2tcpip.h>
#include "connection.h"
namespace spiceapi {
// settings
static const size_t RECEIVE_BUFFER_SIZE = 64 * 1024;
static const int RECEIVE_TIMEOUT = 1000;
}
spiceapi::Connection::Connection(std::string host, uint16_t port, std::string password) {
this->host = host;
this->port = port;
this->password = password;
this->socket = INVALID_SOCKET;
this->cipher = nullptr;
// WSA startup
WSADATA wsa_data;
int error = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (error) {
std::cerr << "Failed to start WSA: " << error << std::endl;
exit(1);
}
}
spiceapi::Connection::~Connection() {
// clean up
if (this->cipher != nullptr)
delete this->cipher;
// cleanup WSA
WSACleanup();
}
void spiceapi::Connection::cipher_alloc() {
// delete old cipher
if (this->cipher != nullptr) {
delete this->cipher;
this->cipher = nullptr;
}
// create new cipher if password is set
if (this->password.length() > 0) {
this->cipher = new RC4(
(uint8_t *) this->password.c_str(),
strlen(this->password.c_str()));
}
}
bool spiceapi::Connection::check() {
int result = 0;
// check if socket is invalid
if (this->socket == INVALID_SOCKET) {
// get all addresses
addrinfo *addr_list;
addrinfo hints{};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if ((result = getaddrinfo(
this->host.c_str(),
std::to_string(this->port).c_str(),
&hints,
&addr_list))) {
std::cerr << "getaddrinfo failed: " << result << std::endl;
return false;
}
// check all addresses
for (addrinfo *addr = addr_list; addr != NULL; addr = addr->ai_next) {
// try open socket
this->socket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (this->socket == INVALID_SOCKET) {
std::cerr << "socket failed: " << WSAGetLastError() << std::endl;
freeaddrinfo(addr_list);
return false;
}
// try connect
result = connect(this->socket, addr->ai_addr, (int) addr->ai_addrlen);
if (result == SOCKET_ERROR) {
closesocket(this->socket);
this->socket = INVALID_SOCKET;
continue;
}
// configure socket
int opt_val;
opt_val = 1;
setsockopt(this->socket, IPPROTO_TCP, TCP_NODELAY, (const char*) &opt_val, sizeof(opt_val));
opt_val = RECEIVE_TIMEOUT;
setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &opt_val, sizeof(opt_val));
// connection successful
this->cipher_alloc();
break;
}
// check if successful
freeaddrinfo(addr_list);
if (this->socket == INVALID_SOCKET) {
return false;
}
}
// socket probably still valid
return true;
}
void spiceapi::Connection::change_pass(std::string password) {
this->password = password;
this->cipher_alloc();
}
std::string spiceapi::Connection::request(std::string json) {
// check connection
if (!this->check())
return "";
// crypt
auto json_len = strlen(json.c_str()) + 1;
uint8_t* json_data = new uint8_t[json_len];
memcpy(json_data, json.c_str(), json_len);
if (this->cipher != nullptr)
this->cipher->crypt(json_data, json_len);
// send
auto send_result = send(this->socket, (const char*) json_data, (int) json_len, 0);
delete[] json_data;
if (send_result == SOCKET_ERROR || send_result < (int) json_len) {
closesocket(this->socket);
this->socket = INVALID_SOCKET;
return "";
}
// receive
uint8_t receive_data[RECEIVE_BUFFER_SIZE];
size_t receive_data_len = 0;
int receive_result;
while ((receive_result = recv(
this->socket,
(char*) &receive_data[receive_data_len],
sizeof(receive_data) - receive_data_len, 0)) > 0) {
// check for buffer overflow
if (receive_data_len + receive_result >= sizeof(receive_data)) {
closesocket(this->socket);
this->socket = INVALID_SOCKET;
return "";
}
// crypt
if (this->cipher != nullptr)
this->cipher->crypt(&receive_data[receive_data_len], (size_t) receive_result);
// increase received data length
receive_data_len += receive_result;
// check for message end
if (receive_data[receive_data_len - 1] == 0)
break;
}
// return resulting json
if (receive_data_len > 0) {
return std::string((const char *) &receive_data[0], receive_data_len - 1);
} else {
// receive error
this->socket = INVALID_SOCKET;
return "";
}
}

View File

@@ -0,0 +1,31 @@
#ifndef SPICEAPI_CONNECTION_H
#define SPICEAPI_CONNECTION_H
#include <string>
#include <winsock2.h>
#include "rc4.h"
namespace spiceapi {
class Connection {
private:
std::string host;
uint16_t port;
std::string password;
SOCKET socket;
RC4* cipher;
void cipher_alloc();
public:
Connection(std::string host, uint16_t port, std::string password = "");
~Connection();
bool check();
void change_pass(std::string password);
std::string request(std::string json);
};
}
#endif //SPICEAPI_CONNECTION_H

View File

@@ -0,0 +1,45 @@
#include "rc4.h"
#include <iterator>
spiceapi::RC4::RC4(uint8_t *key, size_t key_size) {
// initialize S-BOX
for (size_t i = 0; i < std::size(s_box); i++)
s_box[i] = (uint8_t) i;
// check key size
if (!key_size)
return;
// KSA
size_t j = 0;
for (size_t i = 0; i < std::size(s_box); i++) {
// update
j = (j + s_box[i] + key[i % key_size]) % std::size(s_box);
// swap
auto tmp = s_box[i];
s_box[i] = s_box[j];
s_box[j] = tmp;
}
}
void spiceapi::RC4::crypt(uint8_t *data, size_t size) {
// iterate all bytes
for (size_t pos = 0; pos < size; pos++) {
// update
a = (a + 1) % std::size(s_box);
b = (b + s_box[a]) % std::size(s_box);
// swap
auto tmp = s_box[a];
s_box[a] = s_box[b];
s_box[b] = tmp;
// crypt
data[pos] ^= s_box[(s_box[a] + s_box[b]) % std::size(s_box)];
}
}

View File

@@ -0,0 +1,21 @@
#ifndef SPICEAPI_RC4_H
#define SPICEAPI_RC4_H
#include <cstdint>
namespace spiceapi {
class RC4 {
private:
uint8_t s_box[256];
size_t a = 0, b = 0;
public:
RC4(uint8_t *key, size_t key_size);
void crypt(uint8_t *data, size_t size);
};
}
#endif //SPICEAPI_RC4_H

View File

@@ -0,0 +1,638 @@
#include "wrappers.h"
#include <random>
#include <string>
/*
* RapidJSON dependency
* You might need to adjust the paths when importing into your own project.
*/
#include "external/rapidjson/document.h"
#include "external/rapidjson/writer.h"
using namespace rapidjson;
namespace spiceapi {
static inline std::string doc2str(Document &doc) {
StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
doc.Accept(writer);
return sb.GetString();
}
static inline Document request_gen(const char *module, const char *function) {
// create document
Document doc;
doc.SetObject();
// add attributes
auto &alloc = doc.GetAllocator();
doc.AddMember("id", msg_gen_id(), alloc);
doc.AddMember("module", StringRef(module), alloc);
doc.AddMember("function", StringRef(function), alloc);
// add params
Value noparam(kArrayType);
doc.AddMember("params", noparam, alloc);
// return document
return doc;
}
static inline Document *response_get(std::string json) {
// parse document
Document *doc = new Document();
doc->Parse(json.c_str());
// check for parse error
if (doc->HasParseError()) {
delete doc;
return nullptr;
}
// check id
auto it_id = doc->FindMember("id");
if (it_id == doc->MemberEnd() || !(*it_id).value.IsUint64()) {
delete doc;
return nullptr;
}
// check errors
auto it_errors = doc->FindMember("errors");
if (it_errors == doc->MemberEnd() || !(*it_errors).value.IsArray()) {
delete doc;
return nullptr;
}
// check error count
if ((*it_errors).value.Size() > 0) {
delete doc;
return nullptr;
}
// check data
auto it_data = doc->FindMember("data");
if (it_data == doc->MemberEnd() || !(*it_data).value.IsArray()) {
delete doc;
return nullptr;
}
// return document
return doc;
}
}
uint64_t spiceapi::msg_gen_id() {
static uint64_t id_global = 0;
// check if global ID was initialized
if (id_global == 0) {
// generate a new ID
std::random_device rd;
std::mt19937_64 gen(rd());
std::uniform_int_distribution<uint64_t> dist(1, (uint64_t) std::llround(std::pow(2, 63)));
id_global = dist(gen);
} else {
// increase by one
id_global++;
}
// return global ID
return id_global;
}
bool spiceapi::analogs_read(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
auto req = request_gen("analogs", "read");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"];
for (auto &val : data.GetArray()) {
AnalogState state;
state.name = val[0].GetString();
state.value = val[1].GetFloat();
states.push_back(state);
}
delete res;
return true;
}
bool spiceapi::analogs_write(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
auto req = request_gen("analogs", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
state_val.PushBack(state.value, alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::analogs_write_reset(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
auto req = request_gen("analogs", "write_reset");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::buttons_read(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
auto req = request_gen("buttons", "read");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"];
for (auto &val : data.GetArray()) {
ButtonState state;
state.name = val[0].GetString();
state.value = val[1].GetFloat();
states.push_back(state);
}
delete res;
return true;
}
bool spiceapi::buttons_write(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
auto req = request_gen("buttons", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
state_val.PushBack(state.value, alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::buttons_write_reset(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
auto req = request_gen("buttons", "write_reset");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::card_insert(spiceapi::Connection &con, size_t index, const char *card_id) {
auto req = request_gen("card", "insert");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(index, alloc);
params.PushBack(StringRef(card_id), alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::coin_get(Connection &con, int &coins) {
auto req = request_gen("coin", "get");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
coins = (*res)["data"][0].GetInt();
delete res;
return true;
}
bool spiceapi::coin_set(Connection &con, int coins) {
auto req = request_gen("coin", "set");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(coins, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::coin_insert(Connection &con, int coins) {
auto req = request_gen("coin", "insert");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(coins, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::coin_blocker_get(Connection &con, bool &closed) {
auto req = request_gen("coin", "blocker_get");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
closed = (*res)["data"][0].GetBool();
delete res;
return true;
}
bool spiceapi::control_raise(spiceapi::Connection &con, const char *signal) {
auto req = request_gen("control", "raise");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(StringRef(signal), alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::control_exit(spiceapi::Connection &con) {
auto req = request_gen("control", "exit");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::control_exit(spiceapi::Connection &con, int exit_code) {
auto req = request_gen("control", "exit");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(exit_code, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::control_restart(spiceapi::Connection &con) {
auto req = request_gen("control", "restart");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::control_session_refresh(spiceapi::Connection &con) {
auto req = request_gen("control", "session_refresh");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto key = (*res)["data"][0].GetString();
con.change_pass(key);
delete res;
return true;
}
bool spiceapi::control_shutdown(spiceapi::Connection &con) {
auto req = request_gen("control", "shutdown");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::control_reboot(spiceapi::Connection &con) {
auto req = request_gen("control", "reboot");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::iidx_ticker_get(spiceapi::Connection &con, char *ticker) {
auto req = request_gen("iidx", "ticker_get");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto data = (*res)["data"][0].GetString();
strncpy(ticker, data, 9);
ticker[9] = 0x00;
delete res;
return true;
}
bool spiceapi::iidx_ticker_set(spiceapi::Connection &con, const char *ticker) {
auto req = request_gen("iidx", "ticker_set");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(StringRef(ticker), alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::iidx_ticker_reset(spiceapi::Connection &con) {
auto req = request_gen("iidx", "ticker_reset");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::info_avs(spiceapi::Connection &con, spiceapi::InfoAvs &info) {
auto req = request_gen("info", "avs");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"][0];
info.model = data["model"].GetString();
info.dest = data["dest"].GetString();
info.spec = data["spec"].GetString();
info.rev = data["rev"].GetString();
info.ext = data["ext"].GetString();
delete res;
return true;
}
bool spiceapi::info_launcher(spiceapi::Connection &con, spiceapi::InfoLauncher &info) {
auto req = request_gen("info", "launcher");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"][0];
info.version = data["version"].GetString();
info.compile_date = data["compile_date"].GetString();
info.compile_time = data["compile_time"].GetString();
info.system_time = data["system_time"].GetString();
for (auto &arg : data["args"].GetArray())
info.args.push_back(arg.GetString());
delete res;
return true;
}
bool spiceapi::info_memory(spiceapi::Connection &con, spiceapi::InfoMemory &info) {
auto req = request_gen("info", "memory");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"][0];
info.mem_total = data["mem_total"].GetUint64();
info.mem_total_used = data["mem_total_used"].GetUint64();
info.mem_used = data["mem_used"].GetUint64();
info.vmem_total = data["vmem_total"].GetUint64();
info.vmem_total_used = data["vmem_total_used"].GetUint64();
info.vmem_used = data["vmem_used"].GetUint64();
delete res;
return true;
}
bool spiceapi::keypads_write(spiceapi::Connection &con, unsigned int keypad, const char *input) {
auto req = request_gen("keypads", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(keypad, alloc);
params.PushBack(StringRef(input), alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::keypads_set(spiceapi::Connection &con, unsigned int keypad, std::vector<char> &keys) {
auto req = request_gen("keypads", "set");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(keypad, alloc);
for (auto &key : keys)
params.PushBack(StringRef(&key, 1), alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::keypads_get(spiceapi::Connection &con, unsigned int keypad, std::vector<char> &keys) {
auto req = request_gen("keypads", "get");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(keypad, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"];
for (auto &val : data.GetArray())
keys.push_back(val.GetString()[0]);
delete res;
return true;
}
bool spiceapi::lights_read(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
auto req = request_gen("lights", "read");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"];
for (auto &val : data.GetArray()) {
LightState state;
state.name = val[0].GetString();
state.value = val[1].GetFloat();
states.push_back(state);
}
delete res;
return true;
}
bool spiceapi::lights_write(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
auto req = request_gen("lights", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
state_val.PushBack(state.value, alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::lights_write_reset(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
auto req = request_gen("lights", "write_reset");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(StringRef(state.name.c_str()), alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::memory_write(spiceapi::Connection &con, const char *dll_name, const char *hex, uint32_t offset) {
auto req = request_gen("memory", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(StringRef(dll_name), alloc);
params.PushBack(StringRef(hex), alloc);
params.PushBack(offset, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::memory_read(spiceapi::Connection &con, const char *dll_name, uint32_t offset, uint32_t size,
std::string &hex) {
auto req = request_gen("memory", "read");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(StringRef(dll_name), alloc);
params.PushBack(offset, alloc);
params.PushBack(size, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
hex = (*res)["data"][0].GetString();
delete res;
return true;
}
bool spiceapi::memory_signature(spiceapi::Connection &con, const char *dll_name, const char *signature,
const char *replacement, uint32_t offset, uint32_t usage, uint32_t &file_offset) {
auto req = request_gen("memory", "signature");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
params.PushBack(StringRef(dll_name), alloc);
params.PushBack(StringRef(signature), alloc);
params.PushBack(StringRef(replacement), alloc);
params.PushBack(offset, alloc);
params.PushBack(usage, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
file_offset = (*res)["data"][0].GetUint();
delete res;
return true;
}
bool spiceapi::touch_read(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
auto req = request_gen("touch", "read");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"];
for (auto &val : data.GetArray()) {
TouchState state;
state.id = val[0].GetUint64();
state.x = val[1].GetInt64();
state.y = val[2].GetInt64();
states.push_back(state);
}
delete res;
return true;
}
bool spiceapi::touch_write(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
auto req = request_gen("touch", "write");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states) {
Value state_val(kArrayType);
state_val.PushBack(state.id, alloc);
state_val.PushBack(state.x, alloc);
state_val.PushBack(state.y, alloc);
params.PushBack(state_val, alloc);
}
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::touch_write_reset(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
auto req = request_gen("touch", "write_reset");
auto &alloc = req.GetAllocator();
Value params(kArrayType);
for (auto &state : states)
params.PushBack(state.id, alloc);
req["params"] = params;
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
delete res;
return true;
}
bool spiceapi::lcd_info(spiceapi::Connection &con, spiceapi::LCDInfo &info) {
auto req = request_gen("lcd", "info");
auto res = response_get(con.request(doc2str(req)));
if (!res)
return false;
auto &data = (*res)["data"][0];
info.enabled = data["enabled"].GetBool();
info.csm = data["csm"].GetString();
info.bri = data["bri"].GetInt();
info.con = data["con"].GetInt();
info.bl = data["bl"].GetInt();
info.red = data["red"].GetInt();
info.green = data["green"].GetInt();
info.blue = data["blue"].GetInt();
delete res;
return true;
}

View File

@@ -0,0 +1,104 @@
#ifndef SPICEAPI_WRAPPERS_H
#define SPICEAPI_WRAPPERS_H
#include <vector>
#include <string>
#include "connection.h"
namespace spiceapi {
struct AnalogState {
std::string name;
float value;
};
struct ButtonState {
std::string name;
float value;
};
struct LightState {
std::string name;
float value;
};
struct InfoAvs {
std::string model, dest, spec, rev, ext;
};
struct InfoLauncher {
std::string version;
std::string compile_date, compile_time, system_time;
std::vector<std::string> args;
};
struct InfoMemory {
uint64_t mem_total, mem_total_used, mem_used;
uint64_t vmem_total, vmem_total_used, vmem_used;
};
struct TouchState {
uint64_t id;
int64_t x, y;
};
struct LCDInfo {
bool enabled;
std::string csm;
uint8_t bri, con, bl, red, green, blue;
};
uint64_t msg_gen_id();
bool analogs_read(Connection &con, std::vector<AnalogState> &states);
bool analogs_write(Connection &con, std::vector<AnalogState> &states);
bool analogs_write_reset(Connection &con, std::vector<AnalogState> &states);
bool buttons_read(Connection &con, std::vector<ButtonState> &states);
bool buttons_write(Connection &con, std::vector<ButtonState> &states);
bool buttons_write_reset(Connection &con, std::vector<ButtonState> &states);
bool card_insert(Connection &con, size_t index, const char *card_id);
bool coin_get(Connection &con, int &coins);
bool coin_set(Connection &con, int coins);
bool coin_insert(Connection &con, int coins=1);
bool coin_blocker_get(Connection &con, bool &closed);
bool control_raise(Connection &con, const char *signal);
bool control_exit(Connection &con);
bool control_exit(Connection &con, int exit_code);
bool control_restart(Connection &con);
bool control_session_refresh(Connection &con);
bool control_shutdown(Connection &con);
bool control_reboot(Connection &con);
bool iidx_ticker_get(Connection &con, char *ticker);
bool iidx_ticker_set(Connection &con, const char *ticker);
bool iidx_ticker_reset(Connection &con);
bool info_avs(Connection &con, InfoAvs &info);
bool info_launcher(Connection &con, InfoLauncher &info);
bool info_memory(Connection &con, InfoMemory &info);
bool keypads_write(Connection &con, unsigned int keypad, const char *input);
bool keypads_set(Connection &con, unsigned int keypad, std::vector<char> &keys);
bool keypads_get(Connection &con, unsigned int keypad, std::vector<char> &keys);
bool lights_read(Connection &con, std::vector<LightState> &states);
bool lights_write(Connection &con, std::vector<LightState> &states);
bool lights_write_reset(Connection &con, std::vector<LightState> &states);
bool memory_write(Connection &con, const char *dll_name, const char *hex, uint32_t offset);
bool memory_read(Connection &con, const char *dll_name, uint32_t offset, uint32_t size, std::string &hex);
bool memory_signature(Connection &con, const char *dll_name, const char *signature, const char *replacement,
uint32_t offset, uint32_t usage, uint32_t &file_offset);
bool touch_read(Connection &con, std::vector<TouchState> &states);
bool touch_write(Connection &con, std::vector<TouchState> &states);
bool touch_write_reset(Connection &con, std::vector<TouchState> &states);
bool lcd_info(Connection &con, LCDInfo &info);
}
#endif //SPICEAPI_WRAPPERS_H