From 69be4e90a925d30319e8f0698ad174f658a2a3f1 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Sat, 20 Jul 2024 10:20:42 -0700 Subject: [PATCH] Migrate to the new PDL rust generator --- Cargo.lock | 35 +++--- Cargo.toml | 4 +- build.rs | 2 +- src/device.rs | 329 ++++++++++++++++++++++++------------------------- src/lib.rs | 12 +- src/packets.rs | 24 ++-- src/session.rs | 21 ++-- 7 files changed, 204 insertions(+), 223 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66528bd..9413ede 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -119,9 +119,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -155,12 +155,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -377,9 +374,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glam" @@ -553,9 +550,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -574,9 +571,9 @@ checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "pdl-compiler" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6853e3b47aa4a5be1287e9115d6fae9b3118971eba855f4d60323d19a66c07cf" +checksum = "bb6114f8249f6d767f90884bfc4305b2e392b1bd70c2f1660a891959f3c8029f" dependencies = [ "argh", "codespan-reporting", @@ -593,9 +590,9 @@ dependencies = [ [[package]] name = "pdl-runtime" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8684812e36689336c83de6033669573b33b6e59c831145ee496c38a71ed0d7c" +checksum = "ba0db8e089042439da5fd81b6be7c741bf7217502fb1c03646fc0ea998a09405" dependencies = [ "bytes", "thiserror", @@ -1059,9 +1056,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 80b1047..550c89e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ default = ["web"] web = ["hyper", "tokio/rt-multi-thread"] [build-dependencies] -pdl-compiler = "0.3.0" +pdl-compiler = "0.3.1" [dependencies] anyhow = "1.0.56" @@ -55,7 +55,7 @@ log = "0.4.20" env_logger = "0.11.1" num-derive = "0.3.3" num-traits = "0.2.17" -pdl-runtime = "0.3.0" +pdl-runtime = "0.3.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0.49" diff --git a/build.rs b/build.rs index c99bdd8..d9002bc 100644 --- a/build.rs +++ b/build.rs @@ -39,7 +39,7 @@ fn generate_module(in_file: &Path) { ) .expect("PDL parse failed"); let analyzed_file = pdl_compiler::analyzer::analyze(&parsed_file).expect("PDL analysis failed"); - let rust_source = pdl_compiler::backends::rust_legacy::generate(&sources, &analyzed_file); + let rust_source = pdl_compiler::backends::rust::generate(&sources, &analyzed_file, &[]); out_file .write_all(rust_source.as_bytes()) .expect("Could not write to output file"); diff --git a/src/device.rs b/src/device.rs index 61547e7..61ebc92 100644 --- a/src/device.rs +++ b/src/device.rs @@ -149,8 +149,7 @@ impl Device { tokio::spawn(async move { time::sleep(Duration::from_millis(5)).await; tx.send( - CoreDeviceStatusNtfBuilder { device_state } - .build() + CoreDeviceStatusNtf { device_state } .encode_to_vec() .unwrap(), ) @@ -217,7 +216,7 @@ impl Device { // The fira norm specify to send a response, then reset, then // send a notification once the reset is done fn core_device_reset(&mut self, cmd: CoreDeviceResetCmd) -> CoreDeviceResetRsp { - let reset_config = cmd.get_reset_config(); + let reset_config = cmd.reset_config; log::debug!("[{}] DeviceReset", self.handle); log::debug!(" reset_config={:?}", reset_config); @@ -230,17 +229,16 @@ impl Device { self.is_reset = true; self.init(); - CoreDeviceResetRspBuilder { + CoreDeviceResetRsp { status: uci::Status::Ok, } - .build() } fn core_get_device_info(&self, _cmd: CoreGetDeviceInfoCmd) -> CoreGetDeviceInfoRsp { // TODO: Implement a fancy build time state machine instead of crash at runtime log::debug!("[{}] GetDeviceInfo", self.handle); assert_eq!(self.state, DeviceState::DeviceStateReady); - CoreGetDeviceInfoRspBuilder { + CoreGetDeviceInfoRsp { status: uci::Status::Ok, uci_version: UCI_VERSION, mac_version: MAC_VERSION, @@ -248,7 +246,6 @@ impl Device { uci_test_version: TEST_VERSION, vendor_spec_info: Vec::new(), } - .build() } pub fn core_get_caps_info(&self, _cmd: CoreGetCapsInfoCmd) -> CoreGetCapsInfoRsp { @@ -262,11 +259,10 @@ impl Device { }) .collect(); - CoreGetCapsInfoRspBuilder { + CoreGetCapsInfoRsp { status: uci::Status::Ok, tlvs: caps, } - .build() } pub fn core_set_config(&mut self, cmd: CoreSetConfigCmd) -> CoreSetConfigRsp { @@ -280,7 +276,7 @@ impl Device { // available in the UWBS. All other configuration parameters should // have been set to the new values within the UWBS. let mut invalid_parameters = vec![]; - for parameter in cmd.get_parameters() { + for parameter in cmd.parameters { match parameter.id { uci::ConfigParameterId::DeviceState => { invalid_parameters.push(uci::ConfigParameterStatus { @@ -301,7 +297,7 @@ impl Device { } } - CoreSetConfigRspBuilder { + CoreSetConfigRsp { status: if invalid_parameters.is_empty() { uci::Status::Ok } else { @@ -309,7 +305,6 @@ impl Device { }, parameters: invalid_parameters, } - .build() } pub fn core_get_config(&self, cmd: CoreGetConfigCmd) -> CoreGetConfigRsp { @@ -324,41 +319,38 @@ impl Device { // that are available in the UWBS. let mut valid_parameters = vec![]; let mut invalid_parameters = vec![]; - for id in cmd.get_parameter_ids() { + for id in cmd.parameter_ids { match id { ConfigParameterId::DeviceState => valid_parameters.push(ConfigParameter { - id: *id, + id, value: vec![self.config.device_state.into()], }), ConfigParameterId::LowPowerMode => valid_parameters.push(ConfigParameter { - id: *id, + id, value: vec![self.config.low_power_mode.into()], }), - ConfigParameterId::Rfu(_) => invalid_parameters.push(ConfigParameter { - id: *id, - value: vec![], - }), + ConfigParameterId::Rfu(_) => { + invalid_parameters.push(ConfigParameter { id, value: vec![] }) + } } } if invalid_parameters.is_empty() { - CoreGetConfigRspBuilder { + CoreGetConfigRsp { status: uci::Status::Ok, parameters: valid_parameters, } - .build() } else { - CoreGetConfigRspBuilder { + CoreGetConfigRsp { status: uci::Status::InvalidParam, parameters: invalid_parameters, } - .build() } } fn session_init(&mut self, cmd: SessionInitCmd) -> SessionInitRsp { - let session_id = cmd.get_session_id(); - let session_type = cmd.get_session_type(); + let session_id = cmd.session_id; + let session_type = cmd.session_type; log::debug!("[{}] Session init", self.handle); log::debug!(" session_id=0x{:x}", session_id); @@ -380,11 +372,11 @@ impl Device { } }; - SessionInitRspBuilder { status }.build() + SessionInitRsp { status } } fn session_deinit(&mut self, cmd: SessionDeinitCmd) -> SessionDeinitRsp { - let session_id = cmd.get_session_token(); + let session_id = cmd.session_token; log::debug!("[{}] Session deinit", self.handle); log::debug!(" session_id=0x{:x}", session_id); @@ -401,21 +393,20 @@ impl Device { } None => uci::Status::ErrorSessionNotExist, }; - SessionDeinitRspBuilder { status }.build() + SessionDeinitRsp { status } } fn session_get_count(&self, _cmd: SessionGetCountCmd) -> SessionGetCountRsp { log::debug!("[{}] Session get count", self.handle); - SessionGetCountRspBuilder { + SessionGetCountRsp { status: uci::Status::Ok, session_count: self.sessions.len() as u8, } - .build() } fn session_set_app_config(&mut self, cmd: SessionSetAppConfigCmd) -> SessionSetAppConfigRsp { - let session_handle = cmd.get_session_token(); + let session_handle = cmd.session_token; log::debug!( "[{}:0x{:x}] Session Set App Config", @@ -424,11 +415,10 @@ impl Device { ); let Some(session) = self.sessions.get_mut(&session_handle) else { - return SessionSetAppConfigRspBuilder { + return SessionSetAppConfigRsp { cfg_status: Vec::new(), status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; assert!( @@ -439,15 +429,14 @@ impl Device { if session.state == SessionState::SessionStateActive { const IMMUTABLE_PARAMETERS: &[AppConfigTlvType] = &[AppConfigTlvType::AoaResultReq]; if cmd - .get_tlvs() + .tlvs .iter() .any(|cfg| IMMUTABLE_PARAMETERS.contains(&cfg.cfg_id)) { - return SessionSetAppConfigRspBuilder { + return SessionSetAppConfigRsp { status: uci::Status::ErrorSessionActive, cfg_status: vec![], - } - .build(); + }; } } @@ -458,7 +447,7 @@ impl Device { } else { let mut app_config = session.app_config.clone(); let mut invalid_parameters = vec![]; - for cfg in cmd.get_tlvs() { + for cfg in cmd.tlvs { match app_config.set(cfg.cfg_id, &cfg.v) { Ok(_) => (), Err(_) => invalid_parameters.push(AppConfigStatus { @@ -491,11 +480,10 @@ impl Device { self.handle, session_handle ); - return SessionSetAppConfigRspBuilder { + return SessionSetAppConfigRsp { status: uci::Status::Rejected, cfg_status: vec![], - } - .build(); + }; } if invalid_parameters.is_empty() { @@ -512,15 +500,14 @@ impl Device { } }; - SessionSetAppConfigRspBuilder { + SessionSetAppConfigRsp { status, cfg_status: invalid_parameters, } - .build() } fn session_get_app_config(&self, cmd: SessionGetAppConfigCmd) -> SessionGetAppConfigRsp { - let session_handle = cmd.get_session_token(); + let session_handle = cmd.session_token; log::debug!( "[{}:0x{:x}] Session Get App Config", @@ -529,24 +516,23 @@ impl Device { ); let Some(session) = self.sessions.get(&session_handle) else { - return SessionGetAppConfigRspBuilder { + return SessionGetAppConfigRsp { tlvs: vec![], status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; let (status, valid_parameters) = { let mut valid_parameters = vec![]; let mut invalid_parameters = vec![]; - for id in cmd.get_app_cfg() { - match session.app_config.get(*id) { + for id in cmd.app_cfg { + match session.app_config.get(id) { Ok(value) => valid_parameters.push(AppConfigTlv { - cfg_id: *id, + cfg_id: id, v: value, }), Err(_) => invalid_parameters.push(AppConfigTlv { - cfg_id: *id, + cfg_id: id, v: vec![], }), } @@ -559,38 +545,35 @@ impl Device { } }; - SessionGetAppConfigRspBuilder { + SessionGetAppConfigRsp { status, tlvs: valid_parameters, } - .build() } fn session_get_state(&self, cmd: SessionGetStateCmd) -> SessionGetStateRsp { - let session_handle = cmd.get_session_token(); + let session_handle = cmd.session_token; log::debug!("[{}:0x{:x}] Session Get State", self.handle, session_handle); let Some(session) = self.sessions.get(&session_handle) else { - return SessionGetStateRspBuilder { + return SessionGetStateRsp { session_state: SessionState::SessionStateInit, status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; - SessionGetStateRspBuilder { + SessionGetStateRsp { status: uci::Status::Ok, session_state: session.state, } - .build() } fn session_update_controller_multicast_list( &mut self, cmd: SessionUpdateControllerMulticastListCmd, ) -> SessionUpdateControllerMulticastListRsp { - let session_handle = cmd.get_session_token(); + let session_handle = cmd.session_token; log::debug!( "[{}:0x{:x}] Session Update Controller Multicast List", @@ -599,10 +582,9 @@ impl Device { ); let Some(session) = self.sessions.get_mut(&session_handle) else { - return SessionUpdateControllerMulticastListRspBuilder { + return SessionUpdateControllerMulticastListRsp { status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; if (session.state != SessionState::SessionStateActive @@ -610,18 +592,17 @@ impl Device { || session.app_config.device_type != Some(DeviceType::Controller) || session.app_config.multi_node_mode != Some(MultiNodeMode::OneToMany) { - return SessionUpdateControllerMulticastListRspBuilder { + return SessionUpdateControllerMulticastListRsp { status: uci::Status::Rejected, - } - .build(); + }; } - let action = cmd.get_action(); + let action = cmd.action; let mut dst_addresses = session.app_config.dst_mac_address.clone(); let new_controlees: Vec = match action { UpdateMulticastListAction::AddControlee | UpdateMulticastListAction::RemoveControlee => { if let Ok(packet) = - SessionUpdateControllerMulticastListCmdPayload::parse(cmd.get_payload()) + SessionUpdateControllerMulticastListCmdPayload::decode_full(&cmd.payload) { packet .controlees @@ -629,16 +610,15 @@ impl Device { .map(|controlee| controlee.into()) .collect() } else { - return SessionUpdateControllerMulticastListRspBuilder { + return SessionUpdateControllerMulticastListRsp { status: uci::Status::SyntaxError, - } - .build(); + }; } } UpdateMulticastListAction::AddControleeWithShortSubSessionKey => { if let Ok(packet) = - SessionUpdateControllerMulticastListCmd_2_0_16_Byte_Payload::parse( - cmd.get_payload(), + SessionUpdateControllerMulticastListCmd_2_0_16_Byte_Payload::decode_full( + &cmd.payload, ) { packet @@ -647,16 +627,15 @@ impl Device { .map(|controlee| controlee.into()) .collect() } else { - return SessionUpdateControllerMulticastListRspBuilder { + return SessionUpdateControllerMulticastListRsp { status: uci::Status::SyntaxError, - } - .build(); + }; } } UpdateMulticastListAction::AddControleeWithExtendedSubSessionKey => { if let Ok(packet) = - SessionUpdateControllerMulticastListCmd_2_0_32_Byte_Payload::parse( - cmd.get_payload(), + SessionUpdateControllerMulticastListCmd_2_0_32_Byte_Payload::decode_full( + &cmd.payload, ) { packet @@ -665,10 +644,9 @@ impl Device { .map(|controlee| controlee.into()) .collect() } else { - return SessionUpdateControllerMulticastListRspBuilder { + return SessionUpdateControllerMulticastListRsp { status: uci::Status::SyntaxError, - } - .build(); + }; } } }; @@ -759,11 +737,10 @@ impl Device { // TODO(#84) remove the sleep. time::sleep(Duration::from_millis(5)).await; tx.send( - SessionUpdateControllerMulticastListNtfBuilder { + SessionUpdateControllerMulticastListNtf { controlee_status, session_token: session_handle, } - .build() .encode_to_vec() .unwrap(), ) @@ -783,26 +760,24 @@ impl Device { ReasonCode::ErrorInvalidNumOfControlees, ) } - SessionUpdateControllerMulticastListRspBuilder { status }.build() + SessionUpdateControllerMulticastListRsp { status } } fn session_start(&mut self, cmd: SessionStartCmd) -> SessionStartRsp { - let session_id = cmd.get_session_id(); + let session_id = cmd.session_id; log::debug!("[{}:0x{:x}] Session Start", self.handle, session_id); let Some(session) = self.sessions.get_mut(&session_id) else { - return SessionStartRspBuilder { + return SessionStartRsp { status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; if session.state != SessionState::SessionStateIdle { - return SessionStartRspBuilder { + return SessionStartRsp { status: uci::Status::ErrorSessionNotConfigured, - } - .build(); + }; } assert!(session.ranging_task.is_none()); @@ -829,29 +804,26 @@ impl Device { self.n_active_sessions += 1; self.set_state(DeviceState::DeviceStateActive); - SessionStartRspBuilder { + SessionStartRsp { status: uci::Status::Ok, } - .build() } fn session_stop(&mut self, cmd: SessionStopCmd) -> SessionStopRsp { - let session_id = cmd.get_session_id(); + let session_id = cmd.session_id; log::debug!("[{}:0x{:x}] Session Stop", self.handle, session_id); let Some(session) = self.sessions.get_mut(&session_id) else { - return SessionStopRspBuilder { + return SessionStopRsp { status: uci::Status::ErrorSessionNotExist, - } - .build(); + }; }; if session.state != SessionState::SessionStateActive { - return SessionStopRspBuilder { + return SessionStopRsp { status: uci::Status::ErrorSessionActive, - } - .build(); + }; } session.stop_ranging_task(); @@ -865,17 +837,16 @@ impl Device { self.set_state(DeviceState::DeviceStateReady); } - SessionStopRspBuilder { + SessionStopRsp { status: uci::Status::Ok, } - .build() } fn session_get_ranging_count( &self, cmd: SessionGetRangingCountCmd, ) -> SessionGetRangingCountRsp { - let session_id = cmd.get_session_id(); + let session_id = cmd.session_id; log::debug!( "[{}:0x{:x}] Session Get Ranging Count", @@ -884,33 +855,31 @@ impl Device { ); let Some(session) = self.sessions.get(&session_id) else { - return SessionGetRangingCountRspBuilder { + return SessionGetRangingCountRsp { status: uci::Status::ErrorSessionNotExist, count: 0, - } - .build(); + }; }; - SessionGetRangingCountRspBuilder { + SessionGetRangingCountRsp { status: uci::Status::Ok, count: session.sequence_number, } - .build() } fn android_set_country_code( &mut self, cmd: AndroidSetCountryCodeCmd, ) -> AndroidSetCountryCodeRsp { - let country_code = *cmd.get_country_code(); + let country_code = cmd.country_code; + log::debug!("[{}] Set country code", self.handle); log::debug!(" country_code={},{}", country_code[0], country_code[1]); self.country_code = country_code; - AndroidSetCountryCodeRspBuilder { + AndroidSetCountryCodeRsp { status: uci::Status::Ok, } - .build() } fn android_get_power_stats( @@ -920,7 +889,7 @@ impl Device { log::debug!("[{}] Get power stats", self.handle); // TODO - AndroidGetPowerStatsRspBuilder { + AndroidGetPowerStatsRsp { stats: PowerStats { status: uci::Status::Ok, idle_time_ms: 0, @@ -929,38 +898,40 @@ impl Device { total_wake_count: 0, }, } - .build() } pub fn data_message_snd(&mut self, data: DataPacket) -> ControlPacket { log::debug!("[{}] data_message_send", self.handle); - match data.specialize() { + match data + .specialize() + .expect("failed to parse Data packet child") + { DataPacketChild::DataMessageSnd(data_msg_snd) => { - let session_token = data_msg_snd.get_session_handle(); + let session_token = data_msg_snd.session_handle; if let Some(session) = self.session_mut(session_token) { session.data_message_snd(data_msg_snd) } else { - SessionDataTransferStatusNtfBuilder { + SessionDataTransferStatusNtf { session_token, status: DataTransferNtfStatusCode::UciDataTransferStatusErrorRejected, tx_count: 1, // TODO: support for retries? uci_sequence_number: 0, } - .build() - .into() + .try_into() + .unwrap() } } DataPacketChild::DataMessageRcv(data_msg_rcv) => { // This function should not be passed anything besides DataMessageSnd - let session_token = data_msg_rcv.get_session_handle(); - SessionDataTransferStatusNtfBuilder { + let session_token = data_msg_rcv.session_handle; + SessionDataTransferStatusNtf { session_token, status: DataTransferNtfStatusCode::UciDataTransferStatusInvalidFormat, tx_count: 1, // TODO: support for retries? uci_sequence_number: 0, } - .build() - .into() + .try_into() + .unwrap() } _ => { unimplemented!() @@ -979,72 +950,90 @@ impl Device { // Reset command. The controller responds with Device Status // Notification with DEVICE_STATE_ERROR otherwise. if !self.is_reset && !cmd.is_core_device_reset_cmd() { - return CoreDeviceStatusNtfBuilder { + return uci::CoreDeviceStatusNtf { device_state: DeviceState::DeviceStateError, } - .build() - .into(); + .try_into() + .unwrap(); } - match cmd.specialize() { - CorePacket(cmd) => match cmd.specialize() { - CoreDeviceResetCmd(cmd) => self.core_device_reset(cmd).into(), - CoreGetDeviceInfoCmd(cmd) => self.core_get_device_info(cmd).into(), - CoreGetCapsInfoCmd(cmd) => self.core_get_caps_info(cmd).into(), - CoreSetConfigCmd(cmd) => self.core_set_config(cmd).into(), - CoreGetConfigCmd(cmd) => self.core_get_config(cmd).into(), - _ => unimplemented!("Unsupported Core oid {:?}", cmd.get_oid()), + match cmd + .specialize() + .expect("Failed to parse Control packet child") + { + CorePacket(cmd) => match cmd.specialize().expect("Failed to parse Core packet child") { + CoreDeviceResetCmd(cmd) => self.core_device_reset(cmd).try_into().unwrap(), + CoreGetDeviceInfoCmd(cmd) => self.core_get_device_info(cmd).try_into().unwrap(), + CoreGetCapsInfoCmd(cmd) => self.core_get_caps_info(cmd).try_into().unwrap(), + CoreSetConfigCmd(cmd) => self.core_set_config(cmd).try_into().unwrap(), + CoreGetConfigCmd(cmd) => self.core_get_config(cmd).try_into().unwrap(), + _ => unimplemented!("Unsupported Core oid {:?}", cmd.oid), }, - SessionConfigPacket(cmd) => match cmd.specialize() { - SessionInitCmd(cmd) => self.session_init(cmd).into(), - SessionDeinitCmd(cmd) => self.session_deinit(cmd).into(), - SessionGetCountCmd(cmd) => self.session_get_count(cmd).into(), - SessionSetAppConfigCmd(cmd) => self.session_set_app_config(cmd).into(), - SessionGetAppConfigCmd(cmd) => self.session_get_app_config(cmd).into(), - SessionGetStateCmd(cmd) => self.session_get_state(cmd).into(), - SessionUpdateControllerMulticastListCmd(cmd) => { - self.session_update_controller_multicast_list(cmd).into() - } - _ => unimplemented!("Unsupported Session Config oid {:?}", cmd.get_oid()), + SessionConfigPacket(cmd) => match cmd + .specialize() + .expect("Failed to parse Session Config packet child") + { + SessionInitCmd(cmd) => self.session_init(cmd).try_into().unwrap(), + SessionDeinitCmd(cmd) => self.session_deinit(cmd).try_into().unwrap(), + SessionGetCountCmd(cmd) => self.session_get_count(cmd).try_into().unwrap(), + SessionSetAppConfigCmd(cmd) => self.session_set_app_config(cmd).try_into().unwrap(), + SessionGetAppConfigCmd(cmd) => self.session_get_app_config(cmd).try_into().unwrap(), + SessionGetStateCmd(cmd) => self.session_get_state(cmd).try_into().unwrap(), + SessionUpdateControllerMulticastListCmd(cmd) => self + .session_update_controller_multicast_list(cmd) + .try_into() + .unwrap(), + _ => unimplemented!("Unsupported Session Config oid {:?}", cmd.oid), }, - SessionControlPacket(cmd) => match cmd.specialize() { - SessionStartCmd(cmd) => self.session_start(cmd).into(), - SessionStopCmd(cmd) => self.session_stop(cmd).into(), - SessionGetRangingCountCmd(cmd) => self.session_get_ranging_count(cmd).into(), - _ => unimplemented!("Unsupported Session Control oid {:?}", cmd.get_oid()), + SessionControlPacket(cmd) => match cmd + .specialize() + .expect("Failed to parse Session Control packet child") + { + SessionStartCmd(cmd) => self.session_start(cmd).try_into().unwrap(), + SessionStopCmd(cmd) => self.session_stop(cmd).try_into().unwrap(), + SessionGetRangingCountCmd(cmd) => { + self.session_get_ranging_count(cmd).try_into().unwrap() + } + _ => unimplemented!("Unsupported Session Control oid {:?}", cmd.oid), }, - AndroidPacket(cmd) => match cmd.specialize() { - AndroidSetCountryCodeCmd(cmd) => self.android_set_country_code(cmd).into(), - AndroidGetPowerStatsCmd(cmd) => self.android_get_power_stats(cmd).into(), - _ => unimplemented!("Unsupported Android oid {:?}", cmd.get_oid()), + AndroidPacket(cmd) => match cmd + .specialize() + .expect("Failed to parse Android packet child") + { + AndroidSetCountryCodeCmd(cmd) => { + self.android_set_country_code(cmd).try_into().unwrap() + } + AndroidGetPowerStatsCmd(cmd) => { + self.android_get_power_stats(cmd).try_into().unwrap() + } + _ => unimplemented!("Unsupported Android oid {:?}", cmd.oid), }, - ControlPacketChild::Payload(_) + ControlPacketChild::None if matches!( - cmd.get_mt(), + cmd.mt, uci::MessageType::Response | uci::MessageType::Notification ) => { - unreachable!("Unhandled control messsage with type {:?}", cmd.get_mt()); + unreachable!("Unhandled control messsage with type {:?}", cmd.mt); } - ControlPacketChild::Payload(payload) => { + ControlPacketChild::None => { // [UCI] 4.3.2 Exception Handling for Control Messages // The UWBS shall respond to an unknown Command (unknown GID // or OID) with a Response having the same GID and OID field // values as the Command, followed by a Status field with the // value of STATUS_UNKNOWN_GID/STATUS_UNKNOWN_OID respectively // and no additional fields. - log::error!("Unsupported gid {:?}", cmd.get_gid()); - ControlPacketBuilder { + log::error!("Unsupported gid {:?}", cmd.gid); + ControlPacket { mt: uci::MessageType::Response, - gid: cmd.get_gid(), - payload: Some( - vec![payload[0], payload[1], 0x1, uci::Status::UnknownGid.into()].into(), - ), + gid: cmd.gid, + payload: vec![ + cmd.payload[0], + cmd.payload[1], + 0x1, + uci::Status::UnknownGid.into(), + ], } - .build() - } - ControlPacketChild::None => { - unreachable!() } } } @@ -1052,7 +1041,7 @@ impl Device { pub fn receive_packet(&mut self, packet: Vec) { let mt = parse_message_type(packet[0]); match mt { - MessageType::Data => match DataPacket::parse(&packet) { + MessageType::Data => match DataPacket::decode_full(&packet) { Ok(packet) => { let notification = self.data_message_snd(packet); self.send_control(notification) @@ -1060,7 +1049,7 @@ impl Device { Err(err) => log::error!("failed to parse incoming Data packet: {}", err), }, MessageType::Command => { - match ControlPacket::parse(&packet) { + match ControlPacket::decode_full(&packet) { // Parsing error. Determine what error response should be // returned to the host: // - response and notifications are ignored, no response diff --git a/src/lib.rs b/src/lib.rs index cf2c480..560f28d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,7 +253,7 @@ impl Pica { .await .ok_or(anyhow::anyhow!("input packet stream closed"))?; let header = - packets::uci::CommonPacketHeader::parse(&packet[0..COMMON_HEADER_SIZE])?; + packets::uci::CommonPacketHeader::decode_full(&packet[0..COMMON_HEADER_SIZE])?; if let Some(file) = pcapng_file { file.write(&packet, pcapng::Direction::Tx)?; @@ -266,8 +266,8 @@ impl Pica { None => complete_packet = Some(packet), } - if header.get_pbf() == packets::uci::PacketBoundaryFlag::Complete - || header.get_mt() == packets::uci::MessageType::Data + if header.pbf == packets::uci::PacketBoundaryFlag::Complete + || header.mt == packets::uci::MessageType::Data { break; } @@ -473,7 +473,7 @@ impl Pica { peer_device .tx .send( - DataMessageRcvBuilder { + DataMessageRcv { application_data: session.data().clone().into(), data_sequence_number: 0x01, pbf: PacketBoundaryFlag::Complete, @@ -481,7 +481,6 @@ impl Pica { source_address: session.app_config.device_mac_address.unwrap().into(), status: uci::Status::Ok, } - .build() .encode_to_vec() .unwrap(), ) @@ -492,7 +491,7 @@ impl Pica { .tx .send( // TODO: support extended address - ShortMacTwoWaySessionInfoNtfBuilder { + ShortMacTwoWaySessionInfoNtf { sequence_number: session.sequence_number, session_token: session_id, rcr_indicator: 0, //TODO @@ -500,7 +499,6 @@ impl Pica { two_way_ranging_measurements: measurements, vendor_data: vec![], } - .build() .encode_to_vec() .unwrap(), ) diff --git a/src/packets.rs b/src/packets.rs index 08b3a82..50c4ff6 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -27,13 +27,10 @@ pub mod uci { impl ControlPacket { pub fn is_core_device_reset_cmd(&self) -> bool { - matches!( - self.controlpacket.child, - ControlPacketDataChild::CorePacket(CorePacketData { - child: CorePacketDataChild::CoreDeviceResetCmd(_), - .. - }) - ) + let Ok(core_packet) = CorePacket::try_from(self) else { + return false; + }; + core_packet.oid == CoreOpcodeId::DeviceReset } } @@ -64,17 +61,18 @@ pub mod uci { socket.read_exact(&mut packet[0..HEADER_SIZE]).await.ok()?; let common_packet_header = - CommonPacketHeader::parse(&packet[0..COMMON_HEADER_SIZE]).ok()?; + CommonPacketHeader::decode_full(&packet[0..COMMON_HEADER_SIZE]).ok()?; - let payload_length = match common_packet_header.get_mt() { + let payload_length = match common_packet_header.mt { MessageType::Data => { - let data_packet_header = DataPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?; - data_packet_header.get_payload_length() as usize + let data_packet_header = + DataPacketHeader::decode_full(&packet[0..HEADER_SIZE]).ok()?; + data_packet_header.payload_length as usize } _ => { let control_packet_header = - ControlPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?; - control_packet_header.get_payload_length() as usize + ControlPacketHeader::decode_full(&packet[0..HEADER_SIZE]).ok()?; + control_packet_header.payload_length as usize } }; diff --git a/src/session.rs b/src/session.rs index 54b98a2..656ad99 100644 --- a/src/session.rs +++ b/src/session.rs @@ -75,12 +75,11 @@ impl Session { tokio::spawn(async move { time::sleep(Duration::from_millis(1)).await; tx.send( - SessionStatusNtfBuilder { + SessionStatusNtf { session_token: session_id, session_state, reason_code: reason_code.into(), } - .build() .encode_to_vec() .unwrap(), ) @@ -134,30 +133,30 @@ impl Session { pub fn data_message_snd(&mut self, data: DataMessageSnd) -> ControlPacket { log::debug!("[{}] data_message_snd", self.device_handle); - let session_token = data.get_session_handle(); - let uci_sequence_number = data.get_data_sequence_number() as u8; + let session_token = data.session_handle; + let uci_sequence_number = data.data_sequence_number as u8; if self.session_type != SessionType::FiraRangingAndInBandDataSession { - return SessionDataTransferStatusNtfBuilder { + return SessionDataTransferStatusNtf { session_token, status: DataTransferNtfStatusCode::UciDataTransferStatusSessionTypeNotSupported, tx_count: 1, // TODO: support for retries? uci_sequence_number, } - .build() - .into(); + .try_into() + .unwrap(); } assert_eq!(self.id, session_token); - self.data.extend_from_slice(data.get_application_data()); + self.data.extend_from_slice(&data.application_data); - SessionDataCreditNtfBuilder { + SessionDataCreditNtf { credit_availability: CreditAvailability::CreditAvailable, session_token, } - .build() - .into() + .try_into() + .unwrap() } }