2
2
3
3
//! USB I/O protocol.
4
4
5
+ use core:: ffi;
6
+
5
7
use uefi_macros:: unsafe_protocol;
6
- use uefi_raw:: protocol:: usb:: io:: UsbIoProtocol ;
8
+ use uefi_raw:: protocol:: usb:: io:: { DataDirection , DeviceRequest , UsbIoProtocol , UsbTransferStatus } ;
7
9
8
10
use crate :: data_types:: PoolString ;
9
11
use crate :: { Char16 , Result , StatusExt } ;
@@ -19,6 +21,194 @@ pub use uefi_raw::protocol::usb::io::{
19
21
pub struct UsbIo ( UsbIoProtocol ) ;
20
22
21
23
impl UsbIo {
24
+ /// Performs a USB Control transfer, allowing the driver to communicate with the USB device.
25
+ pub fn control_transfer (
26
+ & mut self ,
27
+ request_type : u8 ,
28
+ request : u8 ,
29
+ value : u16 ,
30
+ index : u16 ,
31
+ transfer : ControlTransfer ,
32
+ timeout : u32 ,
33
+ ) -> Result < ( ) , UsbTransferStatus > {
34
+ let ( direction, buffer_ptr, length) = match transfer {
35
+ ControlTransfer :: None => ( DataDirection :: NO_DATA , core:: ptr:: null_mut ( ) , 0 ) ,
36
+ ControlTransfer :: DataIn ( buffer) => (
37
+ DataDirection :: DATA_IN ,
38
+ buffer. as_ptr ( ) . cast_mut ( ) ,
39
+ buffer. len ( ) ,
40
+ ) ,
41
+ ControlTransfer :: DataOut ( buffer) => (
42
+ DataDirection :: DATA_OUT ,
43
+ buffer. as_ptr ( ) . cast_mut ( ) ,
44
+ buffer. len ( ) ,
45
+ ) ,
46
+ } ;
47
+
48
+ let mut device_request = DeviceRequest {
49
+ request_type,
50
+ request,
51
+ value,
52
+ index,
53
+ length : length as u16 ,
54
+ } ;
55
+ let mut status = UsbTransferStatus :: default ( ) ;
56
+
57
+ unsafe {
58
+ ( self . 0 . control_transfer ) (
59
+ & mut self . 0 ,
60
+ & mut device_request,
61
+ direction,
62
+ timeout,
63
+ buffer_ptr. cast :: < ffi:: c_void > ( ) ,
64
+ length,
65
+ & mut status,
66
+ )
67
+ }
68
+ . to_result_with_err ( |_| status)
69
+ }
70
+
71
+ /// Sends the provided buffer to a USB device over a bulk transfer pipe.
72
+ ///
73
+ /// Returns the number of bytes that were actually sent to the device.
74
+ pub fn sync_bulk_send (
75
+ & mut self ,
76
+ endpoint : u8 ,
77
+ buffer : & [ u8 ] ,
78
+ timeout : usize ,
79
+ ) -> Result < usize , UsbTransferStatus > {
80
+ let mut status = UsbTransferStatus :: default ( ) ;
81
+ let mut length = buffer. len ( ) ;
82
+
83
+ unsafe {
84
+ ( self . 0 . bulk_transfer ) (
85
+ & mut self . 0 ,
86
+ endpoint & !0x80 ,
87
+ buffer. as_ptr ( ) . cast_mut ( ) . cast :: < ffi:: c_void > ( ) ,
88
+ & mut length,
89
+ timeout,
90
+ & mut status,
91
+ )
92
+ }
93
+ . to_result_with_err ( |_| status)
94
+ . map ( |( ) | length)
95
+ }
96
+
97
+ /// Fills the provided buffer with data from a USB device over a bulk transfer pipe.
98
+ ///
99
+ /// Returns the number of bytes that were actually received from the device.
100
+ pub fn sync_bulk_receive (
101
+ & mut self ,
102
+ endpoint : u8 ,
103
+ buffer : & mut [ u8 ] ,
104
+ timeout : usize ,
105
+ ) -> Result < usize , UsbTransferStatus > {
106
+ let mut status = UsbTransferStatus :: default ( ) ;
107
+ let mut length = buffer. len ( ) ;
108
+
109
+ unsafe {
110
+ ( self . 0 . bulk_transfer ) (
111
+ & mut self . 0 ,
112
+ endpoint | 0x80 ,
113
+ buffer. as_ptr ( ) . cast_mut ( ) . cast :: < ffi:: c_void > ( ) ,
114
+ & mut length,
115
+ timeout,
116
+ & mut status,
117
+ )
118
+ }
119
+ . to_result_with_err ( |_| status)
120
+ . map ( |( ) | length)
121
+ }
122
+
123
+ /// Sends the provided buffer to a USB device through a synchronous interrupt transfer.
124
+ pub fn sync_interrupt_send (
125
+ & mut self ,
126
+ endpoint : u8 ,
127
+ buffer : & [ u8 ] ,
128
+ timeout : usize ,
129
+ ) -> Result < usize , UsbTransferStatus > {
130
+ let mut status = UsbTransferStatus :: default ( ) ;
131
+ let mut length = buffer. len ( ) ;
132
+
133
+ unsafe {
134
+ ( self . 0 . sync_interrupt_transfer ) (
135
+ & mut self . 0 ,
136
+ endpoint & !0x80 ,
137
+ buffer. as_ptr ( ) . cast_mut ( ) . cast :: < ffi:: c_void > ( ) ,
138
+ & mut length,
139
+ timeout,
140
+ & mut status,
141
+ )
142
+ }
143
+ . to_result_with_err ( |_| status)
144
+ . map ( |( ) | length)
145
+ }
146
+
147
+ /// Fills the provided buffer with data from a USB device through a synchronous interrupt
148
+ /// transfer.
149
+ pub fn sync_interrupt_receive (
150
+ & mut self ,
151
+ endpoint : u8 ,
152
+ buffer : & mut [ u8 ] ,
153
+ timeout : usize ,
154
+ ) -> Result < usize , UsbTransferStatus > {
155
+ let mut status = UsbTransferStatus :: default ( ) ;
156
+ let mut length = buffer. len ( ) ;
157
+
158
+ unsafe {
159
+ ( self . 0 . sync_interrupt_transfer ) (
160
+ & mut self . 0 ,
161
+ endpoint | 0x80 ,
162
+ buffer. as_ptr ( ) . cast_mut ( ) . cast :: < ffi:: c_void > ( ) ,
163
+ & mut length,
164
+ timeout,
165
+ & mut status,
166
+ )
167
+ }
168
+ . to_result_with_err ( |_| status)
169
+ . map ( |( ) | length)
170
+ }
171
+
172
+ /// Sends the provided buffer to a USB device over an isochronous transfer pipe.
173
+ pub fn sync_isochronous_send (
174
+ & mut self ,
175
+ endpoint : u8 ,
176
+ buffer : & [ u8 ] ,
177
+ ) -> Result < ( ) , UsbTransferStatus > {
178
+ let mut status = UsbTransferStatus :: default ( ) ;
179
+
180
+ unsafe {
181
+ ( self . 0 . isochronous_transfer ) (
182
+ & mut self . 0 ,
183
+ endpoint & !0x80 ,
184
+ buffer. as_ptr ( ) . cast_mut ( ) . cast :: < ffi:: c_void > ( ) ,
185
+ buffer. len ( ) ,
186
+ & mut status,
187
+ )
188
+ }
189
+ . to_result_with_err ( |_| status)
190
+ }
191
+
192
+ /// Fills the provided buffer with data from a USB device over an isochronous transfer pipe.
193
+ pub fn sync_isochronous_receive (
194
+ & mut self ,
195
+ endpoint : u8 ,
196
+ buffer : & mut [ u8 ] ,
197
+ ) -> Result < ( ) , UsbTransferStatus > {
198
+ let mut status = UsbTransferStatus :: default ( ) ;
199
+
200
+ unsafe {
201
+ ( self . 0 . isochronous_transfer ) (
202
+ & mut self . 0 ,
203
+ endpoint | 0x80 ,
204
+ buffer. as_mut_ptr ( ) . cast :: < ffi:: c_void > ( ) ,
205
+ buffer. len ( ) ,
206
+ & mut status,
207
+ )
208
+ }
209
+ . to_result_with_err ( |_| status)
210
+ }
211
+
22
212
/// Returns information about USB devices, including the device's class, subclass, and number
23
213
/// of configurations.
24
214
pub fn device_descriptor ( & mut self ) -> Result < DeviceDescriptor > {
@@ -85,3 +275,14 @@ impl UsbIo {
85
275
unsafe { ( self . 0 . port_reset ) ( & mut self . 0 ) } . to_result ( )
86
276
}
87
277
}
278
+
279
+ /// Controls what type of USB control transfer operation should occur.
280
+ #[ derive( Debug ) ]
281
+ pub enum ControlTransfer < ' buffer > {
282
+ /// The USB control transfer has no data phase.
283
+ None ,
284
+ /// The USB control transfer has an input data phase.
285
+ DataIn ( & ' buffer mut [ u8 ] ) ,
286
+ /// The USB control transfer has an output data phase.
287
+ DataOut ( & ' buffer [ u8 ] ) ,
288
+ }
0 commit comments