From adea9e3a45965a09bc7ed76c96274ae0051af87a Mon Sep 17 00:00:00 2001 From: 4yn <4yn@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:56:23 +0800 Subject: [PATCH] draft redboard i/o --- .vscode/settings.json | 6 +- src-lzfx/.gitignore | 1 + src-lzfx/Cargo.lock | 182 +++++++++++++ src-lzfx/Cargo.toml | 11 + src-lzfx/build.rs | 13 + src-lzfx/include/lzfx.h | 98 +++++++ src-lzfx/include/lzfxbridge.h | 6 + src-lzfx/src/lib.rs | 13 + src-lzfx/src/lzfx.cc | 395 +++++++++++++++++++++++++++++ src-lzfx/src/lzfxbridge.cc | 32 +++ src-slider_io/Cargo.lock | 146 ++++++++--- src-slider_io/Cargo.toml | 1 + src-slider_io/src/device/config.rs | 5 + src-slider_io/src/device/hid.rs | 261 ++++++++++++------- src-tauri/Cargo.lock | 9 + src/App.svelte | 1 + 16 files changed, 1047 insertions(+), 133 deletions(-) create mode 100644 src-lzfx/.gitignore create mode 100644 src-lzfx/Cargo.lock create mode 100644 src-lzfx/Cargo.toml create mode 100644 src-lzfx/build.rs create mode 100644 src-lzfx/include/lzfx.h create mode 100644 src-lzfx/include/lzfxbridge.h create mode 100644 src-lzfx/src/lib.rs create mode 100644 src-lzfx/src/lzfx.cc create mode 100644 src-lzfx/src/lzfxbridge.cc diff --git a/.vscode/settings.json b/.vscode/settings.json index 513ea11..51607c2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,8 @@ "cmake.sourceDirectory": "${workspaceFolder}/src-serial", "cmake.buildDirectory": "${workspaceFolder}/src-serial/build", "files.associations": { + "*.sage": "python", + "*.svx": "mdx", "xstring": "cpp", "algorithm": "cpp", "atomic": "cpp", @@ -75,6 +77,8 @@ "xlocbuf": "cpp", "xlocmes": "cpp", "xlocmon": "cpp", - "xloctime": "cpp" + "xloctime": "cpp", + "lib.rs.h": "c", + "lzfx.h": "c" } } diff --git a/src-lzfx/.gitignore b/src-lzfx/.gitignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/src-lzfx/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/src-lzfx/Cargo.lock b/src-lzfx/Cargo.lock new file mode 100644 index 0000000..ede5233 --- /dev/null +++ b/src-lzfx/Cargo.lock @@ -0,0 +1,182 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "cxx" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe98ba1789d56fb3db3bee5e032774d4f421b685de7ba703643584ba24effbe" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4ce20f6b8433da4841b1dadfb9468709868022d829d5ca1f2ffbda928455ea3" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20888d9e1d2298e2ff473cee30efe7d5036e437857ab68bbfea84c74dba91da2" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "libc" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "lzfx" +version = "0.1.0" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src-lzfx/Cargo.toml b/src-lzfx/Cargo.toml new file mode 100644 index 0000000..8be0474 --- /dev/null +++ b/src-lzfx/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "lzfx" +version = "0.1.0" +edition = "2018" +publish = false + +[dependencies] +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" diff --git a/src-lzfx/build.rs b/src-lzfx/build.rs new file mode 100644 index 0000000..90b08fd --- /dev/null +++ b/src-lzfx/build.rs @@ -0,0 +1,13 @@ +fn main() { + cxx_build::bridge("src/lib.rs") + .file("src/lzfx.cc") + .file("src/lzfxbridge.cc") + .flag_if_supported("-std=c++14") + .compile("cxxbridge-demo"); + + println!("cargo:rerun-if-changed=src/lib.rs"); + println!("cargo:rerun-if-changed=src/lzfx.cc"); + println!("cargo:rerun-if-changed=src/lzfxbridge.cc"); + println!("cargo:rerun-if-changed=include/lzfx.h"); + println!("cargo:rerun-if-changed=include/lzfxbridge.h"); +} diff --git a/src-lzfx/include/lzfx.h b/src-lzfx/include/lzfx.h new file mode 100644 index 0000000..7557c2f --- /dev/null +++ b/src-lzfx/include/lzfx.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2009 Andrew Collette + * http://lzfx.googlecode.com + * + * Implements an LZF-compatible compressor/decompressor based on the liblzf + * codebase written by Marc Lehmann. This code is released under the BSD + * license. License and original copyright statement follow. + * + * + * Copyright (c) 2000-2008 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LZFX_H +#define LZFX_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Documented behavior, including function signatures and error codes, + is guaranteed to remain unchanged for releases with the same major + version number. Releases of the same major version are also able + to read each other's output, although the output itself is not + guaranteed to be byte-for-byte identical. +*/ +#define LZFX_VERSION_MAJOR 0 +#define LZFX_VERSION_MINOR 1 +#define LZFX_VERSION_STRING "0.1" + +/* Hashtable size (2**LZFX_HLOG entries) */ +#ifndef LZFX_HLOG +#define LZFX_HLOG 16 +#endif + +/* Predefined errors. */ +#define LZFX_ESIZE -1 /* Output buffer too small */ +#define LZFX_ECORRUPT -2 /* Invalid data for decompression */ +#define LZFX_EARGS -3 /* Arguments invalid (NULL) */ + + /* Buffer-to buffer compression. + + Supply pre-allocated input and output buffers via ibuf and obuf, and + their size in bytes via ilen and olen. Buffers may not overlap. + + On success, the function returns a non-negative value and the argument + olen contains the compressed size in bytes. On failure, a negative + value is returned and olen is not modified. + */ + int lzfx_compress(const void *ibuf, unsigned int ilen, + void *obuf, unsigned int *olen); + + /* Buffer-to-buffer decompression. + + Supply pre-allocated input and output buffers via ibuf and obuf, and + their size in bytes via ilen and olen. Buffers may not overlap. + + On success, the function returns a non-negative value and the argument + olen contains the uncompressed size in bytes. On failure, a negative + value is returned. + + If the failure code is LZFX_ESIZE, olen contains the minimum buffer size + required to hold the decompressed data. Otherwise, olen is not modified. + + Supplying a zero *olen is a valid and supported strategy to determine the + required buffer size. This does not require decompression of the entire + stream and is consequently very fast. Argument obuf may be NULL in + this case only. + */ + int lzfx_decompress(const void *ibuf, unsigned int ilen, + void *obuf, unsigned int *olen); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src-lzfx/include/lzfxbridge.h b/src-lzfx/include/lzfxbridge.h new file mode 100644 index 0000000..b3abb28 --- /dev/null +++ b/src-lzfx/include/lzfxbridge.h @@ -0,0 +1,6 @@ +#pragma once +#include "rust/cxx.h" + +uint32_t compress(const rust::Vec &data, rust::Vec &out); + +uint32_t decompress(const rust::Vec &data, rust::Vec &out); \ No newline at end of file diff --git a/src-lzfx/src/lib.rs b/src-lzfx/src/lib.rs new file mode 100644 index 0000000..916ad12 --- /dev/null +++ b/src-lzfx/src/lib.rs @@ -0,0 +1,13 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("lzfx/include/lzfxbridge.h"); + + fn compress(data: &Vec, out: &mut Vec) -> u32; + + fn decompress(data: &Vec, out: &mut Vec) -> u32; + } +} + +pub use ffi::compress; +pub use ffi::decompress; diff --git a/src-lzfx/src/lzfx.cc b/src-lzfx/src/lzfx.cc new file mode 100644 index 0000000..6cfa03d --- /dev/null +++ b/src-lzfx/src/lzfx.cc @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2009 Andrew Collette + * http://lzfx.googlecode.com + * + * Implements an LZF-compatible compressor/decompressor based on the liblzf + * codebase written by Marc Lehmann. This code is released under the BSD + * license. License and original copyright statement follow. + * + * + * Copyright (c) 2000-2008 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lzfx/include/lzfx.h" + +#define LZFX_HSIZE (1 << (LZFX_HLOG)) + +/* We need this for memset */ +#ifdef __cplusplus +#include +#else +#include +#endif + +#if __GNUC__ >= 3 +#define fx_expect_false(expr) __builtin_expect((expr) != 0, 0) +#define fx_expect_true(expr) __builtin_expect((expr) != 0, 1) +#else +#define fx_expect_false(expr) (expr) +#define fx_expect_true(expr) (expr) +#endif + +typedef unsigned char u8; +typedef const u8 *LZSTATE[LZFX_HSIZE]; + +/* Define the hash function */ +#define LZFX_FRST(p) (((p[0]) << 8) | p[1]) +#define LZFX_NEXT(v, p) (((v) << 8) | p[2]) +#define LZFX_IDX(h) (((h >> (3 * 8 - LZFX_HLOG)) - h) & (LZFX_HSIZE - 1)) + +/* These cannot be changed, as they are related to the compressed format. */ +#define LZFX_MAX_LIT (1 << 5) +#define LZFX_MAX_OFF (1 << 13) +#define LZFX_MAX_REF ((1 << 8) + (1 << 3)) + +static int lzfx_getsize(const void *ibuf, unsigned int ilen, unsigned int *olen); + +/* Compressed format + + There are two kinds of structures in LZF/LZFX: literal runs and back + references. The length of a literal run is encoded as L - 1, as it must + contain at least one byte. Literals are encoded as follows: + + 000LLLLL + + Back references are encoded as follows. The smallest possible encoded + length value is 1, as otherwise the control byte would be recognized as + a literal run. Since at least three bytes must match for a back reference + to be inserted, the length is encoded as L - 2 instead of L - 1. The + offset (distance to the desired data in the output buffer) is encoded as + o - 1, as all offsets are at least 1. The binary format is: + + LLLooooo oooooooo for backrefs of real length < 9 (1 <= L < 7) + 111ooooo LLLLLLLL oooooooo for backrefs of real length >= 9 (L > 7) +*/ +int lzfx_compress(const void *const ibuf, const unsigned int ilen, + void *obuf, unsigned int *const olen) +{ + + /* Hash table; an array of u8*'s which point + to various locations in the input buffer */ + const u8 *htab[LZFX_HSIZE]; + + const u8 **hslot; /* Pointer to entry in hash table */ + unsigned int hval; /* Hash value generated by macros above */ + const u8 *ref; /* Pointer to candidate match location in input */ + + const u8 *ip = (const u8 *)ibuf; + const u8 *const in_end = ip + ilen; + + u8 *op = (u8 *)obuf; + const u8 *const out_end = (olen == NULL ? NULL : op + *olen); + + int lit; /* # of bytes in current literal run */ + +#if defined(WIN32) && defined(_M_X64) + unsigned _int64 off; /* workaround for missing POSIX compliance */ +#else + unsigned long off; +#endif + + if (olen == NULL) + return LZFX_EARGS; + if (ibuf == NULL) + { + if (ilen != 0) + return LZFX_EARGS; + *olen = 0; + return 0; + } + if (obuf == NULL) + return LZFX_EARGS; + + memset(htab, 0, sizeof(htab)); + + /* Start a literal run. Whenever we do this the output pointer is + advanced because the current byte will hold the encoded length. */ + lit = 0; + op++; + + hval = LZFX_FRST(ip); + + while (ip + 2 < in_end) + { /* The NEXT macro reads 2 bytes ahead */ + + hval = LZFX_NEXT(hval, ip); + hslot = htab + LZFX_IDX(hval); + + ref = *hslot; + *hslot = ip; + + if (ref < ip && (off = ip - ref - 1) < LZFX_MAX_OFF && ip + 4 < in_end /* Backref takes up to 3 bytes, so don't bother */ + && ref > (u8 *)ibuf && ref[0] == ip[0] && ref[1] == ip[1] && ref[2] == ip[2]) + { + + unsigned int len = 3; /* We already know 3 bytes match */ + const unsigned int maxlen = in_end - ip - 2 > LZFX_MAX_REF ? LZFX_MAX_REF : in_end - ip - 2; + + /* lit == 0: op + 3 must be < out_end (because we undo the run) + lit != 0: op + 3 + 1 must be < out_end */ + if (fx_expect_false(op - !lit + 3 + 1 >= out_end)) + return LZFX_ESIZE; + + op[-lit - 1] = lit - 1; /* Terminate literal run */ + op -= !lit; /* Undo run if length is zero */ + + /* Start checking at the fourth byte */ + while (len < maxlen && ref[len] == ip[len]) + len++; + + len -= 2; /* We encode the length as #octets - 2 */ + + /* Format 1: [LLLooooo oooooooo] */ + if (len < 7) + { + *op++ = (off >> 8) + (len << 5); + *op++ = off; + + /* Format 2: [111ooooo LLLLLLLL oooooooo] */ + } + else + { + *op++ = (off >> 8) + (7 << 5); + *op++ = len - 7; + *op++ = off; + } + + lit = 0; + op++; + + ip += len + 1; /* ip = initial ip + #octets -1 */ + + if (fx_expect_false(ip + 3 >= in_end)) + { + ip++; /* Code following expects exit at bottom of loop */ + break; + } + + hval = LZFX_FRST(ip); + hval = LZFX_NEXT(hval, ip); + htab[LZFX_IDX(hval)] = ip; + + ip++; /* ip = initial ip + #octets */ + } + else + { + /* Keep copying literal bytes */ + + if (fx_expect_false(op >= out_end)) + return LZFX_ESIZE; + + lit++; + *op++ = *ip++; + + if (fx_expect_false(lit == LZFX_MAX_LIT)) + { + op[-lit - 1] = lit - 1; /* stop run */ + lit = 0; + op++; /* start run */ + } + + } /* if() found match in htab */ + + } /* while(ip < ilen -2) */ + + /* At most 3 bytes remain in input. We therefore need 4 bytes available + in the output buffer to store them (3 data + ctrl byte).*/ + if (op + 3 > out_end) + return LZFX_ESIZE; + + while (ip < in_end) + { + + lit++; + *op++ = *ip++; + + if (fx_expect_false(lit == LZFX_MAX_LIT)) + { + op[-lit - 1] = lit - 1; + lit = 0; + op++; + } + } + + op[-lit - 1] = lit - 1; + op -= !lit; + + *olen = op - (u8 *)obuf; + return 0; +} + +/* Decompressor */ +int lzfx_decompress(const void *ibuf, unsigned int ilen, + void *obuf, unsigned int *olen) +{ + + u8 const *ip = (const u8 *)ibuf; + u8 const *const in_end = ip + ilen; + u8 *op = (u8 *)obuf; + u8 const *const out_end = (olen == NULL ? NULL : op + *olen); + + unsigned int remain_len = 0; + int rc; + + if (olen == NULL) + return LZFX_EARGS; + if (ibuf == NULL) + { + if (ilen != 0) + return LZFX_EARGS; + *olen = 0; + return 0; + } + if (obuf == NULL) + { + if (olen != 0) + return LZFX_EARGS; + return lzfx_getsize(ibuf, ilen, olen); + } + + do + { + unsigned int ctrl = *ip++; + + /* Format 000LLLLL: a literal byte string follows, of length L+1 */ + if (ctrl < (1 << 5)) + { + + ctrl++; + + if (fx_expect_false(op + ctrl > out_end)) + { + --ip; /* Rewind to control byte */ + goto guess; + } + if (fx_expect_false(ip + ctrl > in_end)) + return LZFX_ECORRUPT; + + do + *op++ = *ip++; + while (--ctrl); + + /* Format #1 [LLLooooo oooooooo]: backref of length L+1+2 + ^^^^^ ^^^^^^^^ + A B + #2 [111ooooo LLLLLLLL oooooooo] backref of length L+7+2 + ^^^^^ ^^^^^^^^ + A B + In both cases the location of the backref is computed from the + remaining part of the data as follows: + + location = op - A*256 - B - 1 + */ + } + else + { + + unsigned int len = (ctrl >> 5); + u8 *ref = op - ((ctrl & 0x1f) << 8) - 1; + + if (len == 7) + len += *ip++; /* i.e. format #2 */ + + len += 2; /* len is now #octets */ + + if (fx_expect_false(op + len > out_end)) + { + ip -= (len >= 9) ? 2 : 1; /* Rewind to control byte */ + goto guess; + } + if (fx_expect_false(ip >= in_end)) + return LZFX_ECORRUPT; + + ref -= *ip++; + + if (fx_expect_false(ref < (u8 *)obuf)) + return LZFX_ECORRUPT; + + do + *op++ = *ref++; + while (--len); + } + + } while (ip < in_end); + + *olen = op - (u8 *)obuf; + + return 0; + +guess: + rc = lzfx_getsize(ip, ilen - (ip - (u8 *)ibuf), &remain_len); + if (rc >= 0) + *olen = remain_len + (op - (u8 *)obuf); + return rc; +} + +/* Guess len. No parameters may be NULL; this is not checked. */ +static int lzfx_getsize(const void *ibuf, unsigned int ilen, unsigned int *olen) +{ + + u8 const *ip = (const u8 *)ibuf; + u8 const *const in_end = ip + ilen; + int tot_len = 0; + + while (ip < in_end) + { + + unsigned int ctrl = *ip++; + + if (ctrl < (1 << 5)) + { + + ctrl++; + + if (ip + ctrl > in_end) + return LZFX_ECORRUPT; + + tot_len += ctrl; + ip += ctrl; + } + else + { + + unsigned int len = (ctrl >> 5); + + if (len == 7) + { /* i.e. format #2 */ + len += *ip++; + } + + len += 2; /* len is now #octets */ + + if (ip >= in_end) + return LZFX_ECORRUPT; + + ip++; /* skip the ref byte */ + + tot_len += len; + } + } + + *olen = tot_len; + + return 0; +} diff --git a/src-lzfx/src/lzfxbridge.cc b/src-lzfx/src/lzfxbridge.cc new file mode 100644 index 0000000..a2df1c4 --- /dev/null +++ b/src-lzfx/src/lzfxbridge.cc @@ -0,0 +1,32 @@ +#include "lzfx/include/lzfx.h" +#include "lzfx/include/lzfxbridge.h" +#include "lzfx/src/lib.rs.h" + +uint32_t compress(const rust::Vec &data, rust::Vec &out) +{ + std::vector databuf(data.begin(), data.end()); + std::vector outbuf; + outbuf.resize(out.capacity()); + unsigned int olen = out.capacity(); + int ret = lzfx_compress(&databuf[0], databuf.size(), &outbuf[0], &olen); + outbuf.resize(olen); + std::copy( + outbuf.begin(), outbuf.end(), + std::back_inserter(out)); + return olen; +} + +uint32_t decompress(const rust::Vec &data, rust::Vec &out) +{ + + std::vector databuf(data.begin(), data.end()); + std::vector outbuf; + outbuf.resize(out.capacity()); + unsigned int olen = out.capacity(); + int ret = lzfx_decompress(&databuf[0], databuf.size(), &outbuf[0], &olen); + outbuf.resize(olen); + std::copy( + outbuf.begin(), outbuf.end(), + std::back_inserter(out)); + return olen; +} \ No newline at end of file diff --git a/src-slider_io/Cargo.lock b/src-slider_io/Cargo.lock index a7329d0..8aba779 100644 --- a/src-slider_io/Cargo.lock +++ b/src-slider_io/Cargo.lock @@ -462,7 +462,7 @@ checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -658,9 +658,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.117" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libudev" @@ -721,6 +721,14 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "lzfx" +version = "0.1.0" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "mach" version = "0.1.2" @@ -781,24 +789,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", ] [[package]] @@ -814,15 +811,6 @@ dependencies = [ "void", ] -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num-integer" version = "0.1.44" @@ -951,7 +939,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.32.0", ] [[package]] @@ -1102,11 +1090,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1352,6 +1340,7 @@ dependencies = [ "interception", "ipconfig", "log", + "lzfx", "palette", "parking_lot", "phf 0.10.1", @@ -1453,16 +1442,17 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.16.1" +version = "1.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +checksum = "5b57956f83355511a714cba847e66ad8700bf7e8a596b5016f4eae18954cc8d0" dependencies = [ + "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "pin-project-lite", + "socket2", "tokio-macros", "winapi", ] @@ -1576,6 +1566,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -1658,6 +1654,12 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "weezl" version = "0.1.5" @@ -1707,43 +1709,109 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "winreg" version = "0.7.0" diff --git a/src-slider_io/Cargo.toml b/src-slider_io/Cargo.toml index b20cb84..e169d86 100644 --- a/src-slider_io/Cargo.toml +++ b/src-slider_io/Cargo.toml @@ -33,6 +33,7 @@ vigem-client = { version = "0.1.2", features = ["unstable"] } winapi = "0.3.9" interception = {path = "../src-interception" } ipconfig = "0.3.0" +lzfx = {path = "../src-lzfx" } # webserver hyper = { version="0.14.16", features= ["server", "http1", "http2", "tcp", "stream", "runtime"] } diff --git a/src-slider_io/src/device/config.rs b/src-slider_io/src/device/config.rs index 3b294d8..dba97f7 100644 --- a/src-slider_io/src/device/config.rs +++ b/src-slider_io/src/device/config.rs @@ -7,6 +7,7 @@ pub enum HardwareSpec { Yuancon, Yubideck, YubideckThree, + HoriPad, } #[derive(Debug, Clone)] @@ -58,6 +59,10 @@ impl DeviceMode { spec: HardwareSpec::YubideckThree, disable_air: v["disableAirStrings"].as_bool()?, }, + "hori" => DeviceMode::Hardware { + spec: HardwareSpec::HoriPad, + disable_air: v["disableAirStrings"].as_bool()?, + }, "diva" => DeviceMode::DivaSlider { port: v["divaSerialPort"].as_str()?.to_string(), brightness: u8::try_from(v["divaBrightness"].as_i64()?).ok()?, diff --git a/src-slider_io/src/device/hid.rs b/src-slider_io/src/device/hid.rs index b439c35..41e674e 100644 --- a/src-slider_io/src/device/hid.rs +++ b/src-slider_io/src/device/hid.rs @@ -1,12 +1,15 @@ use log::{error, info}; use rusb::{self, DeviceHandle, GlobalContext}; use std::{ + borrow::BorrowMut, error::Error, mem::swap, ops::{Deref, DerefMut}, time::Duration, }; +use lzfx::compress; + use crate::{ shared::{ utils::{Buffer, ShimError}, @@ -18,30 +21,43 @@ use crate::{ use super::config::HardwareSpec; type HidReadCallback = fn(&Buffer, &mut SliderInput) -> (); -type HidLedCallback = fn(&mut Buffer, &mut Buffer, &SliderLights) -> (); +type HidLedCallback = fn(&mut Vec, &SliderLights) -> (); enum WriteType { Bulk, Interrupt, } +pub struct LedSpec { + led_write_type: WriteType, + led_endpoint: u8, + led_buf: Buffer, +} + +impl LedSpec { + fn new(led_write_type: WriteType, led_endpoint: u8) -> Self { + Self { + led_write_type, + led_endpoint, + led_buf: Buffer::new(), + } + } +} + pub struct HidJob { state: SliderState, vid: u16, pid: u16, - read_endpoint: u8, - led_endpoint: u8, disable_air: bool, + read_endpoint: u8, read_callback: HidReadCallback, read_buf: Buffer, last_read_buf: Buffer, - led_write_type: WriteType, + led_specs: Vec, led_callback: HidLedCallback, - led_buf: Buffer, - led_buf_two: Buffer, handle: Option>, } @@ -51,27 +67,28 @@ impl HidJob { state: SliderState, vid: u16, pid: u16, - read_endpoint: u8, - led_endpoint: u8, disable_air: bool, + + read_endpoint: u8, read_callback: HidReadCallback, - led_type: WriteType, + + led_specs: Vec, led_callback: HidLedCallback, ) -> Self { Self { state, vid, pid, - read_endpoint, - led_endpoint, disable_air, + read_callback, + read_endpoint, read_buf: Buffer::new(), last_read_buf: Buffer::new(), - led_write_type: led_type, + led_callback, - led_buf: Buffer::new(), - led_buf_two: Buffer::new(), + led_specs, + handle: None, } } @@ -82,9 +99,8 @@ impl HidJob { state.clone(), 0x1ccf, 0x2333, - 0x84, - 0x03, *disable_air, + 0x84, |buf, input| { if buf.len != 11 { return; @@ -103,8 +119,9 @@ impl HidJob { input.air.copy_from_slice(&bits[28..34]); input.extra[0..2].copy_from_slice(&bits[26..28]); }, - WriteType::Bulk, - |buf, _, lights| { + vec![LedSpec::new(WriteType::Bulk, 0x03)], + |led_specs, lights| { + let buf = led_specs[0].led_buf.borrow_mut(); buf.len = 240; buf.data[0] = 'B' as u8; buf.data[1] = 'L' as u8; @@ -125,9 +142,8 @@ impl HidJob { state.clone(), 0x1ccf, 0x2333, - 0x84, - 0x03, *disable_air, + 0x84, |buf, input| { if buf.len != 36 { return; @@ -140,8 +156,9 @@ impl HidJob { input.air.copy_from_slice(&bits[0..6]); input.extra[0..2].copy_from_slice(&bits[6..8]); }, - WriteType::Bulk, - |buf, _, lights| { + vec![LedSpec::new(WriteType::Bulk, 0x03)], + |led_specs, lights| { + let buf = led_specs[0].led_buf.borrow_mut(); buf.len = 240; buf.data[0] = 'B' as u8; buf.data[1] = 'L' as u8; @@ -175,9 +192,8 @@ impl HidJob { state.clone(), 0x1973, 0x2001, - 0x81, - 0x02, *disable_air, + 0x81, |buf, input| { if buf.len != 34 && buf.len != 35 { return; @@ -191,8 +207,9 @@ impl HidJob { input.extra[2 - i] = (buf.data[1] >> i) & 1; } }, - WriteType::Interrupt, - |buf, _, lights| { + vec![LedSpec::new(WriteType::Interrupt, 0x02)], + |led_specs, lights| { + let buf = led_specs[0].led_buf.borrow_mut(); buf.len = 31 * 2; for (buf_chunk, state_chunk) in buf .data @@ -209,9 +226,8 @@ impl HidJob { state.clone(), 0x1973, 0x2001, - 0x81, // Need to confirm - 0x02, // Need to confirm *disable_air, + 0x81, // Need to confirm |buf, input| { if buf.len != 45 && buf.len != 46 { return; @@ -226,8 +242,10 @@ impl HidJob { input.extra[2 - i] = (buf.data[1] >> i) & 1; } }, - WriteType::Interrupt, - |buf, _, lights| { + vec![LedSpec::new(WriteType::Interrupt, 0x02)], + |led_specs, lights| { + let buf = led_specs[0].led_buf.borrow_mut(); + buf.len = 62; let lights_nibbles: Vec = lights @@ -258,9 +276,8 @@ impl HidJob { state.clone(), 0x1973, 0x2001, - 0x81, // Need to confirm - 0x02, // Need to confirm *disable_air, + 0x81, // Need to confirm |buf, input| { if buf.len != 45 && buf.len != 46 { return; @@ -275,33 +292,111 @@ impl HidJob { input.extra[2 - i] = (buf.data[1] >> i) & 1; } }, - WriteType::Interrupt, - |buf, buf_two, lights| { - buf.len = 61; - buf.data[0] = 0; - buf_two.len = 61; - buf_two.data[0] = 1; + vec![ + LedSpec::new(WriteType::Interrupt, 0x02), + LedSpec::new(WriteType::Interrupt, 0x02), + ], + |led_specs, lights| { + if let [led_spec_a, led_spec_b] = led_specs.as_mut_slice() { + let buf_a = &mut led_spec_a.led_buf; + let buf_b = &mut led_spec_b.led_buf; - for (buf_chunk, state_chunk) in buf.data[1..61] - .chunks_mut(3) - .zip(lights.ground.chunks(3).skip(11).take(20).rev()) - { - buf_chunk[0] = state_chunk[0]; - buf_chunk[1] = state_chunk[1]; - buf_chunk[2] = state_chunk[2]; + buf_a.len = 61; + buf_a.data[0] = 0; + buf_b.len = 61; + buf_b.data[0] = 1; + + for (buf_chunk, state_chunk) in buf_a.data[1..61] + .chunks_mut(3) + .zip(lights.ground.chunks(3).skip(11).take(20).rev()) + { + buf_chunk[0] = state_chunk[0]; + buf_chunk[1] = state_chunk[1]; + buf_chunk[2] = state_chunk[2]; + } + + for (buf_chunk, state_chunk) in buf_b.data[1..34] + .chunks_mut(3) + .zip(lights.ground.chunks(3).take(11).rev()) + { + buf_chunk[0] = state_chunk[0]; + buf_chunk[1] = state_chunk[1]; + buf_chunk[2] = state_chunk[2]; + } + + buf_b.data[34..37].copy_from_slice(&lights.air_left[3..6]); + buf_b.data[37..40].copy_from_slice(&lights.air_right[3..6]); + } else { + panic!(); + } + }, + ), + HardwareSpec::HoriPad => Self::new( + state.clone(), + 0x0f0d, + 0x0092, + *disable_air, + 0x84, + |buf, input| { + if buf.len != 9 { + return; } - for (buf_chunk, state_chunk) in buf_two.data[1..34] - .chunks_mut(3) - .zip(lights.ground.chunks(3).take(11).rev()) - { - buf_chunk[0] = state_chunk[0]; - buf_chunk[1] = state_chunk[1]; - buf_chunk[2] = state_chunk[2]; + let bits: Vec = buf.data[1..8] + .iter() + .flat_map(|x| (0..8).map(move |i| ((x ^ 128) >> i) & 1)) + .collect(); + for i in 0..32 { + input.ground[i] = bits[7 * 8 - 1 - i] * 255; } + input.air.copy_from_slice(&bits[0..6]); - buf_two.data[34..37].copy_from_slice(&lights.air_left[3..6]); - buf_two.data[37..40].copy_from_slice(&lights.air_right[3..6]); + input.extra[0] = 0; + input.extra[1] = 0; + input.extra[2] = 0; + }, + vec![ + LedSpec::new(WriteType::Interrupt, 0x04), + LedSpec::new(WriteType::Interrupt, 0x05), + LedSpec::new(WriteType::Interrupt, 0x06), + LedSpec::new(WriteType::Interrupt, 0x0b), + ], + |led_specs, lights| { + if let [led_spec_ga, led_spec_gb, led_spec_air, led_spec_comp] = led_specs.as_mut_slice() + { + let buf_ga = &mut led_spec_ga.led_buf; + let buf_gb = &mut led_spec_gb.led_buf; + let buf_air = &mut led_spec_air.led_buf; + let buf_comp = &mut led_spec_comp.led_buf; + + let light_rgb_buf: Vec = lights + .ground + .iter() + .chain(lights.air_left.iter()) + .chain(lights.air_right.iter()) + .map(|x| *x) + .collect(); + let light_brg_buf: Vec = light_rgb_buf + .chunks(3) + .map(|x| [x[2], x[0], x[1]]) + .flatten() + .collect(); + + let mut light_brg_buf_compress: Vec = vec![]; + light_brg_buf_compress.reserve(512); + compress(&light_brg_buf, &mut light_brg_buf_compress); + // info!("raw {:?}", light_brg_buf); + // info!("compress {:?}", light_brg_buf_compress); + + if light_brg_buf_compress.len() < 63 { + buf_comp.data[0..light_brg_buf_compress.len()] + .copy_from_slice(light_brg_buf_compress.as_slice()); + } else { + buf_ga.data[0..48].copy_from_slice(&light_brg_buf[0..48]); + buf_gb.data[0..45].copy_from_slice(&light_brg_buf[48..(48 + 45)]); + buf_air.data[0..18].copy_from_slice(&light_brg_buf[(48 + 45)..(48 + 45 + 18)]); + } + } }, ), } @@ -379,50 +474,30 @@ impl ThreadJob for HidJob { { let mut lights_handle = self.state.lights.lock(); if lights_handle.dirty { - (self.led_callback)( - &mut self.led_buf, - &mut self.led_buf_two, - lights_handle.deref(), - ); + (self.led_callback)(&mut self.led_specs, lights_handle.deref()); lights_handle.dirty = false; } } - if self.led_buf.len != 0 { - let res = (match self.led_write_type { - WriteType::Bulk => handle.write_bulk(self.led_endpoint, self.led_buf.slice(), TIMEOUT), - WriteType::Interrupt => { - handle.write_interrupt(self.led_endpoint, &self.led_buf.slice(), TIMEOUT) + for led_spec in self.led_specs.iter_mut() { + if led_spec.led_buf.len != 0 { + let res = (match led_spec.led_write_type { + WriteType::Bulk => { + handle.write_bulk(led_spec.led_endpoint, &led_spec.led_buf.slice(), TIMEOUT) + } + WriteType::Interrupt => { + handle.write_interrupt(led_spec.led_endpoint, &led_spec.led_buf.slice(), TIMEOUT) + } + }) + .map_err(|e| { + // debug!("Device write error {}", e); + e + }) + .unwrap_or(0); + if res == led_spec.led_buf.len + 1 { + work = true; + led_spec.led_buf.len = 0; } - }) - .map_err(|e| { - // debug!("Device write error {}", e); - e - }) - .unwrap_or(0); - if res == self.led_buf.len + 1 { - // work = true; - self.led_buf.len = 0; - } - } - - if self.led_buf_two.len != 0 { - let res = (match self.led_write_type { - WriteType::Bulk => { - handle.write_bulk(self.led_endpoint, self.led_buf_two.slice(), TIMEOUT) - } - WriteType::Interrupt => { - handle.write_interrupt(self.led_endpoint, &self.led_buf_two.slice(), TIMEOUT) - } - }) - .map_err(|e| { - // debug!("Device write error {}", e); - e - }) - .unwrap_or(0); - if res == self.led_buf_two.len + 1 { - // work = true; - self.led_buf_two.len = 0; } } } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 07c4f90..85a235d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1750,6 +1750,14 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lzfx" +version = "0.1.0" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "mac" version = "0.1.1" @@ -2977,6 +2985,7 @@ dependencies = [ "interception", "ipconfig", "log", + "lzfx", "palette", "parking_lot 0.12.1", "phf 0.10.1", diff --git a/src/App.svelte b/src/App.svelte index 465d59d..1db4d48 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -198,6 +198,7 @@ +