Remove SubscribableCallback from ADC driver
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0524df2..0ab5997 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
   - Buttons
   - GPIO
   - Temperature
+  - ADC (partially)
 - The timer API now supports concurrent sleep operations
 
 ### Syscalls
diff --git a/examples/adc.rs b/examples/adc.rs
index ef100a3..2304889 100644
--- a/examples/adc.rs
+++ b/examples/adc.rs
@@ -8,23 +8,25 @@
 #[libtock::main]
 async fn main() -> TockResult<()> {
     let Drivers {
-        console_driver,
+        mut adc_driver_factory,
         timer_context,
-        adc_driver,
+        console_driver,
         ..
     } = libtock::retrieve_drivers()?;
 
+    let adc_driver = adc_driver_factory.init_driver()?;
     let mut driver = timer_context.create_timer_driver();
     let timer_driver = driver.activate()?;
     let mut console = console_driver.create_console();
-    let mut with_callback = adc_driver.with_callback(|channel: usize, value: usize| {
-        writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
-    });
 
-    let adc = with_callback.init()?;
+    let mut callback = |channel, value| {
+        writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
+    };
+
+    let _subscription = adc_driver.subscribe(&mut callback)?;
 
     loop {
-        adc.sample(0)?;
+        adc_driver.sample(0)?;
         timer_driver.sleep(Duration::from_ms(2000)).await?;
     }
 }
diff --git a/examples/adc_buffer.rs b/examples/adc_buffer.rs
index b948b93..d06f356 100644
--- a/examples/adc_buffer.rs
+++ b/examples/adc_buffer.rs
@@ -10,25 +10,28 @@
 /// Reads a 128 byte sample into a buffer and prints the first value to the console.
 async fn main() -> TockResult<()> {
     let Drivers {
+        mut adc_driver_factory,
         console_driver,
-        adc_driver,
         ..
     } = libtock::retrieve_drivers()?;
+
+    let adc_driver = adc_driver_factory.init_driver()?;
     let mut console = console_driver.create_console();
+
     let mut adc_buffer = AdcBuffer::default();
     let mut temp_buffer = [0; libtock::adc::BUFFER_SIZE];
 
-    let adc_buffer = libtock::adc::Adc::init_buffer(&mut adc_buffer)?;
+    let adc_buffer = adc_driver.init_buffer(&mut adc_buffer)?;
 
-    let mut with_callback = adc_driver.with_callback(|_, _| {
+    let mut callback = |_, _| {
         adc_buffer.read_bytes(&mut temp_buffer[..]);
         writeln!(console, "First sample in buffer: {}", temp_buffer[0]).unwrap();
-    });
+    };
 
-    let adc = with_callback.init()?;
+    let _subscription = adc_driver.subscribe(&mut callback)?;
 
     loop {
-        adc.sample_continuous_buffered(0, 128)?;
+        adc_driver.sample_continuous_buffered(0, 128)?;
         unsafe { syscalls::raw::yieldk() };
     }
 }
diff --git a/src/adc.rs b/src/adc.rs
index 23b7f86..7d351df 100644
--- a/src/adc.rs
+++ b/src/adc.rs
@@ -1,9 +1,11 @@
-use crate::callback::{CallbackSubscription, SubscribableCallback};
+use crate::callback::CallbackSubscription;
+use crate::callback::Consumer;
 use crate::result::TockResult;
 use crate::shared_memory::SharedMemory;
 use crate::syscalls;
+use core::marker::PhantomData;
 
-pub const DRIVER_NUM: usize = 0x0005;
+pub const DRIVER_NUMBER: usize = 0x0005;
 pub const BUFFER_SIZE: usize = 128;
 
 mod command_nr {
@@ -25,11 +27,16 @@
 }
 
 #[non_exhaustive]
-pub struct AdcDriver;
+pub struct AdcDriverFactory;
 
-impl AdcDriver {
-    pub fn with_callback<CB>(self, callback: CB) -> WithCallback<CB> {
-        WithCallback { callback }
+impl AdcDriverFactory {
+    pub fn init_driver(&mut self) -> TockResult<Adc> {
+        let adc = Adc {
+            // num_channels
+            num_channels: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
+            lifetime: PhantomData,
+        };
+        Ok(adc)
     }
 }
 
@@ -47,66 +54,61 @@
 }
 
 pub struct Adc<'a> {
-    count: usize,
-    #[allow(dead_code)] // Used in drop
-    subscription: CallbackSubscription<'a>,
+    num_channels: usize,
+    lifetime: PhantomData<&'a ()>,
 }
 
-pub struct WithCallback<CB> {
-    callback: CB,
-}
+struct AdcEventConsumer;
 
-impl<CB: FnMut(usize, usize)> SubscribableCallback for WithCallback<CB> {
-    fn call_rust(&mut self, _: usize, channel: usize, value: usize) {
-        (self.callback)(channel, value);
-    }
-}
-
-impl<CB: FnMut(usize, usize)> WithCallback<CB> {
-    pub fn init(&mut self) -> TockResult<Adc> {
-        let adc = Adc {
-            count: syscalls::command(DRIVER_NUM, command_nr::COUNT, 0, 0)?,
-            subscription: syscalls::subscribe_cb(
-                DRIVER_NUM,
-                subscribe_nr::SUBSCRIBE_CALLBACK,
-                self,
-            )?,
-        };
-        Ok(adc)
+impl<CB: FnMut(usize, usize)> Consumer<CB> for AdcEventConsumer {
+    fn consume(data: &mut CB, _: usize, channel: usize, value: usize) {
+        data(channel, value);
     }
 }
 
 impl<'a> Adc<'a> {
-    pub fn init_buffer(buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
-        syscalls::allow(DRIVER_NUM, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into)
+    pub fn init_buffer(&self, buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
+        syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into)
     }
 
-    pub fn init_alt_buffer(alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
-        syscalls::allow(DRIVER_NUM, allow_nr::BUFFER_ALT, &mut alt_buffer.buffer)
+    pub fn init_alt_buffer(&self, alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
+        syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER_ALT, &mut alt_buffer.buffer)
             .map_err(Into::into)
     }
 
     /// Return the number of available channels
     pub fn count(&self) -> usize {
-        self.count
+        self.num_channels
+    }
+
+    pub fn subscribe<CB: FnMut(usize, usize)>(
+        &self,
+        callback: &'a mut CB,
+    ) -> TockResult<CallbackSubscription> {
+        syscalls::subscribe::<AdcEventConsumer, _>(
+            DRIVER_NUMBER,
+            subscribe_nr::SUBSCRIBE_CALLBACK,
+            callback,
+        )
+        .map_err(Into::into)
     }
 
     /// Start a single sample of channel
     pub fn sample(&self, channel: usize) -> TockResult<()> {
-        syscalls::command(DRIVER_NUM, command_nr::START, channel, 0)?;
+        syscalls::command(DRIVER_NUMBER, command_nr::START, channel, 0)?;
         Ok(())
     }
 
     /// Start continuous sampling of channel
     pub fn sample_continuous(&self, channel: usize) -> TockResult<()> {
-        syscalls::command(DRIVER_NUM, command_nr::START_REPEAT, channel, 0)?;
+        syscalls::command(DRIVER_NUMBER, command_nr::START_REPEAT, channel, 0)?;
         Ok(())
     }
 
     /// Start continuous sampling to first buffer
     pub fn sample_continuous_buffered(&self, channel: usize, frequency: usize) -> TockResult<()> {
         syscalls::command(
-            DRIVER_NUM,
+            DRIVER_NUMBER,
             command_nr::START_REPEAT_BUFFER,
             channel,
             frequency,
@@ -121,7 +123,7 @@
         frequency: usize,
     ) -> TockResult<()> {
         syscalls::command(
-            DRIVER_NUM,
+            DRIVER_NUMBER,
             command_nr::START_REPEAT_BUFFER_ALT,
             channel,
             frequency,
@@ -131,7 +133,7 @@
 
     /// Stop any started sampling operation
     pub fn stop(&self) -> TockResult<()> {
-        syscalls::command(DRIVER_NUM, command_nr::STOP, 0, 0)?;
+        syscalls::command(DRIVER_NUMBER, command_nr::STOP, 0, 0)?;
         Ok(())
     }
 }
diff --git a/src/drivers.rs b/src/drivers.rs
index b25addf..b7c9845 100644
--- a/src/drivers.rs
+++ b/src/drivers.rs
@@ -1,4 +1,4 @@
-use crate::adc::AdcDriver;
+use crate::adc::AdcDriverFactory;
 use crate::buttons::ButtonsDriverFactory;
 use crate::console::ConsoleDriver;
 use crate::gpio::GpioDriverFactory;
@@ -26,7 +26,7 @@
     pub gpio_driver_factory: GpioDriverFactory,
     pub temperature_driver_factory: TemperatureDriverFactory,
     pub buttons_driver_factory: ButtonsDriverFactory,
-    pub adc_driver: AdcDriver,
+    pub adc_driver_factory: AdcDriverFactory,
     pub rng_driver: RngDriver,
     pub ble_advertising_driver: BleAdvertisingDriver,
     pub ble_scanning_driver: BleScanningDriver,
@@ -56,7 +56,7 @@
 
 #[allow(clippy::declare_interior_mutable_const)]
 const DRIVERS: Drivers = Drivers {
-    adc_driver: AdcDriver,
+    adc_driver_factory: AdcDriverFactory,
     ble_advertising_driver: BleAdvertisingDriver,
     ble_scanning_driver: BleScanningDriver,
     buttons_driver_factory: ButtonsDriverFactory,