11 Commits
Author SHA1 Message Date
4yn cfa786ce2b split chupico and redboard specs. leds wip 2023-10-08 09:26:33 +08:00
4yn adea9e3a45 draft redboard i/o 2023-10-05 23:56:23 +08:00
4yn 6124dee2db bump version number 2023-10-05 21:05:11 +08:00
4yn cbbfcdc99e Merge branch 'main' of github.com:4yn/slidershim 2023-10-05 20:27:31 +08:00
si yuan b77f5f105f Merge pull request #13 from kokarare1212/main
WebSocket SSL Support
2023-10-05 20:26:07 +08:00
4yn 743424dc01 bump proc-macro2 dependency to work with latest nightly 2023-10-05 20:09:17 +08:00
碧舞すみほ 1b131d7ea7 Update src.js 2023-10-05 20:31:15 +09:00
碧舞すみほ df9ee3b57f Update app.js 2023-10-05 20:30:47 +09:00
4yn 3bd7ee8586 yubideck v3 firmware support 2022-11-18 01:42:05 +08:00
4yn 828f480424 bump version and add readme 2022-08-08 23:00:53 +08:00
4yn e285bdb999 fix hid regression on yubideck 2022-08-08 22:58:24 +08:00
22 changed files with 1225 additions and 93 deletions
+5 -1
View File
@@ -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"
}
}
+13
View File
@@ -12,6 +12,12 @@ Software adapter for various Chunithm slider controllers with a built-in Brokeni
## Changelog
- v0.5.1
- Support SSL/wss if brokenithm used with tunnelling. Thanks @kokarare1212
- v0.5.0
- Support for Yubideck 3.0 firmware
- v0.4.3
- Make Yubideck USB reports more flexible when reading data
- v0.4.2
- Fix HORI Project Diva gamepad slider output order
- v0.4.1
@@ -20,6 +26,11 @@ Software adapter for various Chunithm slider controllers with a built-in Brokeni
- v0.4.0
- Add DirectInput keyboard emulation using [oblitum/Interception](https://github.com/oblitum/Interception)
- Add slide LED support for some controllers
<details>
<summary>Older changelog</summary>
- v0.3.1
- Fix wrong key in UMIGURI keyboard layout
- v0.3.0
@@ -57,6 +68,8 @@ Software adapter for various Chunithm slider controllers with a built-in Brokeni
- v0.1.4
- Initial public release
</details>
## Setup Instructions
1. [Download here](https://github.com/4yn/slidershim/releases/latest)
+1
View File
@@ -0,0 +1 @@
target/
+182
View File
@@ -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"
+11
View File
@@ -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"
+13
View File
@@ -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");
}
+98
View File
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2009 Andrew Collette <andrew.collette at gmail.com>
* 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 <schmorp@schmorp.de>
*
* 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
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include "rust/cxx.h"
uint32_t compress(const rust::Vec<uint8_t> &data, rust::Vec<uint8_t> &out);
uint32_t decompress(const rust::Vec<uint8_t> &data, rust::Vec<uint8_t> &out);
+13
View File
@@ -0,0 +1,13 @@
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("lzfx/include/lzfxbridge.h");
fn compress(data: &Vec<u8>, out: &mut Vec<u8>) -> u32;
fn decompress(data: &Vec<u8>, out: &mut Vec<u8>) -> u32;
}
}
pub use ffi::compress;
pub use ffi::decompress;
+395
View File
@@ -0,0 +1,395 @@
/*
* Copyright (c) 2009 Andrew Collette <andrew.collette at gmail.com>
* 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 <schmorp@schmorp.de>
*
* 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 <cstring>
#else
#include <string.h>
#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 <L+1 bytes>
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;
}
+32
View File
@@ -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<uint8_t> &data, rust::Vec<uint8_t> &out)
{
std::vector<uint8_t> databuf(data.begin(), data.end());
std::vector<uint8_t> 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<uint8_t> &data, rust::Vec<uint8_t> &out)
{
std::vector<uint8_t> databuf(data.begin(), data.end());
std::vector<uint8_t> 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;
}
+107 -39
View File
@@ -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"
+1
View File
@@ -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"] }
File diff suppressed because one or more lines are too long
@@ -223,7 +223,7 @@ var ws = null;
var wsTimeout = 0;
var wsConnected = false;
const wsConnect = () => {
ws = new WebSocket("ws://" + location.host + "/ws");
ws = new WebSocket((location.protocol == "https:" ? "wss://" : "ws://") + location.host + "/ws");
ws.binaryType = "arraybuffer";
ws.onopen = () => {
ws.send("alive?");
+15
View File
@@ -6,6 +6,9 @@ pub enum HardwareSpec {
TasollerTwo,
Yuancon,
Yubideck,
YubideckThree,
HoriPico,
HoriRed,
}
#[derive(Debug, Clone)]
@@ -53,6 +56,18 @@ impl DeviceMode {
spec: HardwareSpec::Yubideck,
disable_air: v["disableAirStrings"].as_bool()?,
},
"yubideck-three" => DeviceMode::Hardware {
spec: HardwareSpec::YubideckThree,
disable_air: v["disableAirStrings"].as_bool()?,
},
"hori-pico" => DeviceMode::Hardware {
spec: HardwareSpec::HoriPico,
disable_air: v["disableAirStrings"].as_bool()?,
},
"hori-red" => DeviceMode::Hardware {
spec: HardwareSpec::HoriRed,
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()?,
+306 -44
View File
@@ -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,29 +21,43 @@ use crate::{
use super::config::HardwareSpec;
type HidReadCallback = fn(&Buffer, &mut SliderInput) -> ();
type HidLedCallback = fn(&mut Buffer, &SliderLights) -> ();
type HidLedCallback = fn(&mut Vec<LedSpec>, &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<LedSpec>,
led_callback: HidLedCallback,
led_buf: Buffer,
handle: Option<DeviceHandle<GlobalContext>>,
}
@@ -50,26 +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<LedSpec>,
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_specs,
handle: None,
}
}
@@ -80,9 +99,8 @@ impl HidJob {
state.clone(),
0x1ccf,
0x2333,
0x84,
0x03,
*disable_air,
0x84,
|buf, input| {
if buf.len != 11 {
return;
@@ -101,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;
@@ -123,9 +142,8 @@ impl HidJob {
state.clone(),
0x1ccf,
0x2333,
0x84,
0x03,
*disable_air,
0x84,
|buf, input| {
if buf.len != 36 {
return;
@@ -138,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;
@@ -173,9 +192,8 @@ impl HidJob {
state.clone(),
0x1973,
0x2001,
0x81,
0x02,
*disable_air,
0x81,
|buf, input| {
if buf.len != 34 && buf.len != 35 {
return;
@@ -189,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
@@ -207,15 +226,15 @@ 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 {
if buf.len != 45 && buf.len != 46 {
return;
}
input.ground.copy_from_slice(&buf.data[2..34]);
input.flip_vert();
for i in 0..6 {
input.air[i ^ 1] = (buf.data[0] >> i) & 1;
}
@@ -223,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<u8> = lights
@@ -251,6 +272,243 @@ impl HidJob {
}
},
),
HardwareSpec::YubideckThree => Self::new(
state.clone(),
0x1973,
0x2001,
*disable_air,
0x81, // Need to confirm
|buf, input| {
if buf.len != 45 && buf.len != 46 {
return;
}
input.ground.copy_from_slice(&buf.data[2..34]);
input.flip_vert();
for i in 0..6 {
input.air[i ^ 1] = (buf.data[0] >> i) & 1;
}
for i in 0..3 {
input.extra[2 - i] = (buf.data[1] >> i) & 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;
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::HoriPico => Self::new(
state.clone(),
0x0f0d,
0x0092,
*disable_air,
0x84,
|buf, input| {
// info!("log hid {:?} {:?}", buf.len, buf.data);
if buf.len != 9 {
return;
}
let bits: Vec<u8> = 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]);
input.extra[0] = 0;
input.extra[1] = 0;
input.extra[2] = 0;
},
vec![
LedSpec::new(WriteType::Interrupt, 0x01),
LedSpec::new(WriteType::Interrupt, 0x01),
LedSpec::new(WriteType::Interrupt, 0x01),
LedSpec::new(WriteType::Interrupt, 0x01),
],
|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<u8> = lights
.ground
.iter()
.chain(lights.air_left.iter())
.chain(lights.air_right.iter())
.map(|x| *x)
.collect();
let light_brg_buf: Vec<u8> = light_rgb_buf
.chunks(3)
.map(|x| [x[2], x[0], x[1]])
.flatten()
.collect();
let mut light_brg_buf_compress: Vec<u8> = 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] = 0x0b;
buf_comp.data[1..(light_brg_buf_compress.len() + 1)]
.copy_from_slice(light_brg_buf_compress.as_slice());
buf_comp.len = light_brg_buf_compress.len() + 1;
info!(
"Sending compressed led data {:?} {:?}",
buf_comp.len, buf_comp.data
);
} else {
buf_ga.data[0] = 0x04;
buf_ga.data[1..(48 + 1)].copy_from_slice(&light_brg_buf[0..48]);
buf_ga.len = 48 + 1;
buf_gb.data[0] = 0x05;
buf_gb.data[1..(45 + 1)].copy_from_slice(&light_brg_buf[48..(48 + 45)]);
buf_gb.len = 45 + 1;
buf_air.data[0] = 0x06;
buf_air.data[1..(18 + 1)].copy_from_slice(&light_brg_buf[(48 + 45)..(48 + 45 + 18)]);
buf_air.len = 18 + 1;
info!("Sending uncompressed led data");
info!("{:?} {:?}", buf_ga.len, buf_ga.data);
info!("{:?} {:?}", buf_gb.len, buf_gb.data);
info!("{:?} {:?}", buf_air.len, buf_air.data);
}
}
},
),
HardwareSpec::HoriRed => Self::new(
state.clone(),
0x0f0d,
0x0092,
*disable_air,
0x81,
|buf, input| {
// info!("log hid {:?} {:?}", buf.len, buf.data);
if buf.len != 9 {
return;
}
let bits: Vec<u8> = buf.data[0..7]
.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[0] = bits[3];
input.air[1] = bits[0];
input.air[2] = bits[1];
input.air[3] = bits[2];
input.air[4] = bits[4];
input.air[5] = bits[5];
input.extra[0] = 0;
input.extra[1] = 0;
input.extra[2] = 0;
},
vec![
LedSpec::new(WriteType::Interrupt, 0x02),
LedSpec::new(WriteType::Interrupt, 0x02),
LedSpec::new(WriteType::Interrupt, 0x02),
LedSpec::new(WriteType::Interrupt, 0x02),
],
|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<u8> = lights
.ground
.iter()
.chain(lights.air_left.iter())
.chain(lights.air_right.iter())
.map(|x| *x)
.collect();
let light_brg_buf: Vec<u8> = light_rgb_buf
.chunks(3)
.map(|x| [x[2], x[0], x[1]])
.flatten()
.collect();
let mut light_brg_buf_compress: Vec<u8> = 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] = 0x0b;
buf_comp.data[1..(light_brg_buf_compress.len() + 1)]
.copy_from_slice(light_brg_buf_compress.as_slice());
buf_comp.len = light_brg_buf_compress.len() + 1;
info!(
"Sending compressed led data {:?} {:?}",
buf_comp.len, buf_comp.data
);
} else {
buf_ga.data[0] = 0x04;
buf_ga.data[1..(48 + 1)].copy_from_slice(&light_brg_buf[0..48]);
buf_ga.len = 48 + 1;
buf_gb.data[0] = 0x05;
buf_gb.data[1..(45 + 1)].copy_from_slice(&light_brg_buf[48..(48 + 45)]);
buf_gb.len = 45 + 1;
buf_air.data[0] = 0x06;
buf_air.data[1..(18 + 1)].copy_from_slice(&light_brg_buf[(48 + 45)..(48 + 45 + 18)]);
buf_air.len = 18 + 1;
info!("Sending uncompressed led data");
info!("{:?} {:?}", buf_ga.len, buf_ga.data);
info!("{:?} {:?}", buf_gb.len, buf_gb.data);
info!("{:?} {:?}", buf_air.len, buf_air.data);
}
}
},
),
}
}
@@ -326,26 +584,30 @@ impl ThreadJob for HidJob {
{
let mut lights_handle = self.state.lights.lock();
if lights_handle.dirty {
(self.led_callback)(&mut self.led_buf, 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| {
error!("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;
}
}
}
+12 -3
View File
@@ -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"
@@ -2462,9 +2470,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.40"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]
@@ -2977,6 +2985,7 @@ dependencies = [
"interception",
"ipconfig",
"log",
"lzfx",
"palette",
"parking_lot 0.12.1",
"phf 0.10.1",
@@ -2996,7 +3005,7 @@ dependencies = [
[[package]]
name = "slidershim"
version = "0.4.2"
version = "0.5.1"
dependencies = [
"env_logger",
"log",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "slidershim"
version = "0.4.2"
version = "0.5.1"
description = "slidershim"
authors = ["4yn"]
license = ""
+7 -1
View File
@@ -2,13 +2,19 @@
___| (_) __| | ___ _ __ ___| |__ (_)_ __ ___
/ __| | |/ _` |/ _ \ '__/ __| '_ \| | '_ ` _ \
\__ \ | | (_| | __/ | \__ \ | | | | | | | | |
|___/_|_|\__,_|\___|_| |___/_| |_|_|_| |_| |_| v0.4.2
|___/_|_|\__,_|\___|_| |___/_| |_|_|_| |_| |_| v0.5.1
===============================================
https://github.com/4yn/slidershim
# Changelog
- v0.5.1
- Support SSL/wss if brokenithm used with tunnelling. Thanks @kokarare1212
- v0.5.0
- Support for Yubideck 3.0 firmware
- v0.4.3
- Make Yubideck USB reports more flexible when reading data
- v0.4.2
- Fix HORI Project Diva gamepad slider output order
- v0.4.1
+1 -1
View File
@@ -1,7 +1,7 @@
{
"package": {
"productName": "slidershim",
"version": "0.4.2"
"version": "0.5.1"
},
"build": {
"distDir": "../public",
+4 -1
View File
@@ -196,7 +196,10 @@
<option value="tasoller-one">GAMO2 Tasoller, 1.0 HID Firmware</option>
<option value="tasoller-two">GAMO2 Tasoller, 2.0 HID Firmware</option>
<option value="yuancon">Yuancon Laverita, HID Firmware</option>
<option value="yubideck">大四 / Yubideck, HID Firmware</option>
<option value="yubideck">大四 / Yubideck, HID Firmware 1.0</option>
<option value="yubideck-three">大四 / Yubideck, HID Firmware 3.0</option>
<option value="hori-pico">HORI (Chu Pico)</option>
<option value="hori-red">HORI (Redboard)</option>
<option value="diva">Slider over Serial</option>
<option value="brokenithm">Brokenithm</option>
<option value="brokenithm-led">Brokenithm + Led</option>