@@ -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+ }
0 commit comments