chore: refactor HID file organization

This commit is contained in:
Naxdy 2024-10-14 16:20:15 +02:00
parent a5ed42b365
commit a2e90c3734
Signed by: Naxdy
GPG key ID: CC15075846BCE91B
8 changed files with 160 additions and 144 deletions

View file

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

@ -0,0 +1,2 @@
pub mod gcc;
pub mod procon;

View file

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

View file

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

View file

@ -2,7 +2,7 @@ use defmt::warn;
use crate::{
config::{is_awaitable_button_pressed, AwaitableButtons},
usb_comms::GcState,
hid::gcc::GcState,
};
/**

View file

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

View file

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