android_usb_serial/drivers/
cdc_acm.rs1use super::{line_coding_bytes, Driver, EndpointPair, ModemStatus, WRITE_TIMEOUT_MS};
4use crate::config::{FlowControl, LineConfig, PurgeKind};
5use crate::error::{Result, UsbSerialError};
6use crate::reader::SerialReader;
7use crate::transport::{ControlRequest, SharedTransport, USB_RECIP_INTERFACE, USB_TYPE_CLASS};
8
9const USB_SUBCLASS_ACM: u8 = 2;
10const SET_LINE_CODING: u8 = 0x20;
11const SET_CONTROL_LINE_STATE: u8 = 0x22;
12const SEND_BREAK: u8 = 0x23;
13
14pub struct CdcAcmDriver {
15 port_index: usize,
16 control_index: u8,
17 control_iface: u8,
18 data_iface: u8,
19 dtr: bool,
20 rts: bool,
21 endpoints: Option<EndpointPair>,
22 transport: Option<SharedTransport>,
23 reader: Option<SerialReader>,
24}
25
26impl CdcAcmDriver {
27 pub fn new(port_index: usize) -> Self {
28 Self {
29 port_index,
30 control_index: 0,
31 control_iface: 0,
32 data_iface: 0,
33 dtr: false,
34 rts: false,
35 endpoints: None,
36 transport: None,
37 reader: None,
38 }
39 }
40
41 fn acm_control(&self, request: u8, value: u16, data: Vec<u8>) -> Result<()> {
42 let transport = self.transport.as_ref().unwrap();
43 let req = ControlRequest {
44 request_type: USB_TYPE_CLASS | USB_RECIP_INTERFACE,
45 request,
46 value,
47 index: self.control_index as u16,
48 data,
49 timeout_ms: WRITE_TIMEOUT_MS,
50 };
51 transport.control_out(&req)?;
52 Ok(())
53 }
54
55 fn resolve_interfaces(&mut self, transport: &SharedTransport) -> Result<()> {
56 let ifaces = transport.interfaces();
57 let desc = transport.raw_device_descriptor();
58 let is_iad = desc.len() >= 7 && desc[4] == 0xEF && desc[5] == 0x02 && desc[6] == 0x01;
59 if is_iad {
60 if let Some((ctrl, data)) = resolve_iad_pair(transport, self.port_index) {
61 self.control_iface = ctrl;
62 self.data_iface = data;
63 self.control_index = ctrl;
64 return Ok(());
65 }
66 }
67 let comm: Vec<u8> = ifaces
68 .iter()
69 .filter(|i| i.class == 2 && i.subclass == USB_SUBCLASS_ACM)
70 .map(|i| i.id)
71 .collect();
72 let data: Vec<u8> = ifaces
73 .iter()
74 .filter(|i| i.class == 10)
75 .map(|i| i.id)
76 .collect();
77 if comm.is_empty() && data.is_empty() {
78 if let Some(iface) = ifaces.first() {
80 self.control_iface = iface.id;
81 self.data_iface = iface.id;
82 self.control_index = iface.id;
83 return Ok(());
84 }
85 return Err(UsbSerialError::ProbeFailed("no CDC interfaces".into()));
86 }
87 if comm.is_empty() {
88 return Err(UsbSerialError::ProbeFailed("no CDC comm interfaces".into()));
89 }
90 let idx = self.port_index.min(comm.len() - 1);
91 self.control_iface = comm[idx];
92 self.data_iface = data.get(idx).copied().unwrap_or(comm[idx]);
93 self.control_index = self.control_iface;
94 Ok(())
95 }
96}
97
98fn resolve_iad_pair(transport: &SharedTransport, port_index: usize) -> Option<(u8, u8)> {
99 let raw = transport.raw_descriptors();
100 let mut iad_ports: Vec<(u8, u8)> = Vec::new();
101 let mut pos = 0usize;
102 while pos + 2 <= raw.len() {
103 let len = raw[pos] as usize;
104 if len < 2 || pos + len > raw.len() {
105 break;
106 }
107 if raw[pos + 1] == 0x0B && len >= 8 && raw[pos + 4] == 2 && raw[pos + 5] == 2 {
108 let first = raw[pos + 2];
109 let count = raw[pos + 3];
110 if count >= 2 {
111 iad_ports.push((first, first + 1));
112 }
113 }
114 pos += len;
115 }
116 iad_ports.get(port_index).copied()
117}
118
119impl Driver for CdcAcmDriver {
120 fn open(&mut self, transport: &SharedTransport) -> Result<()> {
121 self.transport = Some(transport.clone());
122 self.resolve_interfaces(transport)?;
123 transport.claim_interface(self.control_iface)?;
124 if self.data_iface != self.control_iface {
125 transport.claim_interface(self.data_iface)?;
126 }
127 self.endpoints = Some(EndpointPair::open(transport, self.data_iface)?);
128 Ok(())
129 }
130
131 fn close(&mut self) -> Result<()> {
132 if let Some(mut r) = self.reader.take() {
133 r.stop();
134 }
135 if let Some(t) = &self.transport {
136 let _ = t.release_interface(self.data_iface);
137 if self.control_iface != self.data_iface {
138 let _ = t.release_interface(self.control_iface);
139 }
140 }
141 self.endpoints = None;
142 Ok(())
143 }
144
145 fn write(&mut self, data: &[u8]) -> Result<usize> {
146 let transport = self.transport.as_ref().unwrap();
147 self.endpoints.as_mut().unwrap().write(transport, data)
148 }
149
150 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
151 if let Some(reader) = &mut self.reader {
152 return reader.try_read(buf);
153 }
154 Ok(0)
155 }
156
157 fn set_line_config(&mut self, cfg: LineConfig) -> Result<()> {
158 self.acm_control(SET_LINE_CODING, 0, line_coding_bytes(&cfg).to_vec())
159 }
160
161 fn set_flow_control(&mut self, flow: FlowControl) -> Result<()> {
162 if flow == FlowControl::None {
163 Ok(())
164 } else {
165 Err(UsbSerialError::Unsupported("flow control".into()))
166 }
167 }
168
169 fn set_dtr(&mut self, value: bool) -> Result<()> {
170 self.dtr = value;
171 let v = (self.rts as u16) << 1 | (self.dtr as u16);
172 self.acm_control(SET_CONTROL_LINE_STATE, v, vec![])
173 }
174
175 fn set_rts(&mut self, value: bool) -> Result<()> {
176 self.rts = value;
177 let v = (self.rts as u16) << 1 | (self.dtr as u16);
178 self.acm_control(SET_CONTROL_LINE_STATE, v, vec![])
179 }
180
181 fn set_break(&mut self, enabled: bool) -> Result<()> {
182 self.acm_control(SEND_BREAK, if enabled { 0xffff } else { 0 }, vec![])
183 }
184
185 fn purge(&mut self, _kind: PurgeKind) -> Result<()> {
186 Ok(())
187 }
188
189 fn modem_status(&mut self) -> Result<ModemStatus> {
190 Ok(ModemStatus::default())
191 }
192
193 fn bulk_in_mps(&self) -> u16 {
194 self.endpoints.as_ref().map(|e| e.mps).unwrap_or(64)
195 }
196
197 fn take_bulk_in(&mut self) -> Option<Box<dyn crate::transport::BulkIn>> {
198 let transport = self.transport.as_ref()?;
199 self.endpoints.as_mut()?.take_in(transport)
200 }
201}