chore: refactor HID file organization
This commit is contained in:
parent
c5d247cc96
commit
7faf9d05f9
8 changed files with 160 additions and 144 deletions
|
@ -17,6 +17,7 @@ use packed_struct::{
|
|||
|
||||
use crate::{
|
||||
helpers::{PackedFloat, ToPackedFloatArray, ToRegularArray, XyValuePair},
|
||||
hid::gcc::{GcButtons1, GcButtons2, GcState},
|
||||
input::{
|
||||
read_ext_adc, Stick, StickAxis, FLOAT_ORIGIN, SPI_ACS_SHARED, SPI_CCS_SHARED, SPI_SHARED,
|
||||
},
|
||||
|
@ -25,10 +26,7 @@ use crate::{
|
|||
LinearizedCalibration, NotchCalibration, NotchStatus, CALIBRATION_ORDER,
|
||||
NOTCH_ADJUSTMENT_ORDER, NO_OF_ADJ_NOTCHES, NO_OF_CALIBRATION_POINTS, NO_OF_NOTCHES,
|
||||
},
|
||||
usb_comms::{
|
||||
GcButtons1, GcButtons2, MUTEX_CONTROLLER_MODE, MUTEX_INPUT_CONSISTENCY_MODE,
|
||||
SIGNAL_CHANGE_RUMBLE_STRENGTH,
|
||||
},
|
||||
usb_comms::{MUTEX_INPUT_CONSISTENCY_MODE, SIGNAL_CHANGE_RUMBLE_STRENGTH},
|
||||
ADDR_OFFSET, FLASH_SIZE,
|
||||
};
|
||||
|
||||
|
@ -39,7 +37,7 @@ use embassy_sync::{
|
|||
};
|
||||
use embassy_time::Timer;
|
||||
|
||||
use crate::{input::CHANNEL_GCC_STATE, usb_comms::GcState};
|
||||
use crate::input::CHANNEL_GCC_STATE;
|
||||
|
||||
/// Whether we are currently calibrating the sticks. Updates are dispatched when the status changes.
|
||||
/// Initial status is assumed to be false.
|
||||
|
|
141
src/hid/gcc.rs
Normal file
141
src/hid/gcc.rs
Normal file
|
@ -0,0 +1,141 @@
|
|||
use defmt::{info, trace, Format};
|
||||
use embassy_usb::{
|
||||
class::hid::{ReportId, RequestHandler},
|
||||
control::OutResponse,
|
||||
};
|
||||
|
||||
use crate::usb_comms::{HidReportBuilder, SIGNAL_RUMBLE};
|
||||
use packed_struct::{derive::PackedStruct, PackedStruct};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct GcButtons1 {
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_a: bool,
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_b: bool,
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_x: bool,
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_y: bool,
|
||||
#[packed_field(bits = "4")]
|
||||
pub dpad_left: bool,
|
||||
#[packed_field(bits = "5")]
|
||||
pub dpad_right: bool,
|
||||
#[packed_field(bits = "6")]
|
||||
pub dpad_down: bool,
|
||||
#[packed_field(bits = "7")]
|
||||
pub dpad_up: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct GcButtons2 {
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_start: bool,
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_z: bool,
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_r: bool,
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_l: bool,
|
||||
#[packed_field(bits = "4..=7")]
|
||||
pub blank1: u8,
|
||||
}
|
||||
|
||||
///
|
||||
/// Struct representing the controller state. Used for HID communications in
|
||||
/// GCC adapter mode, as well as for the internal representation of the controller.
|
||||
///
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "msb0", size_bytes = "8")]
|
||||
pub struct GcState {
|
||||
#[packed_field(bits = "0..=7")]
|
||||
pub buttons_1: GcButtons1,
|
||||
#[packed_field(bits = "8..=15")]
|
||||
pub buttons_2: GcButtons2,
|
||||
#[packed_field(bits = "16..=23")]
|
||||
pub stick_x: u8,
|
||||
#[packed_field(bits = "24..=31")]
|
||||
pub stick_y: u8,
|
||||
#[packed_field(bits = "32..=39")]
|
||||
pub cstick_x: u8,
|
||||
#[packed_field(bits = "40..=47")]
|
||||
pub cstick_y: u8,
|
||||
#[packed_field(bits = "48..=55")]
|
||||
pub trigger_l: u8,
|
||||
#[packed_field(bits = "56..=63")]
|
||||
pub trigger_r: u8,
|
||||
}
|
||||
|
||||
impl Default for GcState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buttons_1: GcButtons1::default(),
|
||||
buttons_2: GcButtons2::default(),
|
||||
stick_x: 127,
|
||||
stick_y: 127,
|
||||
cstick_x: 127,
|
||||
cstick_y: 127,
|
||||
trigger_l: 0,
|
||||
trigger_r: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GcReportBuilder {
|
||||
gc_first: bool,
|
||||
}
|
||||
|
||||
impl HidReportBuilder<37> for GcReportBuilder {
|
||||
async fn get_hid_report(&mut self, state: &GcState) -> [u8; 37] {
|
||||
let mut buffer = [0u8; 37];
|
||||
|
||||
buffer[0] = 0x21;
|
||||
buffer[1] |= 0x14;
|
||||
|
||||
let data = state.pack().expect("Failed to pack GC input data");
|
||||
|
||||
if !self.gc_first {
|
||||
buffer[1] |= 0x04;
|
||||
buffer[10] |= 0x04;
|
||||
buffer[19] |= 0x04;
|
||||
buffer[28] |= 0x04;
|
||||
self.gc_first = true;
|
||||
} else {
|
||||
// controller in "port 1"
|
||||
buffer[2..=9].copy_from_slice(&data);
|
||||
}
|
||||
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GccRequestHandler;
|
||||
|
||||
impl RequestHandler for GccRequestHandler {
|
||||
fn get_report(&mut self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
|
||||
info!("Get report for {:?}", id);
|
||||
None
|
||||
}
|
||||
|
||||
fn set_report(&mut self, id: ReportId, data: &[u8]) -> OutResponse {
|
||||
trace!("Set report for {:?}: {:x}", id, data);
|
||||
|
||||
if data.len() > 1 {
|
||||
SIGNAL_RUMBLE.signal((data[1] & 0x01) != 0);
|
||||
}
|
||||
|
||||
OutResponse::Accepted
|
||||
}
|
||||
|
||||
fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
|
||||
info!("Set idle rate for {:?} to {:?}", id, dur);
|
||||
}
|
||||
|
||||
fn get_idle_ms(&mut self, id: Option<ReportId>) -> Option<u32> {
|
||||
info!("Get idle rate for {:?}", id);
|
||||
None
|
||||
}
|
||||
}
|
2
src/hid/mod.rs
Normal file
2
src/hid/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod gcc;
|
||||
pub mod procon;
|
|
@ -18,7 +18,9 @@ use embassy_usb::{
|
|||
use packed_struct::{derive::PackedStruct, PackedStruct};
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::usb_comms::{GcState, HidReportBuilder};
|
||||
use crate::usb_comms::HidReportBuilder;
|
||||
|
||||
use super::gcc::GcState;
|
||||
|
||||
const SW_INFO_SET_MAC: u8 = 0x01;
|
||||
|
|
@ -22,9 +22,10 @@ use crate::{
|
|||
},
|
||||
filter::{run_waveshaping, FilterGains, KalmanState, WaveshapingValues, FILTER_GAINS},
|
||||
helpers::XyValuePair,
|
||||
hid::gcc::GcState,
|
||||
input_filter::{DummyFilter, InputFilter},
|
||||
stick::{linearize, notch_remap, StickParams},
|
||||
usb_comms::{GcState, MUTEX_CONTROLLER_MODE, MUTEX_INPUT_CONSISTENCY_MODE},
|
||||
usb_comms::{MUTEX_CONTROLLER_MODE, MUTEX_INPUT_CONSISTENCY_MODE},
|
||||
};
|
||||
|
||||
/// Used to send the button state to the usb task and the calibration task
|
||||
|
|
|
@ -2,7 +2,7 @@ use defmt::warn;
|
|||
|
||||
use crate::{
|
||||
config::{is_awaitable_button_pressed, AwaitableButtons},
|
||||
usb_comms::GcState,
|
||||
hid::gcc::GcState,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
mod config;
|
||||
mod filter;
|
||||
mod helpers;
|
||||
mod hid;
|
||||
mod input;
|
||||
mod input_filter;
|
||||
mod procon_hid;
|
||||
mod stick;
|
||||
mod usb_comms;
|
||||
|
||||
|
|
142
src/usb_comms.rs
142
src/usb_comms.rs
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
use core::{default::Default, future::Future};
|
||||
|
||||
use defmt::{debug, info, trace, warn, Format};
|
||||
use defmt::{debug, info, trace, warn};
|
||||
use embassy_futures::join::join;
|
||||
use embassy_rp::{
|
||||
peripherals::{PIN_25, PIN_29, PWM_SLICE4, PWM_SLICE6, USB},
|
||||
|
@ -15,22 +15,23 @@ use embassy_rp::{
|
|||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal};
|
||||
use embassy_time::{Duration, Instant, Timer};
|
||||
use embassy_usb::{
|
||||
class::hid::{HidReader, HidReaderWriter, HidWriter, ReportId, RequestHandler, State},
|
||||
control::OutResponse,
|
||||
class::hid::{HidReader, HidReaderWriter, HidWriter, RequestHandler, State},
|
||||
driver::Driver,
|
||||
msos::{self, windows_version},
|
||||
Builder, Handler, UsbDevice,
|
||||
};
|
||||
use libm::powf;
|
||||
use packed_struct::{derive::PackedStruct, PackedStruct};
|
||||
|
||||
use crate::{
|
||||
config::{ControllerMode, InputConsistencyMode},
|
||||
hid::{
|
||||
gcc::{GcReportBuilder, GcState, GccRequestHandler},
|
||||
procon::{ProconReportBuilder, ProconRequestHandler, PROCON_REPORT_DESCRIPTOR},
|
||||
},
|
||||
input::CHANNEL_GCC_STATE,
|
||||
procon_hid::{ProconReportBuilder, ProconRequestHandler, PROCON_REPORT_DESCRIPTOR},
|
||||
};
|
||||
|
||||
static SIGNAL_RUMBLE: Signal<CriticalSectionRawMutex, bool> = Signal::new();
|
||||
pub static SIGNAL_RUMBLE: Signal<CriticalSectionRawMutex, bool> = Signal::new();
|
||||
|
||||
/// We could turn the config change signal into a PubSubChannel instead, but that
|
||||
/// would just transmit unnecessary amounts of data.
|
||||
|
@ -116,135 +117,6 @@ struct UsbConfig {
|
|||
report_descriptor: &'static [u8],
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct GcButtons1 {
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_a: bool,
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_b: bool,
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_x: bool,
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_y: bool,
|
||||
#[packed_field(bits = "4")]
|
||||
pub dpad_left: bool,
|
||||
#[packed_field(bits = "5")]
|
||||
pub dpad_right: bool,
|
||||
#[packed_field(bits = "6")]
|
||||
pub dpad_down: bool,
|
||||
#[packed_field(bits = "7")]
|
||||
pub dpad_up: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct GcButtons2 {
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_start: bool,
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_z: bool,
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_r: bool,
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_l: bool,
|
||||
#[packed_field(bits = "4..=7")]
|
||||
pub blank1: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "msb0", size_bytes = "8")]
|
||||
pub struct GcState {
|
||||
#[packed_field(bits = "0..=7")]
|
||||
pub buttons_1: GcButtons1,
|
||||
#[packed_field(bits = "8..=15")]
|
||||
pub buttons_2: GcButtons2,
|
||||
#[packed_field(bits = "16..=23")]
|
||||
pub stick_x: u8,
|
||||
#[packed_field(bits = "24..=31")]
|
||||
pub stick_y: u8,
|
||||
#[packed_field(bits = "32..=39")]
|
||||
pub cstick_x: u8,
|
||||
#[packed_field(bits = "40..=47")]
|
||||
pub cstick_y: u8,
|
||||
#[packed_field(bits = "48..=55")]
|
||||
pub trigger_l: u8,
|
||||
#[packed_field(bits = "56..=63")]
|
||||
pub trigger_r: u8,
|
||||
}
|
||||
|
||||
impl Default for GcState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buttons_1: GcButtons1::default(),
|
||||
buttons_2: GcButtons2::default(),
|
||||
stick_x: 127,
|
||||
stick_y: 127,
|
||||
cstick_x: 127,
|
||||
cstick_y: 127,
|
||||
trigger_l: 0,
|
||||
trigger_r: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct GcReportBuilder {
|
||||
gc_first: bool,
|
||||
}
|
||||
|
||||
impl HidReportBuilder<37> for GcReportBuilder {
|
||||
async fn get_hid_report(&mut self, state: &GcState) -> [u8; 37] {
|
||||
let mut buffer = [0u8; 37];
|
||||
|
||||
buffer[0] = 0x21;
|
||||
buffer[1] |= 0x14;
|
||||
|
||||
let data = state.pack().expect("Failed to pack GC input data");
|
||||
|
||||
if !self.gc_first {
|
||||
buffer[1] |= 0x04;
|
||||
buffer[10] |= 0x04;
|
||||
buffer[19] |= 0x04;
|
||||
buffer[28] |= 0x04;
|
||||
self.gc_first = true;
|
||||
} else {
|
||||
// controller in "port 1"
|
||||
buffer[2..=9].copy_from_slice(&data);
|
||||
}
|
||||
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
struct GccRequestHandler;
|
||||
|
||||
impl RequestHandler for GccRequestHandler {
|
||||
fn get_report(&mut self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
|
||||
info!("Get report for {:?}", id);
|
||||
None
|
||||
}
|
||||
|
||||
fn set_report(&mut self, id: ReportId, data: &[u8]) -> OutResponse {
|
||||
trace!("Set report for {:?}: {:x}", id, data);
|
||||
|
||||
if data.len() > 1 {
|
||||
SIGNAL_RUMBLE.signal((data[1] & 0x01) != 0);
|
||||
}
|
||||
|
||||
OutResponse::Accepted
|
||||
}
|
||||
|
||||
fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
|
||||
info!("Set idle rate for {:?} to {:?}", id, dur);
|
||||
}
|
||||
|
||||
fn get_idle_ms(&mut self, id: Option<ReportId>) -> Option<u32> {
|
||||
info!("Get idle rate for {:?}", id);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
struct MyDeviceHandler {
|
||||
configured: bool,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue