Skip to content

Commit a397b5e

Browse files
tpamborBerrysoft
andauthored
feat(driver): Add DeviceIoControl opcode (#429)
* feat(driver): Add DeviceIoControl opcode * use AsFd --------- Co-authored-by: 王宇逸 <[email protected]>
1 parent dea067c commit a397b5e

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

compio-driver/src/iocp/op.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use windows_sys::{
3434
},
3535
Storage::FileSystem::{FlushFileBuffers, ReadFile, WriteFile},
3636
System::{
37-
IO::{CancelIoEx, OVERLAPPED},
37+
IO::{CancelIoEx, DeviceIoControl, OVERLAPPED},
3838
Pipes::ConnectNamedPipe,
3939
},
4040
},
@@ -978,3 +978,66 @@ impl<S: AsFd> OpCode for ConnectNamedPipe<S> {
978978
cancel(self.fd.as_fd().as_raw_fd(), optr)
979979
}
980980
}
981+
982+
/// Send a control code to a device.
983+
pub struct DeviceIoControl<S, I: IoBuf, O: IoBufMut> {
984+
pub(crate) fd: S,
985+
pub(crate) ioctl_code: u32,
986+
pub(crate) input_buffer: Option<I>,
987+
pub(crate) output_buffer: Option<O>,
988+
_p: PhantomPinned,
989+
}
990+
991+
impl<S, I: IoBuf, O: IoBufMut> DeviceIoControl<S, I, O> {
992+
/// Create [`DeviceIoControl`].
993+
pub fn new(fd: S, ioctl_code: u32, input_buffer: Option<I>, output_buffer: Option<O>) -> Self {
994+
Self {
995+
fd,
996+
ioctl_code,
997+
input_buffer,
998+
output_buffer,
999+
_p: PhantomPinned,
1000+
}
1001+
}
1002+
}
1003+
1004+
impl<S, I: IoBuf, O: IoBufMut> IntoInner for DeviceIoControl<S, I, O> {
1005+
type Inner = (Option<I>, Option<O>);
1006+
1007+
fn into_inner(self) -> Self::Inner {
1008+
(self.input_buffer, self.output_buffer)
1009+
}
1010+
}
1011+
1012+
impl<S: AsFd, I: IoBuf, O: IoBufMut> OpCode for DeviceIoControl<S, I, O> {
1013+
unsafe fn operate(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
1014+
let this = self.get_unchecked_mut();
1015+
let fd = this.fd.as_fd().as_raw_fd();
1016+
let input_len = this.input_buffer.as_ref().map_or(0, |x| x.buf_len());
1017+
let input_ptr = this
1018+
.input_buffer
1019+
.as_ref()
1020+
.map_or(std::ptr::null(), |x| x.as_buf_ptr());
1021+
let output_len = this.output_buffer.as_ref().map_or(0, |x| x.buf_len());
1022+
let output_ptr = this
1023+
.output_buffer
1024+
.as_mut()
1025+
.map_or(std::ptr::null_mut(), |x| x.as_buf_mut_ptr());
1026+
let mut transferred = 0;
1027+
let res = DeviceIoControl(
1028+
fd,
1029+
this.ioctl_code,
1030+
input_ptr as _,
1031+
input_len as _,
1032+
output_ptr as _,
1033+
output_len as _,
1034+
&mut transferred,
1035+
optr,
1036+
);
1037+
win32_result(res, transferred)
1038+
}
1039+
1040+
unsafe fn cancel(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> io::Result<()> {
1041+
cancel(self.fd.as_fd().as_raw_fd(), optr)
1042+
}
1043+
}

compio-driver/src/op.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, SetBufInit};
1010
use socket2::SockAddr;
1111

1212
#[cfg(windows)]
13-
pub use crate::sys::op::ConnectNamedPipe;
13+
pub use crate::sys::op::{ConnectNamedPipe, DeviceIoControl};
1414
pub use crate::sys::op::{
1515
Accept, Recv, RecvFrom, RecvFromVectored, RecvMsg, RecvVectored, Send, SendMsg, SendTo,
1616
SendToVectored, SendVectored,

0 commit comments

Comments
 (0)