diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a803f50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/dist \ No newline at end of file diff --git a/build-all.sh b/build-all.sh new file mode 100644 index 0000000..130f2e8 --- /dev/null +++ b/build-all.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +mkdir -p dist/chusan +mkdir -p dist/chuni + +for backend in tasoller_v1 tasoller_v2 yubideck_v3 +do + cargo build --target i686-pc-windows-msvc --release --features chusan,$backend + cargo build --target x86_64-pc-windows-msvc --release --features chusan,$backend + + cp target/i686-pc-windows-msvc/release/chuniio_rs.dll dist/chusan/chuniio_${backend}_chusan.dll + cp target/x86_64-pc-windows-msvc/release/chuniio_rs.dll dist/chusan/chuniio_${backend}_amdaemon.dll + + cargo build --target i686-pc-windows-msvc --release --features $backend + cp target/i686-pc-windows-msvc/release/chuniio_rs.dll dist/chuni/chuniio_${backend}.dll +done \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 271800c..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "nightly" \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..a086693 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +imports_granularity = "Crate" +reorder_imports = true +group_imports = "StdExternalCrate" diff --git a/src/backends/dummy.rs b/src/backends/dummy.rs index 50c8b7b..c0d5072 100644 --- a/src/backends/dummy.rs +++ b/src/backends/dummy.rs @@ -1,4 +1,6 @@ +#[cfg(any(chuni, chusanapp))] use anyhow::Result; +#[cfg(any(chuni, chusanapp))] use rusb::{DeviceHandle, UsbContext}; use super::ReadType; @@ -11,13 +13,13 @@ pub const INPUT_MEMORY_SIZE: usize = 1; pub const OUTPUT_MEMORY_SIZE: usize = 1; /// Poll JVS input. -/// +/// /// The return value is a tuple: /// - The first value returns the cabinet test/service state, where bit 0 is Test /// and bit 1 is Service. /// - The second value returns the IR beams that are currently broken, where bit 0 /// is the lowest IR beam and bit 5 is the highest IR beam, for a total of 6 beams. -/// +/// /// Both bit masks are active-high. #[cfg(any(chuni, amdaemon))] pub fn jvs_poll(_input: &[u8]) -> (u8, u8) { @@ -31,15 +33,15 @@ pub fn is_coin_button_pressed(_input: &[u8]) -> bool { } /// Reads slider pressure information from USB input. -/// +/// /// There are a total of 32 regions on the touch slider. Each region can return /// an 8-bit pressure value. The operator menu allows the operator to adjust the /// pressure level at which a region is considered to be pressed; the factory /// default value for this setting is 20. -/// +/// /// You should return an array of 32 unsigned 8-bit integers, starting from top right /// and going from top to bottom, right to left. -/// +/// /// ```ignore /// ^^ Towards screen ^^ /// ----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ @@ -53,7 +55,7 @@ pub fn read_pressure_data(_input: &[u8]) -> [u8; 32] { [0u8; 32] } -/// Update the RGB lighting on the slider. A slice `rgb` is provided, alternating +/// Update the RGB lighting on the slider. A slice `rgb` is provided, alternating /// between 16 touch pad pixels and 15 divider pixels, going from right to left. #[cfg(any(chuni, chusanapp))] pub fn set_slider_leds( @@ -64,14 +66,14 @@ pub fn set_slider_leds( Ok(()) } -/// Update the RGB LEDs. -/// +/// Update the RGB LEDs. +/// /// Board 0 corresponds to the left LEDs, with 5 * 10 * 3 RGB values for the /// billboard, followed by 3 RGB values for the air tower. -/// +/// /// Board 1 corresponds to the right LEDs, with 6 * 10 * 3 RGB values for the /// billboard, followed by 3 RGB values for the air tower. -/// +/// /// Note that billboard strips have alternating direction (bottom to top, top /// to bottom...) #[cfg(any(chuni, chusanapp))] diff --git a/src/backends/tasoller_v1.rs b/src/backends/tasoller_v1.rs index f4230a7..de836ea 100644 --- a/src/backends/tasoller_v1.rs +++ b/src/backends/tasoller_v1.rs @@ -1,20 +1,20 @@ //! # Tasoller CFW1.0 //! USB device: 1CCF:2333 -//! +//! //! USB interface: 0 -//! +//! //! ## Protocol information -//! +//! //! ### IN Interrupt (0x84) //! It is more useful to think of the input as a sequence of bits, //! going from the least significant bit to the most significant. -//! +//! //! ``` //! let bits = input //! .iter() //! .flat_map(|x| (0..8).map(move |i| (x >> i) & 1)); //! ``` -//! +//! //! - Content length: 11 bytes (88 bits) //! - Bits 0..26: ??? //! - Bit 26 (byte 3): FN1 (1 = pressed) @@ -22,18 +22,21 @@ //! - Bits 28..34: ir1-6 (1 = blocked) //! - Bits 34..66: touch sensor 1-32 (1 = held) //! - Bits 66..88: ??? -//! +//! //! ### OUT Bulk (0x03) //! - Content length: 240 bytes -//! - Bytes 0..3: magic bytes [0x42, 0x4C, 0x00] +//! - Bytes 0..3: magic bytes [0x42, 0x4C, 0x00] //! - Bytes 3..96: Slider LED (GRB order, right -> left) //! - Bytes 96..240: Nothing. +#[cfg(any(chuni, chusanapp))] use anyhow::Result; +#[cfg(any(chuni, chusanapp))] use rusb::{DeviceHandle, UsbContext}; -use crate::TIMEOUT; use super::ReadType; +#[cfg(any(chuni, chusanapp))] +use crate::TIMEOUT; pub const DEVICE_VID: u16 = 0x1CCF; pub const DEVICE_PID: u16 = 0x2333; @@ -111,11 +114,7 @@ pub fn set_slider_leds( output[1] = 0x4C; output[2] = 0; - for (buf_chunk, state_chunk) in output[3..96] - .chunks_mut(3) - .take(31) - .zip(rgb.chunks(3)) - { + for (buf_chunk, state_chunk) in output[3..96].chunks_mut(3).take(31).zip(rgb.chunks(3)) { buf_chunk[0] = state_chunk[1]; buf_chunk[1] = state_chunk[0]; buf_chunk[2] = state_chunk[2]; diff --git a/src/backends/tasoller_v2.rs b/src/backends/tasoller_v2.rs index 95ed8d6..375d2df 100644 --- a/src/backends/tasoller_v2.rs +++ b/src/backends/tasoller_v2.rs @@ -1,10 +1,10 @@ //! # Tasoller CFW2.0 //! USB device: 1CCF:2333 -//! +//! //! USB interface: 0 -//! +//! //! ## Protocol information -//! +//! //! ### IN Interrupt (0x84) //! - Content length: 36 bytes //! - Bytes 0..3: Magic bytes [0x68, 0x66, 0x84] @@ -12,20 +12,23 @@ //! - Bit 0..6: ir 1-6 (1 = blocked) //! - Bit 6: FN1 (1 = pressed) //! - Bit 7: FN2 (1 = pressed) -//! - Bytes 4..36: Touch sensor pressure (starts from top left, +//! - Bytes 4..36: Touch sensor pressure (starts from top left, //! top to bottom then left to right) -//! +//! //! ### OUT Bulk (0x03) //! - Content length: 240 bytes -//! - Bytes 0..3: magic bytes [0x42, 0x4C, 0x00] +//! - Bytes 0..3: magic bytes [0x42, 0x4C, 0x00] //! - Bytes 3..96: Slider LED (GRB order, right -> left) //! - Bytes 96..240: Nothing. +#[cfg(any(chuni, chusanapp))] use anyhow::Result; +#[cfg(any(chuni, chusanapp))] use rusb::{DeviceHandle, UsbContext}; -use crate::TIMEOUT; use super::ReadType; +#[cfg(any(chuni, chusanapp))] +use crate::TIMEOUT; pub const DEVICE_VID: u16 = 0x1CCF; pub const DEVICE_PID: u16 = 0x2333; @@ -73,11 +76,7 @@ pub fn set_slider_leds( output[1] = 0x4C; output[2] = 0; - for (buf_chunk, state_chunk) in output[3..96] - .chunks_mut(3) - .take(31) - .zip(rgb.chunks(3)) - { + for (buf_chunk, state_chunk) in output[3..96].chunks_mut(3).take(31).zip(rgb.chunks(3)) { buf_chunk[0] = state_chunk[1]; buf_chunk[1] = state_chunk[0]; buf_chunk[2] = state_chunk[2]; @@ -97,7 +96,7 @@ pub fn set_led_colors( rgb: &[u8], ) -> Result<()> { if board != 0 && board != 1 { - return Ok(()) + return Ok(()); } output[0] = 0x42; diff --git a/src/backends/yubideck_v3.rs b/src/backends/yubideck_v3.rs index a111f36..47259c3 100644 --- a/src/backends/yubideck_v3.rs +++ b/src/backends/yubideck_v3.rs @@ -1,10 +1,10 @@ //! # YubiDeck v3 //! USB device: 1973:2001 -//! +//! //! USB interface: 0 -//! +//! //! ## Protocol information -//! +//! //! ### IN Interrupt (0x81) //! - Content length: 45 bytes //! - Byte 0: IR data (bit 0 for lowest IR to bit 6 for highest) @@ -12,11 +12,11 @@ //! - Bit 0: Test //! - Bit 1: Service //! - Bit 2: Coin -//! - Bytes 2..34: Touch sensor pressure (starts from top left, +//! - Bytes 2..34: Touch sensor pressure (starts from top left, //! top to bottom then left to right) //! - Byte 34: Card type: (0: no card, 1: MIFARE Classic, 2: FeliCa) //! - Byte 35..45: Card IDm/access code -//! +//! //! ### OUT Interrupt (0x02) //! - Content length: 61 bytes //! - Byte 0: Packet type @@ -27,13 +27,16 @@ //! - Bytes 34..37: Left air LED (RGB) //! - Bytes 37..40: Right air LED (RGB) //! - Bytes 40..43: Card reader LED (RGB) -//! - Bytes 43..61: Padding +//! - Bytes 43..61: Padding +#[cfg(any(chuni, chusanapp))] use anyhow::Result; +#[cfg(any(chuni, chusanapp))] use rusb::{DeviceHandle, UsbContext}; -use crate::TIMEOUT; use super::ReadType; +#[cfg(any(chuni, chusanapp))] +use crate::TIMEOUT; pub const DEVICE_VID: u16 = 0x1973; pub const DEVICE_PID: u16 = 0x2001; @@ -72,10 +75,7 @@ pub fn set_slider_leds( output[0] = 0; output[61] = 1; - for (buf_chunk, state_chunk) in output[1..61] - .chunks_mut(3) - .zip(rgb.chunks(3).take(20)) - { + for (buf_chunk, state_chunk) in output[1..61].chunks_mut(3).zip(rgb.chunks(3).take(20)) { buf_chunk[0] = state_chunk[0]; buf_chunk[1] = state_chunk[1]; buf_chunk[2] = state_chunk[2]; @@ -104,7 +104,7 @@ pub fn set_led_colors( rgb: &[u8], ) -> Result<()> { if board != 0 && board != 1 { - return Ok(()) + return Ok(()); } output[61] = 1; @@ -120,7 +120,7 @@ pub fn set_led_colors( output[99] = rgb[181]; output[100] = rgb[182]; } - _ => unreachable!() + _ => unreachable!(), } device.write_interrupt(0x02, &output[61..], TIMEOUT)?; diff --git a/src/lib.rs b/src/lib.rs index df5a3d9..a907807 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,19 +5,17 @@ pub mod backends; mod configuration; mod log; -use ::log::{error, info}; -use rusb::{DeviceHandle, GlobalContext}; use std::{ ffi::c_void, fmt::Display, rc::Rc, - sync::{ - atomic::{AtomicBool, Ordering}, - OnceLock, RwLock, - }, - thread::{self, JoinHandle}, + sync::atomic::{AtomicBool, Ordering}, time::Duration, }; + +use ::log::error; +use anyhow::{anyhow, Result}; +use shared_memory::{Shmem, ShmemConf, ShmemError}; use winapi::{ shared::{ minwindef::{BOOL, DWORD, HINSTANCE, LPVOID, TRUE}, @@ -26,10 +24,6 @@ use winapi::{ um::winnt::{DLL_PROCESS_ATTACH, HRESULT}, }; -use anyhow::{anyhow, Result}; -use shared_memory::{Shmem, ShmemConf, ShmemError}; - -use crate::backends::ReadType; use crate::log::init_logger; cfg_if::cfg_if! { @@ -48,6 +42,14 @@ cfg_if::cfg_if! { if #[cfg(any(chuni, chusanapp))] { type SliderCallbackFn = unsafe extern "C" fn(data: *const u8); + use std::{sync::{RwLock, OnceLock}, thread::{self, JoinHandle}}; + + use ::log::info; + use rusb::{DeviceHandle, GlobalContext}; + + use crate::backends::ReadType; + + static DEVICE: OnceLock> = OnceLock::new(); static mut SLIDER_THREAD: OnceLock> = OnceLock::new(); static SLIDER_ACTIVE: AtomicBool = AtomicBool::new(false); static SLIDER_OUTPUT: RwLock<[u8; con_impl::OUTPUT_MEMORY_SIZE]> = RwLock::new([0u8; con_impl::OUTPUT_MEMORY_SIZE]); @@ -102,7 +104,6 @@ cfg_if::cfg_if! { } pub static TIMEOUT: Duration = Duration::from_millis(20); -static DEVICE: OnceLock> = OnceLock::new(); static mut INPUT_SHMEM: Option> = None; #[no_mangle] @@ -319,6 +320,7 @@ pub unsafe extern "C" fn chuni_io_led_set_colors(board: u8, rgb: *const u8) { #[cfg(amdaemon)] pub extern "C" fn chuni_io_led_set_colors(_rgb: *const u8) {} +#[cfg(any(chuni, chusanapp))] fn device_init() -> Result<()> { let Some(mut device) = rusb::open_device_with_vid_pid(con_impl::DEVICE_VID, con_impl::DEVICE_PID) @@ -337,6 +339,7 @@ fn device_init() -> Result<()> { Ok(()) } +#[cfg(any(chuni, chusanapp))] fn input_thread_proc() { info!("Input thread started");