summaryrefslogtreecommitdiff
path: root/crates/windows-kernel-rs/src/ioctl.rs
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-01-03 03:20:12 -0800
committerFuwn <[email protected]>2022-01-03 03:20:12 -0800
commit85db2b507f3f69b32811c54a89d9ac7bbbc46121 (patch)
tree2efd66da452f8a6a2cc6c91584c925f237506ddf /crates/windows-kernel-rs/src/ioctl.rs
downloaddriver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.tar.xz
driver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.zip
feat(driver): commit primer
Diffstat (limited to 'crates/windows-kernel-rs/src/ioctl.rs')
-rw-r--r--crates/windows-kernel-rs/src/ioctl.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/crates/windows-kernel-rs/src/ioctl.rs b/crates/windows-kernel-rs/src/ioctl.rs
new file mode 100644
index 0000000..c1d493f
--- /dev/null
+++ b/crates/windows-kernel-rs/src/ioctl.rs
@@ -0,0 +1,111 @@
+use bitflags::bitflags;
+use windows_kernel_sys::base::{
+ FILE_ANY_ACCESS,
+ FILE_READ_DATA,
+ FILE_WRITE_DATA,
+ METHOD_BUFFERED,
+ METHOD_IN_DIRECT,
+ METHOD_NEITHER,
+ METHOD_OUT_DIRECT,
+};
+
+use crate::device::DeviceType;
+
+bitflags! {
+ pub struct RequiredAccess: u32 {
+ const ANY_ACCESS = FILE_ANY_ACCESS;
+ const READ_DATA = FILE_READ_DATA;
+ const WRITE_DATA = FILE_WRITE_DATA;
+ const READ_WRITE_DATA = FILE_READ_DATA | FILE_WRITE_DATA;
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[repr(u32)]
+pub enum TransferMethod {
+ Neither = METHOD_NEITHER,
+ InputDirect = METHOD_IN_DIRECT,
+ OutputDirect = METHOD_OUT_DIRECT,
+ Buffered = METHOD_BUFFERED,
+}
+
+impl From<u32> for TransferMethod {
+ fn from(value: u32) -> Self {
+ match value & 0x3 {
+ METHOD_NEITHER => Self::Neither,
+ METHOD_IN_DIRECT => Self::InputDirect,
+ METHOD_OUT_DIRECT => Self::OutputDirect,
+ METHOD_BUFFERED => Self::Buffered,
+ _ => unreachable!(),
+ }
+ }
+}
+
+impl Into<u32> for TransferMethod {
+ fn into(self) -> u32 {
+ match self {
+ Self::Neither => METHOD_NEITHER,
+ Self::InputDirect => METHOD_IN_DIRECT,
+ Self::OutputDirect => METHOD_OUT_DIRECT,
+ Self::Buffered => METHOD_BUFFERED,
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ControlCode(
+ pub DeviceType,
+ pub RequiredAccess,
+ pub u32,
+ pub TransferMethod,
+);
+
+impl ControlCode {
+ const ACCESS_BITS: usize = 2;
+ const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;
+ const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;
+ const METHOD_BITS: usize = 2;
+ const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;
+ const METHOD_SHIFT: usize = 0;
+ const NUM_BITS: usize = 12;
+ const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;
+ const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;
+ const TYPE_BITS: usize = 16;
+ const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;
+ const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;
+
+ pub fn device_type(&self) -> DeviceType { self.0 }
+
+ pub fn required_access(&self) -> RequiredAccess { self.1 }
+
+ pub fn number(&self) -> u32 { self.2 }
+
+ pub fn transfer_method(&self) -> TransferMethod { self.3 }
+}
+
+impl From<u32> for ControlCode {
+ fn from(value: u32) -> Self {
+ let method = (value >> Self::METHOD_SHIFT) & Self::METHOD_MASK;
+ let num = (value >> Self::NUM_SHIFT) & Self::NUM_MASK;
+ let access = (value >> Self::ACCESS_SHIFT) & Self::ACCESS_MASK;
+ let ty = (value >> Self::TYPE_SHIFT) & Self::TYPE_MASK;
+
+ Self(
+ ty.into(),
+ RequiredAccess::from_bits(access).unwrap_or(RequiredAccess::READ_DATA),
+ num,
+ method.into(),
+ )
+ }
+}
+
+impl Into<u32> for ControlCode {
+ fn into(self) -> u32 {
+ let method = Into::<u32>::into(self.3) << Self::METHOD_SHIFT;
+ let num = self.2 << Self::NUM_SHIFT;
+ let access = self.1.bits() << Self::ACCESS_SHIFT;
+ let ty = Into::<u32>::into(self.0) << Self::TYPE_SHIFT;
+
+ ty | access | num | method
+ }
+}