1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::{
io,
net::UdpSocket,
time::Duration,
};
use crate::{
Access,
Error,
StdTimeout,
Timeout,
timeout,
};
use super::*;
pub struct AccessLpcSim {
socket: UdpSocket,
timeout: StdTimeout,
}
impl AccessLpcSim {
pub unsafe fn new(timeout: Duration) -> Result<Self, Error> {
let socket = UdpSocket::bind("127.0.0.1:0")?;
socket.connect("127.0.0.1:8587")?;
let mut access = Self {
socket,
timeout: StdTimeout::new(timeout),
};
access.transaction(0x00, 0, 0)?;
Ok(access)
}
fn transaction(&mut self, kind: u8, addr: u16, value: u8) -> io::Result<u8> {
let addr = addr.to_le_bytes();
let request = [kind as u8, addr[0], addr[1], value];
if self.socket.send(&request)? != request.len() {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"Socket request incorrect size"
));
}
let mut response = [0];
if self.socket.recv(&mut response)? != response.len() {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"Socket response incorrect size"
));
}
Ok(response[0])
}
pub fn inb(&mut self, addr: u16) -> Result<u8, Error> {
Ok(self.transaction(0x01, addr, 0)?)
}
pub fn outb(&mut self, addr: u16, value: u8) -> Result<(), Error> {
self.transaction(0x02, addr, value)?;
Ok(())
}
unsafe fn read_cmd(&mut self, addr: u8) -> Result<u8, Error> {
self.inb(SMFI_CMD_BASE + u16::from(addr))
}
unsafe fn write_cmd(&mut self, addr: u8, data: u8) -> Result<(), Error> {
self.outb(SMFI_CMD_BASE + u16::from(addr), data)
}
unsafe fn command_check(&mut self) -> Result<(), Error> {
if self.read_cmd(SMFI_CMD_CMD)? == 0 {
Ok(())
} else {
Err(Error::WouldBlock)
}
}
}
impl Access for AccessLpcSim {
unsafe fn command(&mut self, cmd: u8, data: &mut [u8]) -> Result<u8, Error> {
if data.len() > self.data_size() {
return Err(Error::DataLength(data.len()));
}
self.command_check()?;
for i in 0..data.len() {
self.write_cmd(i as u8 + SMFI_CMD_DATA, data[i])?;
}
self.write_cmd(SMFI_CMD_CMD, cmd as u8)?;
self.timeout.reset();
timeout!(self.timeout, self.command_check())?;
for i in 0..data.len() {
data[i] = self.read_cmd(i as u8 + SMFI_CMD_DATA)?;
}
self.read_cmd(SMFI_CMD_RES)
}
fn data_size(&self) -> usize {
SMFI_CMD_SIZE - SMFI_CMD_DATA as usize
}
unsafe fn read_debug(&mut self, addr: u8) -> Result<u8, Error> {
self.inb(SMFI_DBG_BASE + u16::from(addr))
}
}