diff --git a/Cargo.lock b/Cargo.lock
index 9c74e5103ef6b95bba1a66f32ceb1fab3cf78426..cb9e4a835cbb5f8cc9dfcc0ac9b0b9ce33cd1e33 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,21 +4,21 @@ version = 3
 
 [[package]]
 name = "bitflags"
-version = "2.4.2"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
 
 [[package]]
 name = "libc"
-version = "0.2.153"
+version = "0.2.155"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
 
 [[package]]
 name = "libredox"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "309ba69985d5170852ebbe8fbb33850d20794d0aed5b210dfea2db798df64e10"
+checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
  "bitflags",
  "libc",
@@ -35,9 +35,7 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c178f952cc7eac391f3124bd9851d1ac0bdbc4c9de2d892ccd5f0d8b160e96"
+version = "0.5.1"
 dependencies = [
  "bitflags",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index c41fe90cc73ec25475f67e200292fbdb5856762b..5f4229473633fc63b5a9b385917b91e7df5c22f8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,4 +12,7 @@ description = "Library for writing Redox scheme daemons"
 
 [dependencies]
 redox_syscall = "0.5"
-libredox = "0.1.2"
+libredox = "0.1.3"
+
+[patch.crates-io]
+redox_syscall = { path = "/home/dev/Projects/redox1/cookbook/recipes/core/kernel/source/syscall" }
diff --git a/src/lib.rs b/src/lib.rs
index 4e2291a8c1ba941d51a9d8d27d0f66fdf63eaf81..93fd9050b3e2f06683181e4a274b8297e2bef5cd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
 use core::{slice, str};
 
 use libredox::flag;
+use syscall::schemev2::{Cqe, CqeOpcode, Opcode, Sqe};
 use syscall::{
     Error, Packet, Result, EINTR, EOPNOTSUPP, ESKMSG, KSMSG_CANCEL, KSMSG_MMAP, KSMSG_MSYNC,
     KSMSG_MUNMAP, SKMSG_FRETURNFD,
@@ -81,12 +82,107 @@ use core::mem::size_of;
 
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug, Default)]
-pub struct Request {
-    packet: Packet,
+pub struct Request<V: Version = V2> {
+    sqe: V::RawSqe,
+}
+mod private {
+    use super::*;
+
+    pub trait Impl: Copy + Clone + core::fmt::Debug + Default {
+        type RawSqe: core::fmt::Debug + Clone + Copy + Default;
+        type RawCqe: core::fmt::Debug + Clone + Copy + Default;
+
+        fn sqe_context_id(s: &Self::RawSqe) -> usize;
+        fn sqe_request_id(s: &Self::RawSqe) -> Id;
+        fn sqe_kind(s: Self::RawSqe) -> RequestKind<Self>;
+
+        fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Self::RawCqe;
+    }
+}
+pub trait Version: private::Impl {}
+
+#[derive(Clone, Copy, Debug)]
+pub enum Legacy {}
+#[derive(Clone, Copy, Debug)]
+pub enum V2 {}
+impl Default for Legacy {
+    fn default() -> Self {
+        unreachable!()
+    }
+}
+impl Default for V2 {
+    fn default() -> Self {
+        unreachable!()
+    }
+}
+impl<V: private::Impl> Version for V {}
+
+impl private::Impl for Legacy {
+    type RawSqe = Packet;
+    type RawCqe = Packet;
+
+    fn sqe_context_id(s: &Packet) -> usize {
+        s.pid
+    }
+    fn sqe_request_id(s: &Packet) -> Id {
+        Id(s.id as u32)
+    }
+    fn sqe_kind(packet: Self::RawSqe) -> RequestKind<Self> {
+        // TODO: Should KSMSG_MMAP_PREP be a regular scheme call?
+
+        match packet.a {
+            KSMSG_CANCEL => RequestKind::Cancellation(CancellationRequest {
+                id: Id(packet.b as u32),
+            }),
+            KSMSG_MSYNC => RequestKind::MsyncMsg,
+            KSMSG_MUNMAP => RequestKind::MunmapMsg,
+            KSMSG_MMAP => RequestKind::MmapMsg,
+
+            _ => RequestKind::Call(CallRequest { inner: Request { sqe: packet } }),
+        }
+    }
+    fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Packet {
+        Packet {
+            a: Error::mux(status),
+            id: req.inner.sqe.id,
+            ..Packet::default()
+        }
+    }
+}
+impl private::Impl for V2 {
+    type RawSqe = Sqe;
+    type RawCqe = Cqe;
+
+    fn sqe_context_id(s: &Sqe) -> usize {
+        s.caller as usize
+    }
+    fn sqe_request_id(s: &Sqe) -> Id {
+        Id(s.tag)
+    }
+    fn sqe_kind(sqe: Self::RawSqe) -> RequestKind<Self> {
+        match Opcode::try_from_raw(sqe.opcode) {
+            Some(Opcode::Cancel) => RequestKind::Cancellation(CancellationRequest {
+                id: Id(sqe.tag),
+            }),
+            Some(Opcode::Msync) => RequestKind::MsyncMsg,
+            Some(Opcode::Munmap) => RequestKind::MunmapMsg,
+            Some(Opcode::RequestMmap) => RequestKind::MmapMsg,
+
+            _ => RequestKind::Call(CallRequest { inner: Request { sqe } }),
+        }
+    }
+    fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Cqe {
+        Cqe {
+            flags: CqeOpcode::RespondRegular as u8,
+            extra_raw: [0_u8; 3],
+            result: Error::mux(status) as u64,
+            tag: req.inner.sqe.tag,
+        }
+    }
 }
 
 #[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
-pub struct Id(u64);
+pub struct Id(u32);
 
 #[derive(Debug)]
 pub struct CancellationRequest {
@@ -95,12 +191,12 @@ pub struct CancellationRequest {
 
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug)]
-pub struct CallRequest {
-    inner: Request,
+pub struct CallRequest<V: Version = V2> {
+    inner: Request<V>,
 }
 
-pub enum RequestKind {
-    Call(CallRequest),
+pub enum RequestKind<V: Version = V2> {
+    Call(CallRequest<V>),
     Cancellation(CancellationRequest),
     MsyncMsg,
     MunmapMsg,
@@ -113,63 +209,54 @@ impl CallRequest {
         self.inner
     }
 
-    pub fn handle_scheme(mut self, scheme: &impl Scheme) -> Response {
+}
+impl CallRequest<Legacy> {
+    pub fn handle_scheme(mut self, scheme: &impl Scheme) -> Response<Legacy> {
         unsafe {
-            scheme.handle(&mut self.inner.packet);
+            scheme.handle(&mut self.inner.sqe);
         }
-        Response(self.inner.packet)
+        Response::<Legacy>(self.inner.sqe)
     }
-    pub fn handle_scheme_mut(mut self, scheme: &mut impl SchemeMut) -> Response {
+    pub fn handle_scheme_mut(mut self, scheme: &mut impl SchemeMut) -> Response<Legacy> {
         unsafe {
-            scheme.handle(&mut self.inner.packet);
+            scheme.handle(&mut self.inner.sqe);
         }
-        Response(self.inner.packet)
+        Response::<Legacy>(self.inner.sqe)
     }
-    pub fn handle_scheme_block(mut self, scheme: &mut impl SchemeBlock) -> Result<Response, Self> {
-        match unsafe { scheme.handle(&self.inner.packet) } {
-            Some(code) => Ok(Response(Packet {
+    pub fn handle_scheme_block(self, scheme: &mut impl SchemeBlock) -> Result<Response<Legacy>, Self> {
+        match unsafe { scheme.handle(&self.inner.sqe) } {
+            Some(code) => Ok(Response::<Legacy>(Packet {
                 a: code,
-                ..self.inner.packet
+                ..self.inner.sqe
             })),
             None => Err(self),
         }
     }
     pub fn handle_scheme_block_mut(
-        mut self,
+        self,
         scheme: &mut impl SchemeBlockMut,
-    ) -> Result<Response, Self> {
-        match unsafe { scheme.handle(&self.inner.packet) } {
-            Some(code) => Ok(Response(Packet {
+    ) -> Result<Response<Legacy>, Self> {
+        match unsafe { scheme.handle(&self.inner.sqe) } {
+            Some(code) => Ok(Response::<Legacy>(Packet {
                 a: code,
-                ..self.inner.packet
+                ..self.inner.sqe
             })),
             None => Err(self),
         }
     }
 }
 
-impl Request {
+impl<V: Version> Request<V> {
     #[inline]
     pub fn context_id(&self) -> usize {
-        self.packet.pid
+        V::sqe_context_id(&self.sqe)
     }
     #[inline]
     pub fn request_id(&self) -> Id {
-        Id(self.packet.id)
+        V::sqe_request_id(&self.sqe)
     }
-    pub fn kind(self) -> RequestKind {
-        // TODO: Should KSMSG_MMAP_PREP be a regular scheme call?
-
-        match self.packet.a {
-            KSMSG_CANCEL => RequestKind::Cancellation(CancellationRequest {
-                id: Id((self.packet.b as u64) | ((self.packet.c as u64) << 32)),
-            }),
-            KSMSG_MSYNC => RequestKind::MsyncMsg,
-            KSMSG_MUNMAP => RequestKind::MunmapMsg,
-            KSMSG_MMAP => RequestKind::MmapMsg,
-
-            _ => RequestKind::Call(CallRequest { inner: self }),
-        }
+    pub fn kind(self) -> RequestKind<V> {
+        V::sqe_kind(self.sqe)
     }
 }
 
@@ -230,14 +317,11 @@ impl Socket {
 
 #[repr(transparent)]
 #[derive(Clone, Copy, Default)]
-pub struct Response(Packet);
+pub struct Response<V: Version = V2>(V::RawCqe);
 
-impl Response {
-    pub fn new(req: &CallRequest, status: Result<usize>) -> Self {
-        Self(Packet {
-            a: Error::mux(status),
-            ..req.inner.packet
-        })
+impl<V: Version> Response<V> {
+    pub fn new(req: &CallRequest<V>, status: Result<usize>) -> Self {
+        Self(V::create_cqe(req, status))
     }
 }
 
@@ -248,9 +332,9 @@ pub enum SignalBehavior {
 
 // TODO: Support uninitialized memory
 #[inline]
-pub fn read_requests(
+pub fn read_requests<V: Version>(
     socket: usize,
-    buf: &mut [Request],
+    buf: &mut [Request<V>],
     behavior: SignalBehavior,
 ) -> Result<usize> {
     let len = buf.len().checked_mul(size_of::<Request>()).unwrap();