22
33//! USB I/O protocol.
44
5+ use core:: ffi;
6+
57use uefi_macros:: unsafe_protocol;
6- use uefi_raw:: protocol:: usb:: io:: UsbIoProtocol ;
8+ use uefi_raw:: protocol:: usb:: io:: { DataDirection , DeviceRequest , UsbIoProtocol , UsbTransferStatus } ;
79
810use crate :: data_types:: PoolString ;
911use crate :: { Char16 , Result , StatusExt } ;
@@ -19,6 +21,194 @@ pub use uefi_raw::protocol::usb::io::{
1921pub struct UsbIo ( UsbIoProtocol ) ;
2022
2123impl 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+
22212 /// Returns information about USB devices, including the device's class, subclass, and number
23213 /// of configurations.
24214 pub fn device_descriptor ( & mut self ) -> Result < DeviceDescriptor > {
@@ -85,3 +275,14 @@ impl UsbIo {
85275 unsafe { ( self . 0 . port_reset ) ( & mut self . 0 ) } . to_result ( )
86276 }
87277}
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