1#![warn(clippy::pedantic)]
2#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
3mod common;
4pub use common::*;
5
6mod error;
7pub use error::Error;
8
9pub use uds_protocol_derive::Identifier;
11
12mod protocol_definitions;
13pub use protocol_definitions::{ProtocolIdentifier, ProtocolPayload};
14
15mod request;
16pub use request::Request;
17
18mod response;
19pub use response::{Response, UdsResponse};
20
21mod service;
22pub use service::UdsServiceType;
23
24mod services;
25pub use services::*;
26
27mod traits;
28pub use traits::{
29 DiagnosticDefinition, Identifier, IterableWireFormat, RoutineIdentifier, SingleValueWireFormat,
30 WireFormat,
31};
32
33pub const SUCCESS: u8 = 0x80;
34pub const PENDING: u8 = 0x78;
35
36#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
41#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
42#[derive(Clone, Copy, Debug, Eq, PartialEq)]
43pub struct UdsSpec;
44impl DiagnosticDefinition for UdsSpec {
45 type RID = UDSRoutineIdentifier;
46 type DID = ProtocolIdentifier;
47 type RoutinePayload = ProtocolPayload;
48 type DiagnosticPayload = ProtocolPayload;
49}
50
51pub type ProtocolRequest = Request<UdsSpec>;
53
54pub type ProtocolResponse = Response<UdsSpec>;
56
57#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
59#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
60#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
61#[derive(Clone, Copy, Debug, Eq, PartialEq)]
62pub enum RoutineControlSubFunction {
63 StartRoutine,
69
70 StopRoutine,
73
74 RequestRoutineResults,
76}
77
78impl From<RoutineControlSubFunction> for u8 {
79 fn from(value: RoutineControlSubFunction) -> Self {
80 match value {
81 RoutineControlSubFunction::StartRoutine => 0x01,
82 RoutineControlSubFunction::StopRoutine => 0x02,
83 RoutineControlSubFunction::RequestRoutineResults => 0x03,
84 }
85 }
86}
87
88impl From<u8> for RoutineControlSubFunction {
89 fn from(value: u8) -> Self {
90 match value {
91 0x01 => RoutineControlSubFunction::StartRoutine,
92 0x02 => RoutineControlSubFunction::StopRoutine,
93 0x03 => RoutineControlSubFunction::RequestRoutineResults,
94 _ => panic!("Invalid routine control subfunction: {value}"),
95 }
96 }
97}
98
99impl WireFormat for Vec<u8> {
100 fn decode<T: std::io::Read>(reader: &mut T) -> Result<Option<Self>, Error> {
101 let mut data = Vec::new();
102 reader.read_to_end(&mut data)?;
103 Ok(Some(data))
104 }
105
106 fn required_size(&self) -> usize {
107 self.len()
108 }
109
110 fn encode<T: std::io::Write>(&self, writer: &mut T) -> Result<usize, Error> {
111 writer.write_all(self)?;
112 Ok(self.len())
113 }
114}
115
116impl SingleValueWireFormat for Vec<u8> {}
117impl IterableWireFormat for Vec<u8> {}
118
119#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
120#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
121#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
122#[derive(Clone, Copy, Debug, Eq, PartialEq)]
123pub enum DtcSettings {
124 On,
125 Off,
126}
127
128impl From<DtcSettings> for u8 {
129 fn from(value: DtcSettings) -> Self {
130 match value {
131 DtcSettings::On => 0x01,
132 DtcSettings::Off => 0x02,
133 }
134 }
135}
136
137impl From<u8> for DtcSettings {
138 fn from(value: u8) -> Self {
139 match value {
140 0x01 => Self::On,
141 0x02 => Self::Off,
142 _ => panic!("Invalid DTC setting: {value}"),
143 }
144 }
145}