1
0
mirror of https://github.com/4yn/slidershim.git synced 2024-11-27 23:10:49 +01:00

Tasoller hid

This commit is contained in:
4yn 2022-01-30 16:40:44 +08:00
parent a44220fed1
commit 06707302d1
3 changed files with 115 additions and 129 deletions

116
README.md
View File

@ -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

View File

@ -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();

View File

@ -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<u8> = 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;
}
}
}
}