feat(procon): implement spi functionality
All checks were successful
Code quality / check (pull_request) Successful in 3m46s
All checks were successful
Code quality / check (pull_request) Successful in 3m46s
This commit is contained in:
parent
3b60499fff
commit
e12666cf50
2 changed files with 164 additions and 25 deletions
|
@ -228,18 +228,23 @@ impl ProconByteReport {
|
|||
self[26] = 0x02;
|
||||
}
|
||||
|
||||
fn sw_spi_readfromaddress(&mut self, offset_address: u8, address: u8, length: u8) {
|
||||
fn sw_spi_readfromaddress(
|
||||
&mut self,
|
||||
offset_address: u8,
|
||||
address: u8,
|
||||
length: u8,
|
||||
switch_host_address: &[u8],
|
||||
) {
|
||||
let read_info = [address, offset_address, 0x00, 0x00, length];
|
||||
self[15..(15 + read_info.len())].copy_from_slice(&read_info);
|
||||
|
||||
let mut output_spi_data = [0u8; 30];
|
||||
|
||||
output_spi_data
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.for_each(|(i, e)| *e = sw_spi_getaddressdata(offset_address, address + i as u8));
|
||||
output_spi_data.iter_mut().enumerate().for_each(|(i, e)| {
|
||||
*e = sw_spi_getaddressdata(offset_address, address + i as u8, switch_host_address)
|
||||
});
|
||||
|
||||
self[19..(19 + length as usize)].copy_from_slice(&output_spi_data[..(length as usize)]);
|
||||
self[20..(20 + length as usize)].copy_from_slice(&output_spi_data[..(length as usize)]);
|
||||
}
|
||||
|
||||
fn set_trigerret(&mut self, time_10_ms: u16) {
|
||||
|
@ -252,9 +257,133 @@ impl ProconByteReport {
|
|||
}
|
||||
}
|
||||
|
||||
fn sw_spi_getaddressdata(_offset_address: u8, _address: u8) -> u8 {
|
||||
// TODO
|
||||
0
|
||||
fn sw_spi_getaddressdata(offset_address: u8, address: u8, switch_host_address: &[u8]) -> u8 {
|
||||
match offset_address {
|
||||
0x00 => 0x00,
|
||||
0x20..=0x40 => match address {
|
||||
0x26 | 0x00 => 0x95,
|
||||
// Size of pairing data
|
||||
0x27 | 0x01 => 0x22,
|
||||
// Checksum
|
||||
0x28 | 0x29 | 0x02 | 0x03 => 0x00,
|
||||
// Host BT address (Big-endian)
|
||||
0x2A..=0x2F => switch_host_address[(address - 0x2a) as usize],
|
||||
0x04..=0x09 => switch_host_address[(address - 4) as usize],
|
||||
// Bluetooth LTK (Little-endian) NOT IMPLEMENTED YET
|
||||
0x30..=0x3F => 0x00,
|
||||
0x0A..=0x19 => 0x00,
|
||||
// Host capability 0x68 is Nintendo Switch. 0x08 is PC
|
||||
0x4A | 0x24 => 0x68,
|
||||
0x4B | 0x25 => 0,
|
||||
_ => 0x00,
|
||||
},
|
||||
0x50 => 0x00,
|
||||
0x60 => match address {
|
||||
0x00..0x0f => 0xff,
|
||||
0x12 => 0x03,
|
||||
0x13 => 0x02,
|
||||
0x1b => 0x01,
|
||||
0x20 => 35,
|
||||
0x21 => 0,
|
||||
0x22 => 185,
|
||||
0x23 => 255,
|
||||
0x24 => 26,
|
||||
0x25 => 1,
|
||||
0x26 => 0,
|
||||
0x27 => 64,
|
||||
0x28 => 0,
|
||||
0x29 => 64,
|
||||
0x2A => 0,
|
||||
0x2B => 64,
|
||||
0x2C => 1,
|
||||
0x2D => 0,
|
||||
0x2E => 1,
|
||||
0x2F => 0,
|
||||
0x30 => 1,
|
||||
0x31 => 0,
|
||||
0x32 => 0x3B,
|
||||
0x33 => 0x34,
|
||||
0x34 => 0x3B,
|
||||
0x35 => 0x34,
|
||||
0x36 => 0x3B,
|
||||
0x37 => 0x34,
|
||||
0x3d..=0x45 => mk_switch_analog_calibration_data()[(address - 0x3d) as usize],
|
||||
0x46..=0x4e => mk_switch_analog_calibration_data()[(address - 0x3d) as usize],
|
||||
0x4F => 0xFF,
|
||||
0x50 => 26,
|
||||
0x51 => 26,
|
||||
0x52 => 26,
|
||||
0x53..=0x55 => 94,
|
||||
0x56 => 255,
|
||||
0x57 => 255,
|
||||
0x58 => 255,
|
||||
0x59..=0x5B => 255,
|
||||
0x5C => 0x01,
|
||||
0x80 => 80,
|
||||
0x81 => 253,
|
||||
0x82 => 0,
|
||||
0x83 => 0,
|
||||
0x84 => 198,
|
||||
0x85 => 15,
|
||||
0x98 | 0x86 => 15,
|
||||
0x99 | 0x87 => 48,
|
||||
0x9A | 0x88 => 97,
|
||||
0x9B | 0x89 => 174,
|
||||
0x9C | 0x8A => 144,
|
||||
0x9D | 0x8B => 217,
|
||||
0x9E | 0x8C => 212,
|
||||
0x9F | 0x8D => 20,
|
||||
0xA0 | 0x8E => 84,
|
||||
0xA1 | 0x8F => 65,
|
||||
0xA2 | 0x90 => 21,
|
||||
0xA3 | 0x91 => 84,
|
||||
0xA4 | 0x92 => 199,
|
||||
0xA5 | 0x93 => 121,
|
||||
0xA6 | 0x94 => 156,
|
||||
0xA7 | 0x95 => 51,
|
||||
0xA8 | 0x96 => 54,
|
||||
0xA9 | 0x97 => 99,
|
||||
_ => 0,
|
||||
},
|
||||
0x80 => match address {
|
||||
0x10..=0x1a => 0xff,
|
||||
0x1b..=0x25 => 0xff,
|
||||
0x26..=0x3f => 0xff,
|
||||
_ => 0xff,
|
||||
},
|
||||
_ => 0xff,
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_switch_analog_calibration_data() -> [u8; 18] {
|
||||
fn switch_analog_encode(in_lower: u16, in_upper: u16) -> [u8; 3] {
|
||||
let mut out = [0u8; 3];
|
||||
|
||||
[out[0], out[1]] = in_lower.to_le_bytes();
|
||||
|
||||
out[1] |= ((in_upper & 0xf) << 4) as u8;
|
||||
out[2] = ((in_upper & 0xff0) >> 4) as u8;
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
const MIN: u16 = 128 << 4;
|
||||
const MAXX: u16 = 128 << 4;
|
||||
const CENTER: u16 = 128 << 4;
|
||||
|
||||
let mut out = [0u8; 18];
|
||||
|
||||
out[0..3].copy_from_slice(&switch_analog_encode(MAXX, MAXX));
|
||||
out[3..6].copy_from_slice(&switch_analog_encode(CENTER, CENTER));
|
||||
out[6..9].copy_from_slice(&switch_analog_encode(MIN, MIN));
|
||||
|
||||
out[9..12].copy_from_slice(&switch_analog_encode(CENTER, CENTER));
|
||||
out[12..15].copy_from_slice(&switch_analog_encode(MIN, MIN));
|
||||
out[15..18].copy_from_slice(&switch_analog_encode(MAXX, MAXX));
|
||||
|
||||
info!("Returning switch data: {:x}", out);
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
|
@ -321,7 +450,7 @@ pub struct ProconButtonsLeft {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct, Format)]
|
||||
#[packed_struct(bit_numbering = "msb0", endian = "msb", size_bytes = "9")]
|
||||
#[packed_struct(bit_numbering = "msb0", endian = "lsb", size_bytes = "9")]
|
||||
pub struct ProconState {
|
||||
#[packed_field(bits = "0..=7")]
|
||||
pub buttons_right: ProconButtonsRight,
|
||||
|
@ -333,7 +462,7 @@ pub struct ProconState {
|
|||
pub lstick_x: u16,
|
||||
#[packed_field(bits = "40..=47")]
|
||||
pub lstick_y: u8,
|
||||
#[packed_field(bits = "48..=60")]
|
||||
#[packed_field(bits = "48..=63")]
|
||||
pub rstick_x: u16,
|
||||
#[packed_field(bits = "64..=71")]
|
||||
pub rstick_y: u8,
|
||||
|
@ -374,8 +503,8 @@ impl From<&GcState> for ProconState {
|
|||
button_b: value.buttons_1.button_b,
|
||||
button_x: value.buttons_1.button_x,
|
||||
button_y: value.buttons_1.button_y,
|
||||
trigger_r: value.buttons_2.button_r,
|
||||
trigger_zr: value.buttons_2.button_z,
|
||||
trigger_r: value.buttons_2.button_z,
|
||||
trigger_zr: value.buttons_2.button_r,
|
||||
..Default::default()
|
||||
},
|
||||
buttons_shared: ProconButtonsShared {
|
||||
|
@ -383,9 +512,9 @@ impl From<&GcState> for ProconState {
|
|||
button_home: value.buttons_2.button_start && value.buttons_2.button_z,
|
||||
..Default::default()
|
||||
},
|
||||
lstick_x: value.stick_x as u16 * 257,
|
||||
lstick_x: value.stick_x as u16 * 16,
|
||||
lstick_y: value.stick_y,
|
||||
rstick_x: value.cstick_x as u16 * 257,
|
||||
rstick_x: value.cstick_x as u16 * 16,
|
||||
rstick_y: value.cstick_y,
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +523,7 @@ impl From<&GcState> for ProconState {
|
|||
pub struct ProconReportBuilder {
|
||||
switch_reporting_mode: u8,
|
||||
switch_mac_address: [u8; 6],
|
||||
switch_host_address: [u8; 6],
|
||||
switch_ltk: [u8; 16],
|
||||
}
|
||||
|
||||
|
@ -401,12 +531,26 @@ impl Default for ProconReportBuilder {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
switch_reporting_mode: 0,
|
||||
switch_mac_address: [0u8; 6],
|
||||
switch_mac_address: gen_switch_mac_address(),
|
||||
switch_host_address: [0u8; 6],
|
||||
switch_ltk: gen_switch_ltk(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_switch_mac_address() -> [u8; 6] {
|
||||
let mut mac_addr = [0u8; 6];
|
||||
|
||||
mac_addr.iter_mut().for_each(|e| {
|
||||
*e = RoscRng.next_u64() as u8;
|
||||
});
|
||||
|
||||
mac_addr[0] &= 0xfe;
|
||||
mac_addr[5] = 0x9b;
|
||||
|
||||
mac_addr
|
||||
}
|
||||
|
||||
fn gen_switch_ltk() -> [u8; 16] {
|
||||
let mut switch_ltk = [0u8; 16];
|
||||
|
||||
|
@ -495,6 +639,7 @@ impl ProconReportBuilder {
|
|||
current_report_info.raw_data[12],
|
||||
current_report_info.raw_data[11],
|
||||
current_report_info.raw_data[15],
|
||||
&self.switch_host_address,
|
||||
);
|
||||
}
|
||||
SW_CMD_SET_SHIPMODE => {
|
||||
|
@ -526,18 +671,12 @@ impl ProconReportBuilder {
|
|||
|
||||
match pairing_phase {
|
||||
1 => {
|
||||
self.switch_mac_address
|
||||
self.switch_host_address
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.for_each(|(i, e)| *e = host_address[5 - i]);
|
||||
|
||||
self.switch_mac_address
|
||||
.iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.for_each(|(i, e)| {
|
||||
report[16 + i] = *e;
|
||||
});
|
||||
report[16..=21].copy_from_slice(&self.switch_mac_address);
|
||||
|
||||
report[22..(22 + PRO_CONTROLLER_STRING.len())]
|
||||
.copy_from_slice(&PRO_CONTROLLER_STRING);
|
||||
|
|
|
@ -551,7 +551,7 @@ pub async fn update_stick_states_task(
|
|||
spi_acs: Output<'static>,
|
||||
spi_ccs: Output<'static>,
|
||||
) {
|
||||
Timer::after_secs(1).await;
|
||||
Timer::after_secs(3).await;
|
||||
*SPI_SHARED.lock().await = Some(spi);
|
||||
*SPI_ACS_SHARED.lock().await = Some(spi_acs);
|
||||
*SPI_CCS_SHARED.lock().await = Some(spi_ccs);
|
||||
|
|
Loading…
Reference in a new issue