android_usb_serial/drivers/
cp21xx.rs1use super::{Driver, EndpointPair, ModemStatus, WRITE_TIMEOUT_MS};
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::transport::{ControlRequest, SharedTransport};
10
11const REQTYPE_HOST_TO_DEVICE: u8 = 0x41;
12const REQTYPE_DEVICE_TO_HOST: u8 = 0xC1;
13
14const SILABSER_IFC_ENABLE_REQUEST_CODE: u8 = 0x00;
15const SILABSER_SET_LINE_CTL_REQUEST_CODE: u8 = 0x03;
16const SILABSER_SET_BREAK_REQUEST_CODE: u8 = 0x05;
17const SILABSER_SET_MHS_REQUEST_CODE: u8 = 0x07;
18const SILABSER_GET_MDMSTS_REQUEST_CODE: u8 = 0x08;
19const SILABSER_SET_XON_REQUEST_CODE: u8 = 0x09;
20const SILABSER_SET_XOFF_REQUEST_CODE: u8 = 0x0A;
21const SILABSER_FLUSH_REQUEST_CODE: u8 = 0x12;
22const SILABSER_SET_FLOW_REQUEST_CODE: u8 = 0x13;
23const SILABSER_SET_CHARS_REQUEST_CODE: u8 = 0x19;
24const SILABSER_SET_BAUDRATE_REQUEST_CODE: u8 = 0x1E;
25
26const UART_ENABLE: u16 = 0x0001;
27const UART_DISABLE: u16 = 0x0000;
28
29const DTR_ENABLE: u16 = 0x0101;
30const DTR_DISABLE: u16 = 0x0100;
31const RTS_ENABLE: u16 = 0x0202;
32const RTS_DISABLE: u16 = 0x0200;
33
34const STATUS_CTS: u8 = 0x10;
35const STATUS_DSR: u8 = 0x20;
36const STATUS_RI: u8 = 0x40;
37const STATUS_CD: u8 = 0x80;
38
39pub struct Cp21xxDriver {
40 port_index: usize,
41 iface: u8,
42 dtr: bool,
43 rts: bool,
44 is_restricted_port: bool,
45 endpoints: Option<EndpointPair>,
46 transport: Option<SharedTransport>,
47 reader: Option<SerialReader>,
48}
49
50impl Cp21xxDriver {
51 pub fn new(port_index: usize) -> Self {
52 Self {
53 port_index,
54 iface: port_index as u8,
55 dtr: false,
56 rts: false,
57 is_restricted_port: false,
58 endpoints: None,
59 transport: None,
60 reader: None,
61 }
62 }
63
64 fn cfg_out(&self, request: u8, value: u16) -> Result<()> {
65 self.transport
66 .as_ref()
67 .unwrap()
68 .control_out(&ControlRequest {
69 request_type: REQTYPE_HOST_TO_DEVICE,
70 request,
71 value,
72 index: self.port_index as u16,
73 data: vec![],
74 timeout_ms: WRITE_TIMEOUT_MS,
75 })?;
76 Ok(())
77 }
78
79 fn cfg_out_data(&self, request: u8, value: u16, data: Vec<u8>) -> Result<()> {
80 self.transport
81 .as_ref()
82 .unwrap()
83 .control_out(&ControlRequest {
84 request_type: REQTYPE_HOST_TO_DEVICE,
85 request,
86 value,
87 index: self.port_index as u16,
88 data,
89 timeout_ms: WRITE_TIMEOUT_MS,
90 })?;
91 Ok(())
92 }
93
94 fn cfg_in(&self, request: u8, value: u16, length: usize) -> Result<Vec<u8>> {
95 self.transport
96 .as_ref()
97 .unwrap()
98 .control_in(&ControlRequest {
99 request_type: REQTYPE_DEVICE_TO_HOST,
100 request,
101 value,
102 index: self.port_index as u16,
103 data: vec![0; length],
104 timeout_ms: WRITE_TIMEOUT_MS,
105 })
106 }
107
108 fn set_xon(&self, value: bool) -> Result<()> {
109 self.cfg_out(
110 if value {
111 SILABSER_SET_XON_REQUEST_CODE
112 } else {
113 SILABSER_SET_XOFF_REQUEST_CODE
114 },
115 0,
116 )
117 }
118}
119
120impl Driver for Cp21xxDriver {
121 fn open(&mut self, transport: &SharedTransport) -> Result<()> {
122 self.transport = Some(transport.clone());
123 let iface_count = transport.interfaces().len();
124 if self.port_index >= iface_count {
125 return Err(UsbSerialError::Io(format!(
126 "unknown port number {}",
127 self.port_index
128 )));
129 }
130 self.is_restricted_port = iface_count == 2 && self.port_index == 1;
131 self.iface = self.port_index as u8;
132 transport.claim_interface(self.iface)?;
133 self.endpoints = Some(EndpointPair::open(transport, self.iface)?);
134 self.cfg_out(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE)?;
135 self.cfg_out(
136 SILABSER_SET_MHS_REQUEST_CODE,
137 (if self.dtr { DTR_ENABLE } else { DTR_DISABLE })
138 | (if self.rts { RTS_ENABLE } else { RTS_DISABLE }),
139 )?;
140 self.set_flow_control(FlowControl::None)?;
141 Ok(())
142 }
143
144 fn close(&mut self) -> Result<()> {
145 if let Some(mut r) = self.reader.take() {
146 r.stop();
147 }
148 let _ = self.cfg_out(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
149 if let Some(t) = &self.transport {
150 let _ = t.release_interface(self.iface);
151 }
152 self.endpoints = None;
153 Ok(())
154 }
155
156 fn write(&mut self, data: &[u8]) -> Result<usize> {
157 let t = self.transport.as_ref().unwrap();
158 self.endpoints.as_mut().unwrap().write(t, data)
159 }
160
161 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
162 if let Some(reader) = &mut self.reader {
163 return reader.try_read(buf);
164 }
165 Ok(0)
166 }
167
168 fn set_line_config(&mut self, cfg: LineConfig) -> Result<()> {
169 if cfg.baud_rate == 0 {
170 return Err(UsbSerialError::Unsupported("invalid baud rate".into()));
171 }
172 self.cfg_out_data(
173 SILABSER_SET_BAUDRATE_REQUEST_CODE,
174 0,
175 vec![
176 (cfg.baud_rate & 0xff) as u8,
177 ((cfg.baud_rate >> 8) & 0xff) as u8,
178 ((cfg.baud_rate >> 16) & 0xff) as u8,
179 ((cfg.baud_rate >> 24) & 0xff) as u8,
180 ],
181 )?;
182
183 let mut bits = 0u16;
184 match cfg.data_bits {
185 DataBits::Five => {
186 if self.is_restricted_port {
187 return Err(UsbSerialError::Unsupported("data bits 5".into()));
188 }
189 bits |= 0x0500;
190 }
191 DataBits::Six => {
192 if self.is_restricted_port {
193 return Err(UsbSerialError::Unsupported("data bits 6".into()));
194 }
195 bits |= 0x0600;
196 }
197 DataBits::Seven => {
198 if self.is_restricted_port {
199 return Err(UsbSerialError::Unsupported("data bits 7".into()));
200 }
201 bits |= 0x0700;
202 }
203 DataBits::Eight => bits |= 0x0800,
204 };
205 match cfg.parity {
206 Parity::None => {}
207 Parity::Odd => bits |= 0x0010,
208 Parity::Even => bits |= 0x0020,
209 Parity::Mark => {
210 if self.is_restricted_port {
211 return Err(UsbSerialError::Unsupported("parity mark".into()));
212 }
213 bits |= 0x0030;
214 }
215 Parity::Space => {
216 if self.is_restricted_port {
217 return Err(UsbSerialError::Unsupported("parity space".into()));
218 }
219 bits |= 0x0040;
220 }
221 }
222 match cfg.stop_bits {
223 StopBits::One => {}
224 StopBits::OnePointFive => {
225 return Err(UsbSerialError::Unsupported("stop bits 1.5".into()));
226 }
227 StopBits::Two => {
228 if self.is_restricted_port {
229 return Err(UsbSerialError::Unsupported("stop bits 2".into()));
230 }
231 bits |= 2;
232 }
233 }
234 self.cfg_out(SILABSER_SET_LINE_CTL_REQUEST_CODE, bits)
235 }
236
237 fn set_flow_control(&mut self, flow: FlowControl) -> Result<()> {
238 if flow == FlowControl::XonXoffInline {
239 return Err(UsbSerialError::Unsupported("xon/xoff inline".into()));
240 }
241
242 let mut data = vec![0u8; 16];
243 if flow == FlowControl::RtsCts {
244 data[4] |= 0b1000_0000;
245 data[0] |= 0b0000_1000;
246 } else if self.rts {
247 data[4] |= 0b0100_0000;
248 }
249 if flow == FlowControl::DtrDsr {
250 data[0] |= 0b0000_0010;
251 data[0] |= 0b0001_0000;
252 } else if self.dtr {
253 data[0] |= 0b0000_0001;
254 }
255 if flow == FlowControl::XonXoff {
256 self.cfg_out_data(
257 SILABSER_SET_CHARS_REQUEST_CODE,
258 0,
259 vec![0, 0, 0, 0, CHAR_XON, CHAR_XOFF],
260 )?;
261 data[4] |= 0b0000_0011;
262 data[7] |= 0b1000_0000;
263 data[8] = 128;
264 data[12] = 128;
265 }
266 self.cfg_out_data(SILABSER_SET_FLOW_REQUEST_CODE, 0, data)?;
267 if flow == FlowControl::XonXoff {
268 self.set_xon(true)?;
269 }
270 Ok(())
271 }
272
273 fn set_dtr(&mut self, value: bool) -> Result<()> {
274 self.dtr = value;
275 self.cfg_out(
276 SILABSER_SET_MHS_REQUEST_CODE,
277 if value { DTR_ENABLE } else { DTR_DISABLE },
278 )
279 }
280
281 fn set_rts(&mut self, value: bool) -> Result<()> {
282 self.rts = value;
283 self.cfg_out(
284 SILABSER_SET_MHS_REQUEST_CODE,
285 if value { RTS_ENABLE } else { RTS_DISABLE },
286 )
287 }
288
289 fn set_break(&mut self, enabled: bool) -> Result<()> {
290 self.cfg_out(SILABSER_SET_BREAK_REQUEST_CODE, if enabled { 1 } else { 0 })
291 }
292
293 fn purge(&mut self, kind: PurgeKind) -> Result<()> {
294 let v = match kind {
295 PurgeKind::Rx => 0x0005,
296 PurgeKind::Tx => 0x000a,
297 PurgeKind::Both => 0x000f,
298 };
299 self.cfg_out(SILABSER_FLUSH_REQUEST_CODE, v)
300 }
301
302 fn modem_status(&mut self) -> Result<ModemStatus> {
303 let buf = self.cfg_in(SILABSER_GET_MDMSTS_REQUEST_CODE, 0, 1)?;
304 let status = buf[0];
305 Ok(ModemStatus {
306 cts: (status & STATUS_CTS) != 0,
307 dsr: (status & STATUS_DSR) != 0,
308 ri: (status & STATUS_RI) != 0,
309 cd: (status & STATUS_CD) != 0,
310 })
311 }
312
313 fn bulk_in_mps(&self) -> u16 {
314 self.endpoints.as_ref().map(|e| e.mps).unwrap_or(64)
315 }
316
317 fn take_bulk_in(&mut self) -> Option<Box<dyn crate::transport::BulkIn>> {
318 let transport = self.transport.as_ref()?;
319 self.endpoints.as_mut()?.take_in(transport)
320 }
321}