Better buttons and LEDs API
diff --git a/src/buttons.rs b/src/buttons.rs
index 9bcc2f0..5787f83 100644
--- a/src/buttons.rs
+++ b/src/buttons.rs
@@ -1,5 +1,6 @@
 use crate::callback::CallbackSubscription;
-use crate::callback::SubscribableCallback;
+use crate::callback::Consumer;
+use crate::result::OtherError;
 use crate::result::TockResult;
 use crate::syscalls;
 use core::marker::PhantomData;
@@ -18,50 +19,92 @@
 }
 
 #[non_exhaustive]
-pub struct ButtonDriver;
+pub struct ButtonsDriverFactory;
 
-impl ButtonDriver {
-    pub fn with_callback<CB>(self, callback: CB) -> WithCallback<CB> {
-        WithCallback { callback }
-    }
-}
-
-pub struct WithCallback<CB> {
-    callback: CB,
-}
-
-impl<CB: FnMut(usize, ButtonState)> SubscribableCallback for WithCallback<CB> {
-    fn call_rust(&mut self, button_num: usize, state: usize, _: usize) {
-        (self.callback)(button_num, state.into());
-    }
-}
-
-impl<CB: FnMut(usize, ButtonState)> WithCallback<CB> {
-    pub fn init(&mut self) -> TockResult<Buttons> {
-        let buttons = Buttons {
-            count: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
-            subscription: syscalls::subscribe_cb(
-                DRIVER_NUMBER,
-                subscribe_nr::SUBSCRIBE_CALLBACK,
-                self,
-            )?,
+impl ButtonsDriverFactory {
+    pub fn init_driver(&mut self) -> TockResult<ButtonsDriver> {
+        let buttons_driver = ButtonsDriver {
+            num_buttons: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
+            lifetime: PhantomData,
         };
-        Ok(buttons)
+        Ok(buttons_driver)
+    }
+}
+
+pub struct ButtonsDriver<'a> {
+    num_buttons: usize,
+    lifetime: PhantomData<&'a ()>,
+}
+
+impl<'a> ButtonsDriver<'a> {
+    pub fn num_buttons(&self) -> usize {
+        self.num_buttons
+    }
+
+    pub fn get(&self, button_num: usize) -> Option<Button> {
+        if button_num < self.num_buttons {
+            Some(Button {
+                button_num,
+                lifetime: PhantomData,
+            })
+        } else {
+            None
+        }
+    }
+
+    pub fn buttons(&self) -> Buttons {
+        Buttons {
+            num_buttons: self.num_buttons,
+            curr_button: 0,
+            lifetime: PhantomData,
+        }
+    }
+
+    pub fn subscribe<CB: Fn(usize, ButtonState)>(
+        &self,
+        callback: &'a mut CB,
+    ) -> TockResult<CallbackSubscription> {
+        syscalls::subscribe::<ButtonsEventConsumer, _>(
+            DRIVER_NUMBER,
+            subscribe_nr::SUBSCRIBE_CALLBACK,
+            callback,
+        )
+        .map_err(Into::into)
+    }
+}
+
+struct ButtonsEventConsumer;
+
+impl<CB: Fn(usize, ButtonState)> Consumer<CB> for ButtonsEventConsumer {
+    fn consume(callback: &mut CB, button_num: usize, button_state: usize, _: usize) {
+        let button_state = match button_state {
+            0 => ButtonState::Released,
+            1 => ButtonState::Pressed,
+            _ => return,
+        };
+        callback(button_num, button_state);
     }
 }
 
 pub struct Buttons<'a> {
-    count: usize,
-    #[allow(dead_code)] // Used in drop
-    subscription: CallbackSubscription<'a>,
+    num_buttons: usize,
+    curr_button: usize,
+    lifetime: PhantomData<&'a ()>,
 }
 
-impl<'a> Buttons<'a> {
-    pub fn iter_mut(&mut self) -> ButtonIter {
-        ButtonIter {
-            curr_button: 0,
-            button_count: self.count,
-            _lifetime: Default::default(),
+impl<'a> Iterator for Buttons<'a> {
+    type Item = Button<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.curr_button < self.num_buttons {
+            let item = Button {
+                button_num: self.curr_button,
+                lifetime: PhantomData,
+            };
+            self.curr_button += 1;
+            Some(item)
+        } else {
+            None
         }
     }
 }
@@ -72,65 +115,45 @@
     Released,
 }
 
-impl From<usize> for ButtonState {
-    fn from(state: usize) -> ButtonState {
-        match state {
-            0 => ButtonState::Released,
-            1 => ButtonState::Pressed,
-            _ => unreachable!(),
+impl From<ButtonState> for bool {
+    fn from(button_state: ButtonState) -> Self {
+        match button_state {
+            ButtonState::Released => false,
+            ButtonState::Pressed => true,
         }
     }
 }
 
-impl<'a, 'b> IntoIterator for &'b mut Buttons<'a> {
-    type Item = ButtonHandle<'b>;
-    type IntoIter = ButtonIter<'b>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter_mut()
-    }
-}
-
-pub struct ButtonIter<'a> {
-    curr_button: usize,
-    button_count: usize,
-    _lifetime: PhantomData<&'a ()>,
-}
-
-impl<'a> Iterator for ButtonIter<'a> {
-    type Item = ButtonHandle<'a>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.curr_button < self.button_count {
-            let item = ButtonHandle {
-                button_num: self.curr_button,
-                _lifetime: Default::default(),
-            };
-            self.curr_button += 1;
-            Some(item)
-        } else {
-            None
-        }
-    }
-}
-
-pub struct ButtonHandle<'a> {
+pub struct Button<'a> {
     button_num: usize,
-    _lifetime: PhantomData<&'a ()>,
+    lifetime: PhantomData<&'a ()>,
 }
 
-impl<'a> ButtonHandle<'a> {
-    pub fn enable(&mut self) -> TockResult<Button> {
+impl<'a> Button<'a> {
+    pub fn button_num(&self) -> usize {
+        self.button_num
+    }
+
+    pub fn read(&self) -> TockResult<ButtonState> {
+        let button_state = syscalls::command(DRIVER_NUMBER, command_nr::READ, self.button_num, 0)?;
+        match button_state {
+            0 => Ok(ButtonState::Released),
+            1 => Ok(ButtonState::Pressed),
+            _ => Err(OtherError::ButtonsDriverInvalidState.into()),
+        }
+    }
+
+    pub fn enable_interrupt(&self) -> TockResult<()> {
         syscalls::command(
             DRIVER_NUMBER,
             command_nr::ENABLE_INTERRUPT,
             self.button_num,
             0,
         )?;
-        Ok(Button { handle: self })
+        Ok(())
     }
 
-    pub fn disable(&mut self) -> TockResult<()> {
+    pub fn disable_interrupt(&self) -> TockResult<()> {
         syscalls::command(
             DRIVER_NUMBER,
             command_nr::DISABLE_INTERRUPT,
@@ -140,15 +163,3 @@
         Ok(())
     }
 }
-
-pub struct Button<'a> {
-    handle: &'a ButtonHandle<'a>,
-}
-
-impl<'a> Button<'a> {
-    pub fn read(&self) -> TockResult<ButtonState> {
-        syscalls::command(DRIVER_NUMBER, command_nr::READ, self.handle.button_num, 0)
-            .map(ButtonState::from)
-            .map_err(Into::into)
-    }
-}