android_usb_serial/drivers/
ftdi.rs1use super::{Driver, EndpointPair, ModemStatus};
4use crate::config::{
5 DataBits, FlowControl, LineConfig, Parity, PurgeKind, StopBits, CHAR_XOFF, CHAR_XON,
6};
7use crate::error::{Result, UsbSerialError};
8use crate::reader::SerialReader;
9use crate::rx_filter::{FtdiHeaderFilter, XonXoffRxFilter};
10use crate::transport::{ControlRequest, SharedTransport};
11
12pub struct FtdiDriver {
13 port_index: usize,
14 iface: u8,
15 dtr: bool,
16 rts: bool,
17 baud_with_port: bool,
18 flow: FlowControl,
19 break_enabled: bool,
20 data_config: u16,
21 endpoints: Option<EndpointPair>,
22 transport: Option<SharedTransport>,
23 reader: Option<SerialReader>,
24}
25
26impl FtdiDriver {
27 pub fn new(port_index: usize) -> Self {
28 Self {
29 port_index,
30 iface: port_index as u8,
31 dtr: false,
32 rts: false,
33 baud_with_port: false,
34 flow: FlowControl::None,
35 break_enabled: false,
36 data_config: 0,
37 endpoints: None,
38 transport: None,
39 reader: None,
40 }
41 }
42
43 fn w_index(&self) -> u16 {
44 (self.port_index + 1) as u16
45 }
46
47 fn vendor_out(&self, request: u8, value: u16, index: u16) -> Result<()> {
48 self.transport
49 .as_ref()
50 .unwrap()
51 .control_out(&ControlRequest::vendor_out(request, value, index, vec![]))?;
52 Ok(())
53 }
54
55 fn vendor_in(&self, request: u8, value: u16, index: u16, len: usize) -> Result<Vec<u8>> {
56 self.transport
57 .as_ref()
58 .unwrap()
59 .control_in(&ControlRequest::vendor_in(request, value, index, len))
60 }
61}
62
63impl Driver for FtdiDriver {
64 fn open(&mut self, transport: &SharedTransport) -> Result<()> {
65 self.transport = Some(transport.clone());
66 self.iface = self.port_index as u8;
67 transport.claim_interface(self.iface)?;
68 self.endpoints = Some(EndpointPair::open(transport, self.iface)?);
69 self.vendor_out(0, 0, self.w_index())?;
70 let modem = if self.dtr { 0x0101 } else { 0x0100 } | if self.rts { 0x0202 } else { 0x0200 };
71 self.vendor_out(1, modem, self.w_index())?;
72 self.set_flow_control(FlowControl::None)?;
73 self.baud_with_port = transport.interfaces().len() > 1;
74 let raw = transport.raw_descriptors();
75 if raw.len() >= 14 {
76 let device_type = raw[13];
77 self.baud_with_port =
78 self.baud_with_port || device_type == 7 || device_type == 8 || device_type == 9;
79 }
80 Ok(())
81 }
82
83 fn close(&mut self) -> Result<()> {
84 if let Some(mut r) = self.reader.take() {
85 r.stop();
86 }
87 if let Some(t) = &self.transport {
88 let _ = t.release_interface(self.iface);
89 }
90 self.endpoints = None;
91 Ok(())
92 }
93
94 fn write(&mut self, data: &[u8]) -> Result<usize> {
95 let t = self.transport.as_ref().unwrap();
96 self.endpoints.as_mut().unwrap().write(t, data)
97 }
98
99 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
100 if let Some(reader) = &mut self.reader {
101 return reader.try_read(buf);
102 }
103 Ok(0)
104 }
105
106 fn set_line_config(&mut self, cfg: LineConfig) -> Result<()> {
107 self.set_baud(cfg.baud_rate)?;
108 match cfg.data_bits {
109 DataBits::Seven | DataBits::Eight => {}
110 _ => return Err(UsbSerialError::Unsupported("data bits".into())),
111 }
112 if cfg.stop_bits == StopBits::OnePointFive {
113 return Err(UsbSerialError::Unsupported("stop bits".into()));
114 }
115 self.data_config = ftdi_line_config_value(cfg, self.break_enabled);
116 self.vendor_out(4, self.data_config, self.w_index())
117 }
118
119 fn set_flow_control(&mut self, flow: FlowControl) -> Result<()> {
120 self.flow = flow;
121 let mut value = 0u16;
122 let mut index = self.w_index();
123 match flow {
124 FlowControl::None => {}
125 FlowControl::RtsCts => index |= 0x100,
126 FlowControl::DtrDsr => index |= 0x200,
127 FlowControl::XonXoffInline => {
128 value = u16::from(CHAR_XON) | (u16::from(CHAR_XOFF) << 8);
129 index |= 0x400;
130 }
131 _ => return Err(UsbSerialError::Unsupported("flow control".into())),
132 }
133 self.vendor_out(2, value, index)
134 }
135
136 fn set_dtr(&mut self, value: bool) -> Result<()> {
137 self.dtr = value;
138 let v = if value { 0x0101 } else { 0x0100 };
139 self.vendor_out(1, v, self.w_index())
140 }
141
142 fn set_rts(&mut self, value: bool) -> Result<()> {
143 self.rts = value;
144 let v = if value { 0x0202 } else { 0x0200 };
145 self.vendor_out(1, v, self.w_index())
146 }
147
148 fn set_break(&mut self, enabled: bool) -> Result<()> {
149 self.break_enabled = enabled;
150 if enabled {
151 self.data_config |= 0x4000;
152 } else {
153 self.data_config &= !0x4000;
154 }
155 self.vendor_out(4, self.data_config, self.w_index())
156 }
157
158 fn purge(&mut self, kind: PurgeKind) -> Result<()> {
159 match kind {
160 PurgeKind::Rx => self.vendor_out(0, 1, self.w_index()),
161 PurgeKind::Tx => self.vendor_out(0, 2, self.w_index()),
162 PurgeKind::Both => {
163 self.vendor_out(0, 1, self.w_index())?;
164 self.vendor_out(0, 2, self.w_index())
165 }
166 }
167 }
168
169 fn modem_status(&mut self) -> Result<ModemStatus> {
170 let data = self.vendor_in(5, 0, self.w_index(), 2)?;
171 let status = data.first().copied().unwrap_or(0);
172 Ok(ModemStatus {
173 cts: status & 0x10 != 0,
174 dsr: status & 0x20 != 0,
175 ri: status & 0x40 != 0,
176 cd: status & 0x80 != 0,
177 })
178 }
179
180 fn bulk_in_mps(&self) -> u16 {
181 self.endpoints.as_ref().map(|e| e.mps).unwrap_or(64)
182 }
183
184 fn take_bulk_in(&mut self) -> Option<Box<dyn crate::transport::BulkIn>> {
185 let transport = self.transport.as_ref()?;
186 self.endpoints.as_mut()?.take_in(transport)
187 }
188
189 fn rx_filters(&self) -> Vec<Box<dyn crate::rx_filter::RxFilter>> {
190 let mut filters: Vec<Box<dyn crate::rx_filter::RxFilter>> =
191 vec![Box::new(FtdiHeaderFilter::new(self.bulk_in_mps()))];
192 if self.flow == FlowControl::XonXoffInline {
193 filters.push(Box::new(XonXoffRxFilter::new(true)));
194 }
195 filters
196 }
197}
198
199impl FtdiDriver {
200 fn set_baud(&self, baud: u32) -> Result<()> {
201 if baud > 3_500_000 {
202 return Err(UsbSerialError::Unsupported("baud too high".into()));
203 }
204 let (value, index) = ftdi_baud_encoding(baud, self.baud_with_port, self.port_index)?;
205 self.vendor_out(3, value, index)
206 }
207}
208
209fn ftdi_line_config_value(cfg: LineConfig, break_enabled: bool) -> u16 {
210 let mut config = match cfg.data_bits {
211 DataBits::Seven => 7,
212 DataBits::Eight => 8,
213 _ => 0,
214 };
215 config |= match cfg.parity {
216 Parity::None => 0,
217 Parity::Odd => 0x100,
218 Parity::Even => 0x200,
219 Parity::Mark => 0x300,
220 Parity::Space => 0x400,
221 };
222 if cfg.stop_bits == StopBits::Two {
223 config |= 0x1000;
224 }
225 if break_enabled {
226 config |= 0x4000;
227 }
228 config
229}
230
231pub fn ftdi_baud_encoding(
233 baud: u32,
234 baud_with_port: bool,
235 port_index: usize,
236) -> Result<(u16, u16)> {
237 let (divisor, subdivisor, _) = if baud >= 2_500_000 {
238 (0u32, 0u32, 3_000_000u32)
239 } else if baud >= 1_750_000 {
240 (1, 0, 2_000_000)
241 } else {
242 let mut d = (24_000_000u32 << 1) / baud;
243 d = (d + 1) >> 1;
244 let sub = d & 0x07;
245 d >>= 3;
246 if d > 0x3fff {
247 return Err(UsbSerialError::Unsupported("baud too low".into()));
248 }
249 let effective = (24_000_000u32 << 1) / ((d << 3) + sub);
250 let effective = (effective + 1) >> 1;
251 let err = (1.0 - (effective as f64 / baud as f64)).abs();
252 if err >= 0.031 {
253 return Err(UsbSerialError::Unsupported(format!(
254 "baud deviation {:.1}%",
255 err * 100.0
256 )));
257 }
258 (d, sub, effective)
259 };
260 let mut value = divisor as u16;
261 let mut index = 0u16;
262 match subdivisor {
263 0 => {}
264 4 => value |= 0x4000,
265 2 => value |= 0x8000,
266 1 => value |= 0xc000,
267 3 => index |= 1,
268 5 => {
269 value |= 0x4000;
270 index |= 1;
271 }
272 6 => {
273 value |= 0x8000;
274 index |= 1;
275 }
276 7 => {
277 value |= 0xc000;
278 index |= 1;
279 }
280 _ => {}
281 }
282 if baud_with_port {
283 index = (index << 8) | (port_index as u16 + 1);
284 }
285 Ok((value, index))
286}