1pub mod extend_trait;
2pub mod get_req;
3pub mod get_resp;
4pub mod ident_req;
5pub mod ident_resp;
6pub mod set_req;
7pub mod set_resp;
8
9use crate::comm::BytesWrap;
10use crate::comm::PROFINET_ETHER_TYPE;
11use anyhow::{bail, Result};
12use pnet::util::MacAddr;
13
14#[derive(Debug, Copy, Clone, Eq, PartialEq)]
15pub enum PnDcpTy {
16 HelloReq, HelloRespSuc, HelloRespUnsup, IdentReq, IdentRespSuc, GetReq, GetRespSuc, GetRespUnsup, SetReq, SetRespSuc, SetRespUnsup, }
29impl PnDcpTy {
30 pub fn to_u8_array(&self) -> [u8; 4] {
31 match self {
32 Self::HelloReq => [0xfe, 0xfc, 0x06, 0x00],
33 Self::HelloRespSuc => [0xfe, 0xfc, 0x06, 0x01],
34 Self::HelloRespUnsup => [0xfe, 0xfc, 0x06, 0x05],
35 Self::IdentReq => [0xfe, 0xfe, 0x05, 0x00],
36 Self::IdentRespSuc => [0xfe, 0xff, 0x05, 0x01],
37 Self::GetReq => [0xfe, 0xfd, 0x03, 0x00],
39 Self::GetRespSuc => [0xfe, 0xfd, 0x03, 0x01],
40 Self::GetRespUnsup => [0xfe, 0xfd, 0x03, 0x05],
41 Self::SetReq => [0xfe, 0xfd, 0x04, 0x00],
42 Self::SetRespSuc => [0xfe, 0xfd, 0x04, 0x01],
43 Self::SetRespUnsup => [0xfe, 0xfd, 0x04, 0x05],
44 }
45 }
46}
47impl TryFrom<[u8; 4]> for PnDcpTy {
48 type Error = anyhow::Error;
49 fn try_from(value: [u8; 4]) -> std::result::Result<Self, Self::Error> {
50 match value {
51 [0xfe, 0xfc, 0x06, 0x00] => Ok(Self::HelloReq),
52 [0xfe, 0xfc, 0x06, 0x01] => Ok(Self::HelloRespSuc),
53 [0xfe, 0xfc, 0x06, 0x05] => Ok(Self::HelloRespUnsup),
54 [0xfe, 0xfe, 0x05, 0x00] => Ok(Self::IdentReq),
55 [0xfe, 0xff, 0x05, 0x01] => Ok(Self::IdentRespSuc),
56 [0xfe, 0xfd, 0x03, 0x00] => Ok(Self::GetReq),
58 [0xfe, 0xfd, 0x03, 0x01] => Ok(Self::GetRespSuc),
59 [0xfe, 0xfd, 0x03, 0x05] => Ok(Self::GetRespUnsup),
60 [0xfe, 0xfd, 0x04, 0x00] => Ok(Self::SetReq),
61 [0xfe, 0xfd, 0x04, 0x01] => Ok(Self::SetRespSuc),
62 [0xfe, 0xfd, 0x04, 0x05] => Ok(Self::SetRespUnsup),
63 _ => bail!("not a pn-dcp type!"),
64 }
65 }
66}
67pub struct PnDcp {
68 pub head: DcpHead,
69 pub blocks: BytesWrap,
70}
71
72impl TryFrom<&[u8]> for PnDcp {
73 type Error = anyhow::Error;
74
75 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
76 let head = DcpHead::try_from(value)?;
77 if let Some(blocks_data) = value.get(26..(26 + head.payload_len)) {
78 let blocks: BytesWrap = blocks_data.to_vec().into();
79 return Ok(Self { head, blocks });
80 }
81 bail!("长度不足,非PnDcg包");
82 }
83}
84
85#[derive(Debug, Eq, PartialEq, Clone)]
86pub struct DcpHead {
87 pub destination: MacAddr,
88 pub source: MacAddr,
89 pub ty: PnDcpTy,
90 pub xid: [u8; 4],
91 pub reserved_or_delay: [u8; 2],
92 pub payload_len: usize,
93}
94
95impl DcpHead {
96 pub fn append_data(&self, data: &mut Vec<u8>) {
97 data.extend_from_slice(self.destination.octets().as_slice());
98 data.extend_from_slice(self.source.octets().as_slice());
99 data.extend_from_slice(PROFINET_ETHER_TYPE.0.to_be_bytes().as_slice());
100 data.extend_from_slice(self.ty.to_u8_array().as_slice());
101 data.extend_from_slice(self.xid.as_slice());
102 data.extend_from_slice(self.reserved_or_delay.as_slice());
103 data.extend_from_slice((self.payload_len as u16).to_be_bytes().as_slice());
104 }
105 pub fn new(destination: MacAddr, source: MacAddr, ty: PnDcpTy) -> Self {
106 Self {
107 destination,
108 source,
109 ty,
110 xid: [0u8; 4],
111 reserved_or_delay: [0u8; 2],
112 payload_len: 0,
113 }
114 }
115 pub fn set_xid(&mut self, xid: [u8; 4]) {
116 self.xid = xid;
117 }
118 pub fn set_reserved_or_delay(&mut self, reserved_or_delay: [u8; 2]) {
119 self.reserved_or_delay = reserved_or_delay;
120 }
121 pub fn add_payload_len(&mut self, add: usize) {
125 self.payload_len += add;
126 }
127}
128
129impl TryFrom<&[u8]> for DcpHead {
130 type Error = anyhow::Error;
131
132 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
133 if let Some(payload_len) = value
134 .get(25)
135 .and_then(|x| Some(u16::from_be_bytes([value[24], *x]) as usize))
136 {
137 if PROFINET_ETHER_TYPE.0 != u16::from_be_bytes([value[12], value[13]]) {
138 bail!("the packet is not a pn-dcp!");
139
140 }
141 let ty = PnDcpTy::try_from([value[14], value[15], value[16], value[17]])?;
142 if payload_len + 26 > value.len() {
143 bail!("payload({}) + 26 > {}", payload_len, value.len());
144 }
145 let destination =
146 MacAddr::new(value[0], value[1], value[2], value[3], value[4], value[5]);
147 let source = MacAddr::new(value[6], value[7], value[8], value[9], value[10], value[11]);
148 let xid: [u8; 4] = [value[18], value[19], value[20], value[21]];
149 let reserved_or_delay: [u8; 2] = [value[22], value[23]];
150 return Ok(DcpHead {
151 destination,
152 source,
153 ty,
154 xid,
155 reserved_or_delay,
156 payload_len,
157 });
158 }
159 bail!("长度不足,非PnDcg包");
160 }
161}
162
163pub enum FrameId {
164 Hello,
165 GetOrSet,
166 IdentReq,
167 IdentResp,
168 UnSupport(u8, u8),
169}
170impl From<[u8; 2]> for FrameId {
171 fn from(a: [u8; 2]) -> Self {
172 match a {
173 [0xfe, 0xfc] => Self::Hello,
174 [0xfe, 0xfd] => Self::GetOrSet,
175 [0xfe, 0xfe] => Self::IdentReq,
176 [0xfe, 0xff] => Self::IdentResp,
177 [a, b] => Self::UnSupport(a, b),
178 }
179 }
180}