keebrs 0.3.0

Keyboard firmware building blocks
// Copyright 2019 Guillaume Pinot <texitoi@texitoi.eu>, Josh Robson Chase <josh@robsonchase.com>
// SPDX-License-Identifier: MIT

use crate::{
    led::LedReport,
    translate::Translated,
    usb::{
        hid::{
            HidDevice,
            Protocol,
            ReportType,
            Subclass,
        },
        report::Reporter,
    },
};

pub struct Keyboard<L> {
    reporter: Reporter,
    boot: bool,
    leds: L,
}

impl<L> Keyboard<L> {
    pub fn new(leds: L, reporter: Reporter) -> Keyboard<L> {
        Keyboard {
            leds,
            reporter,
            boot: false,
        }
    }

    pub fn update_report(&mut self, keystroke: Translated) {
        self.reporter.update_report(keystroke)
    }
}

impl<L> HidDevice for Keyboard<L>
where
    L: LedReport,
{
    fn subclass(&self) -> Subclass {
        Subclass::BootInterface
    }

    fn protocol(&self) -> Protocol {
        Protocol::Keyboard
    }

    fn report_descriptor(&self) -> &[u8] {
        if self.boot {
            self.reporter.get_boot_desc()
        } else {
            self.reporter.get_desc()
        }
    }

    fn get_report(
        &mut self,
        report_type: ReportType,
        _report_id: u8,
    ) -> Result<&[u8], &'static str> {
        match report_type {
            ReportType::Input => Ok(if self.boot {
                self.reporter.get_boot_report()
            } else {
                self.reporter.get_report()
            }),
            _ => Err("unsupprted report type"),
        }
    }

    fn set_boot(&mut self, boot: bool) {
        self.boot = boot;
    }

    fn set_report(
        &mut self,
        report_type: ReportType,
        report_id: u8,
        data: &[u8],
    ) -> Result<(), &'static str> {
        if report_type == ReportType::Output && report_id == 0 && data.len() == 1 {
            self.leds.from_report_byte(data[0]);
            return Ok(());
        }
        Err("invalid set_report request")
    }
}