From 06707302d1245b3ac2d46d937c84c994de42b619 Mon Sep 17 00:00:00 2001 From: 4yn Date: Sun, 30 Jan 2022 16:40:44 +0800 Subject: [PATCH] Tasoller hid --- README.md | 116 +++--------------------------- src-tauri/src/bin/test_usb.rs | 13 +++- src-tauri/src/slider_io/device.rs | 115 +++++++++++++++++++++++------ 3 files changed, 115 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index 8ca4fca..3952c7b 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,9 @@ -*Psst — looking for a more complete solution? Check out [SvelteKit](https://kit.svelte.dev), the official framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.* +# Todo -*Looking for a shareable component template instead? You can [use SvelteKit for that as well](https://kit.svelte.dev/docs#packaging) or the older [sveltejs/component-template](https://github.com/sveltejs/component-template)* - ---- - -# svelte app - -This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. - -To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): - -```bash -npx degit sveltejs/template svelte-app -cd svelte-app -``` - -*Note that you will need to have [Node.js](https://nodejs.org) installed.* - - -## Get started - -Install the dependencies... - -```bash -cd svelte-app -npm install -``` - -...then start [Rollup](https://rollupjs.org): - -```bash -npm run dev -``` - -Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. - -By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. - -If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. - -## Building and running in production mode - -To create an optimised version of the app: - -```bash -npm run build -``` - -You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). - - -## Single-page app mode - -By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. - -If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: - -```js -"start": "sirv public --single" -``` - -## Using TypeScript - -This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: - -```bash -node scripts/setupTypeScript.js -``` - -Or remove the script via: - -```bash -rm scripts/setupTypeScript.js -``` - -If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). - -## Deploying to the web - -### With [Vercel](https://vercel.com) - -Install `vercel` if you haven't already: - -```bash -npm install -g vercel -``` - -Then, from within your project folder: - -```bash -cd public -vercel deploy --name my-project -``` - -### With [surge](https://surge.sh/) - -Install `surge` if you haven't already: - -```bash -npm install -g surge -``` - -Then, from within your project folder: - -```bash -npm run build -surge public my-project.surge.sh -``` +- input polling rate counter +- led polling rate settings +- settings serializer +- brokenithm server +- ouptut websocket +- led websocket +- comments diff --git a/src-tauri/src/bin/test_usb.rs b/src-tauri/src/bin/test_usb.rs index 5ee29bc..65fced9 100644 --- a/src-tauri/src/bin/test_usb.rs +++ b/src-tauri/src/bin/test_usb.rs @@ -5,12 +5,23 @@ use std::io; use slidershim::slider_io::{Config, Manager}; fn main() { + // let config = Config::from_str( + // r#"{ + // "deviceMode": "yuancon", + // "outputMode": "kb-32-tasoller", + // "ledMode": "reactive-8", + // "keyboardSensitivity": 50 + // }"#, + // ) + // .unwrap(); + let config = Config::from_str( r#"{ "deviceMode": "yuancon", "outputMode": "kb-32-tasoller", + "keyboardSensitivity": 50, "ledMode": "reactive-8", - "keyboardSensitivity": 50 + "ledSensitivity": 50 }"#, ) .unwrap(); diff --git a/src-tauri/src/slider_io/device.rs b/src-tauri/src/slider_io/device.rs index 715acb7..ecee069 100644 --- a/src-tauri/src/slider_io/device.rs +++ b/src-tauri/src/slider_io/device.rs @@ -1,4 +1,8 @@ -use std::{error, ops::DerefMut, time::Duration}; +use std::{ + error, + ops::{Deref, DerefMut}, + time::Duration, +}; use rusb::{self, DeviceHandle, GlobalContext}; @@ -9,14 +13,14 @@ use crate::slider_io::{ }; pub struct Buffer { - pub data: [u8; 128], + pub data: [u8; 256], pub len: usize, } impl Buffer { pub fn new() -> Self { Buffer { - data: [0; 128], + data: [0; 256], len: 0, } } @@ -27,7 +31,12 @@ impl Buffer { } type HidReadCallback = fn(&Buffer, &mut ControllerState) -> (); -type HidLedCallback = fn(&mut Buffer, &mut LedState) -> (); +type HidLedCallback = fn(&mut Buffer, &LedState) -> (); + +enum WriteType { + Bulk, + Interrupt, +} pub struct HidDeviceJob { state: FullState, @@ -39,6 +48,7 @@ pub struct HidDeviceJob { read_callback: HidReadCallback, read_buf: Buffer, + led_write_type: WriteType, led_callback: HidLedCallback, led_buf: Buffer, @@ -53,6 +63,7 @@ impl HidDeviceJob { read_endpoint: u8, led_endpoint: u8, read_callback: HidReadCallback, + led_type: WriteType, led_callback: HidLedCallback, ) -> Self { Self { @@ -63,6 +74,7 @@ impl HidDeviceJob { led_endpoint, read_callback, read_buf: Buffer::new(), + led_write_type: led_type, led_callback, led_buf: Buffer::new(), handle: None, @@ -71,6 +83,65 @@ impl HidDeviceJob { pub fn from_config(state: &FullState, mode: &DeviceMode) -> Self { match mode { + DeviceMode::TasollerOne => Self::new( + state.clone(), + 0x1ccf, + 0x2333, + 0x84, + 0x03, + |buf, controller_state| { + if buf.len != 11 { + return; + } + + let bits: Vec = buf + .data + .iter() + .flat_map(|x| (0..8).map(move |i| ((x) >> i) & 1)) + .collect(); + for i in 0..32 { + controller_state.ground_state[i] = bits[34 + i] * 255; + } + controller_state.air_state.copy_from_slice(&bits[28..34]); + }, + WriteType::Bulk, + |buf, led_state| { + buf.len = 240; + buf.data[0] = 'B' as u8; + buf.data[1] = 'L' as u8; + buf.data[2] = '\x00' as u8; + buf.data[3..96].copy_from_slice(&led_state.led_state[..3 * 31]); + buf.data[96..240].fill(0); + }, + ), + DeviceMode::TasollerTwo => Self::new( + state.clone(), + 0x1ccf, + 0x2333, + 0x84, + 0x03, + |buf, controller_state| { + if buf.len != 36 { + return; + } + + controller_state + .ground_state + .copy_from_slice(&buf.data[4..36]); + for i in 0..6 { + controller_state.air_state[i] = (buf.data[3] >> (i + 2)) & 1; + } + }, + WriteType::Bulk, + |buf, led_state| { + buf.len = 240; + buf.data[0] = 'B' as u8; + buf.data[1] = 'L' as u8; + buf.data[2] = '\x00' as u8; + buf.data[3..96].copy_from_slice(&led_state.led_state[..3 * 31]); + buf.data[96..240].fill(0); + }, + ), DeviceMode::Yuancon => Self::new( state.clone(), 0x1973, @@ -84,7 +155,7 @@ impl HidDeviceJob { controller_state .ground_state - .clone_from_slice(&buf.data[2..34]); + .copy_from_slice(&buf.data[2..34]); for i in 0..6 { controller_state.air_state[i ^ 1] = if buf.data[0] & (1 << i) == 0 { 1 } else { 0 }; } @@ -92,21 +163,18 @@ impl HidDeviceJob { controller_state.extra_state[i] = if buf.data[1] & (1 << i) == 0 { 1 } else { 0 }; } }, + WriteType::Interrupt, |buf, led_state| { - if !led_state.dirty { - return; - } buf.len = 31 * 2; - buf + for (buf_chunk, state_chunk) in buf .data .chunks_mut(2) .take(31) .zip(led_state.led_state.chunks(3).rev()) - .for_each(|(buf_chunk, state_chunk)| { - buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3); - buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5); - }); - led_state.dirty = false; + { + buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3); + buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5); + } }, ), _ => panic!("Not implemented"), @@ -150,13 +218,20 @@ impl Job for HidDeviceJob { // Led loop { let mut led_state_handle = self.state.led_state.lock().unwrap(); - (self.led_callback)(&mut self.led_buf, led_state_handle.deref_mut()); - if self.led_buf.len != 0 { - let res = handle - .write_interrupt(self.led_endpoint, &self.led_buf.data, TIMEOUT) + if led_state_handle.dirty { + (self.led_callback)(&mut self.led_buf, led_state_handle.deref()); + led_state_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.data, TIMEOUT), + WriteType::Interrupt => { + handle.write_interrupt(self.led_endpoint, &self.led_buf.data, TIMEOUT) + } + }) .unwrap_or(0); - if res == self.led_buf.len + 1 { - self.led_buf.len = 0; + if res == self.led_buf.len + 1 { + self.led_buf.len = 0; + } } } }