android_usb_serial/
transport.rs1use crate::error::{ReadOutcome, Result};
7use std::sync::Arc;
8
9pub const USB_DIR_IN: u8 = 0x80;
11pub const USB_DIR_OUT: u8 = 0x00;
13pub const USB_TYPE_CLASS: u8 = 0x20;
15pub const USB_RECIP_INTERFACE: u8 = 0x01;
17pub const USB_RECIP_DEVICE: u8 = 0x00;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct InterfaceInfo {
23 pub id: u8,
24 pub class: u8,
25 pub subclass: u8,
26 pub protocol: u8,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct EndpointInfo {
32 pub address: u8,
33 pub attributes: u8,
34 pub max_packet_size: u16,
35 pub interval: u8,
36}
37
38impl EndpointInfo {
39 pub fn direction(&self) -> u8 {
41 self.address & USB_DIR_IN
42 }
43
44 pub fn is_bulk_in(&self) -> bool {
45 self.direction() == USB_DIR_IN && (self.attributes & 0x03) == 2
46 }
47
48 pub fn is_bulk_out(&self) -> bool {
49 self.direction() == USB_DIR_OUT && (self.attributes & 0x03) == 2
50 }
51
52 pub fn is_interrupt_in(&self) -> bool {
53 self.direction() == USB_DIR_IN && (self.attributes & 0x03) == 3
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct ControlRequest {
60 pub request_type: u8,
61 pub request: u8,
62 pub value: u16,
63 pub index: u16,
64 pub data: Vec<u8>,
65 pub timeout_ms: u32,
66}
67
68impl ControlRequest {
69 pub fn vendor_out(request: u8, value: u16, index: u16, data: Vec<u8>) -> Self {
71 Self {
72 request_type: 0x40,
73 request,
74 value,
75 index,
76 data,
77 timeout_ms: 5000,
78 }
79 }
80
81 pub fn vendor_in(request: u8, value: u16, index: u16, length: usize) -> Self {
83 Self {
84 request_type: 0xC0,
85 request,
86 value,
87 index,
88 data: vec![0; length],
89 timeout_ms: 5000,
90 }
91 }
92
93 pub fn class_out(request: u8, value: u16, index: u16, data: Vec<u8>) -> Self {
95 Self {
96 request_type: USB_TYPE_CLASS | USB_RECIP_INTERFACE,
97 request,
98 value,
99 index,
100 data,
101 timeout_ms: 5000,
102 }
103 }
104
105 pub fn class_in(request: u8, value: u16, index: u16, length: usize) -> Self {
107 Self {
108 request_type: USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
109 request,
110 value,
111 index,
112 data: vec![0; length],
113 timeout_ms: 5000,
114 }
115 }
116}
117
118pub trait BulkIn: Send {
120 fn read(&mut self, buf: &mut [u8], timeout_ms: u32) -> Result<ReadOutcome>;
121 fn cancel_all(&mut self);
122 fn clear_halt(&mut self) -> Result<()>;
123}
124
125pub trait BulkOut: Send {
127 fn write(&mut self, data: &[u8], timeout_ms: u32) -> Result<usize>;
128 fn clear_halt(&mut self) -> Result<()>;
129}
130
131pub trait Transport: Send + Sync {
133 fn raw_device_descriptor(&self) -> [u8; 18];
134 fn raw_descriptors(&self) -> Vec<u8>;
135 fn device_class(&self) -> u8;
136 fn interfaces(&self) -> Vec<InterfaceInfo>;
137 fn endpoints(&self, interface: u8) -> Vec<EndpointInfo>;
138 fn claim_interface(&self, interface: u8) -> Result<()>;
139 fn release_interface(&self, interface: u8) -> Result<()>;
140 fn control_out(&self, req: &ControlRequest) -> Result<usize>;
141 fn control_in(&self, req: &ControlRequest) -> Result<Vec<u8>>;
142 fn open_bulk_in(&self, endpoint: u8, max_packet_size: u16) -> Result<Box<dyn BulkIn>>;
143 fn open_bulk_out(&self, endpoint: u8, max_packet_size: u16) -> Result<Box<dyn BulkOut>>;
144 fn open_interrupt_in(&self, endpoint: u8, max_packet_size: u16) -> Result<Box<dyn BulkIn>>;
145}
146
147pub type SharedTransport = Arc<dyn Transport>;
149
150pub fn parse_control_recipient(request_type: u8) -> (u8, bool) {
152 let direction_in = request_type & 0x80 != 0;
153 let recipient = request_type & 0x1f;
154 (recipient, direction_in)
155}
156
157pub fn is_device_recipient(request_type: u8) -> bool {
159 (request_type & 0x1f) == USB_RECIP_DEVICE
160}
161
162pub fn is_interface_recipient(request_type: u8) -> bool {
164 (request_type & 0x1f) == USB_RECIP_INTERFACE
165}