use serde_yaml; use types::{NamedValue, Value}; #[derive(Debug, Deserialize)] pub struct RawECURequest { sendto: u16, recvfrom: Option, flowctrl: Option, packet: Vec, } impl RawECURequest { pub fn sendto(&self) -> u16 { self.sendto } pub fn recvfrom(&self) -> u16 { self.recvfrom.unwrap_or(self.sendto + 8) } pub fn flowctrl(&self) -> u16 { self.flowctrl.unwrap_or(self.sendto) } pub fn packet(&self) -> &[u8] { &self.packet } } #[derive(Debug, Deserialize)] pub struct RawECUResponseEntry { name: String, offset: usize, length: usize, check: Option>, kind: Option, base: Option, count: Option, } #[derive(Debug, Deserialize)] pub struct RawECUResponse { length: usize, values: Vec, } #[derive(Debug, Deserialize)] pub struct RawECUEntry { name: String, description: String, request: RawECURequest, response: RawECUResponse, } impl RawECUEntry { pub fn get_all() -> &'static [RawECUEntry] { lazy_static! { static ref ECUS: Vec = serde_yaml::from_slice(include_bytes!("../definitions/raw.yaml")).unwrap(); } &ECUS } pub fn ecu_for(id: u16, payload: &[u8]) -> Option<&'static RawECUEntry> { 'ecu: for ecu in RawECUEntry::get_all() { if (ecu.request().sendto() == id || ecu.request().recvfrom() == id || ecu.request().flowctrl() == id) && ecu.response.length == payload.len() { for entry in &ecu.response.values { if let Some(ref vals) = entry.check { let has = &payload[entry.offset..(entry.offset + vals.len())]; trace!("Check: Does {:?} == {:?}", vals, has); for i in 0..vals.len() { if has[i] != vals[i] { trace!("Oops, not the same"); continue 'ecu; } } } } return Some(ecu); } } None } pub fn name(&self) -> &str { &self.name } pub fn description(&self) -> &str { &self.description } pub fn request(&self) -> &RawECURequest { &self.request } pub fn decode(&self, payload: &[u8]) -> Option> { let mut ret = Vec::new(); if payload.len() != self.response.length { warn!( "Unable to decode, length incorrect. {} != {}", payload.len(), self.response.length ); return None; } for entry in &self.response.values { if let Some(ref kind) = entry.kind { let value: Value = match kind.as_ref() { "unsigned" => { trace!("Unsigned"); match entry.length { 1 => payload[entry.offset].into(), 2 => (((payload[entry.offset] as u16) << 8) + (payload[entry.offset + 1] as u16)) .into(), 3 => (((payload[entry.offset] as u32) << 16) + ((payload[entry.offset + 1] as u32) << 8) + (payload[entry.offset + 2] as u32)) .into(), 4 => (((payload[entry.offset] as u32) << 24) + ((payload[entry.offset + 1] as u32) << 16) + ((payload[entry.offset + 2] as u32) << 8) + (payload[entry.offset + 3] as u32)) .into(), _ => panic!("Unhandled length: {}", entry.length), } } "signed" => { trace!("Signed"); match entry.length { 1 => (payload[entry.offset] as i8).into(), 2 => ((((payload[entry.offset] as u16) << 8) + (payload[entry.offset + 1] as u16)) as i16) .into(), 3 => ((((payload[entry.offset] as u32) << 16) + ((payload[entry.offset + 1] as u32) << 8) + (payload[entry.offset + 2] as u32)) as i32) .into(), 4 => ((((payload[entry.offset] as u32) << 24) + ((payload[entry.offset + 1] as u32) << 16) + ((payload[entry.offset + 2] as u32) << 8) + (payload[entry.offset + 3] as u32)) as i32) .into(), _ => panic!("Unhandled length: {}", entry.length), } } "bit" => { trace!("Bit"); ((payload[entry.offset] & (1 << entry.base.unwrap())) != 0).into() } _ => { panic!("Unhandled"); } }; let name = { let mut n = self.name.clone(); n.push('.'); n.push_str(&entry.name); n }; ret.push(NamedValue::new(&name, Some(value))); } } Some(ret) } }